diff --git a/.changeset/every-node-from-26-vercel.md b/.changeset/every-node-from-26-vercel.md new file mode 100644 index 000000000000..b413b4659e73 --- /dev/null +++ b/.changeset/every-node-from-26-vercel.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/adapter-vercel': patch +--- + +fix: accept every Node.js version from 26 (`nodejs27.x`, `nodejs28.x`, ...), not only even ones diff --git a/documentation/docs/25-build-and-deploy/90-adapter-vercel.md b/documentation/docs/25-build-and-deploy/90-adapter-vercel.md index 1599cc73707d..b8b0ba9b4dae 100644 --- a/documentation/docs/25-build-and-deploy/90-adapter-vercel.md +++ b/documentation/docs/25-build-and-deploy/90-adapter-vercel.md @@ -42,7 +42,7 @@ export const config = { The following options apply to all functions: -- `runtime`: `'edge'`, or an even Node version (for example `'nodejs20.x'`, `'nodejs22.x'`, `'nodejs24.x'`, `'nodejs26.x'`). By default, the adapter will select the `'nodejs.x'` corresponding to the Node version your project is configured to use on the Vercel dashboard +- `runtime`: `'edge'`, or a Node version (for example `'nodejs20.x'`, `'nodejs22.x'`, `'nodejs24.x'`, `'nodejs26.x'`). By default, the adapter will select the `'nodejs.x'` corresponding to the Node version your project is configured to use on the Vercel dashboard > [!NOTE] This option is deprecated and will be removed in a future version, at which point all your functions will use whichever Node version is specified in the project configuration on Vercel - `regions`: an array of [edge network regions](https://vercel.com/docs/concepts/edge-network/regions) (defaulting to `["iad1"]` for serverless functions) or `'all'` if `runtime` is `edge` (its default). Note that multiple regions for serverless functions are only supported on Enterprise plans - `split`: if `true`, causes a route to be deployed as an individual function. If `split` is set to `true` at the adapter level, all routes will be deployed as individual functions diff --git a/packages/adapter-vercel/test/utils.spec.js b/packages/adapter-vercel/test/utils.spec.js index 0bfbf1724050..6ad7253c5e22 100644 --- a/packages/adapter-vercel/test/utils.spec.js +++ b/packages/adapter-vercel/test/utils.spec.js @@ -186,19 +186,29 @@ describe('resolve_runtime', () => { assert.equal(result, 'bun1.x'); }); - test.each(['node18.x', 'nodejs028.x', 'nodejs18.x', 'nodejs33.x', 'nodejs100.x', 'nodejs2,.x'])( - 'throws an error when resolving to an invalid runtime (%s)', - (runtime) => { - assert.throws(() => resolve_runtime(runtime), /Unsupported runtime/); - } - ); + test.each([ + 'node18.x', + 'nodejs028.x', + 'nodejs18.x', + 'nodejs23.x', + 'nodejs25.x', + 'nodejs100.x', + 'nodejs2,.x' + ])('throws an error when resolving to an invalid runtime (%s)', (runtime) => { + assert.throws(() => resolve_runtime(runtime), /Unsupported runtime/); + }); - test.each(['nodejs20.x', 'nodejs22.x', 'nodejs24.x', 'nodejs26.x', 'nodejs96.x', 'nodejs98.x'])( - 'accepts %s', - (runtime) => { - assert.equal(resolve_runtime(runtime), runtime); - } - ); + test.each([ + 'nodejs20.x', + 'nodejs22.x', + 'nodejs24.x', + 'nodejs26.x', + 'nodejs27.x', + 'nodejs33.x', + 'nodejs99.x' + ])('accepts %s', (runtime) => { + assert.equal(resolve_runtime(runtime), runtime); + }); test.each(['bun1.x', 'edge'])('accepts %s', (runtime) => { assert.equal(resolve_runtime(runtime), runtime); @@ -225,9 +235,10 @@ describe('resolve_runtime with node detected', () => { ['22.0.0', 'nodejs22.x'], ['24.1.0', 'nodejs24.x'], ['26.0.0', 'nodejs26.x'], + ['27.0.0', 'nodejs27.x'], ['28.0.0', 'nodejs28.x'], - ['96.1.0', 'nodejs96.x'], - ['98.0.0', 'nodejs98.x'] + ['29.1.0', 'nodejs29.x'], + ['99.0.0', 'nodejs99.x'] ])('detects Node %s', (version, runtime) => { with_node(version, () => { assert.equal(resolve_runtime(undefined, undefined), runtime); @@ -240,13 +251,13 @@ describe('resolve_runtime with node detected', () => { }); }); - test.each(['18.0.0', '25.0.0', '27.0.0'])( + test.each(['18.0.0', '23.0.0', '25.0.0'])( 'throws for an unsupported Node major (%s)', (version) => { with_node(version, () => { assert.throws( () => resolve_runtime(undefined, undefined), - /Unsupported Node\.js version.*Please use an even Node version to build your project/ + /Unsupported Node\.js version.*Please use Node 20, 22, 24, or 26 and later to build your project/ ); }); } diff --git a/packages/adapter-vercel/utils.js b/packages/adapter-vercel/utils.js index abb2c76c9097..a48517285924 100644 --- a/packages/adapter-vercel/utils.js +++ b/packages/adapter-vercel/utils.js @@ -118,7 +118,8 @@ export function resolve_runtime(default_key, override_key) { return key; } -const valid_node_version_regex = /^nodejs[2-9][02468]\.x$/; +// Node 20, 22, 24, and every major from 26 +const valid_node_version_regex = /^nodejs(2[0246-9]|[3-9]\d)\.x$/; /** @returns {RuntimeKey} */ function get_default_runtime() { @@ -130,7 +131,7 @@ function get_default_runtime() { if (!valid_node_version_regex.test(version_key)) { throw new Error( - `Unsupported Node.js version: ${process.version}. Please use an even Node version to build your project, or explicitly specify a runtime in your adapter configuration.` + `Unsupported Node.js version: ${process.version}. Please use Node 20, 22, 24, or 26 and later to build your project, or explicitly specify a runtime in your adapter configuration.` ); } @@ -151,7 +152,7 @@ function assert_is_valid_runtime(key) { !valid_node_version_regex.test(key) ) { throw new Error( - `Unsupported runtime: ${key}. Supported runtimes are: ${valid_non_node_runtimes.join(', ')}, and even Node versions. See the Node.js Version section in your Vercel project settings for info on the currently supported versions.` + `Unsupported runtime: ${key}. Supported runtimes are: ${valid_non_node_runtimes.join(', ')}, and Node 20, 22, 24, or 26 and later. See the Node.js Version section in your Vercel project settings for info on the currently supported versions.` ); } }