@sveltejs/kit 1.25.2 → 1.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -4
- package/src/core/sync/create_manifest_data/index.js +2 -2
- package/src/core/sync/write_types/index.js +39 -8
- package/src/exports/vite/preview/index.js +2 -1
- package/src/runtime/client/client.js +14 -18
- package/src/runtime/client/fetcher.js +27 -4
- package/src/version.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sveltejs/kit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.26.0",
|
|
4
4
|
"description": "The fastest way to build Svelte apps",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -18,17 +18,16 @@
|
|
|
18
18
|
"esm-env": "^1.0.0",
|
|
19
19
|
"kleur": "^4.1.5",
|
|
20
20
|
"magic-string": "^0.30.0",
|
|
21
|
-
"
|
|
21
|
+
"mrmime": "^1.0.1",
|
|
22
22
|
"sade": "^1.8.1",
|
|
23
23
|
"set-cookie-parser": "^2.6.0",
|
|
24
24
|
"sirv": "^2.0.2",
|
|
25
25
|
"tiny-glob": "^0.2.9",
|
|
26
|
-
"undici": "~5.
|
|
26
|
+
"undici": "~5.26.2"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@playwright/test": "1.30.0",
|
|
30
30
|
"@types/connect": "^3.4.35",
|
|
31
|
-
"@types/mime": "^3.0.1",
|
|
32
31
|
"@types/node": "^16.18.6",
|
|
33
32
|
"@types/sade": "^1.7.4",
|
|
34
33
|
"@types/set-cookie-parser": "^2.4.2",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import colors from 'kleur';
|
|
4
|
-
import
|
|
4
|
+
import { lookup } from 'mrmime';
|
|
5
5
|
import { list_files, runtime_directory } from '../../utils.js';
|
|
6
6
|
import { posixify } from '../../../utils/filesystem.js';
|
|
7
7
|
import { parse_route_id } from '../../../utils/routing.js';
|
|
@@ -48,7 +48,7 @@ export function create_assets(config) {
|
|
|
48
48
|
return list_files(config.kit.files.assets).map((file) => ({
|
|
49
49
|
file,
|
|
50
50
|
size: fs.statSync(path.resolve(config.kit.files.assets, file)).size,
|
|
51
|
-
type:
|
|
51
|
+
type: lookup(file) || null
|
|
52
52
|
}));
|
|
53
53
|
}
|
|
54
54
|
|
|
@@ -188,10 +188,18 @@ function update_types(config, routes, route, to_delete = new Set()) {
|
|
|
188
188
|
// add 'Expand' helper
|
|
189
189
|
// Makes sure a type is "repackaged" and therefore more readable
|
|
190
190
|
declarations.push('type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;');
|
|
191
|
+
|
|
192
|
+
// returns the predicate of a matcher's type guard - or string if there is no type guard
|
|
191
193
|
declarations.push(
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
194
|
+
// TS complains on infer U, which seems weird, therefore ts-ignore it
|
|
195
|
+
[
|
|
196
|
+
'// @ts-ignore',
|
|
197
|
+
'type MatcherParam<M> = M extends (param : string) => param is infer U ? U extends string ? U : string : string;'
|
|
198
|
+
].join('\n')
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
declarations.push(
|
|
202
|
+
'type RouteParams = ' + generate_params_type(route.params, outdir, config) + ';'
|
|
195
203
|
);
|
|
196
204
|
|
|
197
205
|
if (route.params.length > 0) {
|
|
@@ -265,7 +273,8 @@ function update_types(config, routes, route, to_delete = new Set()) {
|
|
|
265
273
|
|
|
266
274
|
if (route.layout) {
|
|
267
275
|
let all_pages_have_load = true;
|
|
268
|
-
|
|
276
|
+
/** @type {import('types').RouteParam[]} */
|
|
277
|
+
const layout_params = [];
|
|
269
278
|
const ids = ['RouteId'];
|
|
270
279
|
|
|
271
280
|
route.layout.child_pages?.forEach((page) => {
|
|
@@ -274,7 +283,9 @@ function update_types(config, routes, route, to_delete = new Set()) {
|
|
|
274
283
|
if (leaf.route.page) ids.push(`"${leaf.route.id}"`);
|
|
275
284
|
|
|
276
285
|
for (const param of leaf.route.params) {
|
|
277
|
-
|
|
286
|
+
// skip if already added
|
|
287
|
+
if (layout_params.some((p) => p.name === param.name)) continue;
|
|
288
|
+
layout_params.push({ ...param, optional: true });
|
|
278
289
|
}
|
|
279
290
|
|
|
280
291
|
ensureProxies(page, leaf.proxies);
|
|
@@ -301,9 +312,7 @@ function update_types(config, routes, route, to_delete = new Set()) {
|
|
|
301
312
|
declarations.push(`type LayoutRouteId = ${ids.join(' | ')}`);
|
|
302
313
|
|
|
303
314
|
declarations.push(
|
|
304
|
-
|
|
305
|
-
(param) => `${param}?: string`
|
|
306
|
-
)} }`
|
|
315
|
+
'type LayoutParams = RouteParams & ' + generate_params_type(layout_params, outdir, config)
|
|
307
316
|
);
|
|
308
317
|
|
|
309
318
|
const {
|
|
@@ -567,6 +576,28 @@ function replace_ext_with_js(file_path) {
|
|
|
567
576
|
return file_path.slice(0, -ext.length) + '.js';
|
|
568
577
|
}
|
|
569
578
|
|
|
579
|
+
/**
|
|
580
|
+
* @param {import('types').RouteParam[]} params
|
|
581
|
+
* @param {string} outdir
|
|
582
|
+
* @param {import('types').ValidatedConfig} config
|
|
583
|
+
*/
|
|
584
|
+
function generate_params_type(params, outdir, config) {
|
|
585
|
+
/** @param {string} matcher */
|
|
586
|
+
const path_to_matcher = (matcher) =>
|
|
587
|
+
posixify(path.relative(outdir, path.join(config.kit.files.params, matcher)));
|
|
588
|
+
|
|
589
|
+
return `{ ${params
|
|
590
|
+
.map(
|
|
591
|
+
(param) =>
|
|
592
|
+
`${param.name}${param.optional ? '?' : ''}: ${
|
|
593
|
+
param.matcher
|
|
594
|
+
? `MatcherParam<typeof import('${path_to_matcher(param.matcher)}').match>`
|
|
595
|
+
: 'string'
|
|
596
|
+
}`
|
|
597
|
+
)
|
|
598
|
+
.join('; ')} }`;
|
|
599
|
+
}
|
|
600
|
+
|
|
570
601
|
/**
|
|
571
602
|
* @param {string} content
|
|
572
603
|
* @param {boolean} is_server
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { lookup } from 'mrmime';
|
|
4
5
|
import sirv from 'sirv';
|
|
5
6
|
import { loadEnv, normalizePath } from 'vite';
|
|
6
7
|
import { getRequest, setResponse } from '../../../exports/node/index.js';
|
|
@@ -141,7 +142,7 @@ export async function preview(vite, vite_config, svelte_config) {
|
|
|
141
142
|
|
|
142
143
|
if (prerendered) {
|
|
143
144
|
res.writeHead(200, {
|
|
144
|
-
'content-type': 'text/html',
|
|
145
|
+
'content-type': lookup(pathname) || 'text/html',
|
|
145
146
|
etag
|
|
146
147
|
});
|
|
147
148
|
|
|
@@ -173,7 +173,7 @@ export function create_client(app, target) {
|
|
|
173
173
|
|
|
174
174
|
if (navigation_result) {
|
|
175
175
|
if (navigation_result.type === 'redirect') {
|
|
176
|
-
return goto(new URL(navigation_result.location, url).href, {},
|
|
176
|
+
return goto(new URL(navigation_result.location, url).href, {}, 1, nav_token);
|
|
177
177
|
} else {
|
|
178
178
|
if (navigation_result.props.page !== undefined) {
|
|
179
179
|
page = navigation_result.props.page;
|
|
@@ -208,7 +208,7 @@ export function create_client(app, target) {
|
|
|
208
208
|
/**
|
|
209
209
|
* @param {string | URL} url
|
|
210
210
|
* @param {{ noScroll?: boolean; replaceState?: boolean; keepFocus?: boolean; state?: any; invalidateAll?: boolean }} opts
|
|
211
|
-
* @param {
|
|
211
|
+
* @param {number} redirect_count
|
|
212
212
|
* @param {{}} [nav_token]
|
|
213
213
|
*/
|
|
214
214
|
async function goto(
|
|
@@ -220,7 +220,7 @@ export function create_client(app, target) {
|
|
|
220
220
|
state = {},
|
|
221
221
|
invalidateAll = false
|
|
222
222
|
},
|
|
223
|
-
|
|
223
|
+
redirect_count,
|
|
224
224
|
nav_token
|
|
225
225
|
) {
|
|
226
226
|
if (typeof url === 'string') {
|
|
@@ -231,7 +231,7 @@ export function create_client(app, target) {
|
|
|
231
231
|
url,
|
|
232
232
|
scroll: noScroll ? scroll_state() : null,
|
|
233
233
|
keepfocus: keepFocus,
|
|
234
|
-
|
|
234
|
+
redirect_count,
|
|
235
235
|
details: {
|
|
236
236
|
state,
|
|
237
237
|
replaceState
|
|
@@ -941,7 +941,7 @@ export function create_client(app, target) {
|
|
|
941
941
|
* url: URL;
|
|
942
942
|
* scroll: { x: number, y: number } | null;
|
|
943
943
|
* keepfocus: boolean;
|
|
944
|
-
*
|
|
944
|
+
* redirect_count: number;
|
|
945
945
|
* details: {
|
|
946
946
|
* replaceState: boolean;
|
|
947
947
|
* state: any;
|
|
@@ -957,7 +957,7 @@ export function create_client(app, target) {
|
|
|
957
957
|
url,
|
|
958
958
|
scroll,
|
|
959
959
|
keepfocus,
|
|
960
|
-
|
|
960
|
+
redirect_count,
|
|
961
961
|
details,
|
|
962
962
|
type,
|
|
963
963
|
delta,
|
|
@@ -1014,7 +1014,8 @@ export function create_client(app, target) {
|
|
|
1014
1014
|
}
|
|
1015
1015
|
|
|
1016
1016
|
if (navigation_result.type === 'redirect') {
|
|
1017
|
-
|
|
1017
|
+
// whatwg fetch spec https://fetch.spec.whatwg.org/#http-redirect-fetch says to error after 20 redirects
|
|
1018
|
+
if (redirect_count >= 20) {
|
|
1018
1019
|
navigation_result = await load_root_error_page({
|
|
1019
1020
|
status: 500,
|
|
1020
1021
|
error: await handle_error(new Error('Redirect loop'), {
|
|
@@ -1026,12 +1027,7 @@ export function create_client(app, target) {
|
|
|
1026
1027
|
route: { id: null }
|
|
1027
1028
|
});
|
|
1028
1029
|
} else {
|
|
1029
|
-
goto(
|
|
1030
|
-
new URL(navigation_result.location, url).href,
|
|
1031
|
-
{},
|
|
1032
|
-
[...redirect_chain, url.pathname],
|
|
1033
|
-
nav_token
|
|
1034
|
-
);
|
|
1030
|
+
goto(new URL(navigation_result.location, url).href, {}, redirect_count + 1, nav_token);
|
|
1035
1031
|
return false;
|
|
1036
1032
|
}
|
|
1037
1033
|
} else if (/** @type {number} */ (navigation_result.props.page?.status) >= 400) {
|
|
@@ -1379,7 +1375,7 @@ export function create_client(app, target) {
|
|
|
1379
1375
|
},
|
|
1380
1376
|
|
|
1381
1377
|
goto: (href, opts = {}) => {
|
|
1382
|
-
return goto(href, opts,
|
|
1378
|
+
return goto(href, opts, 0);
|
|
1383
1379
|
},
|
|
1384
1380
|
|
|
1385
1381
|
invalidate: (resource) => {
|
|
@@ -1440,7 +1436,7 @@ export function create_client(app, target) {
|
|
|
1440
1436
|
tick().then(reset_focus);
|
|
1441
1437
|
}
|
|
1442
1438
|
} else if (result.type === 'redirect') {
|
|
1443
|
-
goto(result.location, { invalidateAll: true },
|
|
1439
|
+
goto(result.location, { invalidateAll: true }, 0);
|
|
1444
1440
|
} else {
|
|
1445
1441
|
/** @type {Record<string, any>} */
|
|
1446
1442
|
root.$set({
|
|
@@ -1595,7 +1591,7 @@ export function create_client(app, target) {
|
|
|
1595
1591
|
url,
|
|
1596
1592
|
scroll: options.noscroll ? scroll_state() : null,
|
|
1597
1593
|
keepfocus: options.keep_focus ?? false,
|
|
1598
|
-
|
|
1594
|
+
redirect_count: 0,
|
|
1599
1595
|
details: {
|
|
1600
1596
|
state: {},
|
|
1601
1597
|
replaceState: options.replace_state ?? url.href === location.href
|
|
@@ -1649,7 +1645,7 @@ export function create_client(app, target) {
|
|
|
1649
1645
|
url,
|
|
1650
1646
|
scroll: noscroll ? scroll_state() : null,
|
|
1651
1647
|
keepfocus: keep_focus ?? false,
|
|
1652
|
-
|
|
1648
|
+
redirect_count: 0,
|
|
1653
1649
|
details: {
|
|
1654
1650
|
state: {},
|
|
1655
1651
|
replaceState: replace_state ?? url.href === location.href
|
|
@@ -1687,7 +1683,7 @@ export function create_client(app, target) {
|
|
|
1687
1683
|
url,
|
|
1688
1684
|
scroll,
|
|
1689
1685
|
keepfocus: false,
|
|
1690
|
-
|
|
1686
|
+
redirect_count: 0,
|
|
1691
1687
|
details: null,
|
|
1692
1688
|
accepted: () => {
|
|
1693
1689
|
current_history_index = event.state[INDEX_KEY];
|
|
@@ -23,6 +23,10 @@ if (DEV) {
|
|
|
23
23
|
|
|
24
24
|
check_stack_trace();
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* @param {RequestInfo | URL} input
|
|
28
|
+
* @param {RequestInit & Record<string, any> | undefined} init
|
|
29
|
+
*/
|
|
26
30
|
window.fetch = (input, init) => {
|
|
27
31
|
// Check if fetch was called via load_node. the lock method only checks if it was called at the
|
|
28
32
|
// same time, but not necessarily if it was called from `load`.
|
|
@@ -36,10 +40,14 @@ if (DEV) {
|
|
|
36
40
|
const cutoff = stack_array.findIndex((a) => a.includes('load@') || a.includes('at load'));
|
|
37
41
|
const stack = stack_array.slice(0, cutoff + 2).join('\n');
|
|
38
42
|
|
|
39
|
-
const
|
|
43
|
+
const in_load_heuristic = can_inspect_stack_trace
|
|
40
44
|
? stack.includes('src/runtime/client/client.js')
|
|
41
45
|
: loading;
|
|
42
|
-
|
|
46
|
+
|
|
47
|
+
// This flag is set in initial_fetch and subsequent_fetch
|
|
48
|
+
const used_kit_fetch = init?.__sveltekit_fetch__;
|
|
49
|
+
|
|
50
|
+
if (in_load_heuristic && !used_kit_fetch) {
|
|
43
51
|
console.warn(
|
|
44
52
|
`Loading ${url} using \`window.fetch\`. For best results, use the \`fetch\` that is passed to your \`load\` function: https://kit.svelte.dev/docs/load#making-fetch-requests`
|
|
45
53
|
);
|
|
@@ -86,7 +94,7 @@ export function initial_fetch(resource, opts) {
|
|
|
86
94
|
return Promise.resolve(new Response(body, init));
|
|
87
95
|
}
|
|
88
96
|
|
|
89
|
-
return
|
|
97
|
+
return DEV ? dev_fetch(resource, opts) : window.fetch(resource, opts);
|
|
90
98
|
}
|
|
91
99
|
|
|
92
100
|
/**
|
|
@@ -112,7 +120,22 @@ export function subsequent_fetch(resource, resolved, opts) {
|
|
|
112
120
|
}
|
|
113
121
|
}
|
|
114
122
|
|
|
115
|
-
return
|
|
123
|
+
return DEV ? dev_fetch(resolved, opts) : window.fetch(resolved, opts);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @param {RequestInfo | URL} resource
|
|
128
|
+
* @param {RequestInit & Record<string, any> | undefined} opts
|
|
129
|
+
*/
|
|
130
|
+
function dev_fetch(resource, opts) {
|
|
131
|
+
const patched_opts = { ...opts };
|
|
132
|
+
// This assigns the __sveltekit_fetch__ flag and makes it non-enumerable
|
|
133
|
+
Object.defineProperty(patched_opts, '__sveltekit_fetch__', {
|
|
134
|
+
value: true,
|
|
135
|
+
writable: true,
|
|
136
|
+
configurable: true
|
|
137
|
+
});
|
|
138
|
+
return window.fetch(resource, patched_opts);
|
|
116
139
|
}
|
|
117
140
|
|
|
118
141
|
/**
|
package/src/version.js
CHANGED