@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,6 +1,6 @@
|
|
|
1
1
|
import { BROWSER, DEV } from 'esm-env';
|
|
2
2
|
import { noop } from '../../utils/functions.js';
|
|
3
|
-
import {
|
|
3
|
+
import { hash_request } from '../../utils/hash.js';
|
|
4
4
|
import { base64_decode } from '../utils.js';
|
|
5
5
|
|
|
6
6
|
let loading = 0;
|
|
@@ -172,18 +172,7 @@ function build_selector(resource, opts) {
|
|
|
172
172
|
return null;
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
|
|
176
|
-
const values = [];
|
|
177
|
-
|
|
178
|
-
if (opts.headers) {
|
|
179
|
-
values.push([...new Headers(opts.headers)].join(','));
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
if (body) {
|
|
183
|
-
values.push(/** @type {import('types').StrictBody} */ (body));
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
selector += `[data-hash="${hash(...values)}"]`;
|
|
175
|
+
selector += `[data-hash="${hash_request(opts.headers, body)}"]`;
|
|
187
176
|
}
|
|
188
177
|
|
|
189
178
|
return selector;
|
|
@@ -4,7 +4,7 @@ import { exec, parse_route_id } from '../../utils/routing.js';
|
|
|
4
4
|
* @param {import('./types.js').SvelteKitApp} app
|
|
5
5
|
* @returns {import('types').CSRRoute[]}
|
|
6
6
|
*/
|
|
7
|
-
export function
|
|
7
|
+
export function parse_routes({ nodes, server_loads, dictionary, matchers }) {
|
|
8
8
|
const layouts_with_server_load = new Set(server_loads);
|
|
9
9
|
|
|
10
10
|
return Object.entries(dictionary).map(([id, [leaf, layouts, errors]]) => {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/** @import { RemoteCommand, RemoteQueryUpdate } from '@sveltejs/kit' */
|
|
2
2
|
import { app_dir, base } from '$app/paths/internal/client';
|
|
3
|
-
import { app } from '../client.js';
|
|
4
3
|
import { stringify_command_arg } from '../../shared.js';
|
|
5
4
|
import { get_remote_request_headers, categorize_updates, remote_request } from './shared.svelte.js';
|
|
6
5
|
|
|
@@ -48,7 +47,7 @@ export function command(id) {
|
|
|
48
47
|
const response = await remote_request(`${base}/${app_dir}/remote/${id}`, {
|
|
49
48
|
method: 'POST',
|
|
50
49
|
body: JSON.stringify({
|
|
51
|
-
payload: await stringify_command_arg(arg
|
|
50
|
+
payload: await stringify_command_arg(arg),
|
|
52
51
|
refreshes: Array.from(refreshes ?? [])
|
|
53
52
|
}),
|
|
54
53
|
headers
|
|
@@ -262,13 +262,9 @@ export function form(id) {
|
|
|
262
262
|
|
|
263
263
|
if (response.redirect) {
|
|
264
264
|
// Use internal version to allow redirects to external URLs
|
|
265
|
-
void _goto(
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
refreshAll: should_refresh
|
|
269
|
-
},
|
|
270
|
-
0
|
|
271
|
-
);
|
|
265
|
+
void _goto(response.redirect, {
|
|
266
|
+
refreshAll: should_refresh
|
|
267
|
+
});
|
|
272
268
|
return true;
|
|
273
269
|
}
|
|
274
270
|
|
|
@@ -57,7 +57,7 @@ function put(url, encoded) {
|
|
|
57
57
|
*/
|
|
58
58
|
export function prerender(id) {
|
|
59
59
|
return (arg) => {
|
|
60
|
-
const payload = stringify_remote_arg(arg
|
|
60
|
+
const payload = stringify_remote_arg(arg);
|
|
61
61
|
const cache_key = create_remote_key(id, payload);
|
|
62
62
|
|
|
63
63
|
let resource = prerender_resources.get(cache_key)?.deref();
|
|
@@ -100,7 +100,7 @@ export function prerender(id) {
|
|
|
100
100
|
|
|
101
101
|
if (result.redirect) {
|
|
102
102
|
// Use internal version to allow redirects to external URLs
|
|
103
|
-
void _goto(result.redirect
|
|
103
|
+
void _goto(result.redirect);
|
|
104
104
|
return;
|
|
105
105
|
}
|
|
106
106
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { query_map } from '../../client.js';
|
|
2
2
|
import {
|
|
3
3
|
pin_in_effect,
|
|
4
4
|
pin_while_resolving,
|
|
@@ -29,7 +29,7 @@ export class QueryProxy {
|
|
|
29
29
|
*/
|
|
30
30
|
constructor(id, arg, fn) {
|
|
31
31
|
this.#id = id;
|
|
32
|
-
this.#payload = stringify_remote_arg(arg
|
|
32
|
+
this.#payload = stringify_remote_arg(arg);
|
|
33
33
|
this.#key = create_remote_key(id, this.#payload);
|
|
34
34
|
Object.defineProperty(this, QUERY_RESOURCE_KEY, { value: this.#key });
|
|
35
35
|
this.#fn = fn;
|
|
@@ -50,7 +50,7 @@ export function query_batch(id) {
|
|
|
50
50
|
|
|
51
51
|
if (response.redirect) {
|
|
52
52
|
// Use internal version to allow redirects to external URLs
|
|
53
|
-
await _goto(response.redirect
|
|
53
|
+
await _goto(response.redirect);
|
|
54
54
|
|
|
55
55
|
// settle all batched promises (with `undefined`, like a redirect
|
|
56
56
|
// from a non-batched query) so that callers don't hang forever
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { live_query_map } from '../../client.js';
|
|
2
2
|
import { pin_in_effect, pin_while_resolving, QUERY_RESOURCE_KEY } from '../shared.svelte.js';
|
|
3
3
|
import { create_remote_key, stringify_remote_arg } from '../../../shared.js';
|
|
4
4
|
import { LiveQuery } from './instance.svelte.js';
|
|
@@ -20,7 +20,7 @@ export class LiveQueryProxy {
|
|
|
20
20
|
*/
|
|
21
21
|
constructor(id, arg) {
|
|
22
22
|
this.#id = id;
|
|
23
|
-
this.#payload = stringify_remote_arg(arg
|
|
23
|
+
this.#payload = stringify_remote_arg(arg);
|
|
24
24
|
this.#key = create_remote_key(id, this.#payload);
|
|
25
25
|
Object.defineProperty(this, QUERY_RESOURCE_KEY, { value: this.#key });
|
|
26
26
|
|
|
@@ -74,16 +74,6 @@ export class LiveQueryProxy {
|
|
|
74
74
|
return this.#get_cached_query().done;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
/**
|
|
78
|
-
* @deprecated Use `for await (const value of liveQuery())` instead.
|
|
79
|
-
* @returns {AsyncGenerator<T>}
|
|
80
|
-
*/
|
|
81
|
-
run() {
|
|
82
|
-
throw new Error(
|
|
83
|
-
'`.run()` has been removed from live queries. Use `for await (const value of liveQuery())` instead.'
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
77
|
reconnect() {
|
|
88
78
|
return this.#get_cached_query().reconnect();
|
|
89
79
|
}
|
|
@@ -197,7 +197,7 @@ export async function remote_request(url, init) {
|
|
|
197
197
|
export async function handle_side_channel_response(response) {
|
|
198
198
|
if (response.type === 'redirect') {
|
|
199
199
|
// Use internal version to allow redirects to external URLs
|
|
200
|
-
await _goto(response.location
|
|
200
|
+
await _goto(response.location);
|
|
201
201
|
throw new Redirect(307, response.location);
|
|
202
202
|
}
|
|
203
203
|
|
|
@@ -122,6 +122,7 @@ export function get_link_info(a, base, uses_hash_router) {
|
|
|
122
122
|
/** @type {URL | undefined} */
|
|
123
123
|
let url;
|
|
124
124
|
|
|
125
|
+
// TODO replace the try/catch with `URL.parse` when browser support allows (Chrome 126, Firefox 126, Safari 18)
|
|
125
126
|
try {
|
|
126
127
|
url = new URL(a instanceof SVGAElement ? a.href.baseVal : a.href, document.baseURI);
|
|
127
128
|
|
|
@@ -3,12 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
import { DEV } from 'esm-env';
|
|
5
5
|
import * as devalue from 'devalue';
|
|
6
|
-
import { text_encoder } from './utils.js';
|
|
6
|
+
import { text_decoder, text_encoder } from './utils.js';
|
|
7
7
|
import { noop } from '../utils/functions.js';
|
|
8
8
|
import { SvelteKitError } from '@sveltejs/kit/internal';
|
|
9
9
|
|
|
10
|
-
const decoder = new TextDecoder();
|
|
11
|
-
|
|
12
10
|
/**
|
|
13
11
|
* Sets a parsed form field value in a nested object, mutating the original object.
|
|
14
12
|
* @param {Record<string, any>} object
|
|
@@ -283,7 +281,7 @@ export async function deserialize_binary_form(request, form_id) {
|
|
|
283
281
|
const file_offsets_buffer = await get_buffer(HEADER_BYTES + data_length, file_offsets_length);
|
|
284
282
|
if (!file_offsets_buffer) throw deserialize_error('file offset table too short');
|
|
285
283
|
|
|
286
|
-
const parsed_offsets = JSON.parse(
|
|
284
|
+
const parsed_offsets = JSON.parse(text_decoder.decode(file_offsets_buffer));
|
|
287
285
|
|
|
288
286
|
if (
|
|
289
287
|
!Array.isArray(parsed_offsets) ||
|
|
@@ -298,7 +296,7 @@ export async function deserialize_binary_form(request, form_id) {
|
|
|
298
296
|
|
|
299
297
|
/** @type {Array<{ offset: number, size: number }>} */
|
|
300
298
|
const file_spans = [];
|
|
301
|
-
const [data, meta] = devalue.parse(
|
|
299
|
+
const [data, meta] = devalue.parse(text_decoder.decode(data_buffer), {
|
|
302
300
|
File: ([name, type, size, last_modified, index]) => {
|
|
303
301
|
if (
|
|
304
302
|
typeof name !== 'string' ||
|
|
@@ -488,7 +486,7 @@ class LazyFile {
|
|
|
488
486
|
});
|
|
489
487
|
}
|
|
490
488
|
async text() {
|
|
491
|
-
return
|
|
489
|
+
return text_decoder.decode(await this.arrayBuffer());
|
|
492
490
|
}
|
|
493
491
|
}
|
|
494
492
|
|
package/src/runtime/pathname.js
CHANGED
|
@@ -22,13 +22,14 @@ export function strip_data_suffix(pathname) {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
const ROUTE_SUFFIX = '/__route.js';
|
|
25
|
+
const HTML_ROUTE_SUFFIX = '.html__route.js';
|
|
25
26
|
|
|
26
27
|
/**
|
|
27
28
|
* @param {string} pathname
|
|
28
29
|
* @returns {boolean}
|
|
29
30
|
*/
|
|
30
31
|
export function has_resolution_suffix(pathname) {
|
|
31
|
-
return pathname.endsWith(ROUTE_SUFFIX);
|
|
32
|
+
return pathname.endsWith(ROUTE_SUFFIX) || pathname.endsWith(HTML_ROUTE_SUFFIX);
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
/**
|
|
@@ -37,6 +38,7 @@ export function has_resolution_suffix(pathname) {
|
|
|
37
38
|
* @returns {string}
|
|
38
39
|
*/
|
|
39
40
|
export function add_resolution_suffix(pathname) {
|
|
41
|
+
if (pathname.endsWith('.html')) return pathname.replace(/\.html$/, HTML_ROUTE_SUFFIX);
|
|
40
42
|
return pathname.replace(/\/$/, '') + ROUTE_SUFFIX;
|
|
41
43
|
}
|
|
42
44
|
|
|
@@ -45,5 +47,46 @@ export function add_resolution_suffix(pathname) {
|
|
|
45
47
|
* @returns {string}
|
|
46
48
|
*/
|
|
47
49
|
export function strip_resolution_suffix(pathname) {
|
|
50
|
+
if (pathname.endsWith(HTML_ROUTE_SUFFIX)) {
|
|
51
|
+
return pathname.slice(0, -HTML_ROUTE_SUFFIX.length) + '.html';
|
|
52
|
+
}
|
|
53
|
+
|
|
48
54
|
return pathname.slice(0, -ROUTE_SUFFIX.length);
|
|
49
55
|
}
|
|
56
|
+
|
|
57
|
+
const ROUTES_PREFIX = '/routes';
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The pathname of the route-ID-keyed resolution module for a given route ID,
|
|
61
|
+
* e.g. `/_app/routes/blog/[slug]/__route.js` (before prefixing with `base`).
|
|
62
|
+
* @param {string} app_dir
|
|
63
|
+
* @param {string} route_id
|
|
64
|
+
* @returns {string}
|
|
65
|
+
*/
|
|
66
|
+
export function route_id_resolution_pathname(app_dir, route_id) {
|
|
67
|
+
return add_resolution_suffix(`/${app_dir}${ROUTES_PREFIX}${route_id === '/' ? '' : route_id}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Whether a pathname (with the `/__route.js` suffix already stripped, and `base` NOT yet stripped)
|
|
72
|
+
* is a route-ID resolution request rather than a pathname resolution request.
|
|
73
|
+
* @param {string} pathname
|
|
74
|
+
* @param {string} base
|
|
75
|
+
* @param {string} app_dir
|
|
76
|
+
* @returns {boolean}
|
|
77
|
+
*/
|
|
78
|
+
export function is_route_id_resolution_path(pathname, base, app_dir) {
|
|
79
|
+
const prefix = `${base}/${app_dir}${ROUTES_PREFIX}`;
|
|
80
|
+
return pathname === prefix || pathname.startsWith(prefix + '/');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Extract the route ID from a decoded, base-stripped, suffix-stripped pathname,
|
|
85
|
+
* e.g. `/_app/routes/blog/[slug]` -> `/blog/[slug]`, `/_app/routes` -> `/`.
|
|
86
|
+
* @param {string} pathname
|
|
87
|
+
* @param {string} app_dir
|
|
88
|
+
* @returns {string}
|
|
89
|
+
*/
|
|
90
|
+
export function extract_route_id(pathname, app_dir) {
|
|
91
|
+
return pathname.slice(`/${app_dir}${ROUTES_PREFIX}`.length) || '/';
|
|
92
|
+
}
|
|
@@ -11,22 +11,20 @@ import { with_version_header } from '../utils.js';
|
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* @param {import('@sveltejs/kit').RequestEvent} event
|
|
14
|
-
* @param {import('types').RequestState}
|
|
14
|
+
* @param {import('types').RequestState} state
|
|
15
15
|
* @param {import('types').SSRRoute} route
|
|
16
16
|
* @param {import('types').SSROptions} options
|
|
17
17
|
* @param {import('@sveltejs/kit').SSRManifest} manifest
|
|
18
|
-
* @param {import('types').SSRState} state
|
|
19
18
|
* @param {boolean[] | undefined} invalidated_data_nodes
|
|
20
19
|
* @param {import('types').TrailingSlash} trailing_slash
|
|
21
20
|
* @returns {Promise<Response>}
|
|
22
21
|
*/
|
|
23
22
|
export async function render_data(
|
|
24
23
|
event,
|
|
25
|
-
|
|
24
|
+
state,
|
|
26
25
|
route,
|
|
27
26
|
options,
|
|
28
27
|
manifest,
|
|
29
|
-
state,
|
|
30
28
|
invalidated_data_nodes,
|
|
31
29
|
trailing_slash
|
|
32
30
|
) {
|
|
@@ -60,7 +58,6 @@ export async function render_data(
|
|
|
60
58
|
// load this. for the child, return as is. for the final result, stream things
|
|
61
59
|
return load_server_data({
|
|
62
60
|
event: new_event,
|
|
63
|
-
event_state,
|
|
64
61
|
state,
|
|
65
62
|
node,
|
|
66
63
|
parent: async () => {
|
|
@@ -95,7 +92,7 @@ export async function render_data(
|
|
|
95
92
|
return fn();
|
|
96
93
|
});
|
|
97
94
|
|
|
98
|
-
const data_serializer = server_data_serializer_json(event,
|
|
95
|
+
const data_serializer = server_data_serializer_json(event, state, options);
|
|
99
96
|
await Promise.all(
|
|
100
97
|
promises.map(async (p, i) => {
|
|
101
98
|
const node = await p.catch(async (error) => {
|
|
@@ -103,7 +100,7 @@ export async function render_data(
|
|
|
103
100
|
throw error;
|
|
104
101
|
}
|
|
105
102
|
|
|
106
|
-
const transformed = await handle_error_and_jsonify(event,
|
|
103
|
+
const transformed = await handle_error_and_jsonify(event, state, options, error);
|
|
107
104
|
|
|
108
105
|
return /** @type {import('types').ServerErrorNode} */ ({
|
|
109
106
|
type: 'error',
|
|
@@ -151,7 +148,7 @@ export async function render_data(
|
|
|
151
148
|
if (error instanceof Redirect) {
|
|
152
149
|
return redirect_json_response(error);
|
|
153
150
|
} else {
|
|
154
|
-
const transformed = await handle_error_and_jsonify(event,
|
|
151
|
+
const transformed = await handle_error_and_jsonify(event, state, options, error);
|
|
155
152
|
return json_response(transformed, transformed.status);
|
|
156
153
|
}
|
|
157
154
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const symbol = Symbol.for('sveltekit.global_state');
|
|
2
|
+
const state = /** @type {Record<symbol, any>} */ (
|
|
3
|
+
/** @type {Record<symbol, unknown>} */ (/** @type {unknown} */ (globalThis))[symbol] ??= {}
|
|
4
|
+
);
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Persist a value across dev server reloads, in case a freshly-invalidated module
|
|
8
|
+
* reads global state that is not set until a request is handled
|
|
9
|
+
* @param {symbol} key
|
|
10
|
+
* @param {any} value
|
|
11
|
+
*/
|
|
12
|
+
export function save(key, value) {
|
|
13
|
+
state[key] = value;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Restore a value after a dev server reload
|
|
18
|
+
* @param {symbol} key
|
|
19
|
+
*/
|
|
20
|
+
export function restore(key) {
|
|
21
|
+
return state[key];
|
|
22
|
+
}
|
|
@@ -6,12 +6,11 @@ import { method_not_allowed } from './utils.js';
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* @param {import('@sveltejs/kit').RequestEvent} event
|
|
9
|
-
* @param {import('types').RequestState}
|
|
9
|
+
* @param {import('types').RequestState} state
|
|
10
10
|
* @param {import('types').SSREndpoint} mod
|
|
11
|
-
* @param {import('types').SSRState} state
|
|
12
11
|
* @returns {Promise<Response>}
|
|
13
12
|
*/
|
|
14
|
-
export async function render_endpoint(event,
|
|
13
|
+
export async function render_endpoint(event, state, mod) {
|
|
15
14
|
const method = /** @type {import('types').HttpMethod} */ (event.request.method);
|
|
16
15
|
|
|
17
16
|
let handler = mod[method] || mod.fallback;
|
|
@@ -42,7 +41,7 @@ export async function render_endpoint(event, event_state, mod, state) {
|
|
|
42
41
|
}
|
|
43
42
|
|
|
44
43
|
try {
|
|
45
|
-
const response = await with_request_store({ event, state
|
|
44
|
+
const response = await with_request_store({ event, state }, () =>
|
|
46
45
|
handler(/** @type {import('@sveltejs/kit').RequestEvent<Record<string, any>>} */ (event))
|
|
47
46
|
);
|
|
48
47
|
|
|
@@ -4,13 +4,14 @@ import { respond } from './respond.js';
|
|
|
4
4
|
import * as paths from '$app/paths/internal/server';
|
|
5
5
|
import { read_implementation } from './internal.js';
|
|
6
6
|
import { has_prerendered_path } from './utils.js';
|
|
7
|
+
import { fork_state_for_subrequest } from './state.js';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* @param {{
|
|
10
11
|
* event: import('@sveltejs/kit').RequestEvent;
|
|
11
12
|
* options: import('types').SSROptions;
|
|
12
13
|
* manifest: import('@sveltejs/kit').SSRManifest;
|
|
13
|
-
* state: import('types').
|
|
14
|
+
* state: import('types').RequestState;
|
|
14
15
|
* get_cookie_header: (url: URL, header: string | null) => string;
|
|
15
16
|
* set_internal: (name: string, value: string, opts: import('./page/types.js').Cookie['options']) => void;
|
|
16
17
|
* }} opts
|
|
@@ -194,38 +195,32 @@ function normalize_fetch_input(info, init, url) {
|
|
|
194
195
|
* @param {Request} request
|
|
195
196
|
* @param {import('types').SSROptions} options
|
|
196
197
|
* @param {import('@sveltejs/kit').SSRManifest} manifest
|
|
197
|
-
* @param {import('types').
|
|
198
|
+
* @param {import('types').RequestState} state
|
|
198
199
|
* @returns {Promise<Response>}
|
|
199
200
|
*/
|
|
200
201
|
async function internal_fetch(request, options, manifest, state) {
|
|
201
|
-
if (request.signal) {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
let remove_abort_listener = noop;
|
|
207
|
-
/** @type {Promise<never>} */
|
|
208
|
-
const abort_promise = new Promise((_, reject) => {
|
|
209
|
-
const on_abort = () => {
|
|
210
|
-
reject(new DOMException('The operation was aborted.', 'AbortError'));
|
|
211
|
-
};
|
|
212
|
-
request.signal.addEventListener('abort', on_abort, { once: true });
|
|
213
|
-
remove_abort_listener = () => request.signal.removeEventListener('abort', on_abort);
|
|
214
|
-
});
|
|
202
|
+
if (request.signal?.aborted) {
|
|
203
|
+
throw new DOMException('The operation was aborted.', 'AbortError');
|
|
204
|
+
}
|
|
215
205
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
}),
|
|
221
|
-
abort_promise
|
|
222
|
-
]);
|
|
223
|
-
remove_abort_listener();
|
|
224
|
-
return result;
|
|
225
|
-
} else {
|
|
226
|
-
return await respond(request, options, manifest, {
|
|
227
|
-
...state,
|
|
228
|
-
depth: state.depth + 1
|
|
229
|
-
});
|
|
206
|
+
const subrequest_state = fork_state_for_subrequest(state);
|
|
207
|
+
|
|
208
|
+
if (!request.signal) {
|
|
209
|
+
return await respond(request, options, manifest, subrequest_state);
|
|
230
210
|
}
|
|
211
|
+
|
|
212
|
+
let remove_abort_listener = noop;
|
|
213
|
+
/** @type {Promise<never>} */
|
|
214
|
+
const abort_promise = new Promise((_, reject) => {
|
|
215
|
+
const on_abort = () => {
|
|
216
|
+
reject(new DOMException('The operation was aborted.', 'AbortError'));
|
|
217
|
+
};
|
|
218
|
+
request.signal.addEventListener('abort', on_abort, { once: true });
|
|
219
|
+
remove_abort_listener = () => request.signal.removeEventListener('abort', on_abort);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
return Promise.race([
|
|
223
|
+
respond(request, options, manifest, subrequest_state),
|
|
224
|
+
abort_promise
|
|
225
|
+
]).finally(remove_abort_listener);
|
|
231
226
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { noop } from '../../utils/functions.js';
|
|
2
2
|
import { IN_WEBCONTAINER } from './constants.js';
|
|
3
3
|
import { respond } from './respond.js';
|
|
4
|
+
import { create_request_state } from './state.js';
|
|
4
5
|
import { options, get_hooks } from '__SERVER__/internal.js';
|
|
5
|
-
import { set_read_implementation, set_manifest } from './internal.js';
|
|
6
|
+
import { set_read_implementation, set_manifest, fix_stack_trace } from './internal.js';
|
|
6
7
|
import { set_env } from '__sveltekit/env';
|
|
7
|
-
import { set_app } from './app.js';
|
|
8
8
|
import { SvelteKitError } from '@sveltejs/kit/internal';
|
|
9
|
+
import { DEV } from 'esm-env';
|
|
10
|
+
import { init_transport } from '#app/internal/transport';
|
|
9
11
|
|
|
10
12
|
/** @type {Promise<any>} */
|
|
11
13
|
let init_promise;
|
|
@@ -13,6 +15,38 @@ let init_promise;
|
|
|
13
15
|
/** @type {Promise<void> | null} */
|
|
14
16
|
let current = null;
|
|
15
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Responses that were created with our monkey-patched `fetch`, which may need
|
|
20
|
+
* to have their `content-encoding` and `content-length` headers removed
|
|
21
|
+
* if returned directly (i.e. `fetch` is being used to proxy a request)
|
|
22
|
+
* @type {WeakMap<Response, Error>}
|
|
23
|
+
*/
|
|
24
|
+
const decoded_responses = new WeakMap();
|
|
25
|
+
|
|
26
|
+
if (DEV) {
|
|
27
|
+
const fetch = globalThis.fetch;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {RequestInfo | URL} info
|
|
31
|
+
* @param {RequestInit} [init]
|
|
32
|
+
*/
|
|
33
|
+
globalThis.fetch = async (info, init) => {
|
|
34
|
+
const response = await fetch(info, init);
|
|
35
|
+
const encoding = response.headers.get('content-encoding');
|
|
36
|
+
|
|
37
|
+
if (encoding) {
|
|
38
|
+
decoded_responses.set(
|
|
39
|
+
response,
|
|
40
|
+
new Error(
|
|
41
|
+
`Cannot return \`fetch(...)\` directly from a handler if the response has a \`Content-Encoding: ${encoding}\` header. The body has already been decoded`
|
|
42
|
+
)
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return response;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
16
50
|
export class Server {
|
|
17
51
|
/** @type {import('types').SSROptions} */
|
|
18
52
|
#options;
|
|
@@ -67,31 +101,17 @@ export class Server {
|
|
|
67
101
|
const result = read(file);
|
|
68
102
|
if (result instanceof ReadableStream) {
|
|
69
103
|
return result;
|
|
70
|
-
} else {
|
|
71
|
-
return new ReadableStream({
|
|
72
|
-
async start(controller) {
|
|
73
|
-
try {
|
|
74
|
-
const stream = await Promise.resolve(result);
|
|
75
|
-
if (!stream) {
|
|
76
|
-
controller.close();
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const reader = stream.getReader();
|
|
81
|
-
|
|
82
|
-
while (true) {
|
|
83
|
-
const { done, value } = await reader.read();
|
|
84
|
-
if (done) break;
|
|
85
|
-
controller.enqueue(value);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
controller.close();
|
|
89
|
-
} catch (error) {
|
|
90
|
-
controller.error(error);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
104
|
}
|
|
105
|
+
|
|
106
|
+
// TODO remove the cast once TypeScript's lib includes `ReadableStream.from`
|
|
107
|
+
return /** @type {ReadableStream} */ (
|
|
108
|
+
/** @type {any} */ (ReadableStream).from(
|
|
109
|
+
(async function* () {
|
|
110
|
+
const stream = await result;
|
|
111
|
+
if (stream) yield* stream;
|
|
112
|
+
})()
|
|
113
|
+
)
|
|
114
|
+
);
|
|
95
115
|
};
|
|
96
116
|
|
|
97
117
|
set_read_implementation(wrapped_read);
|
|
@@ -132,15 +152,10 @@ export class Server {
|
|
|
132
152
|
console.error('Remote function schema validation failed:', issues);
|
|
133
153
|
return { message: 'Bad Request', status: 400 };
|
|
134
154
|
}),
|
|
135
|
-
reroute: module.reroute || noop
|
|
136
|
-
transport: module.transport || {}
|
|
155
|
+
reroute: module.reroute || noop
|
|
137
156
|
};
|
|
138
157
|
|
|
139
|
-
|
|
140
|
-
decoders: module.transport
|
|
141
|
-
? Object.fromEntries(Object.entries(module.transport).map(([k, v]) => [k, v.decode]))
|
|
142
|
-
: {}
|
|
143
|
-
});
|
|
158
|
+
init_transport(module.transport ?? {});
|
|
144
159
|
|
|
145
160
|
if (module.init) {
|
|
146
161
|
await module.init();
|
|
@@ -156,13 +171,8 @@ export class Server {
|
|
|
156
171
|
handleValidationError: () => {
|
|
157
172
|
return { message: 'Bad Request' };
|
|
158
173
|
},
|
|
159
|
-
reroute: noop
|
|
160
|
-
transport: {}
|
|
174
|
+
reroute: noop
|
|
161
175
|
};
|
|
162
|
-
|
|
163
|
-
set_app({
|
|
164
|
-
decoders: {}
|
|
165
|
-
});
|
|
166
176
|
} else {
|
|
167
177
|
throw e;
|
|
168
178
|
}
|
|
@@ -172,13 +182,21 @@ export class Server {
|
|
|
172
182
|
|
|
173
183
|
/**
|
|
174
184
|
* @param {Request} request
|
|
175
|
-
* @param {import('types').
|
|
185
|
+
* @param {import('types').InternalRequestOptions} options
|
|
176
186
|
*/
|
|
177
|
-
respond(request, options) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
187
|
+
async respond(request, options) {
|
|
188
|
+
const response = await respond(
|
|
189
|
+
request,
|
|
190
|
+
this.#options,
|
|
191
|
+
this.#manifest,
|
|
192
|
+
create_request_state(options, this.#options.hooks)
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
if (DEV) {
|
|
196
|
+
const error = decoded_responses.get(response);
|
|
197
|
+
if (error) console.error(fix_stack_trace(error));
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return response;
|
|
183
201
|
}
|
|
184
202
|
}
|
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
/** @import { SSRManifest } from '@sveltejs/kit'; */
|
|
2
|
+
import { restore, save } from './dev.js';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export let read_implementation = null
|
|
4
|
+
const read_implementation_key = Symbol.for('sveltekit.read_implementation');
|
|
5
|
+
const manifest_key = Symbol.for('sveltekit.manifest');
|
|
6
|
+
|
|
7
|
+
export let read_implementation = /** @type {((path: string) => ReadableStream<any>) | null} */ (
|
|
8
|
+
(__SVELTEKIT_DEV__ && restore(read_implementation_key)) ?? null
|
|
9
|
+
);
|
|
7
10
|
|
|
8
|
-
export let manifest = /** @type {SSRManifest} */ (
|
|
11
|
+
export let manifest = /** @type {SSRManifest} */ (
|
|
12
|
+
(__SVELTEKIT_DEV__ && restore(manifest_key)) ?? null
|
|
13
|
+
);
|
|
9
14
|
|
|
10
15
|
/**
|
|
11
16
|
* @param {(path: string) => ReadableStream<any>} fn
|
|
12
17
|
*/
|
|
13
18
|
export function set_read_implementation(fn) {
|
|
14
19
|
read_implementation = fn;
|
|
20
|
+
if (__SVELTEKIT_DEV__) save(read_implementation_key, fn);
|
|
15
21
|
}
|
|
16
22
|
|
|
17
23
|
/**
|
|
@@ -20,6 +26,7 @@ export function set_read_implementation(fn) {
|
|
|
20
26
|
*/
|
|
21
27
|
export function set_manifest(value) {
|
|
22
28
|
manifest = value;
|
|
29
|
+
if (__SVELTEKIT_DEV__) save(manifest_key, value);
|
|
23
30
|
}
|
|
24
31
|
|
|
25
32
|
export { fix_stack_trace, set_fix_stack_trace } from './sourcemaps.js';
|