@sveltejs/kit 3.0.0-next.0 → 3.0.0-next.10
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 +33 -21
- package/src/core/adapt/builder.js +29 -43
- package/src/core/adapt/index.js +1 -4
- package/src/core/config/index.js +132 -71
- package/src/core/config/options.js +294 -244
- package/src/core/config/types.d.ts +1 -1
- package/src/core/env.js +121 -5
- package/src/core/generate_manifest/index.js +12 -15
- package/src/core/postbuild/analyse.js +7 -19
- package/src/core/postbuild/crawl.js +22 -6
- package/src/core/postbuild/prerender.js +42 -23
- package/src/core/sync/create_manifest_data/index.js +53 -50
- package/src/core/sync/sync.js +0 -2
- package/src/core/sync/write_client_manifest.js +8 -15
- package/src/core/sync/write_env.js +2 -1
- package/src/core/sync/write_non_ambient.js +12 -9
- package/src/core/sync/write_server.js +13 -14
- package/src/core/sync/write_tsconfig.js +16 -8
- package/src/core/sync/write_tsconfig_test/package.json +7 -0
- package/src/core/sync/write_types/index.js +28 -24
- package/src/core/utils.js +2 -2
- package/src/exports/env/index.js +12 -0
- package/src/exports/hooks/index.js +3 -9
- package/src/exports/hooks/sequence.js +3 -2
- package/src/exports/index.js +35 -13
- package/src/exports/internal/client.js +5 -0
- package/src/exports/internal/env.js +2 -2
- package/src/exports/internal/index.js +1 -90
- package/src/exports/internal/{event.js → server/event.js} +1 -2
- package/src/exports/internal/server/index.js +33 -0
- package/src/exports/internal/shared.js +89 -0
- package/src/exports/node/index.js +62 -15
- package/src/exports/params.js +63 -0
- package/src/exports/public.d.ts +323 -170
- package/src/exports/url.js +86 -0
- package/src/exports/vite/build/build_server.js +53 -59
- package/src/exports/vite/build/remote.js +18 -11
- package/src/exports/vite/build/utils.js +0 -8
- package/src/exports/vite/dev/index.js +42 -44
- package/src/exports/vite/index.js +810 -593
- package/src/exports/vite/preview/index.js +29 -22
- package/src/exports/vite/static_analysis/index.js +2 -4
- package/src/exports/vite/static_analysis/types.d.ts +14 -0
- package/src/exports/vite/utils.js +21 -36
- package/src/runtime/app/env/internal.js +4 -4
- package/src/runtime/app/env/types.d.ts +1 -1
- package/src/runtime/app/environment/index.js +6 -0
- package/src/runtime/app/forms.js +24 -7
- package/src/runtime/app/paths/client.js +4 -10
- package/src/runtime/app/paths/internal/client.js +4 -2
- package/src/runtime/app/paths/internal/server.js +2 -23
- package/src/runtime/app/paths/public.d.ts +0 -28
- package/src/runtime/app/paths/server.js +9 -5
- package/src/runtime/app/server/remote/command.js +0 -3
- package/src/runtime/app/server/remote/form.js +27 -15
- package/src/runtime/app/server/remote/prerender.js +29 -36
- package/src/runtime/app/server/remote/query.js +101 -99
- package/src/runtime/app/server/remote/requested.js +22 -14
- package/src/runtime/app/server/remote/shared.js +30 -26
- package/src/runtime/app/state/client.js +1 -2
- package/src/runtime/app/stores.js +13 -76
- package/src/runtime/client/bundle.js +1 -1
- package/src/runtime/client/client-entry.js +3 -0
- package/src/runtime/client/client.js +411 -318
- package/src/runtime/client/entry.js +24 -3
- package/src/runtime/client/fetcher.js +3 -2
- package/src/runtime/client/ndjson.js +6 -33
- package/src/runtime/client/payload.js +17 -0
- package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
- package/src/runtime/client/remote-functions/command.svelte.js +7 -32
- package/src/runtime/client/remote-functions/form.svelte.js +183 -112
- package/src/runtime/client/remote-functions/prerender.svelte.js +29 -8
- package/src/runtime/client/remote-functions/query/index.js +7 -14
- package/src/runtime/client/remote-functions/query/instance.svelte.js +63 -18
- package/src/runtime/client/remote-functions/query/proxy.js +3 -3
- package/src/runtime/client/remote-functions/query-batch.svelte.js +60 -68
- package/src/runtime/client/remote-functions/query-live/instance.svelte.js +60 -18
- package/src/runtime/client/remote-functions/query-live/iterator.js +36 -55
- package/src/runtime/client/remote-functions/shared.svelte.js +88 -62
- package/src/runtime/client/sse.js +32 -0
- package/src/runtime/client/state.svelte.js +65 -49
- package/src/runtime/client/stream.js +38 -0
- package/src/runtime/client/types.d.ts +11 -7
- package/src/runtime/client/utils.js +0 -96
- package/src/runtime/components/root.svelte +66 -0
- package/src/runtime/env/dynamic/private.js +7 -0
- package/src/runtime/env/dynamic/public.js +7 -0
- package/src/runtime/env/static/private.js +6 -0
- package/src/runtime/env/static/public.js +6 -0
- package/src/runtime/form-utils.js +100 -22
- package/src/runtime/server/cookie.js +69 -52
- package/src/runtime/server/csrf.js +65 -0
- package/src/runtime/server/data/index.js +14 -18
- package/src/runtime/server/env_module.js +0 -5
- package/src/runtime/server/index.js +2 -2
- package/src/runtime/server/page/actions.js +41 -26
- package/src/runtime/server/page/index.js +9 -15
- package/src/runtime/server/page/load_data.js +1 -1
- package/src/runtime/server/page/render.js +112 -187
- package/src/runtime/server/page/respond_with_error.js +7 -8
- package/src/runtime/server/page/server_routing.js +27 -18
- package/src/runtime/server/remote.js +355 -216
- package/src/runtime/server/respond.js +97 -61
- package/src/runtime/server/utils.js +32 -9
- package/src/runtime/shared.js +83 -13
- package/src/runtime/telemetry/otel.js +1 -1
- package/src/runtime/types.d.ts +8 -0
- package/src/types/ambient.d.ts +10 -5
- package/src/types/global-private.d.ts +15 -22
- package/src/types/internal.d.ts +89 -74
- package/src/types/private.d.ts +33 -1
- package/src/utils/error.js +24 -4
- package/src/utils/import.js +6 -1
- package/src/utils/imports.js +83 -0
- package/src/utils/mime.js +9 -0
- package/src/utils/params.js +66 -0
- package/src/utils/routing.js +90 -44
- package/src/utils/shared-iterator.js +5 -0
- package/src/utils/streaming.js +14 -4
- package/src/utils/url.js +20 -2
- package/src/version.js +1 -1
- package/types/index.d.ts +467 -537
- package/types/index.d.ts.map +22 -39
- package/src/core/sync/write_root.js +0 -148
- package/src/exports/internal/server.js +0 -22
- package/src/types/synthetic/$lib.md +0 -5
- /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
package/src/utils/routing.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { BROWSER } from 'esm-env';
|
|
2
|
-
import { decode_params } from './url.js';
|
|
3
2
|
|
|
4
|
-
const param_pattern = /^(\[)?(\.\.\.)?(\w+)(?:=(\w+))?(\])?$/;
|
|
3
|
+
const param_pattern = /^(\[)?(\.\.\.)?([\w-]+)(?:=([\w-]+))?(\])?$/;
|
|
5
4
|
|
|
6
5
|
const root_group_pattern = /^\/\((?:[^)]+)\)$/;
|
|
7
6
|
|
|
@@ -20,7 +19,7 @@ export function parse_route_id(id) {
|
|
|
20
19
|
`^${get_route_segments(id)
|
|
21
20
|
.map((segment) => {
|
|
22
21
|
// special case — /[...rest]/ could contain zero segments
|
|
23
|
-
const rest_match = /^\[\.\.\.(\w+)(?:=(\w+))?\]$/.exec(segment);
|
|
22
|
+
const rest_match = /^\[\.\.\.([\w-]+)(?:=([\w-]+))?\]$/.exec(segment);
|
|
24
23
|
if (rest_match) {
|
|
25
24
|
params.push({
|
|
26
25
|
name: rest_match[1],
|
|
@@ -32,7 +31,7 @@ export function parse_route_id(id) {
|
|
|
32
31
|
return '(?:/([^]*))?';
|
|
33
32
|
}
|
|
34
33
|
// special case — /[[optional]]/ could contain zero segments
|
|
35
|
-
const optional_match = /^\[\[(\w+)(?:=(\w+))?\]\]$/.exec(segment);
|
|
34
|
+
const optional_match = /^\[\[([\w-]+)(?:=([\w-]+))?\]\]$/.exec(segment);
|
|
36
35
|
if (optional_match) {
|
|
37
36
|
params.push({
|
|
38
37
|
name: optional_match[1],
|
|
@@ -73,7 +72,7 @@ export function parse_route_id(id) {
|
|
|
73
72
|
const match = /** @type {RegExpExecArray} */ (param_pattern.exec(content));
|
|
74
73
|
if (!BROWSER && !match) {
|
|
75
74
|
throw new Error(
|
|
76
|
-
`Invalid param: ${content}. Params and matcher names can only have underscores and alphanumeric characters.`
|
|
75
|
+
`Invalid param: ${content}. Params and matcher names can only have underscores, hyphens, and alphanumeric characters.`
|
|
77
76
|
);
|
|
78
77
|
}
|
|
79
78
|
|
|
@@ -104,7 +103,7 @@ export function parse_route_id(id) {
|
|
|
104
103
|
return { pattern, params };
|
|
105
104
|
}
|
|
106
105
|
|
|
107
|
-
const optional_param_regex = /\/\[\[\w+?(
|
|
106
|
+
const optional_param_regex = /\/\[\[[\w-]+?(?:=[\w-]+)?\]\]/;
|
|
108
107
|
|
|
109
108
|
/**
|
|
110
109
|
* Removes optional params from a route ID.
|
|
@@ -134,13 +133,43 @@ export function get_route_segments(route) {
|
|
|
134
133
|
return route.slice(1).split('/').filter(affects_path);
|
|
135
134
|
}
|
|
136
135
|
|
|
136
|
+
/**
|
|
137
|
+
* @param {import('@sveltejs/kit').ParamMatcher} matcher
|
|
138
|
+
* @param {string} value
|
|
139
|
+
* @returns {{ success: true, value: any } | { success: false }}
|
|
140
|
+
*/
|
|
141
|
+
function run_matcher(matcher, value) {
|
|
142
|
+
const result = matcher['~standard'].validate(value);
|
|
143
|
+
|
|
144
|
+
if (result instanceof Promise) {
|
|
145
|
+
throw new Error('Async param matchers are not supported');
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (result.issues) {
|
|
149
|
+
return { success: false };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const parsed = result.value;
|
|
153
|
+
|
|
154
|
+
if (
|
|
155
|
+
typeof parsed !== 'string' &&
|
|
156
|
+
typeof parsed !== 'number' &&
|
|
157
|
+
typeof parsed !== 'boolean' &&
|
|
158
|
+
typeof parsed !== 'bigint'
|
|
159
|
+
) {
|
|
160
|
+
throw new Error('Param matcher must return a string, number, boolean, or bigint');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return { success: true, value: parsed };
|
|
164
|
+
}
|
|
165
|
+
|
|
137
166
|
/**
|
|
138
167
|
* @param {RegExpMatchArray} match
|
|
139
168
|
* @param {import('types').RouteParam[]} params
|
|
140
169
|
* @param {Record<string, import('@sveltejs/kit').ParamMatcher>} matchers
|
|
141
170
|
*/
|
|
142
171
|
export function exec(match, params, matchers) {
|
|
143
|
-
/** @type {Record<string,
|
|
172
|
+
/** @type {Record<string, any>} */
|
|
144
173
|
const result = {};
|
|
145
174
|
|
|
146
175
|
const values = match.slice(1);
|
|
@@ -173,37 +202,41 @@ export function exec(match, params, matchers) {
|
|
|
173
202
|
}
|
|
174
203
|
}
|
|
175
204
|
|
|
176
|
-
|
|
177
|
-
result[param.name] = value;
|
|
205
|
+
const decoded = decodeURIComponent(value);
|
|
178
206
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
207
|
+
if (param.matcher) {
|
|
208
|
+
const outcome = run_matcher(matchers[param.matcher], decoded);
|
|
209
|
+
|
|
210
|
+
if (!outcome.success) {
|
|
211
|
+
// in the `/[[a=b]]/...` case, if the value didn't satisfy the matcher,
|
|
212
|
+
// keep track of the number of skipped optional parameters and continue
|
|
213
|
+
if (param.optional && param.chained) {
|
|
214
|
+
buffered++;
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
186
217
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
!next_param &&
|
|
190
|
-
!next_value &&
|
|
191
|
-
Object.keys(result).length === values_needing_match.length
|
|
192
|
-
) {
|
|
193
|
-
buffered = 0;
|
|
218
|
+
// otherwise, if the matcher returns `false`, the route did not match
|
|
219
|
+
return;
|
|
194
220
|
}
|
|
195
|
-
|
|
221
|
+
|
|
222
|
+
result[param.name] = outcome.value;
|
|
223
|
+
} else {
|
|
224
|
+
result[param.name] = decoded;
|
|
196
225
|
}
|
|
197
226
|
|
|
198
|
-
//
|
|
199
|
-
//
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
227
|
+
// Now that the params match, reset the buffer if the next param isn't the [...rest]
|
|
228
|
+
// and the next value is defined, otherwise the buffer will cause us to skip values
|
|
229
|
+
const next_param = params[i + 1];
|
|
230
|
+
const next_value = values[i + 1];
|
|
231
|
+
if (next_param && !next_param.rest && next_param.optional && next_value && param.chained) {
|
|
232
|
+
buffered = 0;
|
|
203
233
|
}
|
|
204
234
|
|
|
205
|
-
//
|
|
206
|
-
|
|
235
|
+
// There are no more params and no more values, but all non-empty values have been matched
|
|
236
|
+
if (!next_param && !next_value && Object.keys(result).length === values_needing_match.length) {
|
|
237
|
+
buffered = 0;
|
|
238
|
+
}
|
|
239
|
+
continue;
|
|
207
240
|
}
|
|
208
241
|
|
|
209
242
|
if (buffered) return;
|
|
@@ -227,7 +260,7 @@ function escape(str) {
|
|
|
227
260
|
);
|
|
228
261
|
}
|
|
229
262
|
|
|
230
|
-
const basic_param_pattern = /\[(\[)?(\.\.\.)?(\w+?)(?:=(\w+))?\]\]?/g;
|
|
263
|
+
const basic_param_pattern = /\[(\[)?(\.\.\.)?([\w-]+?)(?:=([\w-]+))?\]\]?/g;
|
|
231
264
|
|
|
232
265
|
/**
|
|
233
266
|
* Populate a route ID with params to resolve a pathname.
|
|
@@ -242,7 +275,7 @@ const basic_param_pattern = /\[(\[)?(\.\.\.)?(\w+?)(?:=(\w+))?\]\]?/g;
|
|
|
242
275
|
* ); // `/blog/hello-world/something/else`
|
|
243
276
|
* ```
|
|
244
277
|
* @param {string} id
|
|
245
|
-
* @param {Record<string,
|
|
278
|
+
* @param {Record<string, import('@sveltejs/kit').ParamValue | undefined>} params
|
|
246
279
|
* @returns {string}
|
|
247
280
|
*/
|
|
248
281
|
export function resolve_route(id, params) {
|
|
@@ -254,20 +287,33 @@ export function resolve_route(id, params) {
|
|
|
254
287
|
segments
|
|
255
288
|
.map((segment) =>
|
|
256
289
|
segment.replace(basic_param_pattern, (_, optional, rest, name) => {
|
|
257
|
-
const
|
|
290
|
+
const value = params[name];
|
|
258
291
|
|
|
259
|
-
|
|
260
|
-
if (!param_value) {
|
|
292
|
+
if (value === undefined || value === '') {
|
|
261
293
|
if (optional) return '';
|
|
262
|
-
if (rest &&
|
|
294
|
+
if (rest && value !== undefined) return '';
|
|
263
295
|
throw new Error(`Missing parameter '${name}' in route ${id}`);
|
|
264
296
|
}
|
|
265
297
|
|
|
266
|
-
if (
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
298
|
+
if (typeof value === 'string') {
|
|
299
|
+
if (value.startsWith('/') || value.endsWith('/')) {
|
|
300
|
+
throw new Error(
|
|
301
|
+
`Parameter '${name}' in route ${id} cannot start or end with a slash -- this would cause an invalid route like foo//bar`
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return value;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (
|
|
309
|
+
typeof value === 'number' ||
|
|
310
|
+
typeof value === 'boolean' ||
|
|
311
|
+
typeof value === 'bigint'
|
|
312
|
+
) {
|
|
313
|
+
return String(value);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
throw new Error('Parameter values must be a string, number, boolean, or bigint');
|
|
271
317
|
})
|
|
272
318
|
)
|
|
273
319
|
.filter(Boolean)
|
|
@@ -290,7 +336,7 @@ export function has_server_load(node) {
|
|
|
290
336
|
* @param {string} path - The decoded pathname to match
|
|
291
337
|
* @param {Route[]} routes
|
|
292
338
|
* @param {Record<string, import('@sveltejs/kit').ParamMatcher>} matchers
|
|
293
|
-
* @returns {{ route: Route, params: Record<string,
|
|
339
|
+
* @returns {{ route: Route, params: Record<string, any> } | null}
|
|
294
340
|
*/
|
|
295
341
|
export function find_route(path, routes, matchers) {
|
|
296
342
|
for (const route of routes) {
|
|
@@ -301,7 +347,7 @@ export function find_route(path, routes, matchers) {
|
|
|
301
347
|
if (matched) {
|
|
302
348
|
return {
|
|
303
349
|
route,
|
|
304
|
-
params:
|
|
350
|
+
params: matched
|
|
305
351
|
};
|
|
306
352
|
}
|
|
307
353
|
}
|
|
@@ -52,6 +52,11 @@ export class SharedIterator {
|
|
|
52
52
|
/** @type {unknown} */
|
|
53
53
|
#terminal_error = undefined;
|
|
54
54
|
|
|
55
|
+
/** Whether `done()` or `fail()` has been broadcast. */
|
|
56
|
+
get closed() {
|
|
57
|
+
return this.#closed;
|
|
58
|
+
}
|
|
59
|
+
|
|
55
60
|
/**
|
|
56
61
|
* @param {(instance: SharedIterator<T>) => (() => void)} [start]
|
|
57
62
|
*/
|
package/src/utils/streaming.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { noop } from './functions.js';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Create an async iterator and a function to push values into it
|
|
3
5
|
* @template T
|
|
@@ -30,10 +32,18 @@ export function create_async_iterator() {
|
|
|
30
32
|
};
|
|
31
33
|
},
|
|
32
34
|
add: (promise) => {
|
|
33
|
-
|
|
34
|
-
void promise.
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
const next = Promise.withResolvers();
|
|
36
|
+
void next.promise.catch(noop); // prevent unhandled rejection potentially crashing the process
|
|
37
|
+
deferred.push(next);
|
|
38
|
+
|
|
39
|
+
void promise.then(
|
|
40
|
+
(value) => {
|
|
41
|
+
deferred[++resolved].resolve(value);
|
|
42
|
+
},
|
|
43
|
+
(error) => {
|
|
44
|
+
deferred[++resolved].reject(error);
|
|
45
|
+
}
|
|
46
|
+
);
|
|
37
47
|
}
|
|
38
48
|
};
|
|
39
49
|
}
|
package/src/utils/url.js
CHANGED
|
@@ -4,7 +4,7 @@ import { BROWSER, DEV } from 'esm-env';
|
|
|
4
4
|
* Matches a URI scheme. See https://www.rfc-editor.org/rfc/rfc3986#section-3.1
|
|
5
5
|
* @type {RegExp}
|
|
6
6
|
*/
|
|
7
|
-
export const SCHEME = /^[a-z][a-z\d+\-.]
|
|
7
|
+
export const SCHEME = /^[a-z][a-z\d+\-.]*:/i;
|
|
8
8
|
|
|
9
9
|
const internal = new URL('a://');
|
|
10
10
|
|
|
@@ -27,6 +27,24 @@ export function is_root_relative(path) {
|
|
|
27
27
|
return path[0] === '/' && path[1] !== '/';
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* @param {string} location
|
|
32
|
+
* @param {string} allowed
|
|
33
|
+
*/
|
|
34
|
+
export function matches_external_allowlist_entry(location, allowed) {
|
|
35
|
+
if (location === allowed) return true;
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
const allow = new URL(allowed);
|
|
39
|
+
const loc = new URL(location, allow);
|
|
40
|
+
|
|
41
|
+
// this is stricter than `loc.origin === allow.origin`, which can fail in `blob:` cases
|
|
42
|
+
return loc.protocol === allow.protocol && loc.host === allow.host;
|
|
43
|
+
} catch {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
30
48
|
/**
|
|
31
49
|
* @param {string} path
|
|
32
50
|
* @param {import('types').TrailingSlash} trailing_slash
|
|
@@ -119,6 +137,7 @@ export function make_trackable(url, callback, search_params_callback, allow_hash
|
|
|
119
137
|
/**
|
|
120
138
|
* URL properties that could change during the lifetime of the page,
|
|
121
139
|
* which excludes things like `origin`
|
|
140
|
+
* @type {(keyof URL)[]}
|
|
122
141
|
*/
|
|
123
142
|
const tracked_url_properties = ['href', 'pathname', 'search', 'toString', 'toJSON'];
|
|
124
143
|
if (allow_hash) tracked_url_properties.push('hash');
|
|
@@ -127,7 +146,6 @@ export function make_trackable(url, callback, search_params_callback, allow_hash
|
|
|
127
146
|
Object.defineProperty(tracked, property, {
|
|
128
147
|
get() {
|
|
129
148
|
callback();
|
|
130
|
-
// @ts-expect-error
|
|
131
149
|
return url[property];
|
|
132
150
|
},
|
|
133
151
|
|
package/src/version.js
CHANGED