Files
pn-new-crm/src/server-runtime-preamble.ts
Matt 319fd7fd1a
All checks were successful
Build & Push Docker Images / lint (push) Successful in 2m43s
Build & Push Docker Images / build-and-push (push) Successful in 7m31s
fix(server): resolve socket.io deps via NODE_PATH + polyfill AsyncLocalStorage
Two runtime defects in the crm-app prod image (never exercised before this
deploy; CI only builds + pushes):

1. Replacing the standalone node_modules wholesale to add socket.io's deps
   swapped out Next's standalone-tuned `next` and broke its runtime
   ("Invariant: AsyncLocalStorage accessed in runtime where it is not
   available"). Instead, stage the complete hoisted prod tree in a separate
   dir on NODE_PATH: the standalone node_modules (and its `next`) stay
   intact, and only the socket server's otherwise-missing deps
   (engine.io→accepts/ws/cors, @socket.io/redis-adapter) fall through to it.

2. Defensively set globalThis.AsyncLocalStorage before Next's app-render
   modules load, via a preamble that is the first import in server.ts.
   Next's node-environment-baseline normally sets it during the standalone
   bootstrap, but the custom server can load app-render storage first.
   Verified in the esbuild bundle that the assignment runs before
   require("next").

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 23:34:28 +02:00

16 lines
781 B
TypeScript

/**
* Runtime preamble — MUST stay the first import in server.ts.
*
* Next's app-render calls createAsyncLocalStorage(), which falls back to a
* throwing FakeAsyncLocalStorage when `globalThis.AsyncLocalStorage` is unset
* ("Invariant: AsyncLocalStorage accessed in runtime where it is not
* available", error E504). next/dist/server/node-environment-baseline sets it
* during Next's own standalone-server bootstrap, but our custom server
* (dist/server.js → server-custom.js) can load app-render storage before that
* runs. Set it up-front, idempotently, so the invariant can never fire.
*/
import { AsyncLocalStorage } from 'node:async_hooks';
const g = globalThis as typeof globalThis & { AsyncLocalStorage?: unknown };
g.AsyncLocalStorage ??= AsyncLocalStorage;