@sveltejs/kit 1.0.11 → 1.0.13

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.
Files changed (45) hide show
  1. package/package.json +3 -3
  2. package/src/core/adapt/builder.js +1 -1
  3. package/src/core/{prerender → postbuild}/crawl.js +0 -0
  4. package/src/core/{prerender → postbuild}/entities.js +0 -0
  5. package/src/core/{prerender → postbuild}/fallback.js +10 -7
  6. package/src/core/postbuild/index.js +104 -0
  7. package/src/core/{prerender → postbuild}/prerender.js +32 -106
  8. package/src/core/{prerender → postbuild}/queue.js +0 -0
  9. package/src/core/sync/sync.js +10 -0
  10. package/src/core/sync/write_client_manifest.js +1 -1
  11. package/src/core/sync/write_server.js +89 -0
  12. package/src/core/utils.js +0 -9
  13. package/src/exports/vite/build/build_server.js +11 -163
  14. package/src/exports/vite/build/build_service_worker.js +3 -2
  15. package/src/exports/vite/build/utils.js +1 -0
  16. package/src/exports/vite/dev/index.js +72 -114
  17. package/src/exports/vite/index.js +26 -27
  18. package/src/exports/vite/preview/index.js +11 -12
  19. package/src/runtime/app/environment.js +1 -1
  20. package/src/runtime/app/paths.js +1 -1
  21. package/src/runtime/client/client.js +8 -2
  22. package/src/runtime/client/fetcher.js +12 -4
  23. package/src/runtime/client/start.js +1 -2
  24. package/src/runtime/client/types.d.ts +1 -1
  25. package/src/runtime/client/utils.js +1 -2
  26. package/src/runtime/control.js +23 -5
  27. package/src/runtime/server/ambient.d.ts +8 -0
  28. package/src/runtime/server/cookie.js +4 -5
  29. package/src/runtime/server/data/index.js +5 -2
  30. package/src/runtime/server/endpoint.js +5 -5
  31. package/src/runtime/server/fetch.js +11 -9
  32. package/src/runtime/server/index.js +54 -395
  33. package/src/runtime/server/page/csp.js +9 -11
  34. package/src/runtime/server/page/index.js +13 -8
  35. package/src/runtime/server/page/load_data.js +2 -3
  36. package/src/runtime/server/page/render.js +28 -25
  37. package/src/runtime/server/page/respond_with_error.js +20 -13
  38. package/src/runtime/server/page/types.d.ts +0 -1
  39. package/src/runtime/server/respond.js +419 -0
  40. package/src/runtime/server/utils.js +21 -4
  41. package/src/runtime/shared.js +28 -0
  42. package/types/index.d.ts +10 -5
  43. package/types/internal.d.ts +22 -39
  44. package/src/runtime/env.js +0 -12
  45. package/src/runtime/paths.js +0 -11
@@ -1,12 +1,14 @@
1
1
  import * as devalue from 'devalue';
2
2
  import { readable, writable } from 'svelte/store';
3
+ import { DEV } from 'esm-env';
3
4
  import { hash } from '../../hash.js';
4
5
  import { serialize_data } from './serialize_data.js';
5
6
  import { s } from '../../../utils/misc.js';
6
7
  import { Csp } from './csp.js';
7
8
  import { uneval_action_response } from './actions.js';
8
9
  import { clarify_devalue_error } from '../utils.js';
9
- import { DEV } from 'esm-env';
10
+ import { assets, base, version } from '../../shared.js';
11
+ import { env } from '../../env-public.js';
10
12
 
11
13
  // TODO rename this function/module
12
14
 
