Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/every-node-from-26-vercel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/adapter-vercel': patch
---

fix: accept every Node.js version from 26 (`nodejs27.x`, `nodejs28.x`, ...), not only even ones
Original file line number Diff line number Diff line change
Expand Up @@ -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<version>.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<version>.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
Expand Down
43 changes: 27 additions & 16 deletions packages/adapter-vercel/test/utils.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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/
);
});
}
Expand Down
7 changes: 4 additions & 3 deletions packages/adapter-vercel/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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.`
);
}

Expand All @@ -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.`
);
}
}
Expand Down
Loading