From 554bf6595731ef8109d3376f76f2ecb609d94daa Mon Sep 17 00:00:00 2001 From: Oleksii Soboliev Date: Fri, 10 Jul 2026 03:55:48 +0200 Subject: [PATCH 1/5] test(adapter-node): boot the built output when instrumentation.server.js is present Adds a fixture app + boot test that builds with adapter-node and starts build/index.js, asserting that (1) the server boots at all and (2) a module-scope $app/env/private read observes the runtime value. Currently red on version-3: with an instrumentation file present, the adapter's env.js is emitted outside the ENV_PREFIX replace filter and the server crashes at startup with 'ReferenceError: ENV_PREFIX is not defined'. Also covers the startup-crash and env-ordering regressions discussed in #16288 / #16302 / #16303. Co-Authored-By: Claude Fable 5 --- packages/adapter-node/package.json | 6 +- .../test/apps/instrumentation/.gitignore | 4 ++ .../test/apps/instrumentation/package.json | 18 +++++ .../test/apps/instrumentation/src/app.html | 12 ++++ .../test/apps/instrumentation/src/env.js | 5 ++ .../src/instrumentation.server.js | 4 ++ .../src/lib/server/api-client.js | 5 ++ .../instrumentation/src/routes/+page.svelte | 1 + .../instrumentation/src/routes/env/+server.js | 9 +++ .../test/apps/instrumentation/test/boot.js | 65 +++++++++++++++++++ .../test/apps/instrumentation/vite.config.js | 14 ++++ pnpm-lock.yaml | 15 +++++ 12 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 packages/adapter-node/test/apps/instrumentation/.gitignore create mode 100644 packages/adapter-node/test/apps/instrumentation/package.json create mode 100644 packages/adapter-node/test/apps/instrumentation/src/app.html create mode 100644 packages/adapter-node/test/apps/instrumentation/src/env.js create mode 100644 packages/adapter-node/test/apps/instrumentation/src/instrumentation.server.js create mode 100644 packages/adapter-node/test/apps/instrumentation/src/lib/server/api-client.js create mode 100644 packages/adapter-node/test/apps/instrumentation/src/routes/+page.svelte create mode 100644 packages/adapter-node/test/apps/instrumentation/src/routes/env/+server.js create mode 100644 packages/adapter-node/test/apps/instrumentation/test/boot.js create mode 100644 packages/adapter-node/test/apps/instrumentation/vite.config.js diff --git a/packages/adapter-node/package.json b/packages/adapter-node/package.json index 5db826ebc684..34ea6ed92983 100644 --- a/packages/adapter-node/package.json +++ b/packages/adapter-node/package.json @@ -35,11 +35,13 @@ "scripts": { "dev": "rolldown -cw", "build": "rolldown -c", - "test": "vitest run", + "test": "pnpm test:unit && pnpm test:apps", "check": "tsc", "lint": "prettier --check .", "format": "pnpm lint --write", - "prepublishOnly": "pnpm build" + "prepublishOnly": "pnpm build", + "test:unit": "vitest run", + "test:apps": "pnpm build && pnpm -r --workspace-concurrency 1 --filter=\"./test/**\" test" }, "devDependencies": { "@polka/url": "catalog:", diff --git a/packages/adapter-node/test/apps/instrumentation/.gitignore b/packages/adapter-node/test/apps/instrumentation/.gitignore new file mode 100644 index 000000000000..762b1c80fa9d --- /dev/null +++ b/packages/adapter-node/test/apps/instrumentation/.gitignore @@ -0,0 +1,4 @@ +.DS_Store +node_modules +/.svelte-kit +/build diff --git a/packages/adapter-node/test/apps/instrumentation/package.json b/packages/adapter-node/test/apps/instrumentation/package.json new file mode 100644 index 000000000000..9899a9690d6a --- /dev/null +++ b/packages/adapter-node/test/apps/instrumentation/package.json @@ -0,0 +1,18 @@ +{ + "name": "test-adapter-node-instrumentation", + "version": "0.0.1", + "private": true, + "type": "module", + "scripts": { + "dev": "vite dev", + "build": "vite build", + "prepare": "svelte-kit sync || echo ''", + "test": "pnpm build && node test/boot.js" + }, + "devDependencies": { + "@sveltejs/kit": "workspace:^", + "@sveltejs/vite-plugin-svelte": "catalog:", + "svelte": "catalog:", + "vite": "catalog:" + } +} diff --git a/packages/adapter-node/test/apps/instrumentation/src/app.html b/packages/adapter-node/test/apps/instrumentation/src/app.html new file mode 100644 index 000000000000..26bc25de4e52 --- /dev/null +++ b/packages/adapter-node/test/apps/instrumentation/src/app.html @@ -0,0 +1,12 @@ + + + + + + %sveltekit.head% + + + +
%sveltekit.body%
+ + diff --git a/packages/adapter-node/test/apps/instrumentation/src/env.js b/packages/adapter-node/test/apps/instrumentation/src/env.js new file mode 100644 index 000000000000..528bb210784a --- /dev/null +++ b/packages/adapter-node/test/apps/instrumentation/src/env.js @@ -0,0 +1,5 @@ +import { defineEnvVars } from '@sveltejs/kit/hooks'; + +export const variables = defineEnvVars({ + MY_BASE_URL: { public: false, static: false } +}); diff --git a/packages/adapter-node/test/apps/instrumentation/src/instrumentation.server.js b/packages/adapter-node/test/apps/instrumentation/src/instrumentation.server.js new file mode 100644 index 000000000000..23bb7c6f0195 --- /dev/null +++ b/packages/adapter-node/test/apps/instrumentation/src/instrumentation.server.js @@ -0,0 +1,4 @@ +// The mere presence of this file makes adapter-node call `builder.instrument()` +// (with `env: 'process.env'` on the eager-env branch), generating the env-init +// facade — the code path under test. +console.log('[instrumentation] evaluated'); diff --git a/packages/adapter-node/test/apps/instrumentation/src/lib/server/api-client.js b/packages/adapter-node/test/apps/instrumentation/src/lib/server/api-client.js new file mode 100644 index 000000000000..9df3c06c4af0 --- /dev/null +++ b/packages/adapter-node/test/apps/instrumentation/src/lib/server/api-client.js @@ -0,0 +1,5 @@ +import { MY_BASE_URL } from '$app/env/private'; + +// Module-scope read — mirrors configuring an API client with `baseUrl` from dynamic +// env. Correct only if env is populated before this module evaluates. +export const CAPTURED_AT_MODULE_SCOPE = MY_BASE_URL; diff --git a/packages/adapter-node/test/apps/instrumentation/src/routes/+page.svelte b/packages/adapter-node/test/apps/instrumentation/src/routes/+page.svelte new file mode 100644 index 000000000000..c45ce6b6da49 --- /dev/null +++ b/packages/adapter-node/test/apps/instrumentation/src/routes/+page.svelte @@ -0,0 +1 @@ +

