@sveltejs/kit 3.0.0-next.1 → 3.0.0-next.11
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/constants.js +2 -0
- package/src/core/adapt/builder.js +32 -49
- package/src/core/adapt/index.js +1 -4
- package/src/core/config/index.js +137 -71
- package/src/core/config/options.js +236 -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/fallback.js +2 -1
- package/src/core/postbuild/prerender.js +114 -48
- package/src/core/postbuild/queue.js +2 -1
- 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 +14 -15
- 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 +30 -5
- package/src/exports/env/index.js +77 -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 +8 -5
- 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 +68 -0
- package/src/exports/public.d.ts +363 -189
- 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 +92 -50
- package/src/exports/vite/index.js +903 -681
- package/src/exports/vite/module_ids.js +0 -2
- package/src/exports/vite/preview/index.js +32 -24
- 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 +40 -35
- 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 +3 -3
- 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 +10 -6
- package/src/runtime/app/server/index.js +1 -1
- 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 +39 -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 +15 -19
- package/src/runtime/server/env_module.js +0 -5
- package/src/runtime/server/errors.js +135 -0
- package/src/runtime/server/fetch.js +1 -1
- package/src/runtime/server/index.js +22 -12
- package/src/runtime/server/internal.js +25 -0
- package/src/runtime/server/page/actions.js +43 -27
- package/src/runtime/server/page/data_serializer.js +10 -10
- package/src/runtime/server/page/index.js +12 -17
- package/src/runtime/server/page/load_data.js +2 -2
- package/src/runtime/server/page/render.js +114 -193
- package/src/runtime/server/page/respond_with_error.js +11 -11
- package/src/runtime/server/page/server_routing.js +27 -18
- package/src/runtime/server/remote-functions.js +596 -0
- package/src/runtime/server/respond.js +100 -68
- package/src/runtime/server/sourcemaps.js +183 -0
- package/src/runtime/server/utils.js +2 -134
- 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-private.d.ts +2 -0
- package/src/types/ambient.d.ts +10 -5
- package/src/types/global-private.d.ts +13 -25
- package/src/types/internal.d.ts +95 -80
- package/src/types/private.d.ts +41 -1
- package/src/utils/error.js +24 -4
- package/src/utils/escape.js +9 -25
- package/src/utils/features.js +1 -1
- package/src/utils/fork.js +7 -2
- package/src/utils/import.js +6 -1
- package/src/utils/imports.js +83 -0
- package/src/utils/mime.js +9 -0
- package/src/utils/page_nodes.js +3 -5
- 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 +537 -557
- package/types/index.d.ts.map +24 -39
- package/src/core/sync/write_root.js +0 -148
- package/src/exports/internal/server.js +0 -22
- package/src/runtime/server/remote.js +0 -457
- package/src/runtime/shared-server.js +0 -7
- package/src/types/synthetic/$lib.md +0 -5
- /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
/** @import { RenderNode } from '../../types.js' */
|
|
1
2
|
import * as devalue from 'devalue';
|
|
2
|
-
import { readable, writable } from 'svelte/store';
|
|
3
3
|
import { DEV } from 'esm-env';
|
|
4
4
|
import { isRedirect, text } from '@sveltejs/kit';
|
|
5
5
|
import * as paths from '$app/paths/internal/server';
|
|
@@ -11,26 +11,18 @@ import { uneval_action_response } from './actions.js';
|
|
|
11
11
|
import { SVELTE_KIT_ASSETS } from '../../../constants.js';
|
|
12
12
|
import { SCHEME } from '../../../utils/url.js';
|
|
13
13
|
import { create_server_routing_response, generate_route_object } from './server_routing.js';
|
|
14
|
-
import { add_resolution_suffix } from '../../pathname.js';
|
|
14
|
+
import { add_data_suffix, add_resolution_suffix } from '../../pathname.js';
|
|
15
15
|
import { try_get_request_store, with_request_store } from '@sveltejs/kit/internal/server';
|
|
16
16
|
import { text_encoder } from '../../utils.js';
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
create_replacer,
|
|
20
|
-
get_global_name,
|
|
21
|
-
handle_error_and_jsonify
|
|
22
|
-
} from '../utils.js';
|
|
23
|
-
import { create_remote_key } from '../../shared.js';
|
|
24
|
-
import { get_status } from '../../../utils/error.js';
|
|
17
|
+
import { count_non_ssi_comments, create_replacer, get_global_name } from '../utils.js';
|
|
18
|
+
import { handle_error_and_jsonify } from '../errors.js';
|
|
25
19
|
import * as env from '__sveltekit/env';
|
|
20
|
+
import { collect_remote_data } from '../remote-functions.js';
|
|
21
|
+
import Root from '../../components/root.svelte';
|
|
22
|
+
import { render } from 'svelte/server';
|
|
26
23
|
|
|
27
24
|
// TODO rename this function/module
|
|
28
25
|
|
|
29
|
-
const updated = {
|
|
30
|
-
...readable(false),
|
|
31
|
-
check: () => false
|
|
32
|
-
};
|
|
33
|
-
|
|
34
26
|
/**
|
|
35
27
|
* Creates the HTML response.
|
|
36
28
|
* @param {{
|
|
@@ -47,7 +39,7 @@ const updated = {
|
|
|
47
39
|
* resolve_opts: import('types').RequiredResolveOptions;
|
|
48
40
|
* action_result?: import('@sveltejs/kit').ActionResult;
|
|
49
41
|
* data_serializer: import('./types.js').ServerDataSerializer;
|
|
50
|
-
* error_components?: Array<import('
|
|
42
|
+
* error_components?: Array<import('svelte').Component | undefined>
|
|
51
43
|
* }} opts
|
|
52
44
|
*/
|
|
53
45
|
export async function render_response({
|
|
@@ -68,7 +60,7 @@ export async function render_response({
|
|
|
68
60
|
}) {
|
|
69
61
|
if (state.prerendering) {
|
|
70
62
|
if (options.csp.mode === 'nonce') {
|
|
71
|
-
throw new Error('Cannot use prerendering if config.
|
|
63
|
+
throw new Error('Cannot use prerendering if config.csp.mode === "nonce"');
|
|
72
64
|
}
|
|
73
65
|
|
|
74
66
|
if (options.app_template_contains_nonce) {
|
|
@@ -78,9 +70,9 @@ export async function render_response({
|
|
|
78
70
|
|
|
79
71
|
const { client } = manifest._;
|
|
80
72
|
|
|
81
|
-
const modulepreloads = new Set(client
|
|
82
|
-
const stylesheets = new Set(client
|
|
83
|
-
const fonts = new Set(client
|
|
73
|
+
const modulepreloads = new Set(client?.imports);
|
|
74
|
+
const stylesheets = new Set(client?.stylesheets);
|
|
75
|
+
const fonts = new Set(client?.fonts);
|
|
84
76
|
|
|
85
77
|
/**
|
|
86
78
|
* The value of the Link header that is added to the response when not prerendering
|
|
@@ -92,7 +84,8 @@ export async function render_response({
|
|
|
92
84
|
// TODO if we add a client entry point one day, we will need to include inline_styles with the entry, otherwise stylesheets will be linked even if they are below inlineStyleThreshold
|
|
93
85
|
const inline_styles = new Map();
|
|
94
86
|
|
|
95
|
-
|
|
87
|
+
// TODO `svelte/server` should expose `RenderOutput`
|
|
88
|
+
/** @type {{ head: string, body: string, hashes: { script: string[] } }} */
|
|
96
89
|
let rendered;
|
|
97
90
|
|
|
98
91
|
const form_value =
|
|
@@ -119,7 +112,12 @@ export async function render_response({
|
|
|
119
112
|
// if appropriate, use relative paths for greater portability
|
|
120
113
|
if (paths.relative) {
|
|
121
114
|
if (!state.prerendering?.fallback) {
|
|
122
|
-
|
|
115
|
+
// the relative path depth must reflect the URL the browser is actually at, which
|
|
116
|
+
// for a data request includes the `__data.json` suffix that was stripped during routing
|
|
117
|
+
const pathname = event.isDataRequest
|
|
118
|
+
? add_data_suffix(event.url.pathname)
|
|
119
|
+
: event.url.pathname;
|
|
120
|
+
const segments = pathname.slice(paths.base.length).split('/').slice(2);
|
|
123
121
|
|
|
124
122
|
base = segments.map(() => '..').join('/') || '.';
|
|
125
123
|
|
|
@@ -138,49 +136,47 @@ export async function render_response({
|
|
|
138
136
|
if (page_config.ssr) {
|
|
139
137
|
/** @type {Record<string, any>} */
|
|
140
138
|
const props = {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
form: form_value
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
if (error_components) {
|
|
159
|
-
if (error) {
|
|
160
|
-
props.error = error;
|
|
139
|
+
components: [],
|
|
140
|
+
resetters: [],
|
|
141
|
+
form: form_value,
|
|
142
|
+
tree: /** @type {RenderNode} */ ({}),
|
|
143
|
+
error,
|
|
144
|
+
page: {
|
|
145
|
+
error,
|
|
146
|
+
params: /** @type {Record<string, any>} */ (event.params),
|
|
147
|
+
route: event.route,
|
|
148
|
+
status,
|
|
149
|
+
url: event.url,
|
|
150
|
+
data: {},
|
|
151
|
+
form: form_value,
|
|
152
|
+
state: {}
|
|
161
153
|
}
|
|
162
|
-
|
|
163
|
-
}
|
|
154
|
+
};
|
|
164
155
|
|
|
165
|
-
let
|
|
156
|
+
let current_node = props.tree;
|
|
157
|
+
let data = props.page.data;
|
|
166
158
|
|
|
167
|
-
// props_n (instead of props[n]) makes it easy to avoid
|
|
168
|
-
// unnecessary updates for layout components
|
|
169
159
|
for (let i = 0; i < branch.length; i += 1) {
|
|
170
|
-
|
|
171
|
-
|
|
160
|
+
const node = branch[i];
|
|
161
|
+
|
|
162
|
+
data = { ...data, ...node.data };
|
|
163
|
+
|
|
164
|
+
// TODO this is undefined sometimes... where does the default error component come from?
|
|
165
|
+
const error = error_components?.slice(0, i + 1).findLast((x) => x);
|
|
166
|
+
|
|
167
|
+
current_node.error = error;
|
|
168
|
+
current_node.component = await node.node.component?.();
|
|
169
|
+
current_node.data = data;
|
|
170
|
+
|
|
171
|
+
if (i < branch.length - 1) {
|
|
172
|
+
current_node.child = /** @type {import('../../types.js').RenderNode} */ ({});
|
|
173
|
+
current_node = current_node.child;
|
|
174
|
+
}
|
|
172
175
|
}
|
|
173
176
|
|
|
174
|
-
props.page =
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
route: event.route,
|
|
178
|
-
status,
|
|
179
|
-
url: event.url,
|
|
180
|
-
data,
|
|
181
|
-
form: form_value,
|
|
182
|
-
state: {}
|
|
183
|
-
};
|
|
177
|
+
props.page.data = data;
|
|
178
|
+
|
|
179
|
+
const render_state = { ...event_state, is_in_render: true };
|
|
184
180
|
|
|
185
181
|
const render_opts = {
|
|
186
182
|
context: new Map([
|
|
@@ -193,15 +189,28 @@ export async function render_response({
|
|
|
193
189
|
]),
|
|
194
190
|
csp: csp.script_needs_nonce ? { nonce: csp.nonce } : { hash: csp.script_needs_hash },
|
|
195
191
|
transformError: error_components
|
|
196
|
-
? /** @param {unknown} e */
|
|
192
|
+
? /** @param {unknown} e */ (e) => {
|
|
197
193
|
if (isRedirect(e)) {
|
|
198
194
|
throw e;
|
|
199
195
|
}
|
|
200
196
|
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
197
|
+
const handled = handle_error_and_jsonify(event, render_state, options, e);
|
|
198
|
+
|
|
199
|
+
// TODO 4.0 make this an async function and await `handled`
|
|
200
|
+
if (handled instanceof Promise) {
|
|
201
|
+
return handled.then((e) => {
|
|
202
|
+
error = e;
|
|
203
|
+
props.page.error = error;
|
|
204
|
+
props.page.status = status = error.status;
|
|
205
|
+
return error;
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
error = handled;
|
|
210
|
+
props.page.error = error;
|
|
211
|
+
props.page.status = status = error.status;
|
|
212
|
+
|
|
213
|
+
return error;
|
|
205
214
|
}
|
|
206
215
|
: undefined
|
|
207
216
|
};
|
|
@@ -227,53 +236,27 @@ export async function render_response({
|
|
|
227
236
|
};
|
|
228
237
|
}
|
|
229
238
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
rendered = await with_request_store({ event, state }, async () => {
|
|
233
|
-
// use relative paths during rendering, so that the resulting HTML is as
|
|
234
|
-
// portable as possible, but reset afterwards
|
|
235
|
-
if (paths.relative) paths.override({ base, assets });
|
|
236
|
-
|
|
237
|
-
const maybe_promise = options.root.render(props, render_opts);
|
|
239
|
+
rendered = await with_request_store({ event, state: render_state }, async () => {
|
|
238
240
|
// We have to invoke .then eagerly here in order to kick off rendering: it's only starting on access,
|
|
239
241
|
// and `await maybe_promise` would eagerly access the .then property but call its function only after a tick, which is too late
|
|
240
242
|
// for the paths.reset() below and for any eager getRequestEvent() calls during rendering without AsyncLocalStorage available.
|
|
241
|
-
const rendered =
|
|
242
|
-
options.async && 'then' in maybe_promise
|
|
243
|
-
? /** @type {ReturnType<typeof options.root.render> & Promise<any>} */ (
|
|
244
|
-
maybe_promise
|
|
245
|
-
).then((r) => r)
|
|
246
|
-
: maybe_promise;
|
|
247
|
-
|
|
248
|
-
// TODO 3.0 remove options.async
|
|
249
|
-
if (options.async) {
|
|
250
|
-
// we reset this synchronously, rather than after async rendering is complete,
|
|
251
|
-
// to avoid cross-talk between requests. This is a breaking change for
|
|
252
|
-
// anyone who opts into async SSR, since `base` and `assets` will no
|
|
253
|
-
// longer be relative to the current pathname.
|
|
254
|
-
// TODO 3.0 remove `base` and `assets` in favour of `resolve(...)` and `asset(...)`
|
|
255
|
-
paths.reset();
|
|
256
|
-
}
|
|
243
|
+
const rendered = render(Root, { ...render_opts, props });
|
|
257
244
|
|
|
258
|
-
const { head,
|
|
259
|
-
options.async ? await rendered : rendered
|
|
260
|
-
);
|
|
245
|
+
const { head, body, hashes } = await rendered;
|
|
261
246
|
|
|
262
247
|
if (hashes) {
|
|
263
248
|
csp.add_script_hashes(hashes.script);
|
|
264
249
|
}
|
|
265
250
|
|
|
266
|
-
return { head,
|
|
251
|
+
return { head, body, hashes };
|
|
267
252
|
});
|
|
268
253
|
} finally {
|
|
269
254
|
if (DEV) {
|
|
270
255
|
globalThis.fetch = fetch;
|
|
271
256
|
}
|
|
272
|
-
|
|
273
|
-
paths.reset(); // just in case `options.root.render(...)` failed
|
|
274
257
|
}
|
|
275
258
|
} else {
|
|
276
|
-
rendered = { head: '',
|
|
259
|
+
rendered = { head: '', body: '', hashes: { script: [] } };
|
|
277
260
|
}
|
|
278
261
|
|
|
279
262
|
for (const { node } of branch) {
|
|
@@ -281,7 +264,7 @@ export async function render_response({
|
|
|
281
264
|
for (const url of node.stylesheets) stylesheets.add(url);
|
|
282
265
|
for (const url of node.fonts) fonts.add(url);
|
|
283
266
|
|
|
284
|
-
if (node.inline_styles && !client
|
|
267
|
+
if (node.inline_styles && !client?.inline) {
|
|
285
268
|
Object.entries(await node.inline_styles()).forEach(([filename, css]) => {
|
|
286
269
|
if (typeof css === 'string') {
|
|
287
270
|
inline_styles.set(filename, css);
|
|
@@ -294,7 +277,7 @@ export async function render_response({
|
|
|
294
277
|
}
|
|
295
278
|
|
|
296
279
|
const head = new Head(rendered.head);
|
|
297
|
-
let body = rendered.
|
|
280
|
+
let body = rendered.body;
|
|
298
281
|
|
|
299
282
|
/** @param {string} path */
|
|
300
283
|
const prefixed = (path) => {
|
|
@@ -307,7 +290,7 @@ export async function render_response({
|
|
|
307
290
|
return `${assets}/${path}`;
|
|
308
291
|
};
|
|
309
292
|
|
|
310
|
-
const style = client
|
|
293
|
+
const style = client?.inline
|
|
311
294
|
? client.inline?.style
|
|
312
295
|
: Array.from(inline_styles.values()).join('\n');
|
|
313
296
|
|
|
@@ -371,10 +354,16 @@ export async function render_response({
|
|
|
371
354
|
.join('\n\t\t\t')}`;
|
|
372
355
|
}
|
|
373
356
|
|
|
374
|
-
if (page_config.csr) {
|
|
375
|
-
const route =
|
|
357
|
+
if (page_config.csr && client) {
|
|
358
|
+
const route = client.routes?.find((r) => r.id === event.route.id) ?? null;
|
|
359
|
+
|
|
360
|
+
// when serving a prerendered page in an app that uses runtime public env vars, we must
|
|
361
|
+
// import the env.js module so that it evaluates before any user code can evaluate.
|
|
362
|
+
// TODO revert to using top-level await once https://bugs.webkit.org/show_bug.cgi?id=242740 is fixed
|
|
363
|
+
// https://github.com/sveltejs/kit/pull/11601
|
|
364
|
+
const load_env_eagerly = client.uses_env_dynamic_public && !!state.prerendering;
|
|
376
365
|
|
|
377
|
-
if (
|
|
366
|
+
if (load_env_eagerly) {
|
|
378
367
|
modulepreloads.add(`${paths.app_dir}/env.js`);
|
|
379
368
|
}
|
|
380
369
|
|
|
@@ -386,7 +375,7 @@ export async function render_response({
|
|
|
386
375
|
/** @type {(path: string) => void} */
|
|
387
376
|
let add_preload;
|
|
388
377
|
|
|
389
|
-
// see the
|
|
378
|
+
// see the output.preloadStrategy option for details on why we have multiple options here
|
|
390
379
|
if (options.link_header_preload && !state.prerendering) {
|
|
391
380
|
add_preload = (path) =>
|
|
392
381
|
link_headers.add(`<${encodeURI(path)}>; rel="modulepreload"; nopush`);
|
|
@@ -400,24 +389,18 @@ export async function render_response({
|
|
|
400
389
|
}
|
|
401
390
|
|
|
402
391
|
// prerender a `/path/to/page/__route.js` module
|
|
403
|
-
if (
|
|
392
|
+
if (client.routes && state.prerendering && !state.prerendering.fallback) {
|
|
404
393
|
const pathname = add_resolution_suffix(event.url.pathname);
|
|
405
394
|
|
|
406
395
|
state.prerendering.dependencies.set(
|
|
407
396
|
pathname,
|
|
408
|
-
create_server_routing_response(route, event.params, new URL(pathname, event.url),
|
|
397
|
+
create_server_routing_response(route, event.params, new URL(pathname, event.url), client)
|
|
409
398
|
);
|
|
410
399
|
}
|
|
411
400
|
|
|
412
401
|
const blocks = [];
|
|
413
402
|
|
|
414
|
-
|
|
415
|
-
// import the env.js module so that it evaluates before any user code can evaluate.
|
|
416
|
-
// TODO revert to using top-level await once https://bugs.webkit.org/show_bug.cgi?id=242740 is fixed
|
|
417
|
-
// https://github.com/sveltejs/kit/pull/11601
|
|
418
|
-
const load_env_eagerly = client.uses_env_dynamic_public && state.prerendering; // TODO implement uses_env_dynamic_public
|
|
419
|
-
|
|
420
|
-
const properties = [`base: ${base_expression}`];
|
|
403
|
+
const properties = [`base: ${base_expression}`, `version: ${s(__SVELTEKIT_APP_VERSION__)}`];
|
|
421
404
|
|
|
422
405
|
if (paths.assets) {
|
|
423
406
|
properties.push(`assets: ${s(paths.assets)}`);
|
|
@@ -438,9 +421,11 @@ export async function render_response({
|
|
|
438
421
|
|
|
439
422
|
if (Object.keys(options.hooks.transport).length > 0) {
|
|
440
423
|
if (client.inline) {
|
|
441
|
-
app_declaration = `const app =
|
|
424
|
+
app_declaration = `const app = ${global}.app.app;`;
|
|
442
425
|
} else if (client.app) {
|
|
443
|
-
app_declaration = `const
|
|
426
|
+
app_declaration = `const kit = await import(${s(prefixed(client.start))});
|
|
427
|
+
kit.init(${global});
|
|
428
|
+
const app = await import(${s(prefixed(client.app))});`;
|
|
444
429
|
} else {
|
|
445
430
|
app_declaration = `const { app } = await import(${s(prefixed(client.start))});`;
|
|
446
431
|
}
|
|
@@ -501,13 +486,13 @@ export async function render_response({
|
|
|
501
486
|
`error: ${serialized.error}`
|
|
502
487
|
];
|
|
503
488
|
|
|
504
|
-
if (status !== 200) {
|
|
489
|
+
if (status !== 200 && !error) {
|
|
505
490
|
hydrate.push(`status: ${status}`);
|
|
506
491
|
}
|
|
507
492
|
|
|
508
|
-
if (
|
|
493
|
+
if (client.routes) {
|
|
509
494
|
if (route) {
|
|
510
|
-
const stringified = generate_route_object(route, event.url,
|
|
495
|
+
const stringified = generate_route_object(route, event.url, client).replaceAll(
|
|
511
496
|
'\n',
|
|
512
497
|
'\n\t\t\t\t\t\t\t'
|
|
513
498
|
); // make output after it's put together with the rest more readable
|
|
@@ -521,87 +506,26 @@ export async function render_response({
|
|
|
521
506
|
args.push(`{\n${indent}\t${hydrate.join(`,\n${indent}\t`)}\n${indent}}`);
|
|
522
507
|
}
|
|
523
508
|
|
|
524
|
-
const
|
|
525
|
-
|
|
526
|
-
let serialized_query_data = '';
|
|
527
|
-
let serialized_prerender_data = '';
|
|
528
|
-
|
|
529
|
-
if (remote.data) {
|
|
530
|
-
/** @type {Record<string, any>} */
|
|
531
|
-
const query = {};
|
|
532
|
-
|
|
533
|
-
/** @type {Record<string, any>} */
|
|
534
|
-
const prerender = {};
|
|
535
|
-
|
|
536
|
-
for (const [internals, cache] of remote.data) {
|
|
537
|
-
// remote functions without an `id` aren't exported, and thus
|
|
538
|
-
// cannot be called from the client
|
|
539
|
-
if (!internals.id) continue;
|
|
540
|
-
|
|
541
|
-
for (const key in cache) {
|
|
542
|
-
const entry = cache[key];
|
|
543
|
-
|
|
544
|
-
if (!entry.serialize) continue;
|
|
545
|
-
|
|
546
|
-
const remote_key = create_remote_key(internals.id, key);
|
|
547
|
-
|
|
548
|
-
const store = internals.type === 'prerender' ? prerender : query;
|
|
549
|
-
|
|
550
|
-
if (
|
|
551
|
-
event_state.remote.refreshes?.has(remote_key) ||
|
|
552
|
-
event_state.remote.reconnects?.has(remote_key)
|
|
553
|
-
) {
|
|
554
|
-
// This entry was refreshed/set by a command or form action.
|
|
555
|
-
// Always await it so the mutation result is serialized.
|
|
556
|
-
store[remote_key] = await entry.data;
|
|
557
|
-
} else {
|
|
558
|
-
// Don't block the response on pending remote data - if a query
|
|
559
|
-
// hasn't settled yet, it wasn't awaited in the template (or is behind a pending boundary).
|
|
560
|
-
const result = await Promise.race([
|
|
561
|
-
Promise.resolve(entry.data).then(
|
|
562
|
-
(v) => /** @type {const} */ ({ settled: true, value: v }),
|
|
563
|
-
(e) => /** @type {const} */ ({ settled: true, error: e })
|
|
564
|
-
),
|
|
565
|
-
new Promise((resolve) => {
|
|
566
|
-
queueMicrotask(() => resolve(/** @type {const} */ ({ settled: false })));
|
|
567
|
-
})
|
|
568
|
-
]);
|
|
569
|
-
|
|
570
|
-
if (result.settled) {
|
|
571
|
-
if ('error' in result) throw result.error;
|
|
572
|
-
store[remote_key] = result.value;
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
const replacer = create_replacer(options.hooks.transport);
|
|
509
|
+
const remote_data = await collect_remote_data({}, event, event_state, options);
|
|
579
510
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
if (Object.keys(prerender).length > 0) {
|
|
585
|
-
serialized_prerender_data = `${global}.prerender = ${devalue.uneval(prerender, replacer)};\n\n\t\t\t\t\t\t`;
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
const serialized_remote_data = `${serialized_query_data}${serialized_prerender_data}`;
|
|
511
|
+
const serialized_data =
|
|
512
|
+
Object.keys(remote_data).length > 0
|
|
513
|
+
? `${global}.data = ${devalue.uneval(remote_data, create_replacer(options.hooks.transport))};\n\n\t\t\t\t\t\t`
|
|
514
|
+
: '';
|
|
590
515
|
|
|
591
516
|
// `client.app` is a proxy for `bundleStrategy === 'split'`
|
|
592
517
|
const boot = client.inline
|
|
593
518
|
? `${client.inline.script}
|
|
594
519
|
|
|
595
|
-
${
|
|
520
|
+
${serialized_data}${global}.app.start(${args.join(', ')});`
|
|
596
521
|
: client.app
|
|
597
|
-
? `
|
|
598
|
-
|
|
599
|
-
import(${s(prefixed(client.app))})
|
|
600
|
-
|
|
601
|
-
${serialized_remote_data}kit.start(app, ${args.join(', ')});
|
|
522
|
+
? `import(${s(prefixed(client.start))}).then(async (kit) => {
|
|
523
|
+
kit.init(${global});
|
|
524
|
+
const app = await import(${s(prefixed(client.app))});
|
|
525
|
+
${serialized_data}kit.start(app, ${args.join(', ')});
|
|
602
526
|
});`
|
|
603
527
|
: `import(${s(prefixed(client.start))}).then((app) => {
|
|
604
|
-
${
|
|
528
|
+
${serialized_data}app.start(${args.join(', ')})
|
|
605
529
|
});`;
|
|
606
530
|
|
|
607
531
|
if (load_env_eagerly) {
|
|
@@ -615,12 +539,9 @@ export async function render_response({
|
|
|
615
539
|
}
|
|
616
540
|
|
|
617
541
|
if (options.service_worker) {
|
|
618
|
-
let opts =
|
|
542
|
+
let opts = ", { type: 'module' }";
|
|
619
543
|
if (options.service_worker_options != null) {
|
|
620
|
-
const service_worker_options = { ...options.service_worker_options };
|
|
621
|
-
if (__SVELTEKIT_DEV__) {
|
|
622
|
-
service_worker_options.type = 'module';
|
|
623
|
-
}
|
|
544
|
+
const service_worker_options = { ...options.service_worker_options, type: 'module' };
|
|
624
545
|
opts = `, ${s(service_worker_options)}`;
|
|
625
546
|
}
|
|
626
547
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Redirect } from '@sveltejs/kit/internal';
|
|
2
2
|
import { render_response } from './render.js';
|
|
3
3
|
import { load_data, load_server_data } from './load_data.js';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { redirect_response } from '../utils.js';
|
|
5
|
+
import { handle_error_and_jsonify, static_error_page } from '../errors.js';
|
|
6
6
|
import { PageNodes } from '../../../utils/page_nodes.js';
|
|
7
7
|
import { server_data_serializer } from './data_serializer.js';
|
|
8
8
|
|
|
@@ -34,12 +34,12 @@ export async function respond_with_error({
|
|
|
34
34
|
}) {
|
|
35
35
|
// reroute to the fallback page to prevent an infinite chain of requests.
|
|
36
36
|
if (event.request.headers.get('x-sveltekit-error')) {
|
|
37
|
-
|
|
37
|
+
const transformed = await handle_error_and_jsonify(event, event_state, options, error);
|
|
38
|
+
return static_error_page(options, status, transformed.message);
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
/** @type {import('./types.js').Fetched[]} */
|
|
41
42
|
const fetched = [];
|
|
42
|
-
|
|
43
43
|
try {
|
|
44
44
|
const branch = [];
|
|
45
45
|
const default_layout = await manifest._.nodes[0](); // 0 is always the root layout
|
|
@@ -47,6 +47,8 @@ export async function respond_with_error({
|
|
|
47
47
|
const ssr = nodes.ssr();
|
|
48
48
|
const csr = nodes.csr();
|
|
49
49
|
const data_serializer = server_data_serializer(event, event_state, options);
|
|
50
|
+
// Do this here first in case the awaits below before rendering themselves error
|
|
51
|
+
const transformed = await handle_error_and_jsonify(event, event_state, options, error);
|
|
50
52
|
|
|
51
53
|
if (ssr) {
|
|
52
54
|
state.error = true;
|
|
@@ -98,8 +100,8 @@ export async function respond_with_error({
|
|
|
98
100
|
ssr,
|
|
99
101
|
csr
|
|
100
102
|
},
|
|
101
|
-
status,
|
|
102
|
-
error:
|
|
103
|
+
status: transformed.status,
|
|
104
|
+
error: transformed,
|
|
103
105
|
branch,
|
|
104
106
|
error_components: [],
|
|
105
107
|
fetched,
|
|
@@ -115,10 +117,8 @@ export async function respond_with_error({
|
|
|
115
117
|
return redirect_response(e.status, e.location);
|
|
116
118
|
}
|
|
117
119
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
(await handle_error_and_jsonify(event, event_state, options, e)).message
|
|
122
|
-
);
|
|
120
|
+
const transformed = await handle_error_and_jsonify(event, event_state, options, e);
|
|
121
|
+
|
|
122
|
+
return static_error_page(options, transformed.status, transformed.message);
|
|
123
123
|
}
|
|
124
124
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** @import { SSRManifest } from '@sveltejs/kit' */
|
|
1
2
|
import { base, assets, relative } from '$app/paths/internal/server';
|
|
2
3
|
import { text } from '@sveltejs/kit';
|
|
3
4
|
import { s } from '../../../utils/misc.js';
|
|
@@ -7,15 +8,15 @@ import { get_relative_path } from '../../utils.js';
|
|
|
7
8
|
/**
|
|
8
9
|
* @param {import('types').SSRClientRoute} route
|
|
9
10
|
* @param {URL} url
|
|
10
|
-
* @param {
|
|
11
|
+
* @param {NonNullable<SSRManifest['_']['client']>} client
|
|
11
12
|
* @returns {string}
|
|
12
13
|
*/
|
|
13
|
-
export function generate_route_object(route, url,
|
|
14
|
+
export function generate_route_object(route, url, client) {
|
|
14
15
|
const { errors, layouts, leaf } = route;
|
|
15
16
|
|
|
16
17
|
const nodes = [...errors, ...layouts.map((l) => l?.[1]), leaf[1]]
|
|
17
18
|
.filter((n) => typeof n === 'number')
|
|
18
|
-
.map((n) => `'${n}': () => ${create_client_import(
|
|
19
|
+
.map((n) => `'${n}': () => ${create_client_import(client.nodes?.[n], url)}`)
|
|
19
20
|
.join(',\n\t\t');
|
|
20
21
|
|
|
21
22
|
// stringified version of
|
|
@@ -60,36 +61,44 @@ function create_client_import(import_path, url) {
|
|
|
60
61
|
/**
|
|
61
62
|
* @param {string} resolved_path
|
|
62
63
|
* @param {URL} url
|
|
63
|
-
* @param {
|
|
64
|
+
* @param {SSRManifest} manifest
|
|
64
65
|
* @returns {Promise<Response>}
|
|
65
66
|
*/
|
|
66
67
|
export async function resolve_route(resolved_path, url, manifest) {
|
|
67
|
-
if (!manifest._.client
|
|
68
|
+
if (!manifest._.client?.routes) {
|
|
68
69
|
return text('Server-side route resolution disabled', { status: 400 });
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
72
|
+
try {
|
|
73
|
+
const matchers = await manifest._.matchers();
|
|
74
|
+
const result = find_route(resolved_path, manifest._.client.routes, matchers);
|
|
75
|
+
|
|
76
|
+
return create_server_routing_response(
|
|
77
|
+
result?.route ?? null,
|
|
78
|
+
result?.params ?? {},
|
|
79
|
+
url,
|
|
80
|
+
manifest._.client
|
|
81
|
+
).response;
|
|
82
|
+
} catch {
|
|
83
|
+
return text('Error resolving route', { status: 500 });
|
|
84
|
+
}
|
|
76
85
|
}
|
|
77
86
|
|
|
78
87
|
/**
|
|
79
88
|
* @param {import('types').SSRClientRoute | null} route
|
|
80
89
|
* @param {Partial<Record<string, string>>} params
|
|
81
90
|
* @param {URL} url
|
|
82
|
-
* @param {
|
|
91
|
+
* @param {NonNullable<SSRManifest['_']['client']>} client
|
|
83
92
|
* @returns {{response: Response, body: string}}
|
|
84
93
|
*/
|
|
85
|
-
export function create_server_routing_response(route, params, url,
|
|
94
|
+
export function create_server_routing_response(route, params, url, client) {
|
|
86
95
|
const headers = new Headers({
|
|
87
96
|
'content-type': 'application/javascript; charset=utf-8'
|
|
88
97
|
});
|
|
89
98
|
|
|
90
99
|
if (route) {
|
|
91
|
-
const csr_route = generate_route_object(route, url,
|
|
92
|
-
const body = `${create_css_import(route, url,
|
|
100
|
+
const csr_route = generate_route_object(route, url, client);
|
|
101
|
+
const body = `${create_css_import(route, url, client)}\nexport const route = ${csr_route}; export const params = ${JSON.stringify(params)};`;
|
|
93
102
|
|
|
94
103
|
return { response: text(body, { headers }), body };
|
|
95
104
|
} else {
|
|
@@ -105,17 +114,17 @@ export function create_server_routing_response(route, params, url, manifest) {
|
|
|
105
114
|
*
|
|
106
115
|
* @param {import('types').SSRClientRoute} route
|
|
107
116
|
* @param {URL} url
|
|
108
|
-
* @param {
|
|
117
|
+
* @param {NonNullable<SSRManifest['_']['client']>} client
|
|
109
118
|
* @returns {string}
|
|
110
119
|
*/
|
|
111
|
-
function create_css_import(route, url,
|
|
120
|
+
function create_css_import(route, url, client) {
|
|
112
121
|
const { errors, layouts, leaf } = route;
|
|
113
122
|
|
|
114
123
|
let css = '';
|
|
115
124
|
|
|
116
125
|
for (const node of [...errors, ...layouts.map((l) => l?.[1]), leaf[1]]) {
|
|
117
126
|
if (typeof node !== 'number') continue;
|
|
118
|
-
const node_css =
|
|
127
|
+
const node_css = client.css?.[node];
|
|
119
128
|
for (const css_path of node_css ?? []) {
|
|
120
129
|
css += `'${assets || base}/${css_path}',`;
|
|
121
130
|
}
|
|
@@ -123,5 +132,5 @@ function create_css_import(route, url, manifest) {
|
|
|
123
132
|
|
|
124
133
|
if (!css) return '';
|
|
125
134
|
|
|
126
|
-
return `${create_client_import(
|
|
135
|
+
return `${create_client_import(client.start, url)}.then(x => x.load_css([${css}]));`;
|
|
127
136
|
}
|