@sveltejs/kit 2.17.3 → 2.19.0
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 +2 -2
- package/src/core/generate_manifest/find_server_assets.js +1 -0
- package/src/core/generate_manifest/index.js +2 -4
- package/src/core/postbuild/analyse.js +6 -20
- package/src/exports/index.js +55 -0
- package/src/exports/public.d.ts +11 -10
- package/src/exports/vite/dev/index.js +6 -9
- package/src/runtime/client/client.js +116 -66
- package/src/runtime/server/cookie.js +23 -4
- package/src/runtime/server/page/actions.js +1 -1
- package/src/runtime/server/page/index.js +16 -22
- package/src/runtime/server/page/load_data.js +1 -1
- 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 +125 -134
- package/src/types/internal.d.ts +56 -44
- package/src/utils/page_nodes.js +95 -0
- package/src/version.js +1 -1
- package/types/index.d.ts +73 -46
- package/types/index.d.ts.map +4 -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
|
@@ -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,
|
|
@@ -78,7 +78,7 @@ export async function load_server_data({ event, state, node, parent }) {
|
|
|
78
78
|
const { href } = new URL(dep, event.url);
|
|
79
79
|
|
|
80
80
|
if (DEV) {
|
|
81
|
-
validate_depends(node.server_id, dep);
|
|
81
|
+
validate_depends(node.server_id || 'missing route ID', dep);
|
|
82
82
|
|
|
83
83
|
if (done && !uses.dependencies.has(href)) {
|
|
84
84
|
console.warn(
|
|
@@ -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;
|
|
@@ -11,21 +11,13 @@ import { exec } from '../../utils/routing.js';
|
|
|
11
11
|
import { redirect_json_response, render_data } from './data/index.js';
|
|
12
12
|
import { add_cookies_to_headers, get_cookies } from './cookie.js';
|
|
13
13
|
import { create_fetch } from './fetch.js';
|
|
14
|
+
import { PageNodes } from '../../utils/page_nodes.js';
|
|
14
15
|
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';
|
|
16
|
+
import { validate_server_exports } from '../../utils/exports.js';
|
|
23
17
|
import { json, text } from '../../exports/index.js';
|
|
24
18
|
import { action_json_redirect, is_action_json_request } from './page/actions.js';
|
|
25
19
|
import { INVALIDATED_PARAM, TRAILING_SLASH_PARAM } from '../shared.js';
|
|
26
20
|
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
21
|
import { resolve_route } from './page/server_routing.js';
|
|
30
22
|
import { validateHeaders } from './validate-headers.js';
|
|
31
23
|
import {
|
|
@@ -111,11 +103,82 @@ export async function respond(request, options, manifest, state) {
|
|
|
111
103
|
url.searchParams.delete(INVALIDATED_PARAM);
|
|
112
104
|
}
|
|
113
105
|
|
|
106
|
+
/** @type {Record<string, string>} */
|
|
107
|
+
const headers = {};
|
|
108
|
+
|
|
109
|
+
const { cookies, new_cookies, get_cookie_header, set_internal, set_trailing_slash } = get_cookies(
|
|
110
|
+
request,
|
|
111
|
+
url
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
/** @type {import('@sveltejs/kit').RequestEvent} */
|
|
115
|
+
const event = {
|
|
116
|
+
cookies,
|
|
117
|
+
// @ts-expect-error `fetch` needs to be created after the `event` itself
|
|
118
|
+
fetch: null,
|
|
119
|
+
getClientAddress:
|
|
120
|
+
state.getClientAddress ||
|
|
121
|
+
(() => {
|
|
122
|
+
throw new Error(
|
|
123
|
+
`${__SVELTEKIT_ADAPTER_NAME__} does not specify getClientAddress. Please raise an issue`
|
|
124
|
+
);
|
|
125
|
+
}),
|
|
126
|
+
locals: {},
|
|
127
|
+
params: {},
|
|
128
|
+
platform: state.platform,
|
|
129
|
+
request,
|
|
130
|
+
route: { id: null },
|
|
131
|
+
setHeaders: (new_headers) => {
|
|
132
|
+
if (__SVELTEKIT_DEV__) {
|
|
133
|
+
validateHeaders(new_headers);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
for (const key in new_headers) {
|
|
137
|
+
const lower = key.toLowerCase();
|
|
138
|
+
const value = new_headers[key];
|
|
139
|
+
|
|
140
|
+
if (lower === 'set-cookie') {
|
|
141
|
+
throw new Error(
|
|
142
|
+
'Use `event.cookies.set(name, value, options)` instead of `event.setHeaders` to set cookies'
|
|
143
|
+
);
|
|
144
|
+
} else if (lower in headers) {
|
|
145
|
+
throw new Error(`"${key}" header is already set`);
|
|
146
|
+
} else {
|
|
147
|
+
headers[lower] = value;
|
|
148
|
+
|
|
149
|
+
if (state.prerendering && lower === 'cache-control') {
|
|
150
|
+
state.prerendering.cache = /** @type {string} */ (value);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
url,
|
|
156
|
+
isDataRequest: is_data_request,
|
|
157
|
+
isSubRequest: state.depth > 0
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
event.fetch = create_fetch({
|
|
161
|
+
event,
|
|
162
|
+
options,
|
|
163
|
+
manifest,
|
|
164
|
+
state,
|
|
165
|
+
get_cookie_header,
|
|
166
|
+
set_internal
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
if (state.emulator?.platform) {
|
|
170
|
+
event.platform = await state.emulator.platform({
|
|
171
|
+
config: {},
|
|
172
|
+
prerender: !!state.prerendering?.fallback
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
114
176
|
let resolved_path;
|
|
115
177
|
|
|
116
178
|
try {
|
|
117
179
|
// reroute could alter the given URL, so we pass a copy
|
|
118
|
-
resolved_path =
|
|
180
|
+
resolved_path =
|
|
181
|
+
(await options.hooks.reroute({ url: new URL(url), fetch: event.fetch })) ?? url.pathname;
|
|
119
182
|
} catch {
|
|
120
183
|
return text('Internal Server Error', {
|
|
121
184
|
status: 500
|
|
@@ -131,9 +194,6 @@ export async function respond(request, options, manifest, state) {
|
|
|
131
194
|
/** @type {import('types').SSRRoute | null} */
|
|
132
195
|
let route = null;
|
|
133
196
|
|
|
134
|
-
/** @type {Record<string, string>} */
|
|
135
|
-
let params = {};
|
|
136
|
-
|
|
137
197
|
if (base && !state.prerendering?.fallback) {
|
|
138
198
|
if (!resolved_path.startsWith(base)) {
|
|
139
199
|
return text('Not found', { status: 404 });
|
|
@@ -167,68 +227,13 @@ export async function respond(request, options, manifest, state) {
|
|
|
167
227
|
const matched = exec(match, candidate.params, matchers);
|
|
168
228
|
if (matched) {
|
|
169
229
|
route = candidate;
|
|
170
|
-
|
|
230
|
+
event.route = { id: route.id };
|
|
231
|
+
event.params = decode_params(matched);
|
|
171
232
|
break;
|
|
172
233
|
}
|
|
173
234
|
}
|
|
174
235
|
}
|
|
175
236
|
|
|
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
237
|
/** @type {import('types').RequiredResolveOptions} */
|
|
233
238
|
let resolve_opts = {
|
|
234
239
|
transformPageChunk: default_transform,
|
|
@@ -236,51 +241,36 @@ export async function respond(request, options, manifest, state) {
|
|
|
236
241
|
preload: default_preload
|
|
237
242
|
};
|
|
238
243
|
|
|
244
|
+
/** @type {import('types').TrailingSlash} */
|
|
245
|
+
let trailing_slash = 'never';
|
|
246
|
+
|
|
239
247
|
try {
|
|
248
|
+
/** @type {PageNodes|undefined} */
|
|
249
|
+
const page_nodes = route?.page
|
|
250
|
+
? new PageNodes(await load_page_nodes(route.page, manifest))
|
|
251
|
+
: undefined;
|
|
252
|
+
|
|
240
253
|
// determine whether we need to redirect to add/remove a trailing slash
|
|
241
254
|
if (route) {
|
|
242
255
|
// if `paths.base === '/a/b/c`, then the root route is `/a/b/c/`,
|
|
243
256
|
// regardless of the `trailingSlash` route option
|
|
244
257
|
if (url.pathname === base || url.pathname === base + '/') {
|
|
245
258
|
trailing_slash = 'always';
|
|
246
|
-
} else if (
|
|
247
|
-
const nodes = await load_page_nodes(route.page, manifest);
|
|
248
|
-
|
|
259
|
+
} else if (page_nodes) {
|
|
249
260
|
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
|
-
}
|
|
261
|
+
page_nodes.validate();
|
|
270
262
|
}
|
|
271
|
-
|
|
272
|
-
trailing_slash = get_option(nodes, 'trailingSlash');
|
|
263
|
+
trailing_slash = page_nodes.trailing_slash();
|
|
273
264
|
} else if (route.endpoint) {
|
|
274
265
|
const node = await route.endpoint();
|
|
275
|
-
trailing_slash = node.trailingSlash;
|
|
276
|
-
|
|
266
|
+
trailing_slash = node.trailingSlash ?? 'never';
|
|
277
267
|
if (DEV) {
|
|
278
268
|
validate_server_exports(node, /** @type {string} */ (route.endpoint_id));
|
|
279
269
|
}
|
|
280
270
|
}
|
|
281
271
|
|
|
282
272
|
if (!is_data_request) {
|
|
283
|
-
const normalized = normalize_path(url.pathname, trailing_slash
|
|
273
|
+
const normalized = normalize_path(url.pathname, trailing_slash);
|
|
284
274
|
|
|
285
275
|
if (normalized !== url.pathname && !state.prerendering?.fallback) {
|
|
286
276
|
return new Response(undefined, {
|
|
@@ -306,10 +296,9 @@ export async function respond(request, options, manifest, state) {
|
|
|
306
296
|
const node = await route.endpoint();
|
|
307
297
|
config = node.config ?? config;
|
|
308
298
|
prerender = node.prerender ?? prerender;
|
|
309
|
-
} else if (
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
prerender = get_option(nodes, 'prerender') ?? false;
|
|
299
|
+
} else if (page_nodes) {
|
|
300
|
+
config = page_nodes.get_config() ?? config;
|
|
301
|
+
prerender = page_nodes.prerender();
|
|
313
302
|
}
|
|
314
303
|
|
|
315
304
|
if (state.before_handle) {
|
|
@@ -320,36 +309,16 @@ export async function respond(request, options, manifest, state) {
|
|
|
320
309
|
event.platform = await state.emulator.platform({ config, prerender });
|
|
321
310
|
}
|
|
322
311
|
}
|
|
323
|
-
} else if (state.emulator?.platform) {
|
|
324
|
-
event.platform = await state.emulator.platform({
|
|
325
|
-
config: {},
|
|
326
|
-
prerender: !!state.prerendering?.fallback
|
|
327
|
-
});
|
|
328
312
|
}
|
|
329
313
|
|
|
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
|
-
});
|
|
314
|
+
set_trailing_slash(trailing_slash);
|
|
346
315
|
|
|
347
316
|
if (state.prerendering && !state.prerendering.fallback) disable_search(url);
|
|
348
317
|
|
|
349
318
|
const response = await options.hooks.handle({
|
|
350
319
|
event,
|
|
351
320
|
resolve: (event, opts) =>
|
|
352
|
-
resolve(event, opts).then((response) => {
|
|
321
|
+
resolve(event, page_nodes, opts).then((response) => {
|
|
353
322
|
// add headers/cookies here, rather than inside `resolve`, so that we
|
|
354
323
|
// can do it once for all responses instead of once per `return`
|
|
355
324
|
for (const key in headers) {
|
|
@@ -357,7 +326,7 @@ export async function respond(request, options, manifest, state) {
|
|
|
357
326
|
response.headers.set(key, /** @type {string} */ (value));
|
|
358
327
|
}
|
|
359
328
|
|
|
360
|
-
add_cookies_to_headers(response.headers, Object.values(
|
|
329
|
+
add_cookies_to_headers(response.headers, Object.values(new_cookies));
|
|
361
330
|
|
|
362
331
|
if (state.prerendering && event.route.id !== null) {
|
|
363
332
|
response.headers.set('x-sveltekit-routeid', encodeURI(event.route.id));
|
|
@@ -418,7 +387,7 @@ export async function respond(request, options, manifest, state) {
|
|
|
418
387
|
: route?.page && is_action_json_request(event)
|
|
419
388
|
? action_json_redirect(e)
|
|
420
389
|
: redirect_response(e.status, e.location);
|
|
421
|
-
add_cookies_to_headers(response.headers, Object.values(
|
|
390
|
+
add_cookies_to_headers(response.headers, Object.values(new_cookies));
|
|
422
391
|
return response;
|
|
423
392
|
}
|
|
424
393
|
return await handle_fatal_error(event, options, e);
|
|
@@ -426,9 +395,10 @@ export async function respond(request, options, manifest, state) {
|
|
|
426
395
|
|
|
427
396
|
/**
|
|
428
397
|
* @param {import('@sveltejs/kit').RequestEvent} event
|
|
398
|
+
* @param {PageNodes | undefined} page_nodes
|
|
429
399
|
* @param {import('@sveltejs/kit').ResolveOptions} [opts]
|
|
430
400
|
*/
|
|
431
|
-
async function resolve(event, opts) {
|
|
401
|
+
async function resolve(event, page_nodes, opts) {
|
|
432
402
|
try {
|
|
433
403
|
if (opts) {
|
|
434
404
|
resolve_opts = {
|
|
@@ -467,13 +437,23 @@ export async function respond(request, options, manifest, state) {
|
|
|
467
437
|
manifest,
|
|
468
438
|
state,
|
|
469
439
|
invalidated_data_nodes,
|
|
470
|
-
trailing_slash
|
|
440
|
+
trailing_slash
|
|
471
441
|
);
|
|
472
442
|
} else if (route.endpoint && (!route.page || is_endpoint_request(event))) {
|
|
473
443
|
response = await render_endpoint(event, await route.endpoint(), state);
|
|
474
444
|
} else if (route.page) {
|
|
475
|
-
if (
|
|
476
|
-
|
|
445
|
+
if (!page_nodes) {
|
|
446
|
+
throw new Error('page_nodes not found. This should never happen');
|
|
447
|
+
} else if (page_methods.has(method)) {
|
|
448
|
+
response = await render_page(
|
|
449
|
+
event,
|
|
450
|
+
route.page,
|
|
451
|
+
options,
|
|
452
|
+
manifest,
|
|
453
|
+
state,
|
|
454
|
+
page_nodes,
|
|
455
|
+
resolve_opts
|
|
456
|
+
);
|
|
477
457
|
} else {
|
|
478
458
|
const allowed_methods = new Set(allowed_page_methods);
|
|
479
459
|
const node = await manifest._.nodes[route.page.leaf]();
|
|
@@ -499,9 +479,8 @@ export async function respond(request, options, manifest, state) {
|
|
|
499
479
|
}
|
|
500
480
|
}
|
|
501
481
|
} else {
|
|
502
|
-
// a route will always have a page or an endpoint, but TypeScript
|
|
503
|
-
|
|
504
|
-
throw new Error('This should never happen');
|
|
482
|
+
// a route will always have a page or an endpoint, but TypeScript doesn't know that
|
|
483
|
+
throw new Error('Route is neither page nor endpoint. This should never happen');
|
|
505
484
|
}
|
|
506
485
|
|
|
507
486
|
// If the route contains a page and an endpoint, we need to add a
|
|
@@ -578,3 +557,15 @@ export async function respond(request, options, manifest, state) {
|
|
|
578
557
|
}
|
|
579
558
|
}
|
|
580
559
|
}
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* @param {import('types').PageNodeIndexes} page
|
|
563
|
+
* @param {import('@sveltejs/kit').SSRManifest} manifest
|
|
564
|
+
*/
|
|
565
|
+
export function load_page_nodes(page, manifest) {
|
|
566
|
+
return Promise.all([
|
|
567
|
+
// we use == here rather than === because [undefined] serializes as "[null]"
|
|
568
|
+
...page.layouts.map((n) => (n == undefined ? n : manifest._.nodes[n]())),
|
|
569
|
+
manifest._.nodes[page.leaf]()
|
|
570
|
+
]);
|
|
571
|
+
}
|