From 9961bc7a490abc7e7373e07f661ed1b961c753a2 Mon Sep 17 00:00:00 2001 From: theandrew168 Date: Fri, 2 Jan 2026 23:53:46 -0600 Subject: [PATCH 01/10] Check for and apply timeouts for keepAlive and headers --- packages/adapter-node/src/env.js | 4 +++- packages/adapter-node/src/index.js | 37 ++++++++++++++++++++++-------- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/packages/adapter-node/src/env.js b/packages/adapter-node/src/env.js index b8e44ee0c7f5..a5eccf6ce85c 100644 --- a/packages/adapter-node/src/env.js +++ b/packages/adapter-node/src/env.js @@ -13,7 +13,9 @@ const expected = new Set([ 'PORT_HEADER', 'BODY_SIZE_LIMIT', 'SHUTDOWN_TIMEOUT', - 'IDLE_TIMEOUT' + 'IDLE_TIMEOUT', + 'KEEP_ALIVE_TIMEOUT', + 'HEADERS_TIMEOUT' ]); const expected_unprefixed = new Set(['LISTEN_PID', 'LISTEN_FDS']); diff --git a/packages/adapter-node/src/index.js b/packages/adapter-node/src/index.js index ef1ab701a2a3..1c8d48b03318 100644 --- a/packages/adapter-node/src/index.js +++ b/packages/adapter-node/src/index.js @@ -1,3 +1,4 @@ +import http from 'node:http'; import process from 'node:process'; import { handler } from 'HANDLER'; import { env } from 'ENV'; @@ -9,6 +10,8 @@ export const port = env('PORT', !path && '3000'); const shutdown_timeout = parseInt(env('SHUTDOWN_TIMEOUT', '30')); const idle_timeout = parseInt(env('IDLE_TIMEOUT', '0')); +const keep_alive_timeout = parseInt(env('KEEP_ALIVE_TIMEOUT', '0')); +const headers_timeout = parseInt(env('HEADERS_TIMEOUT', '0')); const listen_pid = parseInt(env('LISTEN_PID', '0')); const listen_fds = parseInt(env('LISTEN_FDS', '0')); // https://www.freedesktop.org/software/systemd/man/latest/sd_listen_fds.html @@ -31,7 +34,26 @@ let shutdown_timeout_id; /** @type {NodeJS.Timeout | void} */ let idle_timeout_id; -const server = polka().use(handler); +// Initialize the HTTP server here so that we can set properties before starting to listen. +// Otherwise, polka delays creating the server until listen() is called. Settings these +// properties after the server has started listening could lead to race conditions. +const httpServer = http.createServer(); + +// If unspecified, let Node.js use its default keepAliveTimeout: +// https://nodejs.org/api/http.html#serverkeepalivetimeout +if (keep_alive_timeout) { + // Convert the keep-alive timeout from seconds to milliseconds (the unit Node.js expects). + httpServer.keepAliveTimeout = keep_alive_timeout * 1000; +} + +// If unspecified, let Node.js use its default headersTimeout: +// https://nodejs.org/api/http.html#serverheaderstimeout +if (headers_timeout) { + // Convert the headers timeout from seconds to milliseconds (the unit Node.js expects). + httpServer.headersTimeout = headers_timeout * 1000; +} + +const server = polka({ server: httpServer }).use(handler); if (socket_activation) { server.listen({ fd: SD_LISTEN_FDS_START }, () => { @@ -49,10 +71,9 @@ function graceful_shutdown(reason) { // If a connection was opened with a keep-alive header close() will wait for the connection to // time out rather than close it even if it is not handling any requests, so call this first - // @ts-expect-error this was added in 18.2.0 but is not reflected in the types - server.server.closeIdleConnections(); + httpServer.closeIdleConnections(); - server.server.close((error) => { + httpServer.close((error) => { // occurs if the server is already closed if (error) return; @@ -68,13 +89,12 @@ function graceful_shutdown(reason) { }); shutdown_timeout_id = setTimeout( - // @ts-expect-error this was added in 18.2.0 but is not reflected in the types - () => server.server.closeAllConnections(), + () => httpServer.closeAllConnections(), shutdown_timeout * 1000 ); } -server.server.on( +httpServer.on( 'request', /** @param {import('node:http').IncomingMessage} req */ (req) => { @@ -89,8 +109,7 @@ server.server.on( if (shutdown_timeout_id) { // close connections as soon as they become idle, so they don't accept new requests - // @ts-expect-error this was added in 18.2.0 but is not reflected in the types - server.server.closeIdleConnections(); + httpServer.closeIdleConnections(); } if (requests === 0 && socket_activation && idle_timeout) { idle_timeout_id = setTimeout(() => graceful_shutdown('IDLE'), idle_timeout * 1000); From d9a47092af1a139bbdceb4285d111cc2ec835890 Mon Sep 17 00:00:00 2001 From: theandrew168 Date: Sat, 3 Jan 2026 00:03:31 -0600 Subject: [PATCH 02/10] Update docs with new timeout env vars --- documentation/docs/25-build-and-deploy/40-adapter-node.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/documentation/docs/25-build-and-deploy/40-adapter-node.md b/documentation/docs/25-build-and-deploy/40-adapter-node.md index 36b7c01b949d..5441afd54b98 100644 --- a/documentation/docs/25-build-and-deploy/40-adapter-node.md +++ b/documentation/docs/25-build-and-deploy/40-adapter-node.md @@ -140,6 +140,10 @@ The number of seconds to wait before forcefully closing any remaining connection When using systemd socket activation, `IDLE_TIMEOUT` specifies the number of seconds after which the app is automatically put to sleep when receiving no requests. If not set, the app runs continuously. See [Socket activation](#Socket-activation) for more details. +### `KEEP_ALIVE_TIMEOUT` and `HEADERS_TIMEOUT` + +When present, override the default [keepAliveTimeout](https://nodejs.org/api/http.html#serverkeepalivetimeout) and / or [headersTimeout](https://nodejs.org/api/http.html#serverheaderstimeout) for Node's underlying web server. These values should be supplied in seconds (they will be converted to milliseconds automatically). + ## Options The adapter can be configured with various options: From 7008a28a5a74b5dc582a3f38bb08dc678227ee81 Mon Sep 17 00:00:00 2001 From: theandrew168 Date: Sat, 3 Jan 2026 00:06:20 -0600 Subject: [PATCH 03/10] Add changeset for new timeouts --- .changeset/odd-lamps-follow.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/odd-lamps-follow.md diff --git a/.changeset/odd-lamps-follow.md b/.changeset/odd-lamps-follow.md new file mode 100644 index 000000000000..eb6a14cf30ba --- /dev/null +++ b/.changeset/odd-lamps-follow.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/adapter-node': minor +--- + +feat: add env vars for keepAliveTimeout and headersTimeout From d8dd3042801ba6f08c8893305dc575a3a0a56dda Mon Sep 17 00:00:00 2001 From: theandrew168 Date: Sat, 3 Jan 2026 00:23:08 -0600 Subject: [PATCH 04/10] Run the formatter --- packages/adapter-node/src/index.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/adapter-node/src/index.js b/packages/adapter-node/src/index.js index 1c8d48b03318..11380387ac26 100644 --- a/packages/adapter-node/src/index.js +++ b/packages/adapter-node/src/index.js @@ -88,10 +88,7 @@ function graceful_shutdown(reason) { process.emit('sveltekit:shutdown', reason); }); - shutdown_timeout_id = setTimeout( - () => httpServer.closeAllConnections(), - shutdown_timeout * 1000 - ); + shutdown_timeout_id = setTimeout(() => httpServer.closeAllConnections(), shutdown_timeout * 1000); } httpServer.on( From dcebfb1224a46ba19f7c3cb3c79e69a246983fb9 Mon Sep 17 00:00:00 2001 From: theandrew168 Date: Sat, 3 Jan 2026 00:44:32 -0600 Subject: [PATCH 05/10] Tweak the docs wording a bit --- documentation/docs/25-build-and-deploy/40-adapter-node.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/docs/25-build-and-deploy/40-adapter-node.md b/documentation/docs/25-build-and-deploy/40-adapter-node.md index 5441afd54b98..223bc4f553a6 100644 --- a/documentation/docs/25-build-and-deploy/40-adapter-node.md +++ b/documentation/docs/25-build-and-deploy/40-adapter-node.md @@ -142,7 +142,7 @@ When using systemd socket activation, `IDLE_TIMEOUT` specifies the number of sec ### `KEEP_ALIVE_TIMEOUT` and `HEADERS_TIMEOUT` -When present, override the default [keepAliveTimeout](https://nodejs.org/api/http.html#serverkeepalivetimeout) and / or [headersTimeout](https://nodejs.org/api/http.html#serverheaderstimeout) for Node's underlying web server. These values should be supplied in seconds (they will be converted to milliseconds automatically). +When present, override the default [keepAliveTimeout](https://nodejs.org/api/http.html#serverkeepalivetimeout) and / or [headersTimeout](https://nodejs.org/api/http.html#serverheaderstimeout) for the underlying web server. These values should be supplied in seconds (they will be converted to milliseconds automatically). ## Options From 36e4fcd2893e810fd2e859c900c4082c8e147ec3 Mon Sep 17 00:00:00 2001 From: theandrew168 Date: Sun, 4 Jan 2026 11:17:19 -0600 Subject: [PATCH 06/10] Check for empty vars before parsing and validating --- packages/adapter-node/src/index.js | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/packages/adapter-node/src/index.js b/packages/adapter-node/src/index.js index 11380387ac26..ec1381b120c2 100644 --- a/packages/adapter-node/src/index.js +++ b/packages/adapter-node/src/index.js @@ -10,8 +10,6 @@ export const port = env('PORT', !path && '3000'); const shutdown_timeout = parseInt(env('SHUTDOWN_TIMEOUT', '30')); const idle_timeout = parseInt(env('IDLE_TIMEOUT', '0')); -const keep_alive_timeout = parseInt(env('KEEP_ALIVE_TIMEOUT', '0')); -const headers_timeout = parseInt(env('HEADERS_TIMEOUT', '0')); const listen_pid = parseInt(env('LISTEN_PID', '0')); const listen_fds = parseInt(env('LISTEN_FDS', '0')); // https://www.freedesktop.org/software/systemd/man/latest/sd_listen_fds.html @@ -39,16 +37,26 @@ let idle_timeout_id; // properties after the server has started listening could lead to race conditions. const httpServer = http.createServer(); -// If unspecified, let Node.js use its default keepAliveTimeout: -// https://nodejs.org/api/http.html#serverkeepalivetimeout -if (keep_alive_timeout) { +const keep_alive_timeout_var = env('KEEP_ALIVE_TIMEOUT', ''); +if (keep_alive_timeout_var) { + const keep_alive_timeout = parseInt(keep_alive_timeout_var); + if (isNaN(keep_alive_timeout) || keep_alive_timeout < 0) { + throw new Error( + `invalid KEEP_ALIVE_TIMEOUT value ${keep_alive_timeout_var}, expected a non-negative integer` + ); + } // Convert the keep-alive timeout from seconds to milliseconds (the unit Node.js expects). httpServer.keepAliveTimeout = keep_alive_timeout * 1000; } -// If unspecified, let Node.js use its default headersTimeout: -// https://nodejs.org/api/http.html#serverheaderstimeout -if (headers_timeout) { +const headers_timeout_var = env('HEADERS_TIMEOUT', ''); +if (headers_timeout_var) { + const headers_timeout = parseInt(headers_timeout_var); + if (isNaN(headers_timeout) || headers_timeout < 0) { + throw new Error( + `invalid HEADERS_TIMEOUT value ${headers_timeout_var}, expected a non-negative integer` + ); + } // Convert the headers timeout from seconds to milliseconds (the unit Node.js expects). httpServer.headersTimeout = headers_timeout * 1000; } From 1ea509dbfd02a7901e8600ac37069874a3528a3e Mon Sep 17 00:00:00 2001 From: Andrew Dailey Date: Tue, 6 Jan 2026 10:44:40 -0600 Subject: [PATCH 07/10] Update documentation/docs/25-build-and-deploy/40-adapter-node.md Co-authored-by: Tee Ming --- documentation/docs/25-build-and-deploy/40-adapter-node.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/docs/25-build-and-deploy/40-adapter-node.md b/documentation/docs/25-build-and-deploy/40-adapter-node.md index 223bc4f553a6..347396904790 100644 --- a/documentation/docs/25-build-and-deploy/40-adapter-node.md +++ b/documentation/docs/25-build-and-deploy/40-adapter-node.md @@ -142,7 +142,7 @@ When using systemd socket activation, `IDLE_TIMEOUT` specifies the number of sec ### `KEEP_ALIVE_TIMEOUT` and `HEADERS_TIMEOUT` -When present, override the default [keepAliveTimeout](https://nodejs.org/api/http.html#serverkeepalivetimeout) and / or [headersTimeout](https://nodejs.org/api/http.html#serverheaderstimeout) for the underlying web server. These values should be supplied in seconds (they will be converted to milliseconds automatically). +The number of seconds for [`keepAliveTimeout`](https://nodejs.org/api/http.html#serverkeepalivetimeout) and [`headersTimeout`](https://nodejs.org/api/http.html#serverheaderstimeout). ## Options From 1b2753d5c4024d72de9f1ddf3f58c27fa6b76980 Mon Sep 17 00:00:00 2001 From: theandrew168 Date: Thu, 8 Jan 2026 19:25:19 -0600 Subject: [PATCH 08/10] Add a timeout_env helper with corresponding tests --- packages/adapter-node/internal.d.ts | 1 + packages/adapter-node/src/env.js | 47 +++++++++++++++++++ packages/adapter-node/src/index.js | 22 ++------- packages/adapter-node/tests/env.spec.js | 61 +++++++++++++++++++++++++ 4 files changed, 114 insertions(+), 17 deletions(-) create mode 100644 packages/adapter-node/tests/env.spec.js diff --git a/packages/adapter-node/internal.d.ts b/packages/adapter-node/internal.d.ts index fed0584d1851..8387855f7893 100644 --- a/packages/adapter-node/internal.d.ts +++ b/packages/adapter-node/internal.d.ts @@ -1,5 +1,6 @@ declare module 'ENV' { export function env(key: string, fallback?: any): string; + export function timeout_env(key: string, fallback?: any): number | undefined; } declare module 'HANDLER' { diff --git a/packages/adapter-node/src/env.js b/packages/adapter-node/src/env.js index a5eccf6ce85c..05251f8658b2 100644 --- a/packages/adapter-node/src/env.js +++ b/packages/adapter-node/src/env.js @@ -42,3 +42,50 @@ export function env(name, fallback) { const prefixed = prefix + name; return prefixed in process.env ? process.env[prefixed] : fallback; } + +const integer_regexp = /^\d+$/; + +/** + * Throw a consistently-structured parsing error for environment variables. + * @param {string} name + * @param {any} value + * @param {string} description + * @returns {never} + */ +function parsing_error(name, value, description) { + throw new Error( + `Invalid value for environment variable ${name}: ${JSON.stringify(value)} (${description})` + ); +} + +/** + * Check the environment for a timeout value (non-negative integer) in seconds. + * @param {string} name + * @param {number} [fallback] + * @returns {number | undefined} + */ +export function timeout_env(name, fallback) { + const raw = env(name, fallback); + if (!raw) { + return fallback; + } + + if (!integer_regexp.test(raw)) { + parsing_error(name, raw, 'should be a non-negative integer'); + } + + const parsed = Number.parseInt(raw, 10); + + // We don't technically need to check `Number.isNaN` because the value already passed the regexp test. + // However, just in case there's some new codepath introduced somewhere down the line, it's probably good + // to stick this in here. + if (Number.isNaN(parsed)) { + parsing_error(name, raw, 'should be a non-negative integer'); + } + + if (parsed < 0) { + parsing_error(name, raw, 'should be a non-negative integer'); + } + + return parsed; +} diff --git a/packages/adapter-node/src/index.js b/packages/adapter-node/src/index.js index ec1381b120c2..a7a5c96b5184 100644 --- a/packages/adapter-node/src/index.js +++ b/packages/adapter-node/src/index.js @@ -1,7 +1,7 @@ import http from 'node:http'; import process from 'node:process'; import { handler } from 'HANDLER'; -import { env } from 'ENV'; +import { env, timeout_env } from 'ENV'; import polka from 'polka'; export const path = env('SOCKET_PATH', false); @@ -37,26 +37,14 @@ let idle_timeout_id; // properties after the server has started listening could lead to race conditions. const httpServer = http.createServer(); -const keep_alive_timeout_var = env('KEEP_ALIVE_TIMEOUT', ''); -if (keep_alive_timeout_var) { - const keep_alive_timeout = parseInt(keep_alive_timeout_var); - if (isNaN(keep_alive_timeout) || keep_alive_timeout < 0) { - throw new Error( - `invalid KEEP_ALIVE_TIMEOUT value ${keep_alive_timeout_var}, expected a non-negative integer` - ); - } +const keep_alive_timeout = timeout_env('KEEP_ALIVE_TIMEOUT'); +if (keep_alive_timeout !== undefined) { // Convert the keep-alive timeout from seconds to milliseconds (the unit Node.js expects). httpServer.keepAliveTimeout = keep_alive_timeout * 1000; } -const headers_timeout_var = env('HEADERS_TIMEOUT', ''); -if (headers_timeout_var) { - const headers_timeout = parseInt(headers_timeout_var); - if (isNaN(headers_timeout) || headers_timeout < 0) { - throw new Error( - `invalid HEADERS_TIMEOUT value ${headers_timeout_var}, expected a non-negative integer` - ); - } +const headers_timeout = timeout_env('HEADERS_TIMEOUT'); +if (headers_timeout !== undefined) { // Convert the headers timeout from seconds to milliseconds (the unit Node.js expects). httpServer.headersTimeout = headers_timeout * 1000; } diff --git a/packages/adapter-node/tests/env.spec.js b/packages/adapter-node/tests/env.spec.js new file mode 100644 index 000000000000..538a36bade61 --- /dev/null +++ b/packages/adapter-node/tests/env.spec.js @@ -0,0 +1,61 @@ +import { afterEach, expect, test, describe, vi, beforeAll } from 'vitest'; + +describe('env', () => { + /** + * @type {(name: string, fallback?: number) => number | undefined} + */ + let timeout_env; + + // Import env.timeout_env at runtime so that we can stub the ENV_PREFIX global before the module is loaded. + beforeAll(async () => { + vi.stubGlobal('ENV_PREFIX', ''); + const envModule = await import('../src/env.js'); + timeout_env = envModule.timeout_env; + }); + + afterEach(() => { + vi.unstubAllEnvs(); + }); + + describe('timeout_env', () => { + test('parses zero correctly', () => { + vi.stubEnv('TIMEOUT', '0'); + + const timeout = timeout_env('TIMEOUT'); + expect(timeout).toBe(0); + }); + + test('parses positive integers correctly', () => { + vi.stubEnv('TIMEOUT', '60'); + + const timeout = timeout_env('TIMEOUT'); + expect(timeout).toBe(60); + }); + + test('returns the fallback when variable is not set', () => { + const timeout = timeout_env('TIMEOUT', 30); + expect(timeout).toBe(30); + }); + + test('returns undefined when variable is not set and no fallback is provided', () => { + const timeout = timeout_env('TIMEOUT'); + expect(timeout).toBeUndefined(); + }); + + test('throws an error for negative integers', () => { + vi.stubEnv('TIMEOUT', '-10'); + + expect(() => timeout_env('TIMEOUT')).toThrow( + 'Invalid value for environment variable TIMEOUT: "-10" (should be a non-negative integer)' + ); + }); + + test('throws an error for non-integer values', () => { + vi.stubEnv('TIMEOUT', 'abc'); + + expect(() => timeout_env('TIMEOUT')).toThrow( + 'Invalid value for environment variable TIMEOUT: "abc" (should be a non-negative integer)' + ); + }); + }); +}); From c3c95ceb572544581d5874a7a849b481129d4467 Mon Sep 17 00:00:00 2001 From: Elliott Johnson Date: Fri, 9 Jan 2026 10:49:03 -0700 Subject: [PATCH 09/10] fix: convert adapter-node tests to TypeScript for project service compatibility The tsconfig include pattern with brace expansion {js,ts} was not being recognized by TypeScript's project service used by ESLint. Split into separate patterns and converted test files to TypeScript. --- packages/adapter-node/tests/env.spec.js | 61 ----------------------- packages/adapter-node/tests/env.spec.ts | 52 +++++++++++++++++++ packages/adapter-node/tests/utils.spec.js | 21 -------- packages/adapter-node/tests/utils.spec.ts | 16 ++++++ packages/adapter-node/tsconfig.json | 2 +- 5 files changed, 69 insertions(+), 83 deletions(-) delete mode 100644 packages/adapter-node/tests/env.spec.js create mode 100644 packages/adapter-node/tests/env.spec.ts delete mode 100644 packages/adapter-node/tests/utils.spec.js create mode 100644 packages/adapter-node/tests/utils.spec.ts diff --git a/packages/adapter-node/tests/env.spec.js b/packages/adapter-node/tests/env.spec.js deleted file mode 100644 index 538a36bade61..000000000000 --- a/packages/adapter-node/tests/env.spec.js +++ /dev/null @@ -1,61 +0,0 @@ -import { afterEach, expect, test, describe, vi, beforeAll } from 'vitest'; - -describe('env', () => { - /** - * @type {(name: string, fallback?: number) => number | undefined} - */ - let timeout_env; - - // Import env.timeout_env at runtime so that we can stub the ENV_PREFIX global before the module is loaded. - beforeAll(async () => { - vi.stubGlobal('ENV_PREFIX', ''); - const envModule = await import('../src/env.js'); - timeout_env = envModule.timeout_env; - }); - - afterEach(() => { - vi.unstubAllEnvs(); - }); - - describe('timeout_env', () => { - test('parses zero correctly', () => { - vi.stubEnv('TIMEOUT', '0'); - - const timeout = timeout_env('TIMEOUT'); - expect(timeout).toBe(0); - }); - - test('parses positive integers correctly', () => { - vi.stubEnv('TIMEOUT', '60'); - - const timeout = timeout_env('TIMEOUT'); - expect(timeout).toBe(60); - }); - - test('returns the fallback when variable is not set', () => { - const timeout = timeout_env('TIMEOUT', 30); - expect(timeout).toBe(30); - }); - - test('returns undefined when variable is not set and no fallback is provided', () => { - const timeout = timeout_env('TIMEOUT'); - expect(timeout).toBeUndefined(); - }); - - test('throws an error for negative integers', () => { - vi.stubEnv('TIMEOUT', '-10'); - - expect(() => timeout_env('TIMEOUT')).toThrow( - 'Invalid value for environment variable TIMEOUT: "-10" (should be a non-negative integer)' - ); - }); - - test('throws an error for non-integer values', () => { - vi.stubEnv('TIMEOUT', 'abc'); - - expect(() => timeout_env('TIMEOUT')).toThrow( - 'Invalid value for environment variable TIMEOUT: "abc" (should be a non-negative integer)' - ); - }); - }); -}); diff --git a/packages/adapter-node/tests/env.spec.ts b/packages/adapter-node/tests/env.spec.ts new file mode 100644 index 000000000000..20fc23a6c2a6 --- /dev/null +++ b/packages/adapter-node/tests/env.spec.ts @@ -0,0 +1,52 @@ +import { afterEach, expect, test, describe, vi } from 'vitest'; +import { timeout_env } from '../src/env.js'; + +vi.hoisted(() => { + vi.stubGlobal('ENV_PREFIX', ''); +}); + +describe('timeout_env', () => { + afterEach(() => { + vi.unstubAllEnvs(); + }); + + test('parses zero correctly', () => { + vi.stubEnv('TIMEOUT', '0'); + + const timeout = timeout_env('TIMEOUT'); + expect(timeout).toBe(0); + }); + + test('parses positive integers correctly', () => { + vi.stubEnv('TIMEOUT', '60'); + + const timeout = timeout_env('TIMEOUT'); + expect(timeout).toBe(60); + }); + + test('returns the fallback when variable is not set', () => { + const timeout = timeout_env('TIMEOUT', 30); + expect(timeout).toBe(30); + }); + + test('returns undefined when variable is not set and no fallback is provided', () => { + const timeout = timeout_env('TIMEOUT'); + expect(timeout).toBeUndefined(); + }); + + test('throws an error for negative integers', () => { + vi.stubEnv('TIMEOUT', '-10'); + + expect(() => timeout_env('TIMEOUT')).toThrow( + 'Invalid value for environment variable TIMEOUT: "-10" (should be a non-negative integer)' + ); + }); + + test('throws an error for non-integer values', () => { + vi.stubEnv('TIMEOUT', 'abc'); + + expect(() => timeout_env('TIMEOUT')).toThrow( + 'Invalid value for environment variable TIMEOUT: "abc" (should be a non-negative integer)' + ); + }); +}); diff --git a/packages/adapter-node/tests/utils.spec.js b/packages/adapter-node/tests/utils.spec.js deleted file mode 100644 index 06a495fde9ba..000000000000 --- a/packages/adapter-node/tests/utils.spec.js +++ /dev/null @@ -1,21 +0,0 @@ -import { expect, test, describe } from 'vitest'; -import { parse_as_bytes } from '../utils.js'; - -describe('parse_as_bytes', () => { - test('parses correctly', () => { - const testData = { - 200: 200, - '512K': 512 * 1024, - '200M': 200 * 1024 * 1024, - '1G': 1024 * 1024 * 1024, - Infinity, - asdf: NaN - }; - - Object.keys(testData).forEach((input) => { - const expected = testData[/** @type {keyof typeof testData} */ (input)]; - const actual = parse_as_bytes(input); - expect(actual, `Testing input '${input}'`).toBe(expected); - }); - }); -}); diff --git a/packages/adapter-node/tests/utils.spec.ts b/packages/adapter-node/tests/utils.spec.ts new file mode 100644 index 000000000000..75d0f2774e05 --- /dev/null +++ b/packages/adapter-node/tests/utils.spec.ts @@ -0,0 +1,16 @@ +import { expect, test, describe } from 'vitest'; +import { parse_as_bytes } from '../utils.js'; + +describe('parse_as_bytes', () => { + test.each([ + ['200', 200], + ['512K', 512 * 1024], + ['200M', 200 * 1024 * 1024], + ['1G', 1024 * 1024 * 1024], + ['Infinity', Infinity], + ['asdf', NaN] + ] as const)('parses correctly', (input, expected) => { + const actual = parse_as_bytes(input); + expect(actual, `Testing input '${input}'`).toBe(expected); + }); +}); diff --git a/packages/adapter-node/tsconfig.json b/packages/adapter-node/tsconfig.json index 8d5143329387..91c16aba62eb 100644 --- a/packages/adapter-node/tsconfig.json +++ b/packages/adapter-node/tsconfig.json @@ -14,6 +14,6 @@ "@sveltejs/kit": ["../kit/types/index"] } }, - "include": ["index.js", "src/**/*.js", "tests/**/*.js", "internal.d.ts", "utils.js"], + "include": ["index.js", "src/**/*.js", "tests/**/*.js", "tests/**/*.ts", "internal.d.ts", "utils.js"], "exclude": ["tests/smoke.spec_disabled.js"] } From 4548cc643595b4ac3cb0c06cd7a2c0d37ab01cc3 Mon Sep 17 00:00:00 2001 From: Elliott Johnson Date: Fri, 9 Jan 2026 12:17:11 -0700 Subject: [PATCH 10/10] format --- packages/adapter-node/tsconfig.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/adapter-node/tsconfig.json b/packages/adapter-node/tsconfig.json index 91c16aba62eb..4234750243cc 100644 --- a/packages/adapter-node/tsconfig.json +++ b/packages/adapter-node/tsconfig.json @@ -14,6 +14,13 @@ "@sveltejs/kit": ["../kit/types/index"] } }, - "include": ["index.js", "src/**/*.js", "tests/**/*.js", "tests/**/*.ts", "internal.d.ts", "utils.js"], + "include": [ + "index.js", + "src/**/*.js", + "tests/**/*.js", + "tests/**/*.ts", + "internal.d.ts", + "utils.js" + ], "exclude": ["tests/smoke.spec_disabled.js"] }