@sveltejs/kit 2.18.0 → 2.19.1
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 +1 -1
- package/src/core/postbuild/analyse.js +6 -20
- package/src/exports/index.js +1 -0
- package/src/exports/public.d.ts +1 -1
- package/src/runtime/client/client.js +69 -28
- package/src/runtime/server/cookie.js +23 -4
- package/src/runtime/server/fetch.js +2 -4
- package/src/runtime/server/page/actions.js +1 -1
- package/src/runtime/server/page/index.js +16 -22
- package/src/runtime/server/page/render.js +9 -6
- package/src/runtime/server/page/respond_with_error.js +4 -3
- package/src/runtime/server/respond.js +161 -135
- package/src/runtime/server/utils.js +12 -0
- package/src/types/internal.d.ts +34 -24
- package/src/utils/page_nodes.js +95 -0
- package/src/version.js +1 -1
- package/types/index.d.ts +33 -26
- package/types/index.d.ts.map +3 -1
- package/src/runtime/server/page/load_page_nodes.js +0 -11
- package/src/utils/options.js +0 -16
- package/src/utils/route_config.js +0 -21
package/package.json
CHANGED
|
@@ -1,22 +1,15 @@
|
|
|
1
1
|
import { join } from 'node:path';
|
|
2
2
|
import { pathToFileURL } from 'node:url';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
validate_layout_exports,
|
|
6
|
-
validate_layout_server_exports,
|
|
7
|
-
validate_page_exports,
|
|
8
|
-
validate_page_server_exports,
|
|
9
|
-
validate_server_exports
|
|
10
|
-
} from '../../utils/exports.js';
|
|
3
|
+
import { validate_server_exports } from '../../utils/exports.js';
|
|
11
4
|
import { load_config } from '../config/index.js';
|
|
12
5
|
import { forked } from '../../utils/fork.js';
|
|
13
6
|
import { installPolyfills } from '../../exports/node/polyfills.js';
|
|
14
7
|
import { ENDPOINT_METHODS } from '../../constants.js';
|
|
15
8
|
import { filter_private_env, filter_public_env } from '../../utils/env.js';
|
|
16
9
|
import { has_server_load, resolve_route } from '../../utils/routing.js';
|
|
17
|
-
import { get_page_config } from '../../utils/route_config.js';
|
|
18
10
|
import { check_feature } from '../../utils/features.js';
|
|
19
11
|
import { createReadableStream } from '@sveltejs/kit/node';
|
|
12
|
+
import { PageNodes } from '../../utils/page_nodes.js';
|
|
20
13
|
|
|
21
14
|
export default forked(import.meta.url, analyse);
|
|
22
15
|
|
|
@@ -190,25 +183,18 @@ function analyse_endpoint(route, mod) {
|
|
|
190
183
|
* @param {import('types').SSRNode} leaf
|
|
191
184
|
*/
|
|
192
185
|
function analyse_page(layouts, leaf) {
|
|
193
|
-
for (const layout of layouts) {
|
|
194
|
-
if (layout) {
|
|
195
|
-
validate_layout_server_exports(layout.server, layout.server_id);
|
|
196
|
-
validate_layout_exports(layout.universal, layout.universal_id);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
186
|
/** @type {Array<'GET' | 'POST'>} */
|
|
201
187
|
const methods = ['GET'];
|
|
202
188
|
if (leaf.server?.actions) methods.push('POST');
|
|
203
189
|
|
|
204
|
-
|
|
205
|
-
|
|
190
|
+
const nodes = new PageNodes([...layouts, leaf]);
|
|
191
|
+
nodes.validate();
|
|
206
192
|
|
|
207
193
|
return {
|
|
208
|
-
config:
|
|
194
|
+
config: nodes.get_config(),
|
|
209
195
|
entries: leaf.universal?.entries ?? leaf.server?.entries,
|
|
210
196
|
methods,
|
|
211
|
-
prerender:
|
|
197
|
+
prerender: nodes.prerender()
|
|
212
198
|
};
|
|
213
199
|
}
|
|
214
200
|
|
package/src/exports/index.js
CHANGED
|
@@ -229,6 +229,7 @@ export function isActionFailure(e) {
|
|
|
229
229
|
* ```
|
|
230
230
|
* @param {URL | string} url
|
|
231
231
|
* @returns {{ url: URL, wasNormalized: boolean, denormalize: (url?: string | URL) => URL }}
|
|
232
|
+
* @since 2.18.0
|
|
232
233
|
*/
|
|
233
234
|
export function normalizeUrl(url) {
|
|
234
235
|
url = new URL(url, 'http://internal');
|
package/src/exports/public.d.ts
CHANGED
|
@@ -814,7 +814,7 @@ export type ClientInit = () => MaybePromise<void>;
|
|
|
814
814
|
* The [`reroute`](https://svelte.dev/docs/kit/hooks#Universal-hooks-reroute) hook allows you to modify the URL before it is used to determine which route to render.
|
|
815
815
|
* @since 2.3.0
|
|
816
816
|
*/
|
|
817
|
-
export type Reroute = (event: { url: URL }) => MaybePromise<void | string>;
|
|
817
|
+
export type Reroute = (event: { url: URL; fetch: typeof fetch }) => MaybePromise<void | string>;
|
|
818
818
|
|
|
819
819
|
/**
|
|
820
820
|
* The [`transport`](https://svelte.dev/docs/kit/hooks#Universal-hooks-transport) hook allows you to transport custom types across the server/client boundary.
|
|
@@ -188,6 +188,17 @@ const components = [];
|
|
|
188
188
|
/** @type {{id: string, token: {}, promise: Promise<import('./types.js').NavigationResult>} | null} */
|
|
189
189
|
let load_cache = null;
|
|
190
190
|
|
|
191
|
+
/**
|
|
192
|
+
* @type {Map<string, Promise<URL>>}
|
|
193
|
+
* Cache for client-side rerouting, since it could contain async calls which we want to
|
|
194
|
+
* avoid running multiple times which would slow down navigations (e.g. else preloading
|
|
195
|
+
* wouldn't help because on navigation it would be called again). Since `reroute` should be
|
|
196
|
+
* a pure function (i.e. always return the same) value it's safe to cache across navigations.
|
|
197
|
+
* The server reroute calls don't need to be cached because they are called using `import(...)`
|
|
198
|
+
* which is cached per the JS spec.
|
|
199
|
+
*/
|
|
200
|
+
const reroute_cache = new Map();
|
|
201
|
+
|
|
191
202
|
/**
|
|
192
203
|
* Note on before_navigate_callbacks, on_navigate_callbacks and after_navigate_callbacks:
|
|
193
204
|
* do not re-assign as some closures keep references to these Sets
|
|
@@ -679,12 +690,7 @@ async function load_node({ loader, parent, url, params, route, server_data_node
|
|
|
679
690
|
app.hash
|
|
680
691
|
),
|
|
681
692
|
async fetch(resource, init) {
|
|
682
|
-
/** @type {URL | string} */
|
|
683
|
-
let requested;
|
|
684
|
-
|
|
685
693
|
if (resource instanceof Request) {
|
|
686
|
-
requested = resource.url;
|
|
687
|
-
|
|
688
694
|
// we're not allowed to modify the received `Request` object, so in order
|
|
689
695
|
// to fixup relative urls we create a new equivalent `init` object instead
|
|
690
696
|
init = {
|
|
@@ -709,25 +715,15 @@ async function load_node({ loader, parent, url, params, route, server_data_node
|
|
|
709
715
|
signal: resource.signal,
|
|
710
716
|
...init
|
|
711
717
|
};
|
|
712
|
-
} else {
|
|
713
|
-
requested = resource;
|
|
714
718
|
}
|
|
715
719
|
|
|
716
|
-
|
|
717
|
-
|
|
720
|
+
const { resolved, promise } = resolve_fetch_url(resource, init, url);
|
|
721
|
+
|
|
718
722
|
if (is_tracking) {
|
|
719
723
|
depends(resolved.href);
|
|
720
724
|
}
|
|
721
725
|
|
|
722
|
-
|
|
723
|
-
if (resolved.origin === url.origin) {
|
|
724
|
-
requested = resolved.href.slice(url.origin.length);
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
// prerendered pages may be served from any origin, so `initial_fetch` urls shouldn't be resolved
|
|
728
|
-
return started
|
|
729
|
-
? subsequent_fetch(requested, resolved.href, init)
|
|
730
|
-
: initial_fetch(requested, init);
|
|
726
|
+
return promise;
|
|
731
727
|
},
|
|
732
728
|
setHeaders: () => {}, // noop
|
|
733
729
|
depends,
|
|
@@ -782,6 +778,30 @@ async function load_node({ loader, parent, url, params, route, server_data_node
|
|
|
782
778
|
};
|
|
783
779
|
}
|
|
784
780
|
|
|
781
|
+
/**
|
|
782
|
+
* @param {Request | string | URL} input
|
|
783
|
+
* @param {RequestInit | undefined} init
|
|
784
|
+
* @param {URL} url
|
|
785
|
+
*/
|
|
786
|
+
function resolve_fetch_url(input, init, url) {
|
|
787
|
+
let requested = input instanceof Request ? input.url : input;
|
|
788
|
+
|
|
789
|
+
// we must fixup relative urls so they are resolved from the target page
|
|
790
|
+
const resolved = new URL(requested, url);
|
|
791
|
+
|
|
792
|
+
// match ssr serialized data url, which is important to find cached responses
|
|
793
|
+
if (resolved.origin === url.origin) {
|
|
794
|
+
requested = resolved.href.slice(url.origin.length);
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
// prerendered pages may be served from any origin, so `initial_fetch` urls shouldn't be resolved
|
|
798
|
+
const promise = started
|
|
799
|
+
? subsequent_fetch(requested, resolved.href, init)
|
|
800
|
+
: initial_fetch(requested, init);
|
|
801
|
+
|
|
802
|
+
return { resolved, promise };
|
|
803
|
+
}
|
|
804
|
+
|
|
785
805
|
/**
|
|
786
806
|
* @param {boolean} parent_changed
|
|
787
807
|
* @param {boolean} route_changed
|
|
@@ -1201,23 +1221,44 @@ async function load_root_error_page({ status, error, url, route }) {
|
|
|
1201
1221
|
* @returns {Promise<URL | undefined>}
|
|
1202
1222
|
*/
|
|
1203
1223
|
async function get_rerouted_url(url) {
|
|
1224
|
+
const href = url.href;
|
|
1225
|
+
|
|
1226
|
+
if (reroute_cache.has(href)) {
|
|
1227
|
+
return reroute_cache.get(href);
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1204
1230
|
let rerouted;
|
|
1231
|
+
|
|
1205
1232
|
try {
|
|
1206
|
-
|
|
1207
|
-
|
|
1233
|
+
const promise = (async () => {
|
|
1234
|
+
// reroute could alter the given URL, so we pass a copy
|
|
1235
|
+
let rerouted =
|
|
1236
|
+
(await app.hooks.reroute({
|
|
1237
|
+
url: new URL(url),
|
|
1238
|
+
fetch: async (input, init) => {
|
|
1239
|
+
return resolve_fetch_url(input, init, url).promise;
|
|
1240
|
+
}
|
|
1241
|
+
})) ?? url;
|
|
1208
1242
|
|
|
1209
|
-
|
|
1210
|
-
|
|
1243
|
+
if (typeof rerouted === 'string') {
|
|
1244
|
+
const tmp = new URL(url); // do not mutate the incoming URL
|
|
1211
1245
|
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1246
|
+
if (app.hash) {
|
|
1247
|
+
tmp.hash = rerouted;
|
|
1248
|
+
} else {
|
|
1249
|
+
tmp.pathname = rerouted;
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
rerouted = tmp;
|
|
1216
1253
|
}
|
|
1217
1254
|
|
|
1218
|
-
rerouted
|
|
1219
|
-
}
|
|
1255
|
+
return rerouted;
|
|
1256
|
+
})();
|
|
1257
|
+
|
|
1258
|
+
reroute_cache.set(href, promise);
|
|
1259
|
+
rerouted = await promise;
|
|
1220
1260
|
} catch (e) {
|
|
1261
|
+
reroute_cache.delete(href);
|
|
1221
1262
|
if (DEV) {
|
|
1222
1263
|
// in development, print the error...
|
|
1223
1264
|
console.error(e);
|
|
@@ -29,13 +29,13 @@ function validate_options(options) {
|
|
|
29
29
|
/**
|
|
30
30
|
* @param {Request} request
|
|
31
31
|
* @param {URL} url
|
|
32
|
-
* @param {import('types').TrailingSlash} trailing_slash
|
|
33
32
|
*/
|
|
34
|
-
export function get_cookies(request, url
|
|
33
|
+
export function get_cookies(request, url) {
|
|
35
34
|
const header = request.headers.get('cookie') ?? '';
|
|
36
35
|
const initial_cookies = parse(header, { decode: (value) => value });
|
|
37
36
|
|
|
38
|
-
|
|
37
|
+
/** @type {string | undefined} */
|
|
38
|
+
let normalized_url;
|
|
39
39
|
|
|
40
40
|
/** @type {Record<string, import('./page/types.js').Cookie>} */
|
|
41
41
|
const new_cookies = {};
|
|
@@ -149,6 +149,9 @@ export function get_cookies(request, url, trailing_slash) {
|
|
|
149
149
|
let path = options.path;
|
|
150
150
|
|
|
151
151
|
if (!options.domain || options.domain === url.hostname) {
|
|
152
|
+
if (!normalized_url) {
|
|
153
|
+
throw new Error('Cannot serialize cookies until after the route is determined');
|
|
154
|
+
}
|
|
152
155
|
path = resolve(normalized_url, path);
|
|
153
156
|
}
|
|
154
157
|
|
|
@@ -190,12 +193,20 @@ export function get_cookies(request, url, trailing_slash) {
|
|
|
190
193
|
.join('; ');
|
|
191
194
|
}
|
|
192
195
|
|
|
196
|
+
/** @type {Array<() => void>} */
|
|
197
|
+
const internal_queue = [];
|
|
198
|
+
|
|
193
199
|
/**
|
|
194
200
|
* @param {string} name
|
|
195
201
|
* @param {string} value
|
|
196
202
|
* @param {import('./page/types.js').Cookie['options']} options
|
|
197
203
|
*/
|
|
198
204
|
function set_internal(name, value, options) {
|
|
205
|
+
if (!normalized_url) {
|
|
206
|
+
internal_queue.push(() => set_internal(name, value, options));
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
|
|
199
210
|
let path = options.path;
|
|
200
211
|
|
|
201
212
|
if (!options.domain || options.domain === url.hostname) {
|
|
@@ -220,7 +231,15 @@ export function get_cookies(request, url, trailing_slash) {
|
|
|
220
231
|
}
|
|
221
232
|
}
|
|
222
233
|
|
|
223
|
-
|
|
234
|
+
/**
|
|
235
|
+
* @param {import('types').TrailingSlash} trailing_slash
|
|
236
|
+
*/
|
|
237
|
+
function set_trailing_slash(trailing_slash) {
|
|
238
|
+
normalized_url = normalize_path(url.pathname, trailing_slash);
|
|
239
|
+
internal_queue.forEach((fn) => fn());
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return { cookies, new_cookies, get_cookie_header, set_internal, set_trailing_slash };
|
|
224
243
|
}
|
|
225
244
|
|
|
226
245
|
/**
|
|
@@ -2,6 +2,7 @@ import * as set_cookie_parser from 'set-cookie-parser';
|
|
|
2
2
|
import { respond } from './respond.js';
|
|
3
3
|
import * as paths from '__sveltekit/paths';
|
|
4
4
|
import { read_implementation } from '__sveltekit/server';
|
|
5
|
+
import { has_prerendered_path } from './utils.js';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* @param {{
|
|
@@ -112,10 +113,7 @@ export function create_fetch({ event, options, manifest, state, get_cookie_heade
|
|
|
112
113
|
return await fetch(request);
|
|
113
114
|
}
|
|
114
115
|
|
|
115
|
-
if (
|
|
116
|
-
manifest._.prerendered_routes.has(decoded) ||
|
|
117
|
-
(decoded.at(-1) === '/' && manifest._.prerendered_routes.has(decoded.slice(0, -1)))
|
|
118
|
-
) {
|
|
116
|
+
if (has_prerendered_path(manifest, paths.base + decoded)) {
|
|
119
117
|
// The path of something prerendered could match a different route
|
|
120
118
|
// that is still in the manifest, leading to the wrong route being loaded.
|
|
121
119
|
// We therefore bail early here. The prerendered logic is different for
|
|
@@ -214,7 +214,7 @@ function check_named_default_separate(actions) {
|
|
|
214
214
|
|
|
215
215
|
/**
|
|
216
216
|
* @param {import('@sveltejs/kit').RequestEvent} event
|
|
217
|
-
* @param {NonNullable<import('types').
|
|
217
|
+
* @param {NonNullable<import('types').ServerNode['actions']>} actions
|
|
218
218
|
* @throws {Redirect | HttpError | SvelteKitError | Error}
|
|
219
219
|
*/
|
|
220
220
|
async function call_action(event, actions) {
|
|
@@ -13,9 +13,7 @@ import {
|
|
|
13
13
|
import { load_data, load_server_data } from './load_data.js';
|
|
14
14
|
import { render_response } from './render.js';
|
|
15
15
|
import { respond_with_error } from './respond_with_error.js';
|
|
16
|
-
import { get_option } from '../../../utils/options.js';
|
|
17
16
|
import { get_data_json } from '../data/index.js';
|
|
18
|
-
import { load_page_nodes } from './load_page_nodes.js';
|
|
19
17
|
import { DEV } from 'esm-env';
|
|
20
18
|
|
|
21
19
|
/**
|
|
@@ -29,10 +27,11 @@ const MAX_DEPTH = 10;
|
|
|
29
27
|
* @param {import('types').SSROptions} options
|
|
30
28
|
* @param {import('@sveltejs/kit').SSRManifest} manifest
|
|
31
29
|
* @param {import('types').SSRState} state
|
|
30
|
+
* @param {import('../../../utils/page_nodes.js').PageNodes} nodes
|
|
32
31
|
* @param {import('types').RequiredResolveOptions} resolve_opts
|
|
33
32
|
* @returns {Promise<Response>}
|
|
34
33
|
*/
|
|
35
|
-
export async function render_page(event, page, options, manifest, state, resolve_opts) {
|
|
34
|
+
export async function render_page(event, page, options, manifest, state, nodes, resolve_opts) {
|
|
36
35
|
if (state.depth > MAX_DEPTH) {
|
|
37
36
|
// infinite request cycle detected
|
|
38
37
|
return text(`Not found: ${event.url.pathname}`, {
|
|
@@ -46,9 +45,7 @@ export async function render_page(event, page, options, manifest, state, resolve
|
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
try {
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
const leaf_node = /** @type {import('types').SSRNode} */ (nodes.at(-1));
|
|
48
|
+
const leaf_node = /** @type {import('types').SSRNode} */ (nodes.page());
|
|
52
49
|
|
|
53
50
|
let status = 200;
|
|
54
51
|
|
|
@@ -70,16 +67,10 @@ export async function render_page(event, page, options, manifest, state, resolve
|
|
|
70
67
|
}
|
|
71
68
|
}
|
|
72
69
|
|
|
73
|
-
const should_prerender_data = nodes.some(
|
|
74
|
-
// prerender in case of trailingSlash because the client retrieves that value from the server
|
|
75
|
-
(node) => node?.server?.load || node?.server?.trailingSlash !== undefined
|
|
76
|
-
);
|
|
77
|
-
const data_pathname = add_data_suffix(event.url.pathname);
|
|
78
|
-
|
|
79
70
|
// it's crucial that we do this before returning the non-SSR response, otherwise
|
|
80
71
|
// SvelteKit will erroneously believe that the path has been prerendered,
|
|
81
72
|
// causing functions to be omitted from the manifest generated later
|
|
82
|
-
const should_prerender =
|
|
73
|
+
const should_prerender = nodes.prerender();
|
|
83
74
|
if (should_prerender) {
|
|
84
75
|
const mod = leaf_node.server;
|
|
85
76
|
if (mod?.actions) {
|
|
@@ -96,13 +87,16 @@ export async function render_page(event, page, options, manifest, state, resolve
|
|
|
96
87
|
// inherit the prerender option of the page
|
|
97
88
|
state.prerender_default = should_prerender;
|
|
98
89
|
|
|
90
|
+
const should_prerender_data = nodes.should_prerender_data();
|
|
91
|
+
const data_pathname = add_data_suffix(event.url.pathname);
|
|
92
|
+
|
|
99
93
|
/** @type {import('./types.js').Fetched[]} */
|
|
100
94
|
const fetched = [];
|
|
101
95
|
|
|
102
96
|
// renders an empty 'shell' page if SSR is turned off and if there is
|
|
103
97
|
// no server data to prerender. As a result, the load functions and rendering
|
|
104
98
|
// only occur client-side.
|
|
105
|
-
if (
|
|
99
|
+
if (nodes.ssr() === false && !(state.prerendering && should_prerender_data)) {
|
|
106
100
|
// if the user makes a request through a non-enhanced form, the returned value is lost
|
|
107
101
|
// because there is no SSR or client-side handling of the response
|
|
108
102
|
if (DEV && action_result && !event.request.headers.has('x-sveltekit-action')) {
|
|
@@ -123,7 +117,7 @@ export async function render_page(event, page, options, manifest, state, resolve
|
|
|
123
117
|
fetched,
|
|
124
118
|
page_config: {
|
|
125
119
|
ssr: false,
|
|
126
|
-
csr:
|
|
120
|
+
csr: nodes.csr()
|
|
127
121
|
},
|
|
128
122
|
status,
|
|
129
123
|
error: null,
|
|
@@ -142,7 +136,7 @@ export async function render_page(event, page, options, manifest, state, resolve
|
|
|
142
136
|
let load_error = null;
|
|
143
137
|
|
|
144
138
|
/** @type {Array<Promise<import('types').ServerDataNode | null>>} */
|
|
145
|
-
const server_promises = nodes.map((node, i) => {
|
|
139
|
+
const server_promises = nodes.data.map((node, i) => {
|
|
146
140
|
if (load_error) {
|
|
147
141
|
// if an error happens immediately, don't bother with the rest of the nodes
|
|
148
142
|
throw load_error;
|
|
@@ -177,10 +171,10 @@ export async function render_page(event, page, options, manifest, state, resolve
|
|
|
177
171
|
});
|
|
178
172
|
});
|
|
179
173
|
|
|
180
|
-
const csr =
|
|
174
|
+
const csr = nodes.csr();
|
|
181
175
|
|
|
182
176
|
/** @type {Array<Promise<Record<string, any> | null>>} */
|
|
183
|
-
const load_promises = nodes.map((node, i) => {
|
|
177
|
+
const load_promises = nodes.data.map((node, i) => {
|
|
184
178
|
if (load_error) throw load_error;
|
|
185
179
|
return Promise.resolve().then(async () => {
|
|
186
180
|
try {
|
|
@@ -211,8 +205,8 @@ export async function render_page(event, page, options, manifest, state, resolve
|
|
|
211
205
|
for (const p of server_promises) p.catch(() => {});
|
|
212
206
|
for (const p of load_promises) p.catch(() => {});
|
|
213
207
|
|
|
214
|
-
for (let i = 0; i < nodes.length; i += 1) {
|
|
215
|
-
const node = nodes[i];
|
|
208
|
+
for (let i = 0; i < nodes.data.length; i += 1) {
|
|
209
|
+
const node = nodes.data[i];
|
|
216
210
|
|
|
217
211
|
if (node) {
|
|
218
212
|
try {
|
|
@@ -300,7 +294,7 @@ export async function render_page(event, page, options, manifest, state, resolve
|
|
|
300
294
|
});
|
|
301
295
|
}
|
|
302
296
|
|
|
303
|
-
const ssr =
|
|
297
|
+
const ssr = nodes.ssr();
|
|
304
298
|
|
|
305
299
|
return await render_response({
|
|
306
300
|
event,
|
|
@@ -309,7 +303,7 @@ export async function render_page(event, page, options, manifest, state, resolve
|
|
|
309
303
|
state,
|
|
310
304
|
resolve_opts,
|
|
311
305
|
page_config: {
|
|
312
|
-
csr:
|
|
306
|
+
csr: nodes.csr(),
|
|
313
307
|
ssr
|
|
314
308
|
},
|
|
315
309
|
status,
|
|
@@ -116,11 +116,6 @@ export async function render_response({
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
if (page_config.ssr) {
|
|
119
|
-
if (__SVELTEKIT_DEV__ && !branch.at(-1)?.node.component) {
|
|
120
|
-
// Can only be the leaf, layouts have a fallback component generated
|
|
121
|
-
throw new Error(`Missing +page.svelte component for route ${event.route.id}`);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
119
|
/** @type {Record<string, any>} */
|
|
125
120
|
const props = {
|
|
126
121
|
stores: {
|
|
@@ -128,7 +123,15 @@ export async function render_response({
|
|
|
128
123
|
navigating: writable(null),
|
|
129
124
|
updated
|
|
130
125
|
},
|
|
131
|
-
constructors: await Promise.all(
|
|
126
|
+
constructors: await Promise.all(
|
|
127
|
+
branch.map(({ node }) => {
|
|
128
|
+
if (!node.component) {
|
|
129
|
+
// Can only be the leaf, layouts have a fallback component generated
|
|
130
|
+
throw new Error(`Missing +page.svelte component for route ${event.route.id}`);
|
|
131
|
+
}
|
|
132
|
+
return node.component();
|
|
133
|
+
})
|
|
134
|
+
),
|
|
132
135
|
form: form_value
|
|
133
136
|
};
|
|
134
137
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { render_response } from './render.js';
|
|
2
2
|
import { load_data, load_server_data } from './load_data.js';
|
|
3
3
|
import { handle_error_and_jsonify, static_error_page, redirect_response } from '../utils.js';
|
|
4
|
-
import { get_option } from '../../../utils/options.js';
|
|
5
4
|
import { Redirect } from '../../control.js';
|
|
6
5
|
import { get_status } from '../../../utils/error.js';
|
|
6
|
+
import { PageNodes } from '../../../utils/page_nodes.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* @typedef {import('./types.js').Loaded} Loaded
|
|
@@ -40,8 +40,9 @@ export async function respond_with_error({
|
|
|
40
40
|
try {
|
|
41
41
|
const branch = [];
|
|
42
42
|
const default_layout = await manifest._.nodes[0](); // 0 is always the root layout
|
|
43
|
-
const
|
|
44
|
-
const
|
|
43
|
+
const nodes = new PageNodes([default_layout]);
|
|
44
|
+
const ssr = nodes.ssr();
|
|
45
|
+
const csr = nodes.csr();
|
|
45
46
|
|
|
46
47
|
if (ssr) {
|
|
47
48
|
state.error = true;
|
|
@@ -5,30 +5,29 @@ import { render_page } from './page/index.js';
|
|
|
5
5
|
import { render_response } from './page/render.js';
|
|
6
6
|
import { respond_with_error } from './page/respond_with_error.js';
|
|
7
7
|
import { is_form_content_type } from '../../utils/http.js';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
handle_fatal_error,
|
|
10
|
+
has_prerendered_path,
|
|
11
|
+
method_not_allowed,
|
|
12
|
+
redirect_response
|
|
13
|
+
} from './utils.js';
|
|
9
14
|
import { decode_pathname, decode_params, disable_search, normalize_path } from '../../utils/url.js';
|
|
10
15
|
import { exec } from '../../utils/routing.js';
|
|
11
16
|
import { redirect_json_response, render_data } from './data/index.js';
|
|
12
17
|
import { add_cookies_to_headers, get_cookies } from './cookie.js';
|
|
13
18
|
import { create_fetch } from './fetch.js';
|
|
19
|
+
import { PageNodes } from '../../utils/page_nodes.js';
|
|
14
20
|
import { HttpError, Redirect, SvelteKitError } from '../control.js';
|
|
15
|
-
import {
|
|
16
|
-
validate_layout_exports,
|
|
17
|
-
validate_layout_server_exports,
|
|
18
|
-
validate_page_exports,
|
|
19
|
-
validate_page_server_exports,
|
|
20
|
-
validate_server_exports
|
|
21
|
-
} from '../../utils/exports.js';
|
|
22
|
-
import { get_option } from '../../utils/options.js';
|
|
21
|
+
import { validate_server_exports } from '../../utils/exports.js';
|
|
23
22
|
import { json, text } from '../../exports/index.js';
|
|
24
23
|
import { action_json_redirect, is_action_json_request } from './page/actions.js';
|
|
25
24
|
import { INVALIDATED_PARAM, TRAILING_SLASH_PARAM } from '../shared.js';
|
|
26
25
|
import { get_public_env } from './env_module.js';
|
|
27
|
-
import { load_page_nodes } from './page/load_page_nodes.js';
|
|
28
|
-
import { get_page_config } from '../../utils/route_config.js';
|
|
29
26
|
import { resolve_route } from './page/server_routing.js';
|
|
30
27
|
import { validateHeaders } from './validate-headers.js';
|
|
31
28
|
import {
|
|
29
|
+
add_data_suffix,
|
|
30
|
+
add_resolution_suffix,
|
|
32
31
|
has_data_suffix,
|
|
33
32
|
has_resolution_suffix,
|
|
34
33
|
strip_data_suffix,
|
|
@@ -111,11 +110,82 @@ export async function respond(request, options, manifest, state) {
|
|
|
111
110
|
url.searchParams.delete(INVALIDATED_PARAM);
|
|
112
111
|
}
|
|
113
112
|
|
|
113
|
+
/** @type {Record<string, string>} */
|
|
114
|
+
const headers = {};
|
|
115
|
+
|
|
116
|
+
const { cookies, new_cookies, get_cookie_header, set_internal, set_trailing_slash } = get_cookies(
|
|
117
|
+
request,
|
|
118
|
+
url
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
/** @type {import('@sveltejs/kit').RequestEvent} */
|
|
122
|
+
const event = {
|
|
123
|
+
cookies,
|
|
124
|
+
// @ts-expect-error `fetch` needs to be created after the `event` itself
|
|
125
|
+
fetch: null,
|
|
126
|
+
getClientAddress:
|
|
127
|
+
state.getClientAddress ||
|
|
128
|
+
(() => {
|
|
129
|
+
throw new Error(
|
|
130
|
+
`${__SVELTEKIT_ADAPTER_NAME__} does not specify getClientAddress. Please raise an issue`
|
|
131
|
+
);
|
|
132
|
+
}),
|
|
133
|
+
locals: {},
|
|
134
|
+
params: {},
|
|
135
|
+
platform: state.platform,
|
|
136
|
+
request,
|
|
137
|
+
route: { id: null },
|
|
138
|
+
setHeaders: (new_headers) => {
|
|
139
|
+
if (__SVELTEKIT_DEV__) {
|
|
140
|
+
validateHeaders(new_headers);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
for (const key in new_headers) {
|
|
144
|
+
const lower = key.toLowerCase();
|
|
145
|
+
const value = new_headers[key];
|
|
146
|
+
|
|
147
|
+
if (lower === 'set-cookie') {
|
|
148
|
+
throw new Error(
|
|
149
|
+
'Use `event.cookies.set(name, value, options)` instead of `event.setHeaders` to set cookies'
|
|
150
|
+
);
|
|
151
|
+
} else if (lower in headers) {
|
|
152
|
+
throw new Error(`"${key}" header is already set`);
|
|
153
|
+
} else {
|
|
154
|
+
headers[lower] = value;
|
|
155
|
+
|
|
156
|
+
if (state.prerendering && lower === 'cache-control') {
|
|
157
|
+
state.prerendering.cache = /** @type {string} */ (value);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
url,
|
|
163
|
+
isDataRequest: is_data_request,
|
|
164
|
+
isSubRequest: state.depth > 0
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
event.fetch = create_fetch({
|
|
168
|
+
event,
|
|
169
|
+
options,
|
|
170
|
+
manifest,
|
|
171
|
+
state,
|
|
172
|
+
get_cookie_header,
|
|
173
|
+
set_internal
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
if (state.emulator?.platform) {
|
|
177
|
+
event.platform = await state.emulator.platform({
|
|
178
|
+
config: {},
|
|
179
|
+
prerender: !!state.prerendering?.fallback
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
114
183
|
let resolved_path;
|
|
115
184
|
|
|
116
185
|
try {
|
|
117
186
|
// reroute could alter the given URL, so we pass a copy
|
|
118
|
-
resolved_path =
|
|
187
|
+
resolved_path =
|
|
188
|
+
(await options.hooks.reroute({ url: new URL(url), fetch: event.fetch })) ?? url.pathname;
|
|
119
189
|
} catch {
|
|
120
190
|
return text('Internal Server Error', {
|
|
121
191
|
status: 500
|
|
@@ -128,12 +198,37 @@ export async function respond(request, options, manifest, state) {
|
|
|
128
198
|
return text('Malformed URI', { status: 400 });
|
|
129
199
|
}
|
|
130
200
|
|
|
201
|
+
if (
|
|
202
|
+
resolved_path !== url.pathname &&
|
|
203
|
+
!state.prerendering?.fallback &&
|
|
204
|
+
has_prerendered_path(manifest, resolved_path)
|
|
205
|
+
) {
|
|
206
|
+
const url = new URL(request.url);
|
|
207
|
+
url.pathname = is_data_request
|
|
208
|
+
? add_data_suffix(resolved_path)
|
|
209
|
+
: is_route_resolution_request
|
|
210
|
+
? add_resolution_suffix(resolved_path)
|
|
211
|
+
: resolved_path;
|
|
212
|
+
|
|
213
|
+
// `fetch` automatically decodes the body, so we need to delete the related headers to not break the response
|
|
214
|
+
// Also see https://github.com/sveltejs/kit/issues/12197 for more info (we should fix this more generally at some point)
|
|
215
|
+
const response = await fetch(url, request);
|
|
216
|
+
const headers = new Headers(response.headers);
|
|
217
|
+
if (headers.has('content-encoding')) {
|
|
218
|
+
headers.delete('content-encoding');
|
|
219
|
+
headers.delete('content-length');
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return new Response(response.body, {
|
|
223
|
+
headers,
|
|
224
|
+
status: response.status,
|
|
225
|
+
statusText: response.statusText
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
131
229
|
/** @type {import('types').SSRRoute | null} */
|
|
132
230
|
let route = null;
|
|
133
231
|
|
|
134
|
-
/** @type {Record<string, string>} */
|
|
135
|
-
let params = {};
|
|
136
|
-
|
|
137
232
|
if (base && !state.prerendering?.fallback) {
|
|
138
233
|
if (!resolved_path.startsWith(base)) {
|
|
139
234
|
return text('Not found', { status: 404 });
|
|
@@ -167,68 +262,13 @@ export async function respond(request, options, manifest, state) {
|
|
|
167
262
|
const matched = exec(match, candidate.params, matchers);
|
|
168
263
|
if (matched) {
|
|
169
264
|
route = candidate;
|
|
170
|
-
|
|
265
|
+
event.route = { id: route.id };
|
|
266
|
+
event.params = decode_params(matched);
|
|
171
267
|
break;
|
|
172
268
|
}
|
|
173
269
|
}
|
|
174
270
|
}
|
|
175
271
|
|
|
176
|
-
/** @type {import('types').TrailingSlash | void} */
|
|
177
|
-
let trailing_slash = undefined;
|
|
178
|
-
|
|
179
|
-
/** @type {Record<string, string>} */
|
|
180
|
-
const headers = {};
|
|
181
|
-
|
|
182
|
-
/** @type {Record<string, import('./page/types.js').Cookie>} */
|
|
183
|
-
let cookies_to_add = {};
|
|
184
|
-
|
|
185
|
-
/** @type {import('@sveltejs/kit').RequestEvent} */
|
|
186
|
-
const event = {
|
|
187
|
-
// @ts-expect-error `cookies` and `fetch` need to be created after the `event` itself
|
|
188
|
-
cookies: null,
|
|
189
|
-
// @ts-expect-error
|
|
190
|
-
fetch: null,
|
|
191
|
-
getClientAddress:
|
|
192
|
-
state.getClientAddress ||
|
|
193
|
-
(() => {
|
|
194
|
-
throw new Error(
|
|
195
|
-
`${__SVELTEKIT_ADAPTER_NAME__} does not specify getClientAddress. Please raise an issue`
|
|
196
|
-
);
|
|
197
|
-
}),
|
|
198
|
-
locals: {},
|
|
199
|
-
params,
|
|
200
|
-
platform: state.platform,
|
|
201
|
-
request,
|
|
202
|
-
route: { id: route?.id ?? null },
|
|
203
|
-
setHeaders: (new_headers) => {
|
|
204
|
-
if (__SVELTEKIT_DEV__) {
|
|
205
|
-
validateHeaders(new_headers);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
for (const key in new_headers) {
|
|
209
|
-
const lower = key.toLowerCase();
|
|
210
|
-
const value = new_headers[key];
|
|
211
|
-
|
|
212
|
-
if (lower === 'set-cookie') {
|
|
213
|
-
throw new Error(
|
|
214
|
-
'Use `event.cookies.set(name, value, options)` instead of `event.setHeaders` to set cookies'
|
|
215
|
-
);
|
|
216
|
-
} else if (lower in headers) {
|
|
217
|
-
throw new Error(`"${key}" header is already set`);
|
|
218
|
-
} else {
|
|
219
|
-
headers[lower] = value;
|
|
220
|
-
|
|
221
|
-
if (state.prerendering && lower === 'cache-control') {
|
|
222
|
-
state.prerendering.cache = /** @type {string} */ (value);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
},
|
|
227
|
-
url,
|
|
228
|
-
isDataRequest: is_data_request,
|
|
229
|
-
isSubRequest: state.depth > 0
|
|
230
|
-
};
|
|
231
|
-
|
|
232
272
|
/** @type {import('types').RequiredResolveOptions} */
|
|
233
273
|
let resolve_opts = {
|
|
234
274
|
transformPageChunk: default_transform,
|
|
@@ -236,51 +276,36 @@ export async function respond(request, options, manifest, state) {
|
|
|
236
276
|
preload: default_preload
|
|
237
277
|
};
|
|
238
278
|
|
|
279
|
+
/** @type {import('types').TrailingSlash} */
|
|
280
|
+
let trailing_slash = 'never';
|
|
281
|
+
|
|
239
282
|
try {
|
|
283
|
+
/** @type {PageNodes|undefined} */
|
|
284
|
+
const page_nodes = route?.page
|
|
285
|
+
? new PageNodes(await load_page_nodes(route.page, manifest))
|
|
286
|
+
: undefined;
|
|
287
|
+
|
|
240
288
|
// determine whether we need to redirect to add/remove a trailing slash
|
|
241
289
|
if (route) {
|
|
242
290
|
// if `paths.base === '/a/b/c`, then the root route is `/a/b/c/`,
|
|
243
291
|
// regardless of the `trailingSlash` route option
|
|
244
292
|
if (url.pathname === base || url.pathname === base + '/') {
|
|
245
293
|
trailing_slash = 'always';
|
|
246
|
-
} else if (
|
|
247
|
-
const nodes = await load_page_nodes(route.page, manifest);
|
|
248
|
-
|
|
294
|
+
} else if (page_nodes) {
|
|
249
295
|
if (DEV) {
|
|
250
|
-
|
|
251
|
-
const page = nodes.at(-1);
|
|
252
|
-
|
|
253
|
-
for (const layout of layouts) {
|
|
254
|
-
if (layout) {
|
|
255
|
-
validate_layout_server_exports(
|
|
256
|
-
layout.server,
|
|
257
|
-
/** @type {string} */ (layout.server_id)
|
|
258
|
-
);
|
|
259
|
-
validate_layout_exports(
|
|
260
|
-
layout.universal,
|
|
261
|
-
/** @type {string} */ (layout.universal_id)
|
|
262
|
-
);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
if (page) {
|
|
267
|
-
validate_page_server_exports(page.server, /** @type {string} */ (page.server_id));
|
|
268
|
-
validate_page_exports(page.universal, /** @type {string} */ (page.universal_id));
|
|
269
|
-
}
|
|
296
|
+
page_nodes.validate();
|
|
270
297
|
}
|
|
271
|
-
|
|
272
|
-
trailing_slash = get_option(nodes, 'trailingSlash');
|
|
298
|
+
trailing_slash = page_nodes.trailing_slash();
|
|
273
299
|
} else if (route.endpoint) {
|
|
274
300
|
const node = await route.endpoint();
|
|
275
|
-
trailing_slash = node.trailingSlash;
|
|
276
|
-
|
|
301
|
+
trailing_slash = node.trailingSlash ?? 'never';
|
|
277
302
|
if (DEV) {
|
|
278
303
|
validate_server_exports(node, /** @type {string} */ (route.endpoint_id));
|
|
279
304
|
}
|
|
280
305
|
}
|
|
281
306
|
|
|
282
307
|
if (!is_data_request) {
|
|
283
|
-
const normalized = normalize_path(url.pathname, trailing_slash
|
|
308
|
+
const normalized = normalize_path(url.pathname, trailing_slash);
|
|
284
309
|
|
|
285
310
|
if (normalized !== url.pathname && !state.prerendering?.fallback) {
|
|
286
311
|
return new Response(undefined, {
|
|
@@ -306,10 +331,9 @@ export async function respond(request, options, manifest, state) {
|
|
|
306
331
|
const node = await route.endpoint();
|
|
307
332
|
config = node.config ?? config;
|
|
308
333
|
prerender = node.prerender ?? prerender;
|
|
309
|
-
} else if (
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
prerender = get_option(nodes, 'prerender') ?? false;
|
|
334
|
+
} else if (page_nodes) {
|
|
335
|
+
config = page_nodes.get_config() ?? config;
|
|
336
|
+
prerender = page_nodes.prerender();
|
|
313
337
|
}
|
|
314
338
|
|
|
315
339
|
if (state.before_handle) {
|
|
@@ -320,36 +344,16 @@ export async function respond(request, options, manifest, state) {
|
|
|
320
344
|
event.platform = await state.emulator.platform({ config, prerender });
|
|
321
345
|
}
|
|
322
346
|
}
|
|
323
|
-
} else if (state.emulator?.platform) {
|
|
324
|
-
event.platform = await state.emulator.platform({
|
|
325
|
-
config: {},
|
|
326
|
-
prerender: !!state.prerendering?.fallback
|
|
327
|
-
});
|
|
328
347
|
}
|
|
329
348
|
|
|
330
|
-
|
|
331
|
-
request,
|
|
332
|
-
url,
|
|
333
|
-
trailing_slash ?? 'never'
|
|
334
|
-
);
|
|
335
|
-
|
|
336
|
-
cookies_to_add = new_cookies;
|
|
337
|
-
event.cookies = cookies;
|
|
338
|
-
event.fetch = create_fetch({
|
|
339
|
-
event,
|
|
340
|
-
options,
|
|
341
|
-
manifest,
|
|
342
|
-
state,
|
|
343
|
-
get_cookie_header,
|
|
344
|
-
set_internal
|
|
345
|
-
});
|
|
349
|
+
set_trailing_slash(trailing_slash);
|
|
346
350
|
|
|
347
351
|
if (state.prerendering && !state.prerendering.fallback) disable_search(url);
|
|
348
352
|
|
|
349
353
|
const response = await options.hooks.handle({
|
|
350
354
|
event,
|
|
351
355
|
resolve: (event, opts) =>
|
|
352
|
-
resolve(event, opts).then((response) => {
|
|
356
|
+
resolve(event, page_nodes, opts).then((response) => {
|
|
353
357
|
// add headers/cookies here, rather than inside `resolve`, so that we
|
|
354
358
|
// can do it once for all responses instead of once per `return`
|
|
355
359
|
for (const key in headers) {
|
|
@@ -357,7 +361,7 @@ export async function respond(request, options, manifest, state) {
|
|
|
357
361
|
response.headers.set(key, /** @type {string} */ (value));
|
|
358
362
|
}
|
|
359
363
|
|
|
360
|
-
add_cookies_to_headers(response.headers, Object.values(
|
|
364
|
+
add_cookies_to_headers(response.headers, Object.values(new_cookies));
|
|
361
365
|
|
|
362
366
|
if (state.prerendering && event.route.id !== null) {
|
|
363
367
|
response.headers.set('x-sveltekit-routeid', encodeURI(event.route.id));
|
|
@@ -418,7 +422,7 @@ export async function respond(request, options, manifest, state) {
|
|
|
418
422
|
: route?.page && is_action_json_request(event)
|
|
419
423
|
? action_json_redirect(e)
|
|
420
424
|
: redirect_response(e.status, e.location);
|
|
421
|
-
add_cookies_to_headers(response.headers, Object.values(
|
|
425
|
+
add_cookies_to_headers(response.headers, Object.values(new_cookies));
|
|
422
426
|
return response;
|
|
423
427
|
}
|
|
424
428
|
return await handle_fatal_error(event, options, e);
|
|
@@ -426,9 +430,10 @@ export async function respond(request, options, manifest, state) {
|
|
|
426
430
|
|
|
427
431
|
/**
|
|
428
432
|
* @param {import('@sveltejs/kit').RequestEvent} event
|
|
433
|
+
* @param {PageNodes | undefined} page_nodes
|
|
429
434
|
* @param {import('@sveltejs/kit').ResolveOptions} [opts]
|
|
430
435
|
*/
|
|
431
|
-
async function resolve(event, opts) {
|
|
436
|
+
async function resolve(event, page_nodes, opts) {
|
|
432
437
|
try {
|
|
433
438
|
if (opts) {
|
|
434
439
|
resolve_opts = {
|
|
@@ -467,13 +472,23 @@ export async function respond(request, options, manifest, state) {
|
|
|
467
472
|
manifest,
|
|
468
473
|
state,
|
|
469
474
|
invalidated_data_nodes,
|
|
470
|
-
trailing_slash
|
|
475
|
+
trailing_slash
|
|
471
476
|
);
|
|
472
477
|
} else if (route.endpoint && (!route.page || is_endpoint_request(event))) {
|
|
473
478
|
response = await render_endpoint(event, await route.endpoint(), state);
|
|
474
479
|
} else if (route.page) {
|
|
475
|
-
if (
|
|
476
|
-
|
|
480
|
+
if (!page_nodes) {
|
|
481
|
+
throw new Error('page_nodes not found. This should never happen');
|
|
482
|
+
} else if (page_methods.has(method)) {
|
|
483
|
+
response = await render_page(
|
|
484
|
+
event,
|
|
485
|
+
route.page,
|
|
486
|
+
options,
|
|
487
|
+
manifest,
|
|
488
|
+
state,
|
|
489
|
+
page_nodes,
|
|
490
|
+
resolve_opts
|
|
491
|
+
);
|
|
477
492
|
} else {
|
|
478
493
|
const allowed_methods = new Set(allowed_page_methods);
|
|
479
494
|
const node = await manifest._.nodes[route.page.leaf]();
|
|
@@ -499,9 +514,8 @@ export async function respond(request, options, manifest, state) {
|
|
|
499
514
|
}
|
|
500
515
|
}
|
|
501
516
|
} else {
|
|
502
|
-
// a route will always have a page or an endpoint, but TypeScript
|
|
503
|
-
|
|
504
|
-
throw new Error('This should never happen');
|
|
517
|
+
// a route will always have a page or an endpoint, but TypeScript doesn't know that
|
|
518
|
+
throw new Error('Route is neither page nor endpoint. This should never happen');
|
|
505
519
|
}
|
|
506
520
|
|
|
507
521
|
// If the route contains a page and an endpoint, we need to add a
|
|
@@ -578,3 +592,15 @@ export async function respond(request, options, manifest, state) {
|
|
|
578
592
|
}
|
|
579
593
|
}
|
|
580
594
|
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* @param {import('types').PageNodeIndexes} page
|
|
598
|
+
* @param {import('@sveltejs/kit').SSRManifest} manifest
|
|
599
|
+
*/
|
|
600
|
+
export function load_page_nodes(page, manifest) {
|
|
601
|
+
return Promise.all([
|
|
602
|
+
// we use == here rather than === because [undefined] serializes as "[null]"
|
|
603
|
+
...page.layouts.map((n) => (n == undefined ? n : manifest._.nodes[n]())),
|
|
604
|
+
manifest._.nodes[page.leaf]()
|
|
605
|
+
]);
|
|
606
|
+
}
|
|
@@ -163,3 +163,15 @@ export function stringify_uses(node) {
|
|
|
163
163
|
|
|
164
164
|
return `"uses":{${uses.join(',')}}`;
|
|
165
165
|
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Returns `true` if the given path was prerendered
|
|
169
|
+
* @param {import('@sveltejs/kit').SSRManifest} manifest
|
|
170
|
+
* @param {string} pathname Should include the base and be decoded
|
|
171
|
+
*/
|
|
172
|
+
export function has_prerendered_path(manifest, pathname) {
|
|
173
|
+
return (
|
|
174
|
+
manifest._.prerendered_routes.has(pathname) ||
|
|
175
|
+
(pathname.at(-1) === '/' && manifest._.prerendered_routes.has(pathname.slice(0, -1)))
|
|
176
|
+
);
|
|
177
|
+
}
|
package/src/types/internal.d.ts
CHANGED
|
@@ -364,8 +364,28 @@ export interface SSRComponent {
|
|
|
364
364
|
|
|
365
365
|
export type SSRComponentLoader = () => Promise<SSRComponent>;
|
|
366
366
|
|
|
367
|
+
export interface UniversalNode {
|
|
368
|
+
load?: Load;
|
|
369
|
+
prerender?: PrerenderOption;
|
|
370
|
+
ssr?: boolean;
|
|
371
|
+
csr?: boolean;
|
|
372
|
+
trailingSlash?: TrailingSlash;
|
|
373
|
+
config?: any;
|
|
374
|
+
entries?: PrerenderEntryGenerator;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
export interface ServerNode {
|
|
378
|
+
load?: ServerLoad;
|
|
379
|
+
prerender?: PrerenderOption;
|
|
380
|
+
ssr?: boolean;
|
|
381
|
+
csr?: boolean;
|
|
382
|
+
trailingSlash?: TrailingSlash;
|
|
383
|
+
actions?: Actions;
|
|
384
|
+
config?: any;
|
|
385
|
+
entries?: PrerenderEntryGenerator;
|
|
386
|
+
}
|
|
387
|
+
|
|
367
388
|
export interface SSRNode {
|
|
368
|
-
component: SSRComponentLoader;
|
|
369
389
|
/** index into the `nodes` array in the generated `client/app.js`. */
|
|
370
390
|
index: number;
|
|
371
391
|
/** external JS files that are loaded on the client. `imports[0]` is the entry point (e.g. `client/nodes/0.js`) */
|
|
@@ -374,32 +394,18 @@ export interface SSRNode {
|
|
|
374
394
|
stylesheets: string[];
|
|
375
395
|
/** external font files that are loaded on the client */
|
|
376
396
|
fonts: string[];
|
|
377
|
-
/** inlined styles. */
|
|
378
|
-
inline_styles?(): MaybePromise<Record<string, string>>;
|
|
379
|
-
|
|
380
|
-
universal: {
|
|
381
|
-
load?: Load;
|
|
382
|
-
prerender?: PrerenderOption;
|
|
383
|
-
ssr?: boolean;
|
|
384
|
-
csr?: boolean;
|
|
385
|
-
trailingSlash?: TrailingSlash;
|
|
386
|
-
config?: any;
|
|
387
|
-
entries?: PrerenderEntryGenerator;
|
|
388
|
-
};
|
|
389
|
-
|
|
390
|
-
server: {
|
|
391
|
-
load?: ServerLoad;
|
|
392
|
-
prerender?: PrerenderOption;
|
|
393
|
-
ssr?: boolean;
|
|
394
|
-
csr?: boolean;
|
|
395
|
-
trailingSlash?: TrailingSlash;
|
|
396
|
-
actions?: Actions;
|
|
397
|
-
config?: any;
|
|
398
|
-
entries?: PrerenderEntryGenerator;
|
|
399
|
-
};
|
|
400
397
|
|
|
401
398
|
universal_id?: string;
|
|
402
399
|
server_id?: string;
|
|
400
|
+
|
|
401
|
+
/** inlined styles. */
|
|
402
|
+
inline_styles?(): MaybePromise<Record<string, string>>;
|
|
403
|
+
/** Svelte component */
|
|
404
|
+
component?: SSRComponentLoader;
|
|
405
|
+
/** +page.js or +layout.js */
|
|
406
|
+
universal?: UniversalNode;
|
|
407
|
+
/** +page.server.js, +layout.server.js, or +server.js */
|
|
408
|
+
server?: ServerNode;
|
|
403
409
|
}
|
|
404
410
|
|
|
405
411
|
export type SSRNodeLoader = () => Promise<SSRNode>;
|
|
@@ -482,6 +488,10 @@ export interface SSRState {
|
|
|
482
488
|
*/
|
|
483
489
|
prerender_default?: PrerenderOption;
|
|
484
490
|
read?: (file: string) => Buffer;
|
|
491
|
+
/**
|
|
492
|
+
* Used to setup `__SVELTEKIT_TRACK__` which checks if a used feature is supported.
|
|
493
|
+
* E.g. if `read` from `$app/server` is used, it checks whether the route's config is compatible.
|
|
494
|
+
*/
|
|
485
495
|
before_handle?: (event: RequestEvent, config: any, prerender: PrerenderOption) => void;
|
|
486
496
|
emulator?: Emulator;
|
|
487
497
|
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import {
|
|
2
|
+
validate_layout_exports,
|
|
3
|
+
validate_layout_server_exports,
|
|
4
|
+
validate_page_exports,
|
|
5
|
+
validate_page_server_exports
|
|
6
|
+
} from './exports.js';
|
|
7
|
+
|
|
8
|
+
export class PageNodes {
|
|
9
|
+
data;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {Array<import('types').SSRNode | undefined>} nodes
|
|
13
|
+
*/
|
|
14
|
+
constructor(nodes) {
|
|
15
|
+
this.data = nodes;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
layouts() {
|
|
19
|
+
return this.data.slice(0, -1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
page() {
|
|
23
|
+
return this.data.at(-1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
validate() {
|
|
27
|
+
for (const layout of this.layouts()) {
|
|
28
|
+
if (layout) {
|
|
29
|
+
validate_layout_server_exports(layout.server, /** @type {string} */ (layout.server_id));
|
|
30
|
+
validate_layout_exports(layout.universal, /** @type {string} */ (layout.universal_id));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const page = this.page();
|
|
35
|
+
if (page) {
|
|
36
|
+
validate_page_server_exports(page.server, /** @type {string} */ (page.server_id));
|
|
37
|
+
validate_page_exports(page.universal, /** @type {string} */ (page.universal_id));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @template {'prerender' | 'ssr' | 'csr' | 'trailingSlash' | 'entries'} Option
|
|
43
|
+
* @template {(import('types').UniversalNode | import('types').ServerNode)[Option]} Value
|
|
44
|
+
* @param {Option} option
|
|
45
|
+
* @returns {Value | undefined}
|
|
46
|
+
*/
|
|
47
|
+
#get_option(option) {
|
|
48
|
+
return this.data.reduce((value, node) => {
|
|
49
|
+
return /** @type {Value} TypeScript's too dumb to understand this */ (
|
|
50
|
+
node?.universal?.[option] ?? node?.server?.[option] ?? value
|
|
51
|
+
);
|
|
52
|
+
}, /** @type {Value | undefined} */ (undefined));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
csr() {
|
|
56
|
+
return this.#get_option('csr') ?? true;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
ssr() {
|
|
60
|
+
return this.#get_option('ssr') ?? true;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
prerender() {
|
|
64
|
+
return this.#get_option('prerender') ?? false;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
trailing_slash() {
|
|
68
|
+
return this.#get_option('trailingSlash') ?? 'never';
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
get_config() {
|
|
72
|
+
/** @type {any} */
|
|
73
|
+
let current = {};
|
|
74
|
+
|
|
75
|
+
for (const node of this.data) {
|
|
76
|
+
if (!node?.universal?.config && !node?.server?.config) continue;
|
|
77
|
+
|
|
78
|
+
current = {
|
|
79
|
+
...current,
|
|
80
|
+
...node?.universal?.config,
|
|
81
|
+
...node?.server?.config
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// TODO 3.0 always return `current`? then we can get rid of `?? {}` in other places
|
|
86
|
+
return Object.keys(current).length ? current : undefined;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
should_prerender_data() {
|
|
90
|
+
return this.data.some(
|
|
91
|
+
// prerender in case of trailingSlash because the client retrieves that value from the server
|
|
92
|
+
(node) => node?.server?.load || node?.server?.trailingSlash !== undefined
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
}
|
package/src/version.js
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -796,7 +796,7 @@ declare module '@sveltejs/kit' {
|
|
|
796
796
|
* The [`reroute`](https://svelte.dev/docs/kit/hooks#Universal-hooks-reroute) hook allows you to modify the URL before it is used to determine which route to render.
|
|
797
797
|
* @since 2.3.0
|
|
798
798
|
*/
|
|
799
|
-
export type Reroute = (event: { url: URL }) => MaybePromise<void | string>;
|
|
799
|
+
export type Reroute = (event: { url: URL; fetch: typeof fetch }) => MaybePromise<void | string>;
|
|
800
800
|
|
|
801
801
|
/**
|
|
802
802
|
* The [`transport`](https://svelte.dev/docs/kit/hooks#Universal-hooks-transport) hook allows you to transport custom types across the server/client boundary.
|
|
@@ -1842,8 +1842,28 @@ declare module '@sveltejs/kit' {
|
|
|
1842
1842
|
|
|
1843
1843
|
type SSRComponentLoader = () => Promise<SSRComponent>;
|
|
1844
1844
|
|
|
1845
|
+
interface UniversalNode {
|
|
1846
|
+
load?: Load;
|
|
1847
|
+
prerender?: PrerenderOption;
|
|
1848
|
+
ssr?: boolean;
|
|
1849
|
+
csr?: boolean;
|
|
1850
|
+
trailingSlash?: TrailingSlash;
|
|
1851
|
+
config?: any;
|
|
1852
|
+
entries?: PrerenderEntryGenerator;
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1855
|
+
interface ServerNode {
|
|
1856
|
+
load?: ServerLoad;
|
|
1857
|
+
prerender?: PrerenderOption;
|
|
1858
|
+
ssr?: boolean;
|
|
1859
|
+
csr?: boolean;
|
|
1860
|
+
trailingSlash?: TrailingSlash;
|
|
1861
|
+
actions?: Actions;
|
|
1862
|
+
config?: any;
|
|
1863
|
+
entries?: PrerenderEntryGenerator;
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1845
1866
|
interface SSRNode {
|
|
1846
|
-
component: SSRComponentLoader;
|
|
1847
1867
|
/** index into the `nodes` array in the generated `client/app.js`. */
|
|
1848
1868
|
index: number;
|
|
1849
1869
|
/** external JS files that are loaded on the client. `imports[0]` is the entry point (e.g. `client/nodes/0.js`) */
|
|
@@ -1852,32 +1872,18 @@ declare module '@sveltejs/kit' {
|
|
|
1852
1872
|
stylesheets: string[];
|
|
1853
1873
|
/** external font files that are loaded on the client */
|
|
1854
1874
|
fonts: string[];
|
|
1855
|
-
/** inlined styles. */
|
|
1856
|
-
inline_styles?(): MaybePromise<Record<string, string>>;
|
|
1857
|
-
|
|
1858
|
-
universal: {
|
|
1859
|
-
load?: Load;
|
|
1860
|
-
prerender?: PrerenderOption;
|
|
1861
|
-
ssr?: boolean;
|
|
1862
|
-
csr?: boolean;
|
|
1863
|
-
trailingSlash?: TrailingSlash;
|
|
1864
|
-
config?: any;
|
|
1865
|
-
entries?: PrerenderEntryGenerator;
|
|
1866
|
-
};
|
|
1867
|
-
|
|
1868
|
-
server: {
|
|
1869
|
-
load?: ServerLoad;
|
|
1870
|
-
prerender?: PrerenderOption;
|
|
1871
|
-
ssr?: boolean;
|
|
1872
|
-
csr?: boolean;
|
|
1873
|
-
trailingSlash?: TrailingSlash;
|
|
1874
|
-
actions?: Actions;
|
|
1875
|
-
config?: any;
|
|
1876
|
-
entries?: PrerenderEntryGenerator;
|
|
1877
|
-
};
|
|
1878
1875
|
|
|
1879
1876
|
universal_id?: string;
|
|
1880
1877
|
server_id?: string;
|
|
1878
|
+
|
|
1879
|
+
/** inlined styles. */
|
|
1880
|
+
inline_styles?(): MaybePromise<Record<string, string>>;
|
|
1881
|
+
/** Svelte component */
|
|
1882
|
+
component?: SSRComponentLoader;
|
|
1883
|
+
/** +page.js or +layout.js */
|
|
1884
|
+
universal?: UniversalNode;
|
|
1885
|
+
/** +page.server.js, +layout.server.js, or +server.js */
|
|
1886
|
+
server?: ServerNode;
|
|
1881
1887
|
}
|
|
1882
1888
|
|
|
1883
1889
|
type SSRNodeLoader = () => Promise<SSRNode>;
|
|
@@ -2016,7 +2022,8 @@ declare module '@sveltejs/kit' {
|
|
|
2016
2022
|
* console.log(url.pathname); // /blog/post
|
|
2017
2023
|
* console.log(denormalize('/blog/post/a')); // /blog/post/a/__data.json
|
|
2018
2024
|
* ```
|
|
2019
|
-
*
|
|
2025
|
+
* @since 2.18.0
|
|
2026
|
+
*/
|
|
2020
2027
|
export function normalizeUrl(url: URL | string): {
|
|
2021
2028
|
url: URL;
|
|
2022
2029
|
wasNormalized: boolean;
|
package/types/index.d.ts.map
CHANGED
|
@@ -73,6 +73,8 @@
|
|
|
73
73
|
"RouteData",
|
|
74
74
|
"SSRComponent",
|
|
75
75
|
"SSRComponentLoader",
|
|
76
|
+
"UniversalNode",
|
|
77
|
+
"ServerNode",
|
|
76
78
|
"SSRNode",
|
|
77
79
|
"SSRNodeLoader",
|
|
78
80
|
"PageNodeIndexes",
|
|
@@ -161,6 +163,6 @@
|
|
|
161
163
|
null,
|
|
162
164
|
null
|
|
163
165
|
],
|
|
164
|
-
"mappings": "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
|
|
166
|
+
"mappings": "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",
|
|
165
167
|
"ignoreList": []
|
|
166
168
|
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @param {import('types').PageNodeIndexes} page
|
|
3
|
-
* @param {import('@sveltejs/kit').SSRManifest} manifest
|
|
4
|
-
*/
|
|
5
|
-
export function load_page_nodes(page, manifest) {
|
|
6
|
-
return Promise.all([
|
|
7
|
-
// we use == here rather than === because [undefined] serializes as "[null]"
|
|
8
|
-
...page.layouts.map((n) => (n == undefined ? n : manifest._.nodes[n]())),
|
|
9
|
-
manifest._.nodes[page.leaf]()
|
|
10
|
-
]);
|
|
11
|
-
}
|
package/src/utils/options.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @template {'prerender' | 'ssr' | 'csr' | 'trailingSlash' | 'entries'} Option
|
|
3
|
-
* @template {(import('types').SSRNode['universal'] | import('types').SSRNode['server'])[Option]} Value
|
|
4
|
-
*
|
|
5
|
-
* @param {Array<import('types').SSRNode | undefined>} nodes
|
|
6
|
-
* @param {Option} option
|
|
7
|
-
*
|
|
8
|
-
* @returns {Value | undefined}
|
|
9
|
-
*/
|
|
10
|
-
export function get_option(nodes, option) {
|
|
11
|
-
return nodes.reduce((value, node) => {
|
|
12
|
-
return /** @type {Value} TypeScript's too dumb to understand this */ (
|
|
13
|
-
node?.universal?.[option] ?? node?.server?.[option] ?? value
|
|
14
|
-
);
|
|
15
|
-
}, /** @type {Value | undefined} */ (undefined));
|
|
16
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Do a shallow merge (first level) of the config object
|
|
3
|
-
* @param {Array<import('types').SSRNode | undefined>} nodes
|
|
4
|
-
*/
|
|
5
|
-
export function get_page_config(nodes) {
|
|
6
|
-
/** @type {any} */
|
|
7
|
-
let current = {};
|
|
8
|
-
|
|
9
|
-
for (const node of nodes) {
|
|
10
|
-
if (!node?.universal?.config && !node?.server?.config) continue;
|
|
11
|
-
|
|
12
|
-
current = {
|
|
13
|
-
...current,
|
|
14
|
-
...node?.universal?.config,
|
|
15
|
-
...node?.server?.config
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// TODO 3.0 always return `current`? then we can get rid of `?? {}` in other places
|
|
20
|
-
return Object.keys(current).length ? current : undefined;
|
|
21
|
-
}
|