@sveltejs/kit 3.0.0-next.1 → 3.0.0-next.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +33 -21
- package/src/core/adapt/builder.js +29 -43
- package/src/core/adapt/index.js +1 -4
- package/src/core/config/index.js +132 -71
- package/src/core/config/options.js +294 -244
- package/src/core/config/types.d.ts +1 -1
- package/src/core/env.js +121 -5
- package/src/core/generate_manifest/index.js +12 -15
- package/src/core/postbuild/analyse.js +7 -19
- package/src/core/postbuild/crawl.js +22 -6
- package/src/core/postbuild/prerender.js +42 -23
- package/src/core/sync/create_manifest_data/index.js +53 -50
- package/src/core/sync/sync.js +0 -2
- package/src/core/sync/write_client_manifest.js +8 -15
- package/src/core/sync/write_env.js +2 -1
- package/src/core/sync/write_non_ambient.js +12 -9
- package/src/core/sync/write_server.js +13 -14
- package/src/core/sync/write_tsconfig.js +16 -8
- package/src/core/sync/write_tsconfig_test/package.json +7 -0
- package/src/core/sync/write_types/index.js +28 -24
- package/src/core/utils.js +2 -2
- package/src/exports/env/index.js +12 -0
- package/src/exports/hooks/index.js +3 -9
- package/src/exports/hooks/sequence.js +3 -2
- package/src/exports/index.js +35 -13
- package/src/exports/internal/client.js +5 -0
- package/src/exports/internal/env.js +2 -2
- package/src/exports/internal/index.js +1 -90
- package/src/exports/internal/{event.js → server/event.js} +1 -2
- package/src/exports/internal/server/index.js +33 -0
- package/src/exports/internal/shared.js +89 -0
- package/src/exports/node/index.js +62 -15
- package/src/exports/params.js +63 -0
- package/src/exports/public.d.ts +323 -170
- package/src/exports/url.js +86 -0
- package/src/exports/vite/build/build_server.js +53 -59
- package/src/exports/vite/build/remote.js +18 -11
- package/src/exports/vite/build/utils.js +0 -8
- package/src/exports/vite/dev/index.js +42 -44
- package/src/exports/vite/index.js +810 -593
- package/src/exports/vite/preview/index.js +29 -22
- package/src/exports/vite/static_analysis/index.js +2 -4
- package/src/exports/vite/static_analysis/types.d.ts +14 -0
- package/src/exports/vite/utils.js +21 -36
- package/src/runtime/app/env/internal.js +4 -4
- package/src/runtime/app/env/types.d.ts +1 -1
- package/src/runtime/app/environment/index.js +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 +9 -5
- package/src/runtime/app/server/remote/command.js +0 -3
- package/src/runtime/app/server/remote/form.js +27 -15
- package/src/runtime/app/server/remote/prerender.js +29 -36
- package/src/runtime/app/server/remote/query.js +101 -99
- package/src/runtime/app/server/remote/requested.js +22 -14
- package/src/runtime/app/server/remote/shared.js +30 -26
- package/src/runtime/app/state/client.js +1 -2
- package/src/runtime/app/stores.js +13 -76
- package/src/runtime/client/bundle.js +1 -1
- package/src/runtime/client/client-entry.js +3 -0
- package/src/runtime/client/client.js +411 -318
- package/src/runtime/client/entry.js +24 -3
- package/src/runtime/client/fetcher.js +3 -2
- package/src/runtime/client/ndjson.js +6 -33
- package/src/runtime/client/payload.js +17 -0
- package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
- package/src/runtime/client/remote-functions/command.svelte.js +7 -32
- package/src/runtime/client/remote-functions/form.svelte.js +183 -112
- package/src/runtime/client/remote-functions/prerender.svelte.js +29 -8
- package/src/runtime/client/remote-functions/query/index.js +7 -14
- package/src/runtime/client/remote-functions/query/instance.svelte.js +63 -18
- package/src/runtime/client/remote-functions/query/proxy.js +3 -3
- package/src/runtime/client/remote-functions/query-batch.svelte.js +60 -68
- package/src/runtime/client/remote-functions/query-live/instance.svelte.js +60 -18
- package/src/runtime/client/remote-functions/query-live/iterator.js +36 -55
- package/src/runtime/client/remote-functions/shared.svelte.js +88 -62
- package/src/runtime/client/sse.js +32 -0
- package/src/runtime/client/state.svelte.js +65 -49
- package/src/runtime/client/stream.js +38 -0
- package/src/runtime/client/types.d.ts +11 -7
- package/src/runtime/client/utils.js +0 -96
- package/src/runtime/components/root.svelte +66 -0
- package/src/runtime/env/dynamic/private.js +7 -0
- package/src/runtime/env/dynamic/public.js +7 -0
- package/src/runtime/env/static/private.js +6 -0
- package/src/runtime/env/static/public.js +6 -0
- package/src/runtime/form-utils.js +100 -22
- package/src/runtime/server/cookie.js +69 -52
- package/src/runtime/server/csrf.js +65 -0
- package/src/runtime/server/data/index.js +14 -18
- package/src/runtime/server/env_module.js +0 -5
- package/src/runtime/server/index.js +2 -2
- package/src/runtime/server/page/actions.js +41 -26
- package/src/runtime/server/page/index.js +9 -15
- package/src/runtime/server/page/load_data.js +1 -1
- package/src/runtime/server/page/render.js +112 -187
- package/src/runtime/server/page/respond_with_error.js +7 -8
- package/src/runtime/server/page/server_routing.js +27 -18
- package/src/runtime/server/remote.js +355 -216
- package/src/runtime/server/respond.js +97 -61
- package/src/runtime/server/utils.js +32 -9
- package/src/runtime/shared.js +83 -13
- package/src/runtime/telemetry/otel.js +1 -1
- package/src/runtime/types.d.ts +8 -0
- package/src/types/ambient.d.ts +10 -5
- package/src/types/global-private.d.ts +15 -22
- package/src/types/internal.d.ts +89 -74
- package/src/types/private.d.ts +33 -1
- package/src/utils/error.js +24 -4
- package/src/utils/import.js +6 -1
- package/src/utils/imports.js +83 -0
- package/src/utils/mime.js +9 -0
- package/src/utils/params.js +66 -0
- package/src/utils/routing.js +90 -44
- package/src/utils/shared-iterator.js +5 -0
- package/src/utils/streaming.js +14 -4
- package/src/utils/url.js +20 -2
- package/src/version.js +1 -1
- package/types/index.d.ts +467 -537
- package/types/index.d.ts.map +22 -39
- package/src/core/sync/write_root.js +0 -148
- package/src/exports/internal/server.js +0 -22
- package/src/types/synthetic/$lib.md +0 -5
- /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
|
@@ -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,7 +11,7 @@ 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
17
|
import {
|
|
@@ -20,17 +20,13 @@ import {
|
|
|
20
20
|
get_global_name,
|
|
21
21
|
handle_error_and_jsonify
|
|
22
22
|
} from '../utils.js';
|
|
23
|
-
import { create_remote_key } from '../../shared.js';
|
|
24
|
-
import { get_status } from '../../../utils/error.js';
|
|
25
23
|
import * as env from '__sveltekit/env';
|
|
24
|
+
import { collect_remote_data } from '../remote.js';
|
|
25
|
+
import Root from '../../components/root.svelte';
|
|
26
|
+
import { render } from 'svelte/server';
|
|
26
27
|
|
|
27
28
|
// TODO rename this function/module
|
|
28
29
|
|
|
29
|
-
const updated = {
|
|
30
|
-
...readable(false),
|
|
31
|
-
check: () => false
|
|
32
|
-
};
|
|
33
|
-
|
|
34
30
|
/**
|
|
35
31
|
* Creates the HTML response.
|
|
36
32
|
* @param {{
|
|
@@ -47,7 +43,7 @@ const updated = {
|
|
|
47
43
|
* resolve_opts: import('types').RequiredResolveOptions;
|
|
48
44
|
* action_result?: import('@sveltejs/kit').ActionResult;
|
|
49
45
|
* data_serializer: import('./types.js').ServerDataSerializer;
|
|
50
|
-
* error_components?: Array<import('
|
|
46
|
+
* error_components?: Array<import('svelte').Component | undefined>
|
|
51
47
|
* }} opts
|
|
52
48
|
*/
|
|
53
49
|
export async function render_response({
|
|
@@ -68,7 +64,7 @@ export async function render_response({
|
|
|
68
64
|
}) {
|
|
69
65
|
if (state.prerendering) {
|
|
70
66
|
if (options.csp.mode === 'nonce') {
|
|
71
|
-
throw new Error('Cannot use prerendering if config.
|
|
67
|
+
throw new Error('Cannot use prerendering if config.csp.mode === "nonce"');
|
|
72
68
|
}
|
|
73
69
|
|
|
74
70
|
if (options.app_template_contains_nonce) {
|
|
@@ -78,9 +74,9 @@ export async function render_response({
|
|
|
78
74
|
|
|
79
75
|
const { client } = manifest._;
|
|
80
76
|
|
|
81
|
-
const modulepreloads = new Set(client
|
|
82
|
-
const stylesheets = new Set(client
|
|
83
|
-
const fonts = new Set(client
|
|
77
|
+
const modulepreloads = new Set(client?.imports);
|
|
78
|
+
const stylesheets = new Set(client?.stylesheets);
|
|
79
|
+
const fonts = new Set(client?.fonts);
|
|
84
80
|
|
|
85
81
|
/**
|
|
86
82
|
* The value of the Link header that is added to the response when not prerendering
|
|
@@ -92,7 +88,8 @@ export async function render_response({
|
|
|
92
88
|
// 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
89
|
const inline_styles = new Map();
|
|
94
90
|
|
|
95
|
-
|
|
91
|
+
// TODO `svelte/server` should expose `RenderOutput`
|
|
92
|
+
/** @type {{ head: string, body: string, hashes: { script: string[] } }} */
|
|
96
93
|
let rendered;
|
|
97
94
|
|
|
98
95
|
const form_value =
|
|
@@ -119,7 +116,12 @@ export async function render_response({
|
|
|
119
116
|
// if appropriate, use relative paths for greater portability
|
|
120
117
|
if (paths.relative) {
|
|
121
118
|
if (!state.prerendering?.fallback) {
|
|
122
|
-
|
|
119
|
+
// the relative path depth must reflect the URL the browser is actually at, which
|
|
120
|
+
// for a data request includes the `__data.json` suffix that was stripped during routing
|
|
121
|
+
const pathname = event.isDataRequest
|
|
122
|
+
? add_data_suffix(event.url.pathname)
|
|
123
|
+
: event.url.pathname;
|
|
124
|
+
const segments = pathname.slice(paths.base.length).split('/').slice(2);
|
|
123
125
|
|
|
124
126
|
base = segments.map(() => '..').join('/') || '.';
|
|
125
127
|
|
|
@@ -138,49 +140,47 @@ export async function render_response({
|
|
|
138
140
|
if (page_config.ssr) {
|
|
139
141
|
/** @type {Record<string, any>} */
|
|
140
142
|
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;
|
|
143
|
+
components: [],
|
|
144
|
+
resetters: [],
|
|
145
|
+
form: form_value,
|
|
146
|
+
tree: /** @type {RenderNode} */ ({}),
|
|
147
|
+
error,
|
|
148
|
+
page: {
|
|
149
|
+
error,
|
|
150
|
+
params: /** @type {Record<string, any>} */ (event.params),
|
|
151
|
+
route: event.route,
|
|
152
|
+
status,
|
|
153
|
+
url: event.url,
|
|
154
|
+
data: {},
|
|
155
|
+
form: form_value,
|
|
156
|
+
state: {}
|
|
161
157
|
}
|
|
162
|
-
|
|
163
|
-
}
|
|
158
|
+
};
|
|
164
159
|
|
|
165
|
-
let
|
|
160
|
+
let current_node = props.tree;
|
|
161
|
+
let data = props.page.data;
|
|
166
162
|
|
|
167
|
-
// props_n (instead of props[n]) makes it easy to avoid
|
|
168
|
-
// unnecessary updates for layout components
|
|
169
163
|
for (let i = 0; i < branch.length; i += 1) {
|
|
170
|
-
|
|
171
|
-
|
|
164
|
+
const node = branch[i];
|
|
165
|
+
|
|
166
|
+
data = { ...data, ...node.data };
|
|
167
|
+
|
|
168
|
+
// TODO this is undefined sometimes... where does the default error component come from?
|
|
169
|
+
const error = error_components?.slice(0, i + 1).findLast((x) => x);
|
|
170
|
+
|
|
171
|
+
current_node.error = error;
|
|
172
|
+
current_node.component = await node.node.component?.();
|
|
173
|
+
current_node.data = data;
|
|
174
|
+
|
|
175
|
+
if (i < branch.length - 1) {
|
|
176
|
+
current_node.child = /** @type {import('../../types.js').RenderNode} */ ({});
|
|
177
|
+
current_node = current_node.child;
|
|
178
|
+
}
|
|
172
179
|
}
|
|
173
180
|
|
|
174
|
-
props.page =
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
route: event.route,
|
|
178
|
-
status,
|
|
179
|
-
url: event.url,
|
|
180
|
-
data,
|
|
181
|
-
form: form_value,
|
|
182
|
-
state: {}
|
|
183
|
-
};
|
|
181
|
+
props.page.data = data;
|
|
182
|
+
|
|
183
|
+
const render_state = { ...event_state, is_in_render: true };
|
|
184
184
|
|
|
185
185
|
const render_opts = {
|
|
186
186
|
context: new Map([
|
|
@@ -193,15 +193,28 @@ export async function render_response({
|
|
|
193
193
|
]),
|
|
194
194
|
csp: csp.script_needs_nonce ? { nonce: csp.nonce } : { hash: csp.script_needs_hash },
|
|
195
195
|
transformError: error_components
|
|
196
|
-
? /** @param {unknown} e */
|
|
196
|
+
? /** @param {unknown} e */ (e) => {
|
|
197
197
|
if (isRedirect(e)) {
|
|
198
198
|
throw e;
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
201
|
+
const handled = handle_error_and_jsonify(event, render_state, options, e);
|
|
202
|
+
|
|
203
|
+
// TODO 4.0 make this an async function and await `handled`
|
|
204
|
+
if (handled instanceof Promise) {
|
|
205
|
+
return handled.then((e) => {
|
|
206
|
+
error = e;
|
|
207
|
+
props.page.error = error;
|
|
208
|
+
props.page.status = status = error.status;
|
|
209
|
+
return error;
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
error = handled;
|
|
214
|
+
props.page.error = error;
|
|
215
|
+
props.page.status = status = error.status;
|
|
216
|
+
|
|
217
|
+
return error;
|
|
205
218
|
}
|
|
206
219
|
: undefined
|
|
207
220
|
};
|
|
@@ -227,53 +240,27 @@ export async function render_response({
|
|
|
227
240
|
};
|
|
228
241
|
}
|
|
229
242
|
|
|
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);
|
|
243
|
+
rendered = await with_request_store({ event, state: render_state }, async () => {
|
|
238
244
|
// We have to invoke .then eagerly here in order to kick off rendering: it's only starting on access,
|
|
239
245
|
// and `await maybe_promise` would eagerly access the .then property but call its function only after a tick, which is too late
|
|
240
246
|
// 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
|
-
}
|
|
247
|
+
const rendered = render(Root, { ...render_opts, props });
|
|
257
248
|
|
|
258
|
-
const { head,
|
|
259
|
-
options.async ? await rendered : rendered
|
|
260
|
-
);
|
|
249
|
+
const { head, body, hashes } = await rendered;
|
|
261
250
|
|
|
262
251
|
if (hashes) {
|
|
263
252
|
csp.add_script_hashes(hashes.script);
|
|
264
253
|
}
|
|
265
254
|
|
|
266
|
-
return { head,
|
|
255
|
+
return { head, body, hashes };
|
|
267
256
|
});
|
|
268
257
|
} finally {
|
|
269
258
|
if (DEV) {
|
|
270
259
|
globalThis.fetch = fetch;
|
|
271
260
|
}
|
|
272
|
-
|
|
273
|
-
paths.reset(); // just in case `options.root.render(...)` failed
|
|
274
261
|
}
|
|
275
262
|
} else {
|
|
276
|
-
rendered = { head: '',
|
|
263
|
+
rendered = { head: '', body: '', hashes: { script: [] } };
|
|
277
264
|
}
|
|
278
265
|
|
|
279
266
|
for (const { node } of branch) {
|
|
@@ -281,7 +268,7 @@ export async function render_response({
|
|
|
281
268
|
for (const url of node.stylesheets) stylesheets.add(url);
|
|
282
269
|
for (const url of node.fonts) fonts.add(url);
|
|
283
270
|
|
|
284
|
-
if (node.inline_styles && !client
|
|
271
|
+
if (node.inline_styles && !client?.inline) {
|
|
285
272
|
Object.entries(await node.inline_styles()).forEach(([filename, css]) => {
|
|
286
273
|
if (typeof css === 'string') {
|
|
287
274
|
inline_styles.set(filename, css);
|
|
@@ -294,7 +281,7 @@ export async function render_response({
|
|
|
294
281
|
}
|
|
295
282
|
|
|
296
283
|
const head = new Head(rendered.head);
|
|
297
|
-
let body = rendered.
|
|
284
|
+
let body = rendered.body;
|
|
298
285
|
|
|
299
286
|
/** @param {string} path */
|
|
300
287
|
const prefixed = (path) => {
|
|
@@ -307,7 +294,7 @@ export async function render_response({
|
|
|
307
294
|
return `${assets}/${path}`;
|
|
308
295
|
};
|
|
309
296
|
|
|
310
|
-
const style = client
|
|
297
|
+
const style = client?.inline
|
|
311
298
|
? client.inline?.style
|
|
312
299
|
: Array.from(inline_styles.values()).join('\n');
|
|
313
300
|
|
|
@@ -371,10 +358,16 @@ export async function render_response({
|
|
|
371
358
|
.join('\n\t\t\t')}`;
|
|
372
359
|
}
|
|
373
360
|
|
|
374
|
-
if (page_config.csr) {
|
|
375
|
-
const route =
|
|
361
|
+
if (page_config.csr && client) {
|
|
362
|
+
const route = client.routes?.find((r) => r.id === event.route.id) ?? null;
|
|
363
|
+
|
|
364
|
+
// when serving a prerendered page in an app that uses runtime public env vars, we must
|
|
365
|
+
// import the env.js module so that it evaluates before any user code can evaluate.
|
|
366
|
+
// TODO revert to using top-level await once https://bugs.webkit.org/show_bug.cgi?id=242740 is fixed
|
|
367
|
+
// https://github.com/sveltejs/kit/pull/11601
|
|
368
|
+
const load_env_eagerly = client.uses_env_dynamic_public && !!state.prerendering;
|
|
376
369
|
|
|
377
|
-
if (
|
|
370
|
+
if (load_env_eagerly) {
|
|
378
371
|
modulepreloads.add(`${paths.app_dir}/env.js`);
|
|
379
372
|
}
|
|
380
373
|
|
|
@@ -386,7 +379,7 @@ export async function render_response({
|
|
|
386
379
|
/** @type {(path: string) => void} */
|
|
387
380
|
let add_preload;
|
|
388
381
|
|
|
389
|
-
// see the
|
|
382
|
+
// see the output.preloadStrategy option for details on why we have multiple options here
|
|
390
383
|
if (options.link_header_preload && !state.prerendering) {
|
|
391
384
|
add_preload = (path) =>
|
|
392
385
|
link_headers.add(`<${encodeURI(path)}>; rel="modulepreload"; nopush`);
|
|
@@ -400,24 +393,18 @@ export async function render_response({
|
|
|
400
393
|
}
|
|
401
394
|
|
|
402
395
|
// prerender a `/path/to/page/__route.js` module
|
|
403
|
-
if (
|
|
396
|
+
if (client.routes && state.prerendering && !state.prerendering.fallback) {
|
|
404
397
|
const pathname = add_resolution_suffix(event.url.pathname);
|
|
405
398
|
|
|
406
399
|
state.prerendering.dependencies.set(
|
|
407
400
|
pathname,
|
|
408
|
-
create_server_routing_response(route, event.params, new URL(pathname, event.url),
|
|
401
|
+
create_server_routing_response(route, event.params, new URL(pathname, event.url), client)
|
|
409
402
|
);
|
|
410
403
|
}
|
|
411
404
|
|
|
412
405
|
const blocks = [];
|
|
413
406
|
|
|
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}`];
|
|
407
|
+
const properties = [`base: ${base_expression}`, `version: ${s(__SVELTEKIT_APP_VERSION__)}`];
|
|
421
408
|
|
|
422
409
|
if (paths.assets) {
|
|
423
410
|
properties.push(`assets: ${s(paths.assets)}`);
|
|
@@ -438,9 +425,11 @@ export async function render_response({
|
|
|
438
425
|
|
|
439
426
|
if (Object.keys(options.hooks.transport).length > 0) {
|
|
440
427
|
if (client.inline) {
|
|
441
|
-
app_declaration = `const app =
|
|
428
|
+
app_declaration = `const app = ${global}.app.app;`;
|
|
442
429
|
} else if (client.app) {
|
|
443
|
-
app_declaration = `const
|
|
430
|
+
app_declaration = `const kit = await import(${s(prefixed(client.start))});
|
|
431
|
+
kit.init(${global});
|
|
432
|
+
const app = await import(${s(prefixed(client.app))});`;
|
|
444
433
|
} else {
|
|
445
434
|
app_declaration = `const { app } = await import(${s(prefixed(client.start))});`;
|
|
446
435
|
}
|
|
@@ -501,13 +490,13 @@ export async function render_response({
|
|
|
501
490
|
`error: ${serialized.error}`
|
|
502
491
|
];
|
|
503
492
|
|
|
504
|
-
if (status !== 200) {
|
|
493
|
+
if (status !== 200 && !error) {
|
|
505
494
|
hydrate.push(`status: ${status}`);
|
|
506
495
|
}
|
|
507
496
|
|
|
508
|
-
if (
|
|
497
|
+
if (client.routes) {
|
|
509
498
|
if (route) {
|
|
510
|
-
const stringified = generate_route_object(route, event.url,
|
|
499
|
+
const stringified = generate_route_object(route, event.url, client).replaceAll(
|
|
511
500
|
'\n',
|
|
512
501
|
'\n\t\t\t\t\t\t\t'
|
|
513
502
|
); // make output after it's put together with the rest more readable
|
|
@@ -521,87 +510,26 @@ export async function render_response({
|
|
|
521
510
|
args.push(`{\n${indent}\t${hydrate.join(`,\n${indent}\t`)}\n${indent}}`);
|
|
522
511
|
}
|
|
523
512
|
|
|
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);
|
|
513
|
+
const remote_data = await collect_remote_data({}, event, event_state, options);
|
|
579
514
|
|
|
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}`;
|
|
515
|
+
const serialized_data =
|
|
516
|
+
Object.keys(remote_data).length > 0
|
|
517
|
+
? `${global}.data = ${devalue.uneval(remote_data, create_replacer(options.hooks.transport))};\n\n\t\t\t\t\t\t`
|
|
518
|
+
: '';
|
|
590
519
|
|
|
591
520
|
// `client.app` is a proxy for `bundleStrategy === 'split'`
|
|
592
521
|
const boot = client.inline
|
|
593
522
|
? `${client.inline.script}
|
|
594
523
|
|
|
595
|
-
${
|
|
524
|
+
${serialized_data}${global}.app.start(${args.join(', ')});`
|
|
596
525
|
: client.app
|
|
597
|
-
? `
|
|
598
|
-
|
|
599
|
-
import(${s(prefixed(client.app))})
|
|
600
|
-
|
|
601
|
-
${serialized_remote_data}kit.start(app, ${args.join(', ')});
|
|
526
|
+
? `import(${s(prefixed(client.start))}).then(async (kit) => {
|
|
527
|
+
kit.init(${global});
|
|
528
|
+
const app = await import(${s(prefixed(client.app))});
|
|
529
|
+
${serialized_data}kit.start(app, ${args.join(', ')});
|
|
602
530
|
});`
|
|
603
531
|
: `import(${s(prefixed(client.start))}).then((app) => {
|
|
604
|
-
${
|
|
532
|
+
${serialized_data}app.start(${args.join(', ')})
|
|
605
533
|
});`;
|
|
606
534
|
|
|
607
535
|
if (load_env_eagerly) {
|
|
@@ -615,12 +543,9 @@ export async function render_response({
|
|
|
615
543
|
}
|
|
616
544
|
|
|
617
545
|
if (options.service_worker) {
|
|
618
|
-
let opts =
|
|
546
|
+
let opts = ", { type: 'module' }";
|
|
619
547
|
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
|
-
}
|
|
548
|
+
const service_worker_options = { ...options.service_worker_options, type: 'module' };
|
|
624
549
|
opts = `, ${s(service_worker_options)}`;
|
|
625
550
|
}
|
|
626
551
|
|
|
@@ -2,7 +2,6 @@ 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
4
|
import { handle_error_and_jsonify, static_error_page, redirect_response } from '../utils.js';
|
|
5
|
-
import { get_status } from '../../../utils/error.js';
|
|
6
5
|
import { PageNodes } from '../../../utils/page_nodes.js';
|
|
7
6
|
import { server_data_serializer } from './data_serializer.js';
|
|
8
7
|
|
|
@@ -90,6 +89,8 @@ export async function respond_with_error({
|
|
|
90
89
|
);
|
|
91
90
|
}
|
|
92
91
|
|
|
92
|
+
const transformed = await handle_error_and_jsonify(event, event_state, options, error);
|
|
93
|
+
|
|
93
94
|
return await render_response({
|
|
94
95
|
options,
|
|
95
96
|
manifest,
|
|
@@ -98,8 +99,8 @@ export async function respond_with_error({
|
|
|
98
99
|
ssr,
|
|
99
100
|
csr
|
|
100
101
|
},
|
|
101
|
-
status,
|
|
102
|
-
error:
|
|
102
|
+
status: transformed.status,
|
|
103
|
+
error: transformed,
|
|
103
104
|
branch,
|
|
104
105
|
error_components: [],
|
|
105
106
|
fetched,
|
|
@@ -115,10 +116,8 @@ export async function respond_with_error({
|
|
|
115
116
|
return redirect_response(e.status, e.location);
|
|
116
117
|
}
|
|
117
118
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
(await handle_error_and_jsonify(event, event_state, options, e)).message
|
|
122
|
-
);
|
|
119
|
+
const transformed = await handle_error_and_jsonify(event, event_state, options, e);
|
|
120
|
+
|
|
121
|
+
return static_error_page(options, transformed.status, transformed.message);
|
|
123
122
|
}
|
|
124
123
|
}
|
|
@@ -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
|
}
|