Skip to content

Commit 758ec17

Browse files
authored
fix: conditionally access builder properties that only exist on the latest SvelteKit (#14233)
* add null checks for builder properties that may not exist * changeset * format * fix type errors where we're sure it won't be null or undefined
1 parent e9a09c1 commit 758ec17

File tree

18 files changed

+165
-60
lines changed

18 files changed

+165
-60
lines changed

.changeset/pretty-fans-peel.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'@sveltejs/adapter-cloudflare': patch
3+
'@sveltejs/adapter-netlify': patch
4+
'@sveltejs/adapter-vercel': patch
5+
'@sveltejs/adapter-node': patch
6+
---
7+
8+
fix: avoid erroring on builder properties that only exist on the latest version of SvelteKit

packages/adapter-auto/index.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@ import path from 'node:path';
44
import fs from 'node:fs';
55
import process from 'node:process';
66

7+
/**
8+
* @template T
9+
* @template {keyof T} K
10+
* @typedef {Partial<Omit<T, K>> & Required<Pick<T, K>>} PartialExcept
11+
*/
12+
13+
/**
14+
* We use a custom `Builder` type here to support the minimum version of SvelteKit.
15+
* @typedef {PartialExcept<import('@sveltejs/kit').Builder, 'log' | 'rimraf' | 'mkdirp' | 'config' | 'prerendered' | 'routes' | 'createEntries' | 'generateFallback' | 'generateEnvModule' | 'generateManifest' | 'getBuildDirectory' | 'getClientDirectory' | 'getServerDirectory' | 'getAppPath' | 'writeClient' | 'writePrerendered' | 'writePrerendered' | 'writeServer' | 'copy' | 'compress'>} Builder2_0_0
16+
*/
17+
718
/** @type {Record<string, (name: string, version: string) => string>} */
819
const commands = {
920
npm: (name, version) => `npm install -D ${name}@${version}`,
@@ -138,10 +149,11 @@ async function get_adapter() {
138149
/** @type {() => Adapter} */
139150
export default () => ({
140151
name: '@sveltejs/adapter-auto',
152+
/** @param {Builder2_0_0} builder */
141153
adapt: async (builder) => {
142154
const adapter = await get_adapter();
143155

144-
if (adapter) return adapter.adapt(builder);
156+
if (adapter) return adapter.adapt(/** @type {import('@sveltejs/kit').Builder} */ (builder));
145157

146158
builder.log.warn(
147159
'Could not detect a supported production environment. See https://svelte.dev/docs/kit/adapters to learn how to configure your app to run on the platform of your choosing'

packages/adapter-auto/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"checkJs": true,
55
"noEmit": true,
66
"noImplicitAny": true,
7+
"strictNullChecks": true,
78
"target": "es2022",
89
"module": "node16",
910
"moduleResolution": "node16",

packages/adapter-cloudflare/index.js

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,22 @@ import { is_building_for_cloudflare_pages, validate_worker_settings } from './ut
99
const name = '@sveltejs/adapter-cloudflare';
1010
const [kit_major, kit_minor] = VERSION.split('.');
1111

12+
/**
13+
* @template T
14+
* @template {keyof T} K
15+
* @typedef {Partial<Omit<T, K>> & Required<Pick<T, K>>} PartialExcept
16+
*/
17+
18+
/**
19+
* We use a custom `Builder` type here to support the minimum version of SvelteKit.
20+
* @typedef {PartialExcept<import('@sveltejs/kit').Builder, 'log' | 'rimraf' | 'mkdirp' | 'config' | 'prerendered' | 'routes' | 'createEntries' | 'generateFallback' | 'generateEnvModule' | 'generateManifest' | 'getBuildDirectory' | 'getClientDirectory' | 'getServerDirectory' | 'getAppPath' | 'writeClient' | 'writePrerendered' | 'writePrerendered' | 'writeServer' | 'copy' | 'compress'>} Builder2_0_0
21+
*/
22+
1223
/** @type {import('./index.js').default} */
1324
export default function (options = {}) {
1425
return {
1526
name,
27+
/** @param {Builder2_0_0} builder */
1628
async adapt(builder) {
1729
if (existsSync('_routes.json')) {
1830
throw new Error(
@@ -113,8 +125,8 @@ export default function (options = {}) {
113125
ASSETS: assets_binding
114126
}
115127
});
116-
if (builder.hasServerInstrumentationFile()) {
117-
builder.instrument({
128+
if (builder.hasServerInstrumentationFile?.()) {
129+
builder.instrument?.({
118130
entrypoint: worker_dest,
119131
instrumentation: `${builder.getServerDirectory()}/instrumentation.server.js`
120132
});
@@ -197,12 +209,14 @@ export default function (options = {}) {
197209
}
198210

199211
/**
200-
* @param {import('@sveltejs/kit').Builder} builder
212+
* @param {Builder2_0_0} builder
201213
* @param {string[]} assets
202214
* @param {import('./index.js').AdapterOptions['routes']} routes
203215
* @returns {import('./index.js').RoutesJSONSpec}
204216
*/
205-
function get_routes_json(builder, assets, { include = ['/*'], exclude = ['<all>'] }) {
217+
function get_routes_json(builder, assets, routes) {
218+
let { include = ['/*'], exclude = ['<all>'] } = routes || {};
219+
206220
if (!Array.isArray(include) || !Array.isArray(exclude)) {
207221
throw new Error('routes.include and routes.exclude must be arrays');
208222
}
@@ -297,7 +311,7 @@ _redirects
297311
}
298312

299313
/**
300-
* @param {string} config_file
314+
* @param {string | undefined} config_file
301315
* @returns {import('wrangler').Unstable_Config}
302316
*/
303317
function validate_wrangler_config(config_file = undefined) {

packages/adapter-cloudflare/src/worker.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export default {
100100
cf: req.cf
101101
},
102102
getClientAddress() {
103-
return req.headers.get('cf-connecting-ip');
103+
return /** @type {string} */ (req.headers.get('cf-connecting-ip'));
104104
}
105105
});
106106
}

packages/adapter-cloudflare/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"checkJs": true,
55
"noEmit": true,
66
"noImplicitAny": true,
7+
"strictNullChecks": true,
78
"target": "es2022",
89
"module": "node16",
910
"moduleResolution": "node16",

packages/adapter-netlify/index.js

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,17 @@ const [kit_major, kit_minor] = VERSION.split('.');
1717
* } & toml.JsonMap} NetlifyConfig
1818
*/
1919

20+
/**
21+
* @template T
22+
* @template {keyof T} K
23+
* @typedef {Partial<Omit<T, K>> & Required<Pick<T, K>>} PartialExcept
24+
*/
25+
26+
/**
27+
* We use a custom `Builder` type here to support the minimum version of SvelteKit.
28+
* @typedef {PartialExcept<import('@sveltejs/kit').Builder, 'log' | 'rimraf' | 'mkdirp' | 'config' | 'prerendered' | 'routes' | 'createEntries' | 'findServerAssets' | 'generateFallback' | 'generateEnvModule' | 'generateManifest' | 'getBuildDirectory' | 'getClientDirectory' | 'getServerDirectory' | 'getAppPath' | 'writeClient' | 'writePrerendered' | 'writePrerendered' | 'writeServer' | 'copy' | 'compress'>} Builder2_4_0
29+
*/
30+
2031
const name = '@sveltejs/adapter-netlify';
2132
const files = fileURLToPath(new URL('./files', import.meta.url).href);
2233

@@ -30,7 +41,7 @@ const FUNCTION_PREFIX = 'sveltekit-';
3041
export default function ({ split = false, edge = edge_set_in_env_var } = {}) {
3142
return {
3243
name,
33-
44+
/** @param {Builder2_4_0} builder */
3445
async adapt(builder) {
3546
if (!builder.routes) {
3647
throw new Error(
@@ -114,7 +125,7 @@ export default function ({ split = false, edge = edge_set_in_env_var } = {}) {
114125
}
115126
/**
116127
* @param { object } params
117-
* @param {import('@sveltejs/kit').Builder} params.builder
128+
* @param {Builder2_4_0} params.builder
118129
*/
119130
async function generate_edge_functions({ builder }) {
120131
const tmp = builder.getBuildDirectory('netlify-tmp');
@@ -202,16 +213,16 @@ async function generate_edge_functions({ builder }) {
202213
outfile: '.netlify/edge-functions/render.js',
203214
...esbuild_config
204215
}),
205-
builder.hasServerInstrumentationFile() &&
216+
builder.hasServerInstrumentationFile?.() &&
206217
esbuild.build({
207218
entryPoints: [`${builder.getServerDirectory()}/instrumentation.server.js`],
208219
outfile: '.netlify/edge/instrumentation.server.js',
209220
...esbuild_config
210221
})
211222
]);
212223

213-
if (builder.hasServerInstrumentationFile()) {
214-
builder.instrument({
224+
if (builder.hasServerInstrumentationFile?.()) {
225+
builder.instrument?.({
215226
entrypoint: '.netlify/edge-functions/render.js',
216227
instrumentation: '.netlify/edge/instrumentation.server.js',
217228
start: '.netlify/edge/start.js'
@@ -222,7 +233,7 @@ async function generate_edge_functions({ builder }) {
222233
}
223234
/**
224235
* @param { object } params
225-
* @param {import('@sveltejs/kit').Builder} params.builder
236+
* @param {Builder2_4_0} params.builder
226237
* @param { string } params.publish
227238
* @param { boolean } params.split
228239
*/
@@ -294,8 +305,8 @@ function generate_lambda_functions({ builder, publish, split }) {
294305

295306
writeFileSync(`.netlify/functions-internal/${name}.mjs`, fn);
296307
writeFileSync(`.netlify/functions-internal/${name}.json`, fn_config);
297-
if (builder.hasServerInstrumentationFile()) {
298-
builder.instrument({
308+
if (builder.hasServerInstrumentationFile?.()) {
309+
builder.instrument?.({
299310
entrypoint: `.netlify/functions-internal/${name}.mjs`,
300311
instrumentation: '.netlify/server/instrumentation.server.js',
301312
start: `.netlify/functions-start/${name}.start.mjs`,
@@ -318,8 +329,8 @@ function generate_lambda_functions({ builder, publish, split }) {
318329

319330
writeFileSync(`.netlify/functions-internal/${FUNCTION_PREFIX}render.json`, fn_config);
320331
writeFileSync(`.netlify/functions-internal/${FUNCTION_PREFIX}render.mjs`, fn);
321-
if (builder.hasServerInstrumentationFile()) {
322-
builder.instrument({
332+
if (builder.hasServerInstrumentationFile?.()) {
333+
builder.instrument?.({
323334
entrypoint: `.netlify/functions-internal/${FUNCTION_PREFIX}render.mjs`,
324335
instrumentation: '.netlify/server/instrumentation.server.js',
325336
start: `.netlify/functions-start/${FUNCTION_PREFIX}render.start.mjs`,
@@ -356,8 +367,8 @@ function get_netlify_config() {
356367
}
357368

358369
/**
359-
* @param {NetlifyConfig} netlify_config
360-
* @param {import('@sveltejs/kit').Builder} builder
370+
* @param {NetlifyConfig | null} netlify_config
371+
* @param {Builder2_4_0} builder
361372
**/
362373
function get_publish_directory(netlify_config, builder) {
363374
if (netlify_config) {

packages/adapter-netlify/src/serverless.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ import process from 'node:process';
1111
export function init(manifest) {
1212
const server = new Server(manifest);
1313

14+
/** @type {Promise<void> | null} */
1415
let init_promise = server.init({
15-
env: process.env,
16+
env: /** @type {Record<string, string>} */ (process.env),
1617
read: (file) => createReadableStream(`.netlify/server/${file}`)
1718
});
1819

@@ -25,7 +26,7 @@ export function init(manifest) {
2526
const response = await server.respond(to_request(event), {
2627
platform: { context },
2728
getClientAddress() {
28-
return event.headers['x-nf-client-connection-ip'];
29+
return /** @type {string} */ (event.headers['x-nf-client-connection-ip']);
2930
}
3031
});
3132

@@ -56,13 +57,11 @@ export function init(manifest) {
5657
* @param {import('@netlify/functions').HandlerEvent} event
5758
* @returns {Request}
5859
*/
59-
function to_request(event) {
60-
const { httpMethod, headers, rawUrl, body, isBase64Encoded } = event;
61-
60+
function to_request({ httpMethod, headers, rawUrl, body, isBase64Encoded }) {
6261
/** @type {RequestInit} */
6362
const init = {
6463
method: httpMethod,
65-
headers: new Headers(headers)
64+
headers: new Headers(/** @type {Record<string, string>} */ (headers))
6665
};
6766

6867
if (httpMethod !== 'GET' && httpMethod !== 'HEAD') {

packages/adapter-netlify/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"checkJs": true,
55
"noEmit": true,
66
"noImplicitAny": true,
7+
"strictNullChecks": true,
78
"target": "es2022",
89
"module": "node16",
910
"moduleResolution": "node16",

packages/adapter-node/index.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@ import { nodeResolve } from '@rollup/plugin-node-resolve';
55
import commonjs from '@rollup/plugin-commonjs';
66
import json from '@rollup/plugin-json';
77

8+
/**
9+
* @template T
10+
* @template {keyof T} K
11+
* @typedef {Partial<Omit<T, K>> & Required<Pick<T, K>>} PartialExcept
12+
*/
13+
14+
/**
15+
* We use a custom `Builder` type here to support the minimum version of SvelteKit.
16+
* @typedef {PartialExcept<import('@sveltejs/kit').Builder, 'log' | 'rimraf' | 'mkdirp' | 'config' | 'prerendered' | 'routes' | 'createEntries' | 'findServerAssets' | 'generateFallback' | 'generateEnvModule' | 'generateManifest' | 'getBuildDirectory' | 'getClientDirectory' | 'getServerDirectory' | 'getAppPath' | 'writeClient' | 'writePrerendered' | 'writePrerendered' | 'writeServer' | 'copy' | 'compress'>} Builder2_4_0
17+
*/
18+
819
const files = fileURLToPath(new URL('./files', import.meta.url).href);
920

1021
/** @type {import('./index.js').default} */
@@ -13,7 +24,7 @@ export default function (opts = {}) {
1324

1425
return {
1526
name: '@sveltejs/adapter-node',
16-
27+
/** @param {Builder2_4_0} builder */
1728
async adapt(builder) {
1829
const tmp = builder.getBuildDirectory('adapter-node');
1930

@@ -54,7 +65,7 @@ export default function (opts = {}) {
5465
manifest: `${tmp}/manifest.js`
5566
};
5667

57-
if (builder.hasServerInstrumentationFile()) {
68+
if (builder.hasServerInstrumentationFile?.()) {
5869
input['instrumentation.server'] = `${tmp}/instrumentation.server.js`;
5970
}
6071

@@ -97,8 +108,8 @@ export default function (opts = {}) {
97108
}
98109
});
99110

100-
if (builder.hasServerInstrumentationFile()) {
101-
builder.instrument({
111+
if (builder.hasServerInstrumentationFile?.()) {
112+
builder.instrument?.({
102113
entrypoint: `${out}/index.js`,
103114
instrumentation: `${out}/server/instrumentation.server.js`,
104115
module: {

0 commit comments

Comments
 (0)