@@ -21,6 +23,7 @@ const updated = {
21
23
  * branch: Array<import('./types').Loaded>;
22
24
  * fetched: Array<import('./types').Fetched>;
23
25
  * options: import('types').SSROptions;
26
+ * manifest: import('types').SSRManifest;
24
27
  * state: import('types').SSRState;
25
28
  * page_config: { ssr: boolean; csr: boolean };
26
29
  * status: number;
@@ -34,6 +37,7 @@ export async function render_response({
34
37
  branch,
35
38
  fetched,
36
39
  options,
40
+ manifest,
37
41
  state,
38
42
  page_config,
39
43
  status,
@@ -52,11 +56,11 @@ export async function render_response({
52
56
  }
53
57
  }
54
58
 
55
- const { entry } = options.manifest._;
59
+ const { entry } = manifest._;
56
60
 
57
61
  const stylesheets = new Set(entry.stylesheets);
58
62
  const modulepreloads = new Set(entry.imports);
59
- const fonts = new Set(options.manifest._.entry.fonts);
63
+ const fonts = new Set(manifest._.entry.fonts);
60
64
 
61
65
  /** @type {Set<string>} */
62
66
  const link_header_preloads = new Set();
@@ -130,7 +134,6 @@ export async function render_response({
130
134
  let body = rendered.html;
131
135
 
132
136
  const csp = new Csp(options.csp, {
133
- dev: options.dev,
134
137
  prerender: !!state.prerendering
135
138
  });
136
139
 
@@ -140,25 +143,25 @@ export async function render_response({
140
143
  * The prefix to use for static assets. Replaces `%sveltekit.assets%` in the template
141
144
  * @type {string}
142
145
  */
143
- let assets;
146
+ let resolved_assets;
144
147
 
145
- if (options.paths.assets) {
148
+ if (assets) {
146
149
  // if an asset path is specified, use it
147
- assets = options.paths.assets;
150
+ resolved_assets = assets;
148
151
  } else if (state.prerendering?.fallback) {
149
152
  // if we're creating a fallback page, asset paths need to be root-relative
150
- assets = options.paths.base;
153
+ resolved_assets = base;
151
154
  } else {
152
155
  // otherwise we want asset paths to be relative to the page, so that they
153
156
  // will work in odd contexts like IPFS, the internet archive, and so on
154
- const segments = event.url.pathname.slice(options.paths.base.length).split('/').slice(2);
155
- assets = segments.length > 0 ? segments.map(() => '..').join('/') : '.';
157
+ const segments = event.url.pathname.slice(base.length).split('/').slice(2);
158
+ resolved_assets = segments.length > 0 ? segments.map(() => '..').join('/') : '.';
156
159
  }
157
160
 
158
161
  /** @param {string} path */
159
- const prefixed = (path) => (path.startsWith('/') ? path : `${assets}/${path}`);
162
+ const prefixed = (path) => (path.startsWith('/') ? path : `${resolved_assets}/${path}`);
160
163
 
161
- const serialized = { data: '', form: 'null' };
164
+ const serialized = { data: '', form: 'null', error: 'null' };
162
165
 
163
166
  try {
164
167
  serialized.data = `[${branch
@@ -196,11 +199,14 @@ export async function render_response({
196
199
  serialized.form = uneval_action_response(form_value, /** @type {string} */ (event.route.id));
197
200
  }
198
201
 
202
+ if (error) {
203
+ serialized.error = devalue.uneval(error);
204
+ }
205
+
199
206
  if (inline_styles.size > 0) {
200
207
  const content = Array.from(inline_styles.values()).join('\n');
201
208
 
202
- const attributes = [];
203
- if (options.dev) attributes.push(' data-sveltekit');
209
+ const attributes = __SVELTEKIT_DEV__ ? [' data-sveltekit'] : [];
204
210
  if (csp.style_needs_nonce) attributes.push(` nonce="${csp.nonce}"`);
205
211
 
206
212
  csp.add_style(content);
@@ -246,27 +252,24 @@ export async function render_response({
246
252
 
247
253
  if (page_config.csr) {
248
254
  const opts = [
249
- `env: ${s(options.public_env)}`,
250
- `paths: ${s(options.paths)}`,
255
+ `env: ${s(env)}`,
256
+ `paths: ${s({ assets, base })}`,
251
257
  `target: document.querySelector('[data-sveltekit-hydrate="${target}"]').parentNode`,
252
- `version: ${s(options.version)}`
258
+ `version: ${s(version)}`
253
259
  ];
254
260
 
255
261
  if (page_config.ssr) {
256
262
  const hydrate = [
257
263
  `node_ids: [${branch.map(({ node }) => node.index).join(', ')}]`,
258
264
  `data: ${serialized.data}`,
259
- `form: ${serialized.form}`
265
+ `form: ${serialized.form}`,
266
+ `error: ${serialized.error}`
260
267
  ];
261
268
 
262
269
  if (status !== 200) {
263
270
  hydrate.push(`status: ${status}`);
264
271
  }
265
272
 
266
- if (error) {
267
- hydrate.push(`error: ${devalue.uneval(error)}`);
268
- }
269
-
270
273
  if (options.embedded) {
271
274
  hydrate.push(`params: ${devalue.uneval(event.params)}`, `route: ${s(event.route)}`);
272
275
  }
@@ -314,7 +317,7 @@ export async function render_response({
314
317
  }
315
318
 
316
319
  if (options.service_worker) {
317
- const opts = options.dev ? `, { type: 'module' }` : '';
320
+ const opts = __SVELTEKIT_DEV__ ? `, { type: 'module' }` : '';
318
321
 
319
322
  // we use an anonymous function instead of an arrow function to support
320
323
  // older browsers (https://github.com/sveltejs/kit/pull/5417)
@@ -354,10 +357,10 @@ export async function render_response({
354
357
  // add the content after the script/css links so the link elements are parsed first
355
358
  head += rendered.head;
356
359
 
357
- const html = options.app_template({
360
+ const html = options.templates.app({
358
361
  head,
359
362
  body,
360
- assets,
363
+ assets: resolved_assets,
361
364
  nonce: /** @type {string} */ (csp.nonce)
362
365
  });
363
366
 
@@ -11,27 +11,34 @@ import { HttpError, Redirect } from '../../control.js';
11
11
 
12
12
  /**
13
13
  * @typedef {import('./types.js').Loaded} Loaded
14
- * @typedef {import('types').SSROptions} SSROptions
15
- * @typedef {import('types').SSRState} SSRState
16
14
  */
17
15
 
18
16
  /**
19
17
  * @param {{
20
18
  * event: import('types').RequestEvent;
21
- * options: SSROptions;
22
- * state: SSRState;
19
+ * options: import('types').SSROptions;
20
+ * manifest: import('types').SSRManifest;
21
+ * state: import('types').SSRState;
23
22
  * status: number;
24
23
  * error: unknown;
25
24
  * resolve_opts: import('types').RequiredResolveOptions;
26
25
  * }} opts
27
26
  */
28
- export async function respond_with_error({ event, options, state, status, error, resolve_opts }) {
27
+ export async function respond_with_error({
28
+ event,
29
+ options,
30
+ manifest,
31
+ state,
32
+ status,
33
+ error,
34
+ resolve_opts
35
+ }) {
29
36
  /** @type {import('./types').Fetched[]} */
30
37
  const fetched = [];
31
38
 
32
39
  try {
33
40
  const branch = [];
34
- const default_layout = await options.manifest._.nodes[0](); // 0 is always the root layout
41
+ const default_layout = await manifest._.nodes[0](); // 0 is always the root layout
35
42
  const ssr = get_option([default_layout], 'ssr') ?? true;
36
43
  const csr = get_option([default_layout], 'csr') ?? true;
37
44
 
@@ -40,7 +47,6 @@ export async function respond_with_error({ event, options, state, status, error,
40
47
 
41
48
  const server_data_promise = load_server_data({
42
49
  event,
43
- options,
44
50
  state,
45
51
  node: default_layout,
46
52
  parent: async () => ({})
@@ -66,7 +72,7 @@ export async function respond_with_error({ event, options, state, status, error,
66
72
  data
67
73
  },
68
74
  {
69
- node: await options.manifest._.nodes[1](), // 1 is always the root error
75
+ node: await manifest._.nodes[1](), // 1 is always the root error
70
76
  data: null,
71
77
  server_data: null
72
78
  }
@@ -75,6 +81,7 @@ export async function respond_with_error({ event, options, state, status, error,
75
81
 
76
82
  return await render_response({
77
83
  options,
84
+ manifest,
78
85
  state,
79
86
  page_config: {
80
87
  ssr,
@@ -87,17 +94,17 @@ export async function respond_with_error({ event, options, state, status, error,
87
94
  event,
88
95
  resolve_opts
89
96
  });
90
- } catch (error) {
97
+ } catch (e) {
91
98
  // Edge case: If route is a 404 and the user redirects to somewhere from the root layout,
92
99
  // we end up here.
93
- if (error instanceof Redirect) {
94
- return redirect_response(error.status, error.location);
100
+ if (e instanceof Redirect) {
101
+ return redirect_response(e.status, e.location);
95
102
  }
96
103
 
97
104
  return static_error_page(
98
105
  options,
99
- error instanceof HttpError ? error.status : 500,
100
- (await handle_error_and_jsonify(event, options, error)).message
106
+ e instanceof HttpError ? e.status : 500,
107
+ (await handle_error_and_jsonify(event, options, e)).message
101
108
  );
102
109
  }
103
110
  }
@@ -24,7 +24,6 @@ export interface CspConfig {
24
24
  }
25
25
 
26
26
  export interface CspOpts {
27
- dev: boolean;
28
27
  prerender: boolean;
29
28
  }
30
29
 
@@ -0,0 +1,419 @@
1
+ import { DEV } from 'esm-env';
2
+ import { is_endpoint_request, render_endpoint } from './endpoint.js';
3
+ import { render_page } from './page/index.js';
4
+ import { render_response } from './page/render.js';
5
+ import { respond_with_error } from './page/respond_with_error.js';
6
+ import { is_form_content_type } from '../../utils/http.js';
7
+ import { GENERIC_ERROR, get_option, handle_fatal_error, redirect_response } from './utils.js';
8
+ import {
9
+ decode_pathname,
10
+ decode_params,
11
+ disable_search,
12
+ has_data_suffix,
13
+ normalize_path,
14
+ strip_data_suffix
15
+ } from '../../utils/url.js';
16
+ import { exec } from '../../utils/routing.js';
17
+ import { INVALIDATED_PARAM, redirect_json_response, render_data } from './data/index.js';
18
+ import { add_cookies_to_headers, get_cookies } from './cookie.js';
19
+ import { create_fetch } from './fetch.js';
20
+ import { Redirect } from '../control.js';
21
+ import {
22
+ validate_common_exports,
23
+ validate_page_server_exports,
24
+ validate_server_exports
25
+ } from '../../utils/exports.js';
26
+ import { error, json } from '../../exports/index.js';
27
+ import * as paths from '../shared.js';
28
+
29
+ /* global __SVELTEKIT_ADAPTER_NAME__ */
30
+
31
+ /** @type {import('types').RequiredResolveOptions['transformPageChunk']} */
32
+ const default_transform = ({ html }) => html;
33
+
34
+ /** @type {import('types').RequiredResolveOptions['filterSerializedResponseHeaders']} */
35
+ const default_filter = () => false;
36
+
37
+ /** @type {import('types').RequiredResolveOptions['preload']} */
38
+ const default_preload = ({ type }) => type === 'js' || type === 'css';
39
+
40
+ /** @type {import('types').Respond} */
41
+ export async function respond(request, options, manifest, state) {
42
+ /** URL but stripped from the potential `/__data.json` suffix and its search param */
43
+ let url = new URL(request.url);
44
+
45
+ if (options.csrf_check_origin) {
46
+ const forbidden =
47
+ request.method === 'POST' &&
48
+ request.headers.get('origin') !== url.origin &&
49
+ is_form_content_type(request);
50
+
51
+ if (forbidden) {
52
+ const csrf_error = error(403, `Cross-site ${request.method} form submissions are forbidden`);
53
+ if (request.headers.get('accept') === 'application/json') {
54
+ return json(csrf_error.body, { status: csrf_error.status });
55
+ }
56
+ return new Response(csrf_error.body.message, { status: csrf_error.status });
57
+ }
58
+ }
59
+
60
+ let decoded;
61
+ try {
62
+ decoded = decode_pathname(url.pathname);
63
+ } catch {
64
+ return new Response('Malformed URI', { status: 400 });
65
+ }
66
+
67
+ /** @type {import('types').SSRRoute | null} */
68
+ let route = null;
69
+
70
+ /** @type {Record<string, string>} */
71
+ let params = {};
72
+
73
+ if (paths.base && !state.prerendering?.fallback) {
74
+ if (!decoded.startsWith(paths.base)) {
75
+ return new Response('Not found', { status: 404 });
76
+ }
77
+ decoded = decoded.slice(paths.base.length) || '/';
78
+ }
79
+
80
+ const is_data_request = has_data_suffix(decoded);
81
+ /** @type {boolean[] | undefined} */
82
+ let invalidated_data_nodes;
83
+ if (is_data_request) {
84
+ decoded = strip_data_suffix(decoded) || '/';
85
+ url.pathname = strip_data_suffix(url.pathname) || '/';
86
+ invalidated_data_nodes = url.searchParams.get(INVALIDATED_PARAM)?.split('_').map(Boolean);
87
+ url.searchParams.delete(INVALIDATED_PARAM);
88
+ }
89
+
90
+ if (!state.prerendering?.fallback) {
91
+ // TODO this could theoretically break — should probably be inside a try-catch
92
+ const matchers = await manifest._.matchers();
93
+
94
+ for (const candidate of manifest._.routes) {
95
+ const match = candidate.pattern.exec(decoded);
96
+ if (!match) continue;
97
+
98
+ const matched = exec(match, candidate.params, matchers);
99
+ if (matched) {
100
+ route = candidate;
101
+ params = decode_params(matched);
102
+ break;
103
+ }
104
+ }
105
+ }
106
+
107
+ /** @type {import('types').TrailingSlash | void} */
108
+ let trailing_slash = undefined;
109
+
110
+ /** @type {Record<string, string>} */
111
+ const headers = {};
112
+
113
+ /** @type {import('types').RequestEvent} */
114
+ const event = {
115
+ // @ts-expect-error `cookies` and `fetch` need to be created after the `event` itself
116
+ cookies: null,
117
+ // @ts-expect-error
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: route?.id ?? null },
131
+ setHeaders: (new_headers) => {
132
+ for (const key in new_headers) {
133
+ const lower = key.toLowerCase();
134
+ const value = new_headers[key];
135
+
136
+ if (lower === 'set-cookie') {
137
+ throw new Error(
138
+ `Use \`event.cookies.set(name, value, options)\` instead of \`event.setHeaders\` to set cookies`
139
+ );
140
+ } else if (lower in headers) {
141
+ throw new Error(`"${key}" header is already set`);
142
+ } else {
143
+ headers[lower] = value;
144
+
145
+ if (state.prerendering && lower === 'cache-control') {
146
+ state.prerendering.cache = /** @type {string} */ (value);
147
+ }
148
+ }
149
+ }
150
+ },
151
+ url,
152
+ isDataRequest: is_data_request
153
+ };
154
+
155
+ /** @type {import('types').RequiredResolveOptions} */
156
+ let resolve_opts = {
157
+ transformPageChunk: default_transform,
158
+ filterSerializedResponseHeaders: default_filter,
159
+ preload: default_preload
160
+ };
161
+
162
+ try {
163
+ // determine whether we need to redirect to add/remove a trailing slash
164
+ if (route && !is_data_request) {
165
+ if (route.page) {
166
+ const nodes = await Promise.all([
167
+ // we use == here rather than === because [undefined] serializes as "[null]"
168
+ ...route.page.layouts.map((n) => (n == undefined ? n : manifest._.nodes[n]())),
169
+ manifest._.nodes[route.page.leaf]()
170
+ ]);
171
+
172
+ if (DEV) {
173
+ const layouts = nodes.slice(0, -1);
174
+ const page = nodes.at(-1);
175
+
176
+ for (const layout of layouts) {
177
+ if (layout) {
178
+ validate_common_exports(layout.server, /** @type {string} */ (layout.server_id));
179
+ validate_common_exports(
180
+ layout.universal,
181
+ /** @type {string} */ (layout.universal_id)
182
+ );
183
+ }
184
+ }
185
+
186
+ if (page) {
187
+ validate_page_server_exports(page.server, /** @type {string} */ (page.server_id));
188
+ validate_common_exports(page.universal, /** @type {string} */ (page.universal_id));
189
+ }
190
+ }
191
+
192
+ trailing_slash = get_option(nodes, 'trailingSlash');
193
+ } else if (route.endpoint) {
194
+ const node = await route.endpoint();
195
+ trailing_slash = node.trailingSlash;
196
+
197
+ if (DEV) {
198
+ validate_server_exports(node, /** @type {string} */ (route.endpoint_id));
199
+ }
200
+ }
201
+
202
+ const normalized = normalize_path(url.pathname, trailing_slash ?? 'never');
203
+
204
+ if (normalized !== url.pathname && !state.prerendering?.fallback) {
205
+ return new Response(undefined, {
206
+ status: 301,
207
+ headers: {
208
+ 'x-sveltekit-normalize': '1',
209
+ location:
210
+ // ensure paths starting with '//' are not treated as protocol-relative
211
+ (normalized.startsWith('//') ? url.origin + normalized : normalized) +
212
+ (url.search === '?' ? '' : url.search)
213
+ }
214
+ });
215
+ }
216
+ }
217
+
218
+ const { cookies, new_cookies, get_cookie_header } = get_cookies(
219
+ request,
220
+ url,
221
+ trailing_slash ?? 'never'
222
+ );
223
+
224
+ event.cookies = cookies;
225
+ event.fetch = create_fetch({ event, options, manifest, state, get_cookie_header });
226
+
227
+ if (state.prerendering && !state.prerendering.fallback) disable_search(url);
228
+
229
+ const response = await options.hooks.handle({
230
+ event,
231
+ resolve: (event, opts) =>
232
+ resolve(event, opts).then((response) => {
233
+ // add headers/cookies here, rather than inside `resolve`, so that we
234
+ // can do it once for all responses instead of once per `return`
235
+ for (const key in headers) {
236
+ const value = headers[key];
237
+ response.headers.set(key, /** @type {string} */ (value));
238
+ }
239
+
240
+ add_cookies_to_headers(response.headers, Object.values(new_cookies));
241
+
242
+ if (state.prerendering && event.route.id !== null) {
243
+ response.headers.set('x-sveltekit-routeid', encodeURI(event.route.id));
244
+ }
245
+
246
+ return response;
247
+ })
248
+ });
249
+
250
+ // respond with 304 if etag matches
251
+ if (response.status === 200 && response.headers.has('etag')) {
252
+ let if_none_match_value = request.headers.get('if-none-match');
253
+
254
+ // ignore W/ prefix https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match#directives
255
+ if (if_none_match_value?.startsWith('W/"')) {
256
+ if_none_match_value = if_none_match_value.substring(2);
257
+ }
258
+
259
+ const etag = /** @type {string} */ (response.headers.get('etag'));
260
+
261
+ if (if_none_match_value === etag) {
262
+ const headers = new Headers({ etag });
263
+
264
+ // https://datatracker.ietf.org/doc/html/rfc7232#section-4.1 + set-cookie
265
+ for (const key of [
266
+ 'cache-control',
267
+ 'content-location',
268
+ 'date',
269
+ 'expires',
270
+ 'vary',
271
+ 'set-cookie'
272
+ ]) {
273
+ const value = response.headers.get(key);
274
+ if (value) headers.set(key, value);
275
+ }
276
+
277
+ return new Response(undefined, {
278
+ status: 304,
279
+ headers
280
+ });
281
+ }
282
+ }
283
+
284
+ // Edge case: If user does `return Response(30x)` in handle hook while processing a data request,
285
+ // we need to transform the redirect response to a corresponding JSON response.
286
+ if (is_data_request && response.status >= 300 && response.status <= 308) {
287
+ const location = response.headers.get('location');
288
+ if (location) {
289
+ return redirect_json_response(new Redirect(/** @type {any} */ (response.status), location));
290
+ }
291
+ }
292
+
293
+ return response;
294
+ } catch (e) {
295
+ if (e instanceof Redirect) {
296
+ if (is_data_request) {
297
+ return redirect_json_response(e);
298
+ } else {
299
+ return redirect_response(e.status, e.location);
300
+ }
301
+ }
302
+ return await handle_fatal_error(event, options, e);
303
+ }
304
+
305
+ /**
306
+ *
307
+ * @param {import('types').RequestEvent} event
308
+ * @param {import('types').ResolveOptions} [opts]
309
+ */
310
+ async function resolve(event, opts) {
311
+ try {
312
+ if (opts) {
313
+ if ('ssr' in opts) {
314
+ throw new Error(
315
+ 'ssr has been removed, set it in the appropriate +layout.js instead. See the PR for more information: https://github.com/sveltejs/kit/pull/6197'
316
+ );
317
+ }
318
+
319
+ resolve_opts = {
320
+ transformPageChunk: opts.transformPageChunk || default_transform,
321
+ filterSerializedResponseHeaders: opts.filterSerializedResponseHeaders || default_filter,
322
+ preload: opts.preload || default_preload
323
+ };
324
+ }
325
+
326
+ if (state.prerendering?.fallback) {
327
+ return await render_response({
328
+ event,
329
+ options,
330
+ manifest,
331
+ state,
332
+ page_config: { ssr: false, csr: true },
333
+ status: 200,
334
+ error: null,
335
+ branch: [],
336
+ fetched: [],
337
+ resolve_opts
338
+ });
339
+ }
340
+
341
+ if (route) {
342
+ /** @type {Response} */
343
+ let response;
344
+
345
+ if (is_data_request) {
346
+ response = await render_data(
347
+ event,
348
+ route,
349
+ options,
350
+ manifest,
351
+ state,
352
+ invalidated_data_nodes,
353
+ trailing_slash ?? 'never'
354
+ );
355
+ } else if (route.endpoint && (!route.page || is_endpoint_request(event))) {
356
+ response = await render_endpoint(event, await route.endpoint(), state);
357
+ } else if (route.page) {
358
+ response = await render_page(
359
+ event,
360
+ route,
361
+ route.page,
362
+ options,
363
+ manifest,
364
+ state,
365
+ resolve_opts
366
+ );
367
+ } else {
368
+ // a route will always have a page or an endpoint, but TypeScript
369
+ // doesn't know that
370
+ throw new Error('This should never happen');
371
+ }
372
+
373
+ return response;
374
+ }
375
+
376
+ if (state.initiator === GENERIC_ERROR) {
377
+ return new Response('Internal Server Error', {
378
+ status: 500
379
+ });
380
+ }
381
+
382
+ // if this request came direct from the user, rather than
383
+ // via a `fetch` in a `load`, render a 404 page
384
+ if (!state.initiator) {
385
+ return await respond_with_error({
386
+ event,
387
+ options,
388
+ manifest,
389
+ state,
390
+ status: 404,
391
+ error: new Error(`Not found: ${event.url.pathname}`),
392
+ resolve_opts
393
+ });
394
+ }
395
+
396
+ if (state.prerendering) {
397
+ return new Response('not found', { status: 404 });
398
+ }
399
+
400
+ // we can't load the endpoint from our own manifest,
401
+ // so we need to make an actual HTTP request
402
+ return await fetch(request);
403
+ } catch (e) {
404
+ // TODO if `e` is instead named `error`, some fucked up Vite transformation happens
405
+ // and I don't even know how to describe it. need to investigate at some point
406
+
407
+ // HttpError from endpoint can end up here - TODO should it be handled there instead?
408
+ return await handle_fatal_error(event, options, e);
409
+ } finally {
410
+ event.cookies.set = () => {
411
+ throw new Error('Cannot use `cookies.set(...)` after the response has been generated');
412
+ };
413
+
414
+ event.setHeaders = () => {
415
+ throw new Error('Cannot use `setHeaders(...)` after the response has been generated');
416
+ };
417
+ }
418
+ }
419
+ }