@sveltejs/kit 3.0.0-next.13 → 3.0.0-next.16
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 +7 -4
- package/src/cli.js +8 -5
- package/src/core/adapt/builder.js +20 -10
- package/src/core/config/index.js +4 -5
- package/src/core/env.js +3 -3
- package/src/core/generate_manifest/index.js +6 -0
- package/src/core/postbuild/entities.js +8 -2
- package/src/core/postbuild/fallback.js +2 -1
- package/src/core/postbuild/prerender.js +18 -13
- package/src/core/sync/create_manifest_data/conflict.js +1 -1
- package/src/core/sync/create_manifest_data/index.js +33 -2
- package/src/core/sync/sync.js +3 -2
- package/src/core/sync/utils.js +2 -2
- package/src/core/sync/write_app_types.js +72 -27
- package/src/core/sync/write_tsconfig/index.js +73 -54
- package/src/core/sync/write_tsconfig/utils.js +0 -61
- package/src/core/sync/write_tsconfig/validate.js +128 -0
- package/src/core/sync/write_types/index.js +7 -4
- package/src/exports/node/index.js +2 -7
- package/src/exports/public.d.ts +25 -18
- package/src/exports/vite/build/build_server.js +2 -3
- package/src/exports/vite/dev/index.js +44 -36
- package/src/exports/vite/index.js +91 -16
- package/src/exports/vite/utils.js +62 -15
- package/src/runner.js +4 -2
- package/src/runtime/app/forms.js +4 -7
- package/src/runtime/app/internal/transport.js +53 -0
- package/src/runtime/app/paths/client.js +2 -2
- package/src/runtime/app/paths/internal/client.js +2 -2
- package/src/runtime/app/server/remote/prerender.js +6 -10
- package/src/runtime/app/server/remote/query.js +3 -9
- package/src/runtime/app/server/remote/requested.js +2 -2
- package/src/runtime/app/server/remote/shared.js +1 -16
- package/src/runtime/client/client.js +177 -63
- package/src/runtime/client/fetcher.js +2 -13
- package/src/runtime/client/parse.js +1 -1
- package/src/runtime/client/remote-functions/command.svelte.js +1 -2
- package/src/runtime/client/remote-functions/form.svelte.js +3 -7
- package/src/runtime/client/remote-functions/prerender.svelte.js +2 -2
- package/src/runtime/client/remote-functions/query/index.js +1 -1
- package/src/runtime/client/remote-functions/query/proxy.js +2 -2
- package/src/runtime/client/remote-functions/query-batch.svelte.js +1 -1
- package/src/runtime/client/remote-functions/query-live/proxy.js +2 -12
- package/src/runtime/client/remote-functions/shared.svelte.js +1 -1
- package/src/runtime/client/utils.js +1 -0
- package/src/runtime/form-utils.js +4 -6
- package/src/runtime/pathname.js +44 -1
- package/src/runtime/server/data/index.js +5 -8
- package/src/runtime/server/dev.js +22 -0
- package/src/runtime/server/endpoint.js +3 -4
- package/src/runtime/server/fetch.js +25 -30
- package/src/runtime/server/index.js +64 -46
- package/src/runtime/server/internal.js +12 -5
- package/src/runtime/server/page/actions.js +18 -43
- package/src/runtime/server/page/crypto.js +2 -2
- package/src/runtime/server/page/csp.js +2 -1
- package/src/runtime/server/page/data_serializer.js +12 -13
- package/src/runtime/server/page/index.js +16 -32
- package/src/runtime/server/page/load_data.js +28 -44
- package/src/runtime/server/page/render.js +28 -12
- package/src/runtime/server/page/respond_with_error.js +8 -20
- package/src/runtime/server/page/serialize_data.js +2 -13
- package/src/runtime/server/page/server_routing.js +58 -9
- package/src/runtime/server/remote-functions.js +11 -15
- package/src/runtime/server/respond.js +44 -56
- package/src/runtime/server/state.js +60 -0
- package/src/runtime/server/utils.js +0 -20
- package/src/runtime/shared.js +20 -40
- package/src/runtime/utils.js +3 -0
- package/src/types/ambient-private.d.ts +1 -1
- package/src/types/ambient.d.ts +58 -7
- package/src/types/global-private.d.ts +1 -1
- package/src/types/internal.d.ts +47 -53
- package/src/utils/filesystem.js +1 -23
- package/src/utils/hash.js +21 -0
- package/src/utils/http.js +8 -7
- package/src/utils/import.js +2 -1
- package/src/utils/params.js +1 -1
- package/src/utils/regex.js +9 -0
- package/src/utils/routing.js +52 -27
- package/src/utils/url.js +1 -0
- package/src/version.js +1 -1
- package/types/index.d.ts +98 -28
- package/types/index.d.ts.map +1 -1
- package/src/exports/node/polyfills.js +0 -30
- package/src/runtime/server/app.js +0 -9
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @import {
|
|
1
|
+
/** @import { SSRNode } from 'types' */
|
|
2
2
|
import { DEV } from 'esm-env';
|
|
3
3
|
import { json, text } from '@sveltejs/kit';
|
|
4
4
|
import { Redirect, SvelteKitError } from '@sveltejs/kit/internal';
|
|
@@ -26,13 +26,15 @@ import { validate_server_exports } from '../../utils/exports.js';
|
|
|
26
26
|
import { action_json_redirect, is_action_json_request } from './page/actions.js';
|
|
27
27
|
import { INVALIDATED_PARAM, TRAILING_SLASH_PARAM } from '../shared.js';
|
|
28
28
|
import { get_public_env } from './env_module.js';
|
|
29
|
-
import { resolve_route } from './page/server_routing.js';
|
|
29
|
+
import { resolve_route, resolve_route_by_id } from './page/server_routing.js';
|
|
30
30
|
import { validateHeaders } from './validate-headers.js';
|
|
31
31
|
import {
|
|
32
32
|
add_data_suffix,
|
|
33
33
|
add_resolution_suffix,
|
|
34
|
+
extract_route_id,
|
|
34
35
|
has_data_suffix,
|
|
35
36
|
has_resolution_suffix,
|
|
37
|
+
is_route_id_resolution_path,
|
|
36
38
|
strip_data_suffix,
|
|
37
39
|
strip_resolution_suffix
|
|
38
40
|
} from '../pathname.js';
|
|
@@ -82,7 +84,7 @@ export const respond = propagate_context(internal_respond);
|
|
|
82
84
|
* @param {Request} request
|
|
83
85
|
* @param {import('types').SSROptions} options
|
|
84
86
|
* @param {import('@sveltejs/kit').SSRManifest} manifest
|
|
85
|
-
* @param {import('types').
|
|
87
|
+
* @param {import('types').RequestState} state
|
|
86
88
|
* @returns {Promise<Response>}
|
|
87
89
|
*/
|
|
88
90
|
export async function internal_respond(request, options, manifest, state) {
|
|
@@ -138,12 +140,16 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
138
140
|
|
|
139
141
|
let skip_route_resolution = false;
|
|
140
142
|
|
|
143
|
+
/** Whether this is a `/${app_dir}/routes/<route_id>/__route.js` request, used by `preloadCode` */
|
|
144
|
+
let is_route_id_resolution_request = false;
|
|
145
|
+
|
|
141
146
|
if (is_route_resolution_request) {
|
|
142
147
|
/**
|
|
143
148
|
* If the request is for a route resolution, first modify the URL, then continue as normal
|
|
144
149
|
* for path resolution, then return the route object as a JS file.
|
|
145
150
|
*/
|
|
146
151
|
url.pathname = strip_resolution_suffix(url.pathname);
|
|
152
|
+
is_route_id_resolution_request = is_route_id_resolution_path(url.pathname, base, app_dir);
|
|
147
153
|
} else if (is_data_request) {
|
|
148
154
|
url.pathname =
|
|
149
155
|
strip_data_suffix(url.pathname) +
|
|
@@ -174,31 +180,6 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
174
180
|
url
|
|
175
181
|
);
|
|
176
182
|
|
|
177
|
-
/** @type {RequestState} */
|
|
178
|
-
const event_state = {
|
|
179
|
-
prerendering: state.prerendering,
|
|
180
|
-
transport: options.hooks.transport,
|
|
181
|
-
handleValidationError: options.hooks.handleValidationError,
|
|
182
|
-
tracing: {
|
|
183
|
-
record_span
|
|
184
|
-
},
|
|
185
|
-
remote: {
|
|
186
|
-
data: null,
|
|
187
|
-
explicit: null,
|
|
188
|
-
implicit: null,
|
|
189
|
-
forms: null,
|
|
190
|
-
requested: null,
|
|
191
|
-
batches: null,
|
|
192
|
-
live_iterators: null
|
|
193
|
-
},
|
|
194
|
-
is_in_remote_function: false,
|
|
195
|
-
is_in_remote_form_or_command: false,
|
|
196
|
-
is_in_remote_query: false,
|
|
197
|
-
is_in_remote_prerender: false,
|
|
198
|
-
is_in_render: false,
|
|
199
|
-
is_in_universal_load: false
|
|
200
|
-
};
|
|
201
|
-
|
|
202
183
|
/** @type {import('@sveltejs/kit').RequestEvent} */
|
|
203
184
|
const event = {
|
|
204
185
|
cookies,
|
|
@@ -213,7 +194,12 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
213
194
|
}),
|
|
214
195
|
locals: {},
|
|
215
196
|
params: {},
|
|
216
|
-
platform: state.platform
|
|
197
|
+
platform: state.emulator?.platform
|
|
198
|
+
? await state.emulator.platform({
|
|
199
|
+
config: {},
|
|
200
|
+
prerender: !!state.prerendering?.fallback
|
|
201
|
+
})
|
|
202
|
+
: state.platform,
|
|
217
203
|
request,
|
|
218
204
|
route: { id: null },
|
|
219
205
|
setHeaders: (new_headers) => {
|
|
@@ -251,6 +237,7 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
251
237
|
isRemoteRequest: !!remote_id
|
|
252
238
|
};
|
|
253
239
|
|
|
240
|
+
// @ts-expect-error this has to be assigned lazily
|
|
254
241
|
event.fetch = create_fetch({
|
|
255
242
|
event,
|
|
256
243
|
options,
|
|
@@ -260,17 +247,11 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
260
247
|
set_internal
|
|
261
248
|
});
|
|
262
249
|
|
|
263
|
-
if (state.emulator?.platform) {
|
|
264
|
-
event.platform = await state.emulator.platform({
|
|
265
|
-
config: {},
|
|
266
|
-
prerender: !!state.prerendering?.fallback
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
|
|
270
250
|
/** @type {string | null} */
|
|
271
251
|
let resolved_path = url.pathname;
|
|
272
252
|
|
|
273
|
-
|
|
253
|
+
// `reroute` hooks receive pathnames, so they must not run for route-ID resolution requests
|
|
254
|
+
if (!remote_id && !is_route_id_resolution_request) {
|
|
274
255
|
const prerendering_reroute_state = state.prerendering?.inside_reroute;
|
|
275
256
|
try {
|
|
276
257
|
// For the duration or a reroute, disable the prerendering state as reroute could call API endpoints
|
|
@@ -339,7 +320,7 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
339
320
|
statusText: response.statusText
|
|
340
321
|
});
|
|
341
322
|
} catch (error) {
|
|
342
|
-
return await handle_fatal_error(event,
|
|
323
|
+
return await handle_fatal_error(event, state, options, error);
|
|
343
324
|
}
|
|
344
325
|
}
|
|
345
326
|
|
|
@@ -354,6 +335,14 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
354
335
|
}
|
|
355
336
|
|
|
356
337
|
if (is_route_resolution_request) {
|
|
338
|
+
if (is_route_id_resolution_request) {
|
|
339
|
+
return resolve_route_by_id(
|
|
340
|
+
extract_route_id(resolved_path, app_dir),
|
|
341
|
+
new URL(request.url),
|
|
342
|
+
manifest
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
|
|
357
346
|
return resolve_route(resolved_path, new URL(request.url), manifest);
|
|
358
347
|
}
|
|
359
348
|
|
|
@@ -375,11 +364,13 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
375
364
|
|
|
376
365
|
if (result) {
|
|
377
366
|
route = result.route;
|
|
367
|
+
// @ts-expect-error this has to be assigned lazily
|
|
378
368
|
event.route = { id: route.id };
|
|
369
|
+
// @ts-expect-error this has to be assigned lazily
|
|
379
370
|
event.params = result.params;
|
|
380
371
|
}
|
|
381
372
|
} catch (e) {
|
|
382
|
-
return await handle_fatal_error(event,
|
|
373
|
+
return await handle_fatal_error(event, state, options, e);
|
|
383
374
|
}
|
|
384
375
|
}
|
|
385
376
|
|
|
@@ -439,6 +430,7 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
439
430
|
}
|
|
440
431
|
|
|
441
432
|
if (state.emulator?.platform) {
|
|
433
|
+
// @ts-expect-error this has to be assigned lazily
|
|
442
434
|
event.platform = await state.emulator.platform({ config, prerender });
|
|
443
435
|
}
|
|
444
436
|
|
|
@@ -461,10 +453,10 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
461
453
|
add_cookies_to_headers(response.headers, new_cookies.values());
|
|
462
454
|
return response;
|
|
463
455
|
} catch (err) {
|
|
464
|
-
return await handle_fatal_error(event,
|
|
456
|
+
return await handle_fatal_error(event, state, options, err);
|
|
465
457
|
}
|
|
466
458
|
}
|
|
467
|
-
return await handle_fatal_error(event,
|
|
459
|
+
return await handle_fatal_error(event, state, options, e);
|
|
468
460
|
}
|
|
469
461
|
|
|
470
462
|
async function handle() {
|
|
@@ -493,7 +485,7 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
493
485
|
}
|
|
494
486
|
};
|
|
495
487
|
|
|
496
|
-
return await with_request_store({ event: traced_event, state
|
|
488
|
+
return await with_request_store({ event: traced_event, state }, () =>
|
|
497
489
|
options.hooks.handle({
|
|
498
490
|
event: traced_event,
|
|
499
491
|
resolve: (event, opts) => {
|
|
@@ -600,10 +592,9 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
600
592
|
if (resolved_path === null) {
|
|
601
593
|
return await respond_with_error({
|
|
602
594
|
event,
|
|
603
|
-
|
|
595
|
+
state,
|
|
604
596
|
options,
|
|
605
597
|
manifest,
|
|
606
|
-
state,
|
|
607
598
|
error: new SvelteKitError(
|
|
608
599
|
400,
|
|
609
600
|
'Malformed URI',
|
|
@@ -616,10 +607,9 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
616
607
|
if (options.hash_routing || state.prerendering?.fallback) {
|
|
617
608
|
return await render_response({
|
|
618
609
|
event,
|
|
619
|
-
|
|
610
|
+
state,
|
|
620
611
|
options,
|
|
621
612
|
manifest,
|
|
622
|
-
state,
|
|
623
613
|
page_config: { ssr: false, csr: true },
|
|
624
614
|
status: 200,
|
|
625
615
|
error: null,
|
|
@@ -633,12 +623,12 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
633
623
|
],
|
|
634
624
|
fetched: [],
|
|
635
625
|
resolve_opts,
|
|
636
|
-
data_serializer: server_data_serializer(event,
|
|
626
|
+
data_serializer: server_data_serializer(event, state, options)
|
|
637
627
|
});
|
|
638
628
|
}
|
|
639
629
|
|
|
640
630
|
if (remote_id) {
|
|
641
|
-
return await handle_remote_call(event,
|
|
631
|
+
return await handle_remote_call(event, state, options, manifest, remote_id);
|
|
642
632
|
}
|
|
643
633
|
|
|
644
634
|
if (route) {
|
|
@@ -650,11 +640,10 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
650
640
|
if (is_data_request) {
|
|
651
641
|
response = await render_data(
|
|
652
642
|
event,
|
|
653
|
-
|
|
643
|
+
state,
|
|
654
644
|
route,
|
|
655
645
|
options,
|
|
656
646
|
manifest,
|
|
657
|
-
state,
|
|
658
647
|
invalidated_data_nodes,
|
|
659
648
|
trailing_slash
|
|
660
649
|
);
|
|
@@ -679,18 +668,17 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
679
668
|
}
|
|
680
669
|
|
|
681
670
|
if (endpoint) {
|
|
682
|
-
response = await render_endpoint(event,
|
|
671
|
+
response = await render_endpoint(event, state, endpoint);
|
|
683
672
|
} else if (route.page) {
|
|
684
673
|
if (!page_nodes) {
|
|
685
674
|
throw new Error('page_nodes not found. This should never happen');
|
|
686
675
|
} else if (page_methods.has(method)) {
|
|
687
676
|
response = await render_page(
|
|
688
677
|
event,
|
|
689
|
-
|
|
678
|
+
state,
|
|
690
679
|
route.page,
|
|
691
680
|
options,
|
|
692
681
|
manifest,
|
|
693
|
-
state,
|
|
694
682
|
page_nodes,
|
|
695
683
|
resolve_opts
|
|
696
684
|
);
|
|
@@ -776,10 +764,9 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
776
764
|
|
|
777
765
|
return await respond_with_error({
|
|
778
766
|
event,
|
|
779
|
-
|
|
767
|
+
state,
|
|
780
768
|
options,
|
|
781
769
|
manifest,
|
|
782
|
-
state,
|
|
783
770
|
error: new SvelteKitError(404, 'Not Found', `Not found: ${event.url.pathname}`),
|
|
784
771
|
resolve_opts
|
|
785
772
|
});
|
|
@@ -800,12 +787,13 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
800
787
|
// and I don't even know how to describe it. need to investigate at some point
|
|
801
788
|
|
|
802
789
|
// HttpError from endpoint can end up here - TODO should it be handled there instead?
|
|
803
|
-
return await handle_fatal_error(event,
|
|
790
|
+
return await handle_fatal_error(event, state, options, e);
|
|
804
791
|
} finally {
|
|
805
792
|
event.cookies.set = () => {
|
|
806
793
|
throw new Error('Cannot use `cookies.set(...)` after the response has been generated');
|
|
807
794
|
};
|
|
808
795
|
|
|
796
|
+
// @ts-expect-error this has to be assigned lazily
|
|
809
797
|
event.setHeaders = () => {
|
|
810
798
|
throw new Error('Cannot use `setHeaders(...)` after the response has been generated');
|
|
811
799
|
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/** @import { InternalRequestOptions, RequestState, ServerHooks } from 'types' */
|
|
2
|
+
import { record_span } from '../telemetry/record_span.js';
|
|
3
|
+
|
|
4
|
+
/** Per-request caches and context flags — never carried into a fork. */
|
|
5
|
+
function transient_fields() {
|
|
6
|
+
return {
|
|
7
|
+
remote: {
|
|
8
|
+
data: null,
|
|
9
|
+
explicit: null,
|
|
10
|
+
implicit: null,
|
|
11
|
+
forms: null,
|
|
12
|
+
requested: null,
|
|
13
|
+
batches: null,
|
|
14
|
+
live_iterators: null
|
|
15
|
+
},
|
|
16
|
+
is_in_remote_function: false,
|
|
17
|
+
is_in_remote_form_or_command: false,
|
|
18
|
+
is_in_remote_query: false,
|
|
19
|
+
is_in_remote_prerender: false,
|
|
20
|
+
is_in_render: false,
|
|
21
|
+
original_event: undefined
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param {InternalRequestOptions} options
|
|
27
|
+
* @param {ServerHooks} hooks
|
|
28
|
+
* @returns {RequestState}
|
|
29
|
+
*/
|
|
30
|
+
export function create_request_state(options, hooks) {
|
|
31
|
+
// every field is initialized up front so the object shape stays stable
|
|
32
|
+
return {
|
|
33
|
+
getClientAddress: options.getClientAddress,
|
|
34
|
+
platform: options.platform,
|
|
35
|
+
read: options.read,
|
|
36
|
+
before_handle: options.before_handle,
|
|
37
|
+
emulator: options.emulator,
|
|
38
|
+
prerendering: options.prerendering,
|
|
39
|
+
prerender_default: undefined,
|
|
40
|
+
error: false,
|
|
41
|
+
depth: 0,
|
|
42
|
+
handleValidationError: hooks.handleValidationError,
|
|
43
|
+
tracing: {
|
|
44
|
+
record_span
|
|
45
|
+
},
|
|
46
|
+
...transient_fields()
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @param {RequestState} state
|
|
52
|
+
* @returns {RequestState}
|
|
53
|
+
*/
|
|
54
|
+
export function fork_state_for_subrequest(state) {
|
|
55
|
+
return {
|
|
56
|
+
...state,
|
|
57
|
+
...transient_fields(),
|
|
58
|
+
depth: state.depth + 1
|
|
59
|
+
};
|
|
60
|
+
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/** @import { ServerHooks } from 'types' */
|
|
2
|
-
import * as devalue from 'devalue';
|
|
3
1
|
import { text } from '@sveltejs/kit';
|
|
4
2
|
import { ENDPOINT_METHODS } from '../../constants.js';
|
|
5
3
|
|
|
@@ -139,21 +137,3 @@ export function get_node_type(node_id) {
|
|
|
139
137
|
export function count_non_ssi_comments(str) {
|
|
140
138
|
return (str.match(/<!--(?!#)/g) ?? []).length;
|
|
141
139
|
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Creates a serialiser for non-arbitrary POJOs using the app's transport hook
|
|
145
|
-
* @param {ServerHooks['transport']} transport
|
|
146
|
-
* @returns {(thing: unknown) => string | undefined}
|
|
147
|
-
*/
|
|
148
|
-
export function create_replacer(transport) {
|
|
149
|
-
/** @param {unknown} thing */
|
|
150
|
-
const replacer = (thing) => {
|
|
151
|
-
for (const key in transport) {
|
|
152
|
-
const encoded = transport[key].encode(thing);
|
|
153
|
-
if (encoded) {
|
|
154
|
-
return `app.decode('${key}', ${devalue.uneval(encoded, replacer)})`;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
return replacer;
|
|
159
|
-
}
|
package/src/runtime/shared.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
/** @import { Transport } from '@sveltejs/kit' */
|
|
2
1
|
import * as devalue from 'devalue';
|
|
3
|
-
import { base64_decode, base64_encode, text_encoder } from './utils.js';
|
|
2
|
+
import { base64_decode, base64_encode, text_decoder, text_encoder } from './utils.js';
|
|
3
|
+
import { decoders, encoders } from '#app/internal/transport';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @param {string} route_id
|
|
@@ -39,17 +39,6 @@ export function validate_load_response(data, location_description) {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
/**
|
|
43
|
-
* Try to `devalue.stringify` the data object using the provided transport encoders.
|
|
44
|
-
* @param {any} data
|
|
45
|
-
* @param {Transport} transport
|
|
46
|
-
*/
|
|
47
|
-
export function stringify(data, transport) {
|
|
48
|
-
const encoders = Object.fromEntries(Object.entries(transport).map(([k, v]) => [k, v.encode]));
|
|
49
|
-
|
|
50
|
-
return devalue.stringify(data, encoders);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
42
|
const object_proto_names = /* @__PURE__ */ Object.getOwnPropertyNames(Object.prototype)
|
|
54
43
|
.sort()
|
|
55
44
|
.join('\0');
|
|
@@ -102,11 +91,9 @@ const remote_regex_guard = '__skrag';
|
|
|
102
91
|
const remote_arg_marker = Symbol(remote_object);
|
|
103
92
|
|
|
104
93
|
/**
|
|
105
|
-
* @param {Transport} transport
|
|
106
94
|
* @param {boolean} sort
|
|
107
|
-
* @param {Map<any, any>} remote_arg_clones
|
|
108
95
|
*/
|
|
109
|
-
function create_remote_arg_reducers(
|
|
96
|
+
function create_remote_arg_reducers(sort) {
|
|
110
97
|
/** @type {Record<string, (value: unknown) => unknown>} */
|
|
111
98
|
const remote_fns_reducers = {
|
|
112
99
|
/** @param {unknown} value */
|
|
@@ -118,6 +105,8 @@ function create_remote_arg_reducers(transport, sort, remote_arg_clones) {
|
|
|
118
105
|
};
|
|
119
106
|
|
|
120
107
|
if (sort) {
|
|
108
|
+
const clones = new Map();
|
|
109
|
+
|
|
121
110
|
/** @type {(value: unknown) => Array<[unknown, unknown]> | undefined} */
|
|
122
111
|
remote_fns_reducers[remote_map] = (value) => {
|
|
123
112
|
if (!(value instanceof Map)) {
|
|
@@ -167,18 +156,15 @@ function create_remote_arg_reducers(transport, sort, remote_arg_clones) {
|
|
|
167
156
|
return;
|
|
168
157
|
}
|
|
169
158
|
|
|
170
|
-
if (
|
|
171
|
-
return
|
|
159
|
+
if (clones.has(value)) {
|
|
160
|
+
return clones.get(value);
|
|
172
161
|
}
|
|
173
162
|
|
|
174
|
-
return to_sorted(value,
|
|
163
|
+
return to_sorted(value, clones);
|
|
175
164
|
};
|
|
176
165
|
}
|
|
177
166
|
|
|
178
|
-
const
|
|
179
|
-
Object.entries(transport).map(([k, v]) => [k, v.encode])
|
|
180
|
-
);
|
|
181
|
-
const all_reducers = { ...user_reducers, ...remote_fns_reducers };
|
|
167
|
+
const all_reducers = { ...encoders, ...remote_fns_reducers };
|
|
182
168
|
|
|
183
169
|
/** @type {(value: unknown) => string} */
|
|
184
170
|
const stringify = (value) => devalue.stringify(value, all_reducers);
|
|
@@ -186,8 +172,7 @@ function create_remote_arg_reducers(transport, sort, remote_arg_clones) {
|
|
|
186
172
|
return all_reducers;
|
|
187
173
|
}
|
|
188
174
|
|
|
189
|
-
|
|
190
|
-
function create_remote_arg_revivers(transport) {
|
|
175
|
+
function create_remote_arg_revivers() {
|
|
191
176
|
const remote_fns_revivers = {
|
|
192
177
|
/** @type {(value: unknown) => unknown} */
|
|
193
178
|
[remote_object]: (value) => value,
|
|
@@ -251,11 +236,7 @@ function create_remote_arg_revivers(transport) {
|
|
|
251
236
|
}
|
|
252
237
|
};
|
|
253
238
|
|
|
254
|
-
const
|
|
255
|
-
Object.entries(transport).map(([k, v]) => [k, v.decode])
|
|
256
|
-
);
|
|
257
|
-
|
|
258
|
-
const all_revivers = { ...user_revivers, ...remote_fns_revivers };
|
|
239
|
+
const all_revivers = { ...decoders, ...remote_fns_revivers };
|
|
259
240
|
|
|
260
241
|
/** @type {(data: string) => unknown} */
|
|
261
242
|
const parse = (data) => devalue.parse(data, all_revivers);
|
|
@@ -267,13 +248,12 @@ function create_remote_arg_revivers(transport) {
|
|
|
267
248
|
* Stringifies the argument (if any) for a remote function in such a way that
|
|
268
249
|
* it is both a valid URL and a valid file name (necessary for prerendering).
|
|
269
250
|
* @param {any} value
|
|
270
|
-
* @param {Transport} transport
|
|
271
251
|
*/
|
|
272
|
-
export function stringify_remote_arg(value
|
|
252
|
+
export function stringify_remote_arg(value) {
|
|
273
253
|
if (value === undefined) return '';
|
|
274
254
|
|
|
275
255
|
// If people hit file/url size limits, we can look into using something like compress_and_encode_text from svelte.dev beyond a certain size
|
|
276
|
-
const json = devalue.stringify(value, create_remote_arg_reducers(
|
|
256
|
+
const json = devalue.stringify(value, create_remote_arg_reducers(true));
|
|
277
257
|
|
|
278
258
|
return url_friendly_base64_encode(json);
|
|
279
259
|
}
|
|
@@ -281,12 +261,11 @@ export function stringify_remote_arg(value, transport) {
|
|
|
281
261
|
/**
|
|
282
262
|
* Stringifies command arguments, including `File` objects.
|
|
283
263
|
* @param {any} value
|
|
284
|
-
* @param {Transport} transport
|
|
285
264
|
*/
|
|
286
|
-
export async function stringify_command_arg(value
|
|
265
|
+
export async function stringify_command_arg(value) {
|
|
287
266
|
if (value === undefined) return '';
|
|
288
267
|
|
|
289
|
-
const reducers = create_remote_arg_reducers(
|
|
268
|
+
const reducers = create_remote_arg_reducers(false);
|
|
290
269
|
|
|
291
270
|
/** @type {Set<Promise<any>>} */
|
|
292
271
|
const allowed_promises = new Set();
|
|
@@ -331,23 +310,24 @@ export async function stringify_command_arg(value, transport) {
|
|
|
331
310
|
*/
|
|
332
311
|
function url_friendly_base64_encode(string) {
|
|
333
312
|
const bytes = text_encoder.encode(string);
|
|
313
|
+
// TODO replace with `bytes.toBase64({ alphabet: 'base64url', omitPadding: true })` when we require Node >= 25
|
|
334
314
|
return base64_encode(bytes).replaceAll('=', '').replaceAll('+', '-').replaceAll('/', '_');
|
|
335
315
|
}
|
|
336
316
|
|
|
337
317
|
/**
|
|
338
318
|
* Parses the argument (if any) for a remote function
|
|
339
319
|
* @param {string} string
|
|
340
|
-
* @param {Transport} transport
|
|
341
320
|
*/
|
|
342
|
-
export function parse_remote_arg(string
|
|
321
|
+
export function parse_remote_arg(string) {
|
|
343
322
|
if (!string) return undefined;
|
|
344
323
|
|
|
345
|
-
const json_string =
|
|
324
|
+
const json_string = text_decoder.decode(
|
|
325
|
+
// TODO replace with `Uint8Array.fromBase64(string, { alphabet: 'base64url' })` when we require Node >= 25
|
|
346
326
|
// no need to add back `=` characters, atob can handle it
|
|
347
327
|
base64_decode(string.replaceAll('-', '+').replaceAll('_', '/'))
|
|
348
328
|
);
|
|
349
329
|
|
|
350
|
-
return devalue.parse(json_string, create_remote_arg_revivers(
|
|
330
|
+
return devalue.parse(json_string, create_remote_arg_revivers());
|
|
351
331
|
}
|
|
352
332
|
|
|
353
333
|
/**
|
package/src/runtime/utils.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BROWSER } from 'esm-env';
|
|
2
2
|
|
|
3
3
|
export const text_encoder = new TextEncoder();
|
|
4
|
+
export const text_decoder = new TextDecoder();
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Like node's path.relative, but without using node
|
|
@@ -28,6 +29,7 @@ export function get_relative_path(from, to) {
|
|
|
28
29
|
* @returns {string}
|
|
29
30
|
*/
|
|
30
31
|
export function base64_encode(bytes) {
|
|
32
|
+
// TODO replace with `bytes.toBase64()` when we require Node >= 25
|
|
31
33
|
// Using `Buffer` is faster than iterating
|
|
32
34
|
if (!BROWSER && globalThis.Buffer) {
|
|
33
35
|
return globalThis.Buffer.from(bytes).toString('base64');
|
|
@@ -47,6 +49,7 @@ export function base64_encode(bytes) {
|
|
|
47
49
|
* @returns {Uint8Array}
|
|
48
50
|
*/
|
|
49
51
|
export function base64_decode(encoded) {
|
|
52
|
+
// TODO replace with `Uint8Array.fromBase64(encoded)` when we require Node >= 25
|
|
50
53
|
// Using `Buffer` is faster than iterating
|
|
51
54
|
if (!BROWSER && globalThis.Buffer) {
|
|
52
55
|
const buffer = globalThis.Buffer.from(encoded, 'base64');
|
|
@@ -51,5 +51,5 @@ declare module '__sveltekit/manifest-data' {
|
|
|
51
51
|
export const immutable: Array<{ path: string }>;
|
|
52
52
|
export const assets: Array<{ path: string }>;
|
|
53
53
|
export const prerendered: Array<{ path: string }>;
|
|
54
|
-
export const routes: Array<{ id: string }>;
|
|
54
|
+
export const routes: Array<{ id: string; page: boolean; endpoint: boolean }>;
|
|
55
55
|
}
|
package/src/types/ambient.d.ts
CHANGED
|
@@ -78,9 +78,41 @@ declare module '$app/manifest' {
|
|
|
78
78
|
*/
|
|
79
79
|
export const prerendered: Array<{ path: import('$app/types').Path }>;
|
|
80
80
|
/**
|
|
81
|
-
*
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
* A route in your app, along with its capabilities. `page` indicates the presence of a `+page`,
|
|
82
|
+
* while `endpoint` indicates the presence of a `+server`. Both are `true` when both files exist.
|
|
83
|
+
*/
|
|
84
|
+
export type ManifestRoute =
|
|
85
|
+
| {
|
|
86
|
+
id: Exclude<import('$app/types').PageRouteId, import('$app/types').EndpointRouteId>;
|
|
87
|
+
page: true;
|
|
88
|
+
endpoint: false;
|
|
89
|
+
}
|
|
90
|
+
| {
|
|
91
|
+
id: Exclude<import('$app/types').EndpointRouteId, import('$app/types').PageRouteId>;
|
|
92
|
+
page: false;
|
|
93
|
+
endpoint: true;
|
|
94
|
+
}
|
|
95
|
+
| {
|
|
96
|
+
id: Extract<import('$app/types').PageRouteId, import('$app/types').EndpointRouteId>;
|
|
97
|
+
page: true;
|
|
98
|
+
endpoint: true;
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* An array of objects representing the routes in your app. Only routes that the router can match
|
|
102
|
+
* are included — directories that merely hold a `+layout` are not routes of their own.
|
|
103
|
+
*
|
|
104
|
+
* Each object has an `id`, plus `page` and `endpoint` booleans describing whether the route has a
|
|
105
|
+
* `+page` and/or a `+server`. Both are `true` for a route that has both, so the capabilities can
|
|
106
|
+
* be filtered independently:
|
|
107
|
+
*
|
|
108
|
+
* ```js
|
|
109
|
+
* import { routes } from '$app/manifest';
|
|
110
|
+
*
|
|
111
|
+
* const pages = routes.filter((route) => route.page);
|
|
112
|
+
* const endpoints = routes.filter((route) => route.endpoint);
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
export const routes: ManifestRoute[];
|
|
84
116
|
}
|
|
85
117
|
|
|
86
118
|
/**
|
|
@@ -94,6 +126,8 @@ declare module '$app/types' {
|
|
|
94
126
|
// These are all functions so that we can leverage function overloads to get the correct type.
|
|
95
127
|
// Using the return types directly would error with a "not the same type" error.
|
|
96
128
|
// https://www.typescriptlang.org/docs/handbook/declaration-merging.html#merging-interfaces
|
|
129
|
+
PageRouteId(): string;
|
|
130
|
+
EndpointRouteId(): string;
|
|
97
131
|
RouteId(): string;
|
|
98
132
|
RouteParams(): Record<string, Record<string, string>>;
|
|
99
133
|
LayoutParams(): Record<string, Record<string, string>>;
|
|
@@ -103,7 +137,21 @@ declare module '$app/types' {
|
|
|
103
137
|
}
|
|
104
138
|
|
|
105
139
|
/**
|
|
106
|
-
* A union of
|
|
140
|
+
* A union of the route IDs in your app that have a `+page`.
|
|
141
|
+
*
|
|
142
|
+
* A route ID can be in both `PageRouteId` and `EndpointRouteId`, if its directory contains both a `+page` and a `+server`.
|
|
143
|
+
*/
|
|
144
|
+
export type PageRouteId = ReturnType<AppTypes['PageRouteId']>;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* A union of the route IDs in your app that have a `+server`.
|
|
148
|
+
*
|
|
149
|
+
* A route ID can be in both `PageRouteId` and `EndpointRouteId`, if its directory contains both a `+page` and a `+server`.
|
|
150
|
+
*/
|
|
151
|
+
export type EndpointRouteId = ReturnType<AppTypes['EndpointRouteId']>;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* A union of all the route IDs in your app — the union of `PageRouteId` and `EndpointRouteId`. Used for `page.route.id` and `event.route.id`.
|
|
107
155
|
*/
|
|
108
156
|
export type RouteId = ReturnType<AppTypes['RouteId']>;
|
|
109
157
|
|
|
@@ -119,12 +167,15 @@ declare module '$app/types' {
|
|
|
119
167
|
? ReturnType<AppTypes['RouteParams']>[T]
|
|
120
168
|
: Record<string, never>;
|
|
121
169
|
|
|
170
|
+
/**
|
|
171
|
+
* The route IDs accepted by `LayoutParams`. Like `RouteId`, these preserve route groups and `[param]` syntax, but they identify directories containing layouts rather than matchable routes.
|
|
172
|
+
*/
|
|
173
|
+
type LayoutParamsId = keyof ReturnType<AppTypes['LayoutParams']>;
|
|
174
|
+
|
|
122
175
|
/**
|
|
123
176
|
* A utility for getting the parameters associated with a given layout, which is similar to `RouteParams` but also includes optional parameters for any child route.
|
|
124
177
|
*/
|
|
125
|
-
export type LayoutParams<T extends
|
|
126
|
-
? ReturnType<AppTypes['LayoutParams']>[T]
|
|
127
|
-
: Record<string, never>;
|
|
178
|
+
export type LayoutParams<T extends LayoutParamsId> = ReturnType<AppTypes['LayoutParams']>[T];
|
|
128
179
|
|
|
129
180
|
/**
|
|
130
181
|
* A union of all valid paths in your app, relative to the `base` path.
|
|
@@ -53,7 +53,7 @@ declare global {
|
|
|
53
53
|
const __SVELTEKIT_MANIFEST_IMMUTABLE__: string[];
|
|
54
54
|
const __SVELTEKIT_MANIFEST_ASSETS__: string[];
|
|
55
55
|
const __SVELTEKIT_MANIFEST_PRERENDERED__: string[];
|
|
56
|
-
const __SVELTEKIT_MANIFEST_ROUTES__: { id: string }
|
|
56
|
+
const __SVELTEKIT_MANIFEST_ROUTES__: Array<{ id: string }>;
|
|
57
57
|
/**
|
|
58
58
|
* This makes the use of specific features visible at both dev and build time, in such a
|
|
59
59
|
* way that we can error when they are not supported by the target platform.
|