1#!/usr/bin/env node
The Worker as the deploy uploads it: worker/ with a node_modules of its
own, holding exactly its dependencies' closure, so wrangler deploy in a
copy of it outside the repo resolves @simplewebauthn/server and
everything that needs.
worker-closure.mjs <installed worker dir> <out dir>
Run in nix/strudel.nix after pnpm has installed the workspace (worker/ is
a workspace package). pnpm's layout is already self-contained per
package: node_modules/.pnpm/<entry>/node_modules/ holds the package and
relative symlinks to its dependencies' entries beside it. So the closure
is those entries, found by following the symlinks from worker's own
node_modules, copied with their symlinks as they are, plus worker's
top-level links pointing into the copy. pnpm deploy would do this, but
in pnpm 10 it either needs injected workspace packages (changing how the
whole workspace links) or re-resolves every workspace package's
dependencies from the registry (--legacy), which the sandbox cannot.
The .pnpm entry a real path is inside: [store dir, entry name].
The package names in a node_modules directory (name and @scope/name).
worker's own files, without what an install or a dev run leaves in it
55const outStore = join(out, 'node_modules', '.pnpm'); 56const seen = new Set(); 57const queue = []; 58const top = packages(join(from, 'node_modules')); 59for (const name of top) { 60 const real = realpathSync(join(from, 'node_modules', name)); 61 const [store, entry] = entryOf(real); 62 queue.push([store, entry]); 63 const link = join(out, 'node_modules', name); 64 mkdirSync(dirname(link), { recursive: true }); 65 symlinkSync(relative(dirname(link), join(outStore, entry, relative(join(store, entry), real))), link); 66} 67while (queue.length) { 68 const [store, entry] = queue.pop(); 69 if (seen.has(entry)) continue; 70 seen.add(entry); 71 cpSync(join(store, entry), join(outStore, entry), { recursive: true, verbatimSymlinks: true }); 72 const modules = join(store, entry, 'node_modules'); 73 for (const name of packages(modules)) { 74 const path = join(modules, name); 75 if (!lstatSync(path).isSymbolicLink()) continue; // the package itself 76 const target = resolve(dirname(path), readlinkSync(path)); 77 const [depStore, dep] = entryOf(target); 78 if (depStore !== store) throw new Error(`${entry} links outside its store: ${name}`); 79 queue.push([store, dep]); 80 } 81} 82console.error(`worker-closure: ${top.length} dependencies, ${seen.size} packages in their closure`);