From b6c65efd2878ed89c96fcceb2dff9304825e8491 Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com> Date: Thu, 11 Jun 2026 22:07:32 -0300 Subject: [PATCH] fix(build): include webdav-handler.mjs in dist/ bundle (#3687) server-ws.mjs imports ./webdav-handler.mjs but the assembleStandalone pipeline did not copy it from scripts/dev/, causing a startup crash on any fresh install of v3.8.22 (ERR_MODULE_NOT_FOUND). Fix: add the copy entry to assembleStandalone.mjs, add it to APP_STAGING_ALLOWED_EXACT_PATHS and PACK_ARTIFACT_REQUIRED_PATHS in pack-artifact-policy.ts, and add a regression test. Hotfix validated live on VPS (192.168.0.15): server-ws.mjs resolves the module and the process starts healthy after the file was deployed. --- scripts/build/assembleStandalone.mjs | 83 +++++++++++++++++++++---- scripts/build/pack-artifact-policy.ts | 2 + tests/unit/pack-artifact-policy.test.ts | 9 +++ 3 files changed, 81 insertions(+), 13 deletions(-) diff --git a/scripts/build/assembleStandalone.mjs b/scripts/build/assembleStandalone.mjs index e040264bdf..e65cfe86a8 100644 --- a/scripts/build/assembleStandalone.mjs +++ b/scripts/build/assembleStandalone.mjs @@ -73,19 +73,43 @@ async function exists(targetPath) { * for either path/platform. @type {{label:string, src:string[], dest:string[]}[]} */ const NATIVE_ASSET_ENTRIES = [ - { label: "wreq-js native runtime", src: ["node_modules", "wreq-js", "rust"], dest: ["node_modules", "wreq-js", "rust"] }, - { label: "better-sqlite3 native binary", src: ["node_modules", "better-sqlite3", "build"], dest: ["node_modules", "better-sqlite3", "build"] }, + { + label: "wreq-js native runtime", + src: ["node_modules", "wreq-js", "rust"], + dest: ["node_modules", "wreq-js", "rust"], + }, + { + label: "better-sqlite3 native binary", + src: ["node_modules", "better-sqlite3", "build"], + dest: ["node_modules", "better-sqlite3", "build"], + }, ]; /** @type {{label:string, src:string[], dest:string[]}[]} */ const EXTRA_MODULE_ENTRIES = [ - { label: "@swc/helpers", src: ["node_modules", "@swc", "helpers"], dest: ["node_modules", "@swc", "helpers"] }, - { label: "pino-abstract-transport", src: ["node_modules", "pino-abstract-transport"], dest: ["node_modules", "pino-abstract-transport"] }, - { label: "pino-pretty", src: ["node_modules", "pino-pretty"], dest: ["node_modules", "pino-pretty"] }, + { + label: "@swc/helpers", + src: ["node_modules", "@swc", "helpers"], + dest: ["node_modules", "@swc", "helpers"], + }, + { + label: "pino-abstract-transport", + src: ["node_modules", "pino-abstract-transport"], + dest: ["node_modules", "pino-abstract-transport"], + }, + { + label: "pino-pretty", + src: ["node_modules", "pino-pretty"], + dest: ["node_modules", "pino-pretty"], + }, { label: "split2", src: ["node_modules", "split2"], dest: ["node_modules", "split2"] }, { label: "migrations", src: ["src", "lib", "db", "migrations"], dest: ["migrations"] }, { label: "MITM server", src: ["src", "mitm", "server.cjs"], dest: ["src", "mitm", "server.cjs"] }, - { label: "run-standalone script", src: ["scripts", "dev", "run-standalone.mjs"], dest: ["dev", "run-standalone.mjs"] }, + { + label: "run-standalone script", + src: ["scripts", "dev", "run-standalone.mjs"], + dest: ["dev", "run-standalone.mjs"], + }, { // WS-aware wrapper that run-standalone.mjs prefers over bare server.js. // It installs the trusted peer-IP stamp the authz middleware needs to allow @@ -96,14 +120,47 @@ const EXTRA_MODULE_ENTRIES = [ src: ["scripts", "dev", "standalone-server-ws.mjs"], dest: ["server-ws.mjs"], }, - { label: "peer-stamp helper (server-ws.mjs dependency)", src: ["scripts", "dev", "peer-stamp.mjs"], dest: ["peer-stamp.mjs"] }, - { label: "responses-ws-proxy (server-ws.mjs dependency)", src: ["scripts", "dev", "responses-ws-proxy.mjs"], dest: ["responses-ws-proxy.mjs"] }, - { label: "runtime-env script", src: ["scripts", "build", "runtime-env.mjs"], dest: ["build", "runtime-env.mjs"] }, - { label: "bootstrap-env script", src: ["scripts", "build", "bootstrap-env.mjs"], dest: ["build", "bootstrap-env.mjs"] }, - { label: "healthcheck script", src: ["scripts", "dev", "healthcheck.mjs"], dest: ["healthcheck.mjs"] }, + { + label: "peer-stamp helper (server-ws.mjs dependency)", + src: ["scripts", "dev", "peer-stamp.mjs"], + dest: ["peer-stamp.mjs"], + }, + { + label: "responses-ws-proxy (server-ws.mjs dependency)", + src: ["scripts", "dev", "responses-ws-proxy.mjs"], + dest: ["responses-ws-proxy.mjs"], + }, + { + label: "webdav-handler (server-ws.mjs dependency)", + src: ["scripts", "dev", "webdav-handler.mjs"], + dest: ["webdav-handler.mjs"], + }, + { + label: "runtime-env script", + src: ["scripts", "build", "runtime-env.mjs"], + dest: ["build", "runtime-env.mjs"], + }, + { + label: "bootstrap-env script", + src: ["scripts", "build", "bootstrap-env.mjs"], + dest: ["build", "bootstrap-env.mjs"], + }, + { + label: "healthcheck script", + src: ["scripts", "dev", "healthcheck.mjs"], + dest: ["healthcheck.mjs"], + }, { label: "public directory", src: ["public"], dest: ["public"] }, - { label: "playwright-core (dynamic import by gemini-web executor)", src: ["node_modules", "playwright-core"], dest: ["node_modules", "playwright-core"] }, - { label: "sqlite-vec wrapper (vector memory - loaded at runtime via createRequire)", src: ["node_modules", "sqlite-vec"], dest: ["node_modules", "sqlite-vec"] }, + { + label: "playwright-core (dynamic import by gemini-web executor)", + src: ["node_modules", "playwright-core"], + dest: ["node_modules", "playwright-core"], + }, + { + label: "sqlite-vec wrapper (vector memory - loaded at runtime via createRequire)", + src: ["node_modules", "sqlite-vec"], + dest: ["node_modules", "sqlite-vec"], + }, // sqlite-vec's native vec0.so lives in a platform-specific package resolved at // runtime via require.resolve(). Next.js does NOT trace it into the standalone // (the externalized wrapper is copied, but its optional platform dep is missed - diff --git a/scripts/build/pack-artifact-policy.ts b/scripts/build/pack-artifact-policy.ts index 99574dc081..3e4ed17db3 100644 --- a/scripts/build/pack-artifact-policy.ts +++ b/scripts/build/pack-artifact-policy.ts @@ -42,6 +42,7 @@ export const APP_STAGING_ALLOWED_EXACT_PATHS: string[] = [ "scripts/dev/sync-env.mjs", "server.js", "server-ws.mjs", + "webdav-handler.mjs", ]; export const APP_STAGING_ALLOWED_PATH_PREFIXES: string[] = [ @@ -120,6 +121,7 @@ export const PACK_ARTIFACT_REQUIRED_PATHS: string[] = [ "dist/server-ws.mjs", "dist/responses-ws-proxy.mjs", "dist/peer-stamp.mjs", + "dist/webdav-handler.mjs", "bin/cli/program.mjs", "bin/mcp-server.mjs", "bin/nodeRuntimeSupport.mjs", diff --git a/tests/unit/pack-artifact-policy.test.ts b/tests/unit/pack-artifact-policy.test.ts index 71534eeb11..b9688759cb 100644 --- a/tests/unit/pack-artifact-policy.test.ts +++ b/tests/unit/pack-artifact-policy.test.ts @@ -56,6 +56,14 @@ test("findUnexpectedArtifactPaths flags app pack files outside the allowlist", ( assert.deepEqual(unexpectedPaths, ["dist/scripts/build/prepublish.mjs", "docs/extra.md"]); }); +test("webdav-handler.mjs is allowed in staging dist/ (server-ws.mjs dependency, missed in 3.8.22 build)", () => { + const unexpectedPaths = findUnexpectedArtifactPaths(["webdav-handler.mjs"], { + exactPaths: APP_STAGING_ALLOWED_EXACT_PATHS, + prefixPaths: APP_STAGING_ALLOWED_PATH_PREFIXES, + }); + assert.deepEqual(unexpectedPaths, []); +}); + test("setupPolyfill.ts is allowed in the tarball (bin/omniroute.mjs imports it at startup)", () => { const unexpectedPaths = findUnexpectedArtifactPaths(["open-sse/utils/setupPolyfill.ts"], { exactPaths: PACK_ARTIFACT_ALLOWED_EXACT_PATHS, @@ -89,6 +97,7 @@ test("findMissingArtifactPaths flags missing root runtime files in the tarball", "dist/peer-stamp.mjs", "dist/responses-ws-proxy.mjs", "dist/server-ws.mjs", + "dist/webdav-handler.mjs", "scripts/build/native-binary-compat.mjs", "src/shared/utils/nodeRuntimeSupport.ts", ]);