adapter-node instrumentation test app

diff --git a/packages/adapter-node/test/apps/instrumentation/src/routes/env/+server.js b/packages/adapter-node/test/apps/instrumentation/src/routes/env/+server.js new file mode 100644 index 000000000000..6db344c105bf --- /dev/null +++ b/packages/adapter-node/test/apps/instrumentation/src/routes/env/+server.js @@ -0,0 +1,9 @@ +import { json } from '@sveltejs/kit'; +import { CAPTURED_AT_MODULE_SCOPE } from '$lib/server/api-client.js'; + +export function GET() { + return json({ + captured: CAPTURED_AT_MODULE_SCOPE ?? null, + live: process.env.MY_BASE_URL ?? null + }); +} diff --git a/packages/adapter-node/test/apps/instrumentation/test/boot.js b/packages/adapter-node/test/apps/instrumentation/test/boot.js new file mode 100644 index 000000000000..d3486dd795b0 --- /dev/null +++ b/packages/adapter-node/test/apps/instrumentation/test/boot.js @@ -0,0 +1,65 @@ +// Boots the adapter-node build output with an instrumentation file present and +// asserts that (1) the server starts at all — regression for the env-init facade +// resolving `set_env` from the adapter's own `env.js` (sveltejs/kit#16303), +// and (2) a module-scope `$app/env/private` read observes the runtime value — +// regression for sveltejs/kit#16288. +import { spawn } from 'node:child_process'; + +const PORT = 3399; +const EXPECTED = 'https://api.example'; + +const server = spawn(process.execPath, ['build/index.js'], { + env: { + ...process.env, + MY_BASE_URL: EXPECTED, + PORT: String(PORT), + HOST: '127.0.0.1' + }, + stdio: ['ignore', 'pipe', 'pipe'] +}); + +let output = ''; +server.stdout.on('data', (chunk) => (output += chunk)); +server.stderr.on('data', (chunk) => (output += chunk)); + +let exited = false; +server.on('exit', () => (exited = true)); + +function fail(message) { + console.error(`FAIL: ${message}`); + console.error('--- server output ---'); + console.error(output || '(none)'); + server.kill(); + process.exit(1); +} + +try { + let response; + for (let attempt = 0; attempt < 40; attempt++) { + if (exited) fail('server exited before responding (startup crash)'); + await new Promise((resolve) => setTimeout(resolve, 250)); + try { + response = await fetch(`http://127.0.0.1:${PORT}/env`); + break; + } catch { + // not up yet + } + } + if (!response) fail('server never came up'); + + const { captured, live } = await response.json(); + if (live !== EXPECTED) + fail(`live env read is ${JSON.stringify(live)}, expected ${JSON.stringify(EXPECTED)}`); + if (captured !== EXPECTED) { + fail( + `module-scope $app/env/private read captured ${JSON.stringify(captured)} — evaluated before env was set` + ); + } + console.log( + 'PASS: server booted with instrumentation and module-scope env read observed the runtime value' + ); + server.kill(); + process.exit(0); +} catch (error) { + fail(error.message); +} diff --git a/packages/adapter-node/test/apps/instrumentation/vite.config.js b/packages/adapter-node/test/apps/instrumentation/vite.config.js new file mode 100644 index 000000000000..876e6414dc30 --- /dev/null +++ b/packages/adapter-node/test/apps/instrumentation/vite.config.js @@ -0,0 +1,14 @@ +import { sveltekit } from '@sveltejs/kit/vite'; +import adapter from '../../../index.js'; + +/** @type {import('vite').UserConfig} */ +export default { + build: { + minify: false + }, + plugins: [ + sveltekit({ + adapter: adapter() + }) + ] +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f1caf22bd2bc..c3a1b2ffd96d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -351,6 +351,21 @@ importers: specifier: 'catalog:' version: 8.0.16(@types/node@22.19.19)(esbuild@0.28.1)(jiti@2.4.2)(yaml@2.9.0) + packages/adapter-node/test/apps/instrumentation: + devDependencies: + '@sveltejs/kit': + specifier: workspace:^ + version: link:../../../../kit + '@sveltejs/vite-plugin-svelte': + specifier: 'catalog:' + version: 7.0.0(svelte@5.56.3(@typescript-eslint/types@8.61.1))(vite@8.0.16(@types/node@22.19.19)(esbuild@0.28.1)(jiti@2.4.2)(yaml@2.9.0)) + svelte: + specifier: 'catalog:' + version: 5.56.3(@typescript-eslint/types@8.61.1) + vite: + specifier: 'catalog:' + version: 8.0.16(@types/node@22.19.19)(esbuild@0.28.1)(jiti@2.4.2)(yaml@2.9.0) + packages/adapter-static: devDependencies: '@playwright/test': From afef9918faa324360e5a64a9e6be96dcc0c5bc83 Mon Sep 17 00:00:00 2001 From: Oleksii Soboliev Date: Fri, 10 Jul 2026 09:25:34 +0200 Subject: [PATCH 2/5] fix lint: import process from node:process, add app tsconfig --- .../apps/instrumentation/src/routes/env/+server.js | 1 + .../test/apps/instrumentation/test/boot.js | 1 + .../test/apps/instrumentation/tsconfig.json | 13 +++++++++++++ 3 files changed, 15 insertions(+) create mode 100644 packages/adapter-node/test/apps/instrumentation/tsconfig.json diff --git a/packages/adapter-node/test/apps/instrumentation/src/routes/env/+server.js b/packages/adapter-node/test/apps/instrumentation/src/routes/env/+server.js index 6db344c105bf..3b0f47cc8aae 100644 --- a/packages/adapter-node/test/apps/instrumentation/src/routes/env/+server.js +++ b/packages/adapter-node/test/apps/instrumentation/src/routes/env/+server.js @@ -1,3 +1,4 @@ +import process from 'node:process'; import { json } from '@sveltejs/kit'; import { CAPTURED_AT_MODULE_SCOPE } from '$lib/server/api-client.js'; diff --git a/packages/adapter-node/test/apps/instrumentation/test/boot.js b/packages/adapter-node/test/apps/instrumentation/test/boot.js index d3486dd795b0..ae502f7ae841 100644 --- a/packages/adapter-node/test/apps/instrumentation/test/boot.js +++ b/packages/adapter-node/test/apps/instrumentation/test/boot.js @@ -4,6 +4,7 @@ // and (2) a module-scope `$app/env/private` read observes the runtime value — // regression for sveltejs/kit#16288. import { spawn } from 'node:child_process'; +import process from 'node:process'; const PORT = 3399; const EXPECTED = 'https://api.example'; diff --git a/packages/adapter-node/test/apps/instrumentation/tsconfig.json b/packages/adapter-node/test/apps/instrumentation/tsconfig.json new file mode 100644 index 000000000000..c2db702f9bb1 --- /dev/null +++ b/packages/adapter-node/test/apps/instrumentation/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "moduleResolution": "bundler" + }, + "extends": "./.svelte-kit/tsconfig.json" +} From 785c493502ed8c1f3407589106cbe5f656247f29 Mon Sep 17 00:00:00 2001 From: Oleksii Soboliev Date: Fri, 10 Jul 2026 09:55:32 +0200 Subject: [PATCH 3/5] =?UTF-8?q?provide=20MY=5FBASE=5FURL=20to=20the=20buil?= =?UTF-8?q?d=20phase=20=E2=80=94=20kit=20validates=20declared=20env=20vars?= =?UTF-8?q?=20at=20build=20time?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/adapter-node/test/apps/instrumentation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/adapter-node/test/apps/instrumentation/package.json b/packages/adapter-node/test/apps/instrumentation/package.json index 9899a9690d6a..2761d85f8b0c 100644 --- a/packages/adapter-node/test/apps/instrumentation/package.json +++ b/packages/adapter-node/test/apps/instrumentation/package.json @@ -7,7 +7,7 @@ "dev": "vite dev", "build": "vite build", "prepare": "svelte-kit sync || echo ''", - "test": "pnpm build && node test/boot.js" + "test": "MY_BASE_URL=https://api.example pnpm build && node test/boot.js" }, "devDependencies": { "@sveltejs/kit": "workspace:^", From f067143111561eb1165f7483ff3d141bb483efdd Mon Sep 17 00:00:00 2001 From: Oleksii Soboliev Date: Tue, 21 Jul 2026 22:29:32 +0200 Subject: [PATCH 4/5] chore: regenerate lockfile after version-3 merge --- pnpm-lock.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 839d7f19a8ab..87e56bebed43 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -358,13 +358,13 @@ importers: version: link:../../../../kit '@sveltejs/vite-plugin-svelte': specifier: 'catalog:' - version: 7.0.0(svelte@5.56.3(@typescript-eslint/types@8.61.1))(vite@8.0.16(@types/node@22.19.19)(esbuild@0.28.1)(jiti@2.4.2)(yaml@2.9.0)) + version: 7.0.0(svelte@5.56.3(@typescript-eslint/types@8.61.1))(vite@8.1.5(@types/node@22.19.19)(esbuild@0.28.1)(jiti@2.4.2)(yaml@2.9.0)) svelte: specifier: 'catalog:' version: 5.56.3(@typescript-eslint/types@8.61.1) vite: specifier: 'catalog:' - version: 8.0.16(@types/node@22.19.19)(esbuild@0.28.1)(jiti@2.4.2)(yaml@2.9.0) + version: 8.1.5(@types/node@22.19.19)(esbuild@0.28.1)(jiti@2.4.2)(yaml@2.9.0) packages/adapter-static: devDependencies: From 38778c5bf48f2d86f2c09fa24e7bcc567d26df70 Mon Sep 17 00:00:00 2001 From: Oleksii Soboliev Date: Wed, 22 Jul 2026 10:20:33 +0200 Subject: [PATCH 5/5] server booted with instrumentation and module-scope env read observed the runtime value --- packages/adapter-node/test/apps/instrumentation/package.json | 3 +++ packages/adapter-node/test/apps/instrumentation/src/env.js | 2 +- .../test/apps/instrumentation/src/routes/env/+server.js | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/adapter-node/test/apps/instrumentation/package.json b/packages/adapter-node/test/apps/instrumentation/package.json index 2761d85f8b0c..35a1f2f8c7e6 100644 --- a/packages/adapter-node/test/apps/instrumentation/package.json +++ b/packages/adapter-node/test/apps/instrumentation/package.json @@ -3,6 +3,9 @@ "version": "0.0.1", "private": true, "type": "module", + "imports": { + "#lib/*": "./src/lib/*" + }, "scripts": { "dev": "vite dev", "build": "vite build", diff --git a/packages/adapter-node/test/apps/instrumentation/src/env.js b/packages/adapter-node/test/apps/instrumentation/src/env.js index 528bb210784a..301360a310b3 100644 --- a/packages/adapter-node/test/apps/instrumentation/src/env.js +++ b/packages/adapter-node/test/apps/instrumentation/src/env.js @@ -1,4 +1,4 @@ -import { defineEnvVars } from '@sveltejs/kit/hooks'; +import { defineEnvVars } from '@sveltejs/kit/env'; export const variables = defineEnvVars({ MY_BASE_URL: { public: false, static: false } diff --git a/packages/adapter-node/test/apps/instrumentation/src/routes/env/+server.js b/packages/adapter-node/test/apps/instrumentation/src/routes/env/+server.js index 3b0f47cc8aae..ce060e8890dc 100644 --- a/packages/adapter-node/test/apps/instrumentation/src/routes/env/+server.js +++ b/packages/adapter-node/test/apps/instrumentation/src/routes/env/+server.js @@ -1,6 +1,6 @@ import process from 'node:process'; import { json } from '@sveltejs/kit'; -import { CAPTURED_AT_MODULE_SCOPE } from '$lib/server/api-client.js'; +import { CAPTURED_AT_MODULE_SCOPE } from '#lib/server/api-client.js'; export function GET() { return json({