Skip to content

endpoint imports node:fs via digest/tree.ts, breaking the Cloudflare adapter #2

Description

@hev

Problem

The endpoint bundle pulls in node:fs, which workerd only provides under the
nodejs_compat compatibility flag. On a stock @astrojs/cloudflare site the
module fails to resolve and the whole site 500s — not just /api/ask, since the
dev server can't build the route:

[vite]: Rolldown failed to resolve import "node:fs"
  (resolved id: node:fs) in @hevmind/ask/src/digest/tree.ts.

astro build warns about the same thing more quietly:

[WARN] [vite] Unexpected Node.js imports for environment "prerender".
Do you need to enable the "nodejs_compat" compatibility flag?

Cause

endpoint.ts:12
statically imports from the digest tree module:

import { digestTreeFiles } from './digest/tree.ts';

and tree.ts:1
imports fs at module top level:

import { readFileSync, readdirSync, statSync } from 'node:fs';
import path from 'node:path';

Why this one is easy

digestTreeFiles doesn't use fs at all. It's pure — it takes an in-memory
Digest and renders it to DigestTreeFile[]
(tree.ts:74),
and the endpoint hands it the digest it already got from the
virtual:hev-ask/digest module, not from disk
(endpoint.ts:201).

Every actual fs caller in that file is build-time or CLI only:

Function Uses fs Called from
digestTreeFiles no the endpoint (worker)
renderMetaFile, renderNodeFile, nodePath, … no digestTreeFiles
readDigestArtifact statSync integration.ts (Node)
readDigestTree readFileSync Node
readLegacyJson readFileSync Node
walk readdirSync Node

So the worker is paying for a Node dependency it never calls. It's purely an
import-graph artifact.

Fix

Split the module along the line that already exists:

  • digest/tree-render.ts — the pure serializers (digestTreeFiles and the
    render* / *Path helpers). No node:fs, no node:path.
  • digest/tree.ts — keeps the fs readers, imports the pure module.

The endpoint then imports only tree-render.ts and the worker bundle has no
Node builtins from this path. No behavior change, no nodejs_compat needed, and
it keeps ask digest bundle / the tarball route working as-is.

node:path usage in the pure helpers (if any survive the split) should become
plain string joins — it's all POSIX-style digest-relative paths.

Note

Telling users to enable nodejs_compat would also make the error go away, but
it's the wrong fix: it papers over a Node dependency in worker code that isn't
needed, and it's an extra config step on the path we advertise as turnkey.


Found while wiring 0.3.4 into a Starlight docs site. Present on main
(a3204b4), not just the 0.3.4 tag. Fixing this alone is not sufficient to get
the Cloudflare path working — #3 is waiting immediately
behind it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions