Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Dockerfile.worker
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,10 @@ COPY . .
USER node
# Long-poll worker; WORKER_* env vars control claim batch size, concurrency,
# and the stale-claim window (see src/lib/env.ts).
CMD ["node", "node_modules/tsx/dist/cli.mjs", "worker/index.ts"]
#
# Route through scripts/run-tsx.mjs, NOT bare tsx: worker/index.ts imports
# src/lib/env, which begins with `import "server-only"`. Under bare tsx that
# import throws and the worker crash-loops on boot. run-tsx.mjs registers the
# server-only stub hook so the import resolves outside the Next bundler.
# Guarded by tests/tsx-server-only-runner.test.ts.
CMD ["node", "scripts/run-tsx.mjs", "worker/index.ts"]
15 changes: 15 additions & 0 deletions tests/tsx-server-only-runner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,21 @@ describe("standalone TSX server-only compatibility", () => {
expect(packageJson.scripts["check:supabase-project"]).toContain("scripts/run-tsx.mjs");
});

it("boots the worker image through the server-only-aware runner, not bare tsx", () => {
const dockerfile = readFileSync(new URL("../Dockerfile.worker", import.meta.url), "utf8");
const cmdLine = dockerfile.split(/\r?\n/).find((line) => line.trimStart().startsWith("CMD"));
expect(cmdLine, "Dockerfile.worker must define a CMD").toBeDefined();
// worker/index.ts imports src/lib/env, which is `import "server-only"`.
// Bare tsx throws on that import at boot; the entrypoint must route through
// scripts/run-tsx.mjs, which registers the server-only stub hook. Assert the
// exact exec-form vector so no bare-tsx variant (["tsx", …], ["npx","tsx", …],
// tsx/dist/cli.mjs, or a reordered command) can slip through.
const bracket = cmdLine!.indexOf("[");
expect(bracket, "worker CMD must use JSON exec form").toBeGreaterThan(-1);
const execVector = JSON.parse(cmdLine!.slice(bracket)) as string[];
expect(execVector).toEqual(["node", "scripts/run-tsx.mjs", "worker/index.ts"]);
});

it("keeps the Next server-only marker while stubbing it only for standalone runners", () => {
expect(readFileSync(new URL("../src/lib/env.ts", import.meta.url), "utf8")).toMatch(/^import ["']server-only["'];/);
expect(readFileSync(new URL("../scripts/register-server-only.mjs", import.meta.url), "utf8")).toContain(
Expand Down
Loading