@sveltejs/kit 3.0.0-next.23 → 3.0.0-next.24

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 (92) hide show
  1. package/package.json +40 -5
  2. package/src/cli.js +3 -3
  3. package/src/constants.js +13 -1
  4. package/src/core/adapt/builder.js +2 -3
  5. package/src/core/env.js +139 -181
  6. package/src/core/postbuild/analyse.js +9 -4
  7. package/src/core/postbuild/prerender.js +3 -4
  8. package/src/core/sync/create_manifest_data/index.js +29 -33
  9. package/src/core/sync/sync.js +23 -40
  10. package/src/core/sync/write_app_manifest.js +83 -0
  11. package/src/core/sync/write_client_manifest.js +6 -4
  12. package/src/core/sync/write_server.js +10 -6
  13. package/src/core/sync/write_types/index.js +2 -2
  14. package/src/core/utils.js +0 -28
  15. package/src/exports/hooks/public.d.ts +9 -1
  16. package/src/exports/node/index.js +77 -5
  17. package/src/exports/vite/build/build_server.js +3 -3
  18. package/src/exports/vite/build/utils.js +48 -4
  19. package/src/exports/vite/dev/index.js +11 -22
  20. package/src/exports/vite/index.js +62 -345
  21. package/src/exports/vite/module_ids.js +1 -11
  22. package/src/exports/vite/plugins/env-vars.js +117 -0
  23. package/src/exports/vite/preview/index.js +6 -4
  24. package/src/exports/vite/utils.js +2 -4
  25. package/src/runtime/app/env/{types.d.ts → client.js} +9 -4
  26. package/src/runtime/app/env/index.js +1 -2
  27. package/src/runtime/app/env/private/index.js +1 -0
  28. package/src/runtime/app/env/public/client.js +1 -1
  29. package/src/runtime/app/env/public/server.js +1 -1
  30. package/src/runtime/app/env/{internal.js → server.js} +4 -4
  31. package/src/runtime/app/forms/client.js +263 -0
  32. package/src/runtime/app/forms/index.js +1 -263
  33. package/src/runtime/app/forms/public.d.ts +1 -1
  34. package/src/runtime/app/forms/server.js +6 -0
  35. package/src/runtime/app/forms/shared.js +34 -0
  36. package/src/runtime/app/manifest/index.js +1 -1
  37. package/src/runtime/app/navigation/client.js +15 -0
  38. package/src/runtime/app/navigation/index.js +1 -15
  39. package/src/runtime/app/navigation/public.d.ts +1 -1
  40. package/src/runtime/app/navigation/server.js +15 -0
  41. package/src/runtime/app/paths/server.js +1 -1
  42. package/src/runtime/app/server/remote/form.js +11 -1
  43. package/src/runtime/app/server/remote/prerender.js +1 -2
  44. package/src/runtime/app/server/remote/query.js +1 -1
  45. package/src/runtime/app/state/client.svelte.js +207 -0
  46. package/src/runtime/app/state/index.js +1 -66
  47. package/src/runtime/app/state/public.d.ts +1 -1
  48. package/src/runtime/client/bundle.js +1 -1
  49. package/src/runtime/client/client.js +206 -274
  50. package/src/runtime/client/fetcher.js +18 -8
  51. package/src/runtime/client/remote-functions/form.svelte.js +9 -6
  52. package/src/runtime/client/remote-functions/prerender.svelte.js +1 -1
  53. package/src/runtime/client/remote-functions/query-live/iterator.js +1 -1
  54. package/src/runtime/client/remote-functions/shared.svelte.js +2 -2
  55. package/src/runtime/client/snapshots.js +1 -3
  56. package/src/runtime/client/stream.js +27 -20
  57. package/src/runtime/client/utils.js +7 -3
  58. package/src/runtime/components/root.svelte +5 -5
  59. package/src/runtime/env/dynamic/private.js +1 -1
  60. package/src/runtime/env/static/private.js +1 -1
  61. package/src/runtime/error-chain.js +54 -0
  62. package/src/runtime/form-utils.js +53 -77
  63. package/src/runtime/invalid-import.js +1 -0
  64. package/src/runtime/props.svelte.js +1 -1
  65. package/src/runtime/server/data/index.js +1 -1
  66. package/src/runtime/server/endpoint.js +8 -3
  67. package/src/runtime/server/env_module.js +1 -1
  68. package/src/runtime/server/errors.js +2 -2
  69. package/src/runtime/server/index.js +2 -2
  70. package/src/runtime/server/page/actions.js +77 -122
  71. package/src/runtime/server/page/index.js +37 -69
  72. package/src/runtime/server/page/render.js +18 -23
  73. package/src/runtime/server/remote-functions.js +14 -42
  74. package/src/runtime/server/respond.js +23 -3
  75. package/src/telemetry.js +1 -33
  76. package/src/types/ambient-private.d.ts +9 -17
  77. package/src/types/internal.d.ts +20 -4
  78. package/src/types/private.d.ts +1 -1
  79. package/src/utils/exports.js +1 -0
  80. package/src/utils/filesystem.js +9 -21
  81. package/src/utils/functions.js +10 -0
  82. package/src/utils/routing.js +0 -11
  83. package/src/utils/url.js +0 -11
  84. package/src/version.js +1 -1
  85. package/types/index.d.ts +34 -28
  86. package/types/index.d.ts.map +7 -5
  87. package/src/runtime/app/env/private.js +0 -1
  88. package/src/runtime/app/env/standard-schema.d.ts +0 -0
  89. package/src/runtime/app/state/client.js +0 -63
  90. package/src/runtime/client/state.svelte.js +0 -98
  91. package/src/runtime/server/ambient.d.ts +0 -4
  92. package/src/utils/path.js +0 -23
@@ -1,8 +1,7 @@
1
1
  /** @import { RequestEvent, Actions } from '@sveltejs/kit' */
2
2
  /** @import { ActionResult } from '$app/forms' */
3
- /** @import { SSROptions, SSRNode, ServerNode } from 'types' */
3
+ /** @import { SSROptions, SSRNode, ServerNode, ServerActionResult } from 'types' */
4
4
  import { DEV } from 'esm-env';
5
- import { json } from '@sveltejs/kit';
6
5
  import { HttpError, Redirect, ActionFailure, SvelteKitError } from '@sveltejs/kit/internal';
7
6
  import { with_request_store, merge_tracing, record_span } from '@sveltejs/kit/internal/server';
8
7
  import { normalize_error } from '../../../utils/error.js';
@@ -28,98 +27,44 @@ export function is_action_json_request(event) {
28
27
  * @param {SSRNode['server'] | undefined} server
29
28
  */
30
29
  export async function handle_action_json_request(event, state, options, server) {
31
- const actions = server?.actions;
32
- const location = get_action_location(event.url);
33
-
34
- if (!actions) {
35
- const no_actions_error = new SvelteKitError(
36
- 405,
37
- 'Method Not Allowed',
38
- `POST method not allowed. No form actions exist for ${DEV ? `the page at ${event.route.id}` : 'this page'}`
39
- );
30
+ const result = await handle_action_request(event, state, server);
31
+ return action_result_json(event, state, options, result);
32
+ }
40
33
 
41
- const error = await handle_error_and_jsonify(event, state, options, no_actions_error);
34
+ /**
35
+ * @param {RequestEvent} event
36
+ * @param {import('types').RequestState} state
37
+ * @param {SSROptions} options
38
+ * @param {ServerActionResult} result
39
+ * @returns {Promise<Response>}
40
+ */
41
+ async function action_result_json(event, state, options, result) {
42
+ if (result.type === 'redirect') {
43
+ return action_json(result);
44
+ }
42
45
 
43
- return action_json(
44
- {
45
- type: 'error',
46
- error,
47
- location
48
- },
49
- {
50
- status: error.status,
51
- headers: {
52
- // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/405
53
- // "The server must generate an Allow header field in a 405 status code response"
54
- allow: 'GET'
55
- }
56
- }
57
- );
46
+ if (result.type === 'error') {
47
+ const error = await handle_error_and_jsonify(event, state, options, result.error);
48
+ return action_json({ ...result, error }, { status: error.status });
58
49
  }
59
50
 
60
- check_named_default_separate(actions);
51
+ if (result.type === 'success' && !result.data) {
52
+ return action_json({ ...result, status: 204, data: undefined });
53
+ }
61
54
 
62
55
  try {
63
- const data = await call_action(event, state, actions);
64
-
65
- if (DEV) {
66
- validate_action_return(data);
67
- }
68
-
69
- if (data instanceof ActionFailure) {
70
- return action_json(
71
- {
72
- type: 'failure',
73
- status: data.status,
74
- location,
75
- // @ts-expect-error we assign a string to what is supposed to be an object. That's ok
76
- // because we don't use the object outside, and this way we have better code navigation
77
- // through knowing where the related interface is used.
78
- data: try_serialize(data.data, stringify, /** @type {string} */ (event.route.id))
79
- },
80
- {
81
- status: data.status
82
- }
83
- );
84
- } else if (data) {
85
- return action_json({
86
- type: 'success',
87
- status: 200,
88
- location,
89
- // @ts-expect-error see comment above
90
- data: try_serialize(data, stringify, /** @type {string} */ (event.route.id))
91
- });
92
- } else {
93
- return action_json({
94
- type: 'success',
95
- status: 204,
96
- location
97
- });
98
- }
99
- } catch (e) {
100
- const err = normalize_error(e);
101
-
102
- if (err instanceof Redirect) {
103
- return action_json_redirect(err);
104
- }
105
-
106
- const transformed = await handle_error_and_jsonify(
107
- event,
108
- state,
109
- options,
110
- check_incorrect_fail_use(err)
111
- );
112
-
113
56
  return action_json(
114
57
  {
115
- type: 'error',
116
- error: transformed,
117
- location
58
+ ...result,
59
+ // @ts-expect-error we assign a string to what is supposed to be an object. That's ok
60
+ // because we don't use the object outside, and this way we have better code navigation
61
+ // through knowing where the related interface is used.
62
+ data: try_serialize(result.data, stringify, /** @type {string} */ (event.route.id))
118
63
  },
119
- {
120
- status: transformed.status
121
- }
64
+ { status: result.status }
122
65
  );
66
+ } catch (e) {
67
+ return action_result_json(event, state, options, action_error_result(e, result.location));
123
68
  }
124
69
  }
125
70
 
@@ -140,12 +85,48 @@ export function get_action_location(url) {
140
85
  }
141
86
 
142
87
  /**
143
- * @param {HttpError | Error} error
88
+ * @param {RequestEvent} event
89
+ * @param {string} location
90
+ * @returns {Extract<ServerActionResult, { type: 'error' }>}
144
91
  */
145
- export function check_incorrect_fail_use(error) {
146
- return error instanceof ActionFailure
147
- ? new Error('Cannot "throw fail()". Use "return fail()"')
148
- : error;
92
+ export function method_not_allowed_result(event, location) {
93
+ event.setHeaders({
94
+ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/405
95
+ // "The server must generate an Allow header field in a 405 status code response"
96
+ allow: 'GET'
97
+ });
98
+ return {
99
+ type: 'error',
100
+ location,
101
+ error: new SvelteKitError(
102
+ 405,
103
+ 'Method Not Allowed',
104
+ `POST method not allowed. No form actions exist for ${DEV ? `the page at ${event.route.id}` : 'this page'}`
105
+ )
106
+ };
107
+ }
108
+
109
+ /**
110
+ * @param {unknown} e
111
+ * @param {string} location
112
+ * @returns {Extract<ServerActionResult, { type: 'redirect' | 'error' }>}
113
+ */
114
+ export function action_error_result(e, location) {
115
+ const err = normalize_error(e);
116
+
117
+ if (err instanceof Redirect) {
118
+ return {
119
+ type: 'redirect',
120
+ status: err.status,
121
+ location: err.location
122
+ };
123
+ }
124
+
125
+ return {
126
+ type: 'error',
127
+ location,
128
+ error: err
129
+ };
149
130
  }
150
131
 
151
132
  /**
@@ -164,7 +145,7 @@ export function action_json_redirect(redirect) {
164
145
  * @param {ResponseInit} [init]
165
146
  */
166
147
  function action_json(data, init) {
167
- return with_version_header(json(data, init));
148
+ return with_version_header(Response.json(data, init));
168
149
  }
169
150
 
170
151
  /**
@@ -178,7 +159,7 @@ export function is_action_request(event) {
178
159
  * @param {RequestEvent} event
179
160
  * @param {import('types').RequestState} state
180
161
  * @param {SSRNode['server'] | undefined} server
181
- * @returns {Promise<ActionResult>}
162
+ * @returns {Promise<ServerActionResult>}
182
163
  */
183
164
  export async function handle_action_request(event, state, server) {
184
165
  const actions = server?.actions;
@@ -186,21 +167,7 @@ export async function handle_action_request(event, state, server) {
186
167
 
187
168
  if (!actions) {
188
169
  // TODO should this be a different error altogether?
189
- event.setHeaders({
190
- // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/405
191
- // "The server must generate an Allow header field in a 405 status code response"
192
- allow: 'GET'
193
- });
194
- return {
195
- type: 'error',
196
- location,
197
- // We're lying a bit with the types here; this will be transformed into a proper App.Error object later
198
- error: new SvelteKitError(
199
- 405,
200
- 'Method Not Allowed',
201
- `POST method not allowed. No form actions exist for ${DEV ? `the page at ${event.route.id}` : 'this page'}`
202
- )
203
- };
170
+ return method_not_allowed_result(event, location);
204
171
  }
205
172
 
206
173
  check_named_default_separate(actions);
@@ -229,22 +196,10 @@ export async function handle_action_request(event, state, server) {
229
196
  };
230
197
  }
231
198
  } catch (e) {
232
- const err = normalize_error(e);
233
-
234
- if (err instanceof Redirect) {
235
- return {
236
- type: 'redirect',
237
- status: err.status,
238
- location: err.location
239
- };
240
- }
241
-
242
- return {
243
- type: 'error',
244
- location,
245
- // @ts-expect-error We're lying a bit with the types here; this will be transformed into a proper App.Error object later
246
- error: check_incorrect_fail_use(err)
247
- };
199
+ return action_error_result(
200
+ e instanceof ActionFailure ? new Error('Cannot "throw fail()". Use "return fail()"') : e,
201
+ location
202
+ );
248
203
  }
249
204
  }
250
205
 
@@ -1,6 +1,4 @@
1
- /** @import { Component } from 'svelte' */
2
1
  /** @import { RequestEvent, SSRManifest } from '@sveltejs/kit' */
3
- /** @import { ActionResult } from '$app/forms' */
4
2
  /** @import { PageNodeIndexes, RequestState, RequiredResolveOptions, ServerDataNode, SSRNode, SSROptions } from 'types' */
5
3
  import { text } from '@sveltejs/kit';
6
4
  import { Redirect } from '@sveltejs/kit/internal';
@@ -8,6 +6,7 @@ import { compact } from '../../../utils/array.js';
8
6
  import { get_status, normalize_error } from '../../../utils/error.js';
9
7
  import { noop } from '../../../utils/functions.js';
10
8
  import { add_data_suffix } from '../../pathname.js';
9
+ import { build_error_chain, nearest_error_pages } from '../../error-chain.js';
11
10
  import { redirect_response } from '../utils.js';
12
11
  import { static_error_page, handle_error_and_jsonify } from '../errors.js';
13
12
  import {
@@ -57,7 +56,7 @@ export async function render_page(event, state, page, options, manifest, nodes,
57
56
 
58
57
  let status = 200;
59
58
 
60
- /** @type {ActionResult | undefined} */
59
+ /** @type {import('types').ServerActionResult | undefined} */
61
60
  let action_result = undefined;
62
61
 
63
62
  if (is_action_request(event)) {
@@ -278,42 +277,36 @@ export async function render_page(event, state, page, options, manifest, nodes,
278
277
  const error = await handle_error_and_jsonify(event, state, options, err);
279
278
  const status = error.status;
280
279
 
281
- while (i--) {
282
- if (page.errors[i]) {
283
- const index = /** @type {number} */ (page.errors[i]);
284
- const node = await manifest._.nodes[index]();
285
-
286
- let j = i;
287
- while (!branch[j]) j -= 1;
288
-
289
- data_serializer.set_max_nodes(j + 1);
290
-
291
- const layouts = compact(branch.slice(0, j + 1));
292
- const nodes = new PageNodes(layouts.map((layout) => layout.node));
293
- const error_branch = layouts.concat({
294
- node,
295
- data: null,
296
- server_data: null
297
- });
298
-
299
- return await render_response({
300
- event,
301
- state,
302
- options,
303
- manifest,
304
- resolve_opts,
305
- page_config: {
306
- ssr: nodes.ssr(),
307
- csr: nodes.csr()
308
- },
309
- status,
310
- error,
311
- error_components: await load_error_components(ssr, error_branch, page, manifest),
312
- branch: error_branch,
313
- fetched,
314
- data_serializer
315
- });
316
- }
280
+ for (const { error: index, idx } of nearest_error_pages(i, branch, page.errors)) {
281
+ const node = await manifest._.nodes[index]();
282
+
283
+ data_serializer.set_max_nodes(idx);
284
+
285
+ const layouts = compact(branch.slice(0, idx));
286
+ const nodes = new PageNodes(layouts.map((layout) => layout.node));
287
+ const error_branch = layouts.concat({
288
+ node,
289
+ data: null,
290
+ server_data: null
291
+ });
292
+
293
+ return await render_response({
294
+ event,
295
+ state,
296
+ options,
297
+ manifest,
298
+ resolve_opts,
299
+ page_config: {
300
+ ssr: nodes.ssr(),
301
+ csr: nodes.csr()
302
+ },
303
+ status,
304
+ error,
305
+ error_components: await load_error_components(ssr, error_branch, page, manifest),
306
+ branch: error_branch,
307
+ fetched,
308
+ data_serializer
309
+ });
317
310
  }
318
311
 
319
312
  // if we're still here, it means the error happened in the root layout,
@@ -386,35 +379,10 @@ export async function render_page(event, state, page, options, manifest, nodes,
386
379
  * @param {PageNodeIndexes} page
387
380
  * @param {SSRManifest} manifest
388
381
  */
389
- async function load_error_components(ssr, branch, page, manifest) {
390
- /** @type {Array<Component | undefined> | undefined} */
391
- let error_components;
392
-
393
- if (ssr) {
394
- let last_idx = -1;
395
- error_components = await Promise.all(
396
- // eslint-disable-next-line @typescript-eslint/await-thenable
397
- branch
398
- .map((b, i) => {
399
- if (i === 0) return undefined; // root layout wraps root error component, not the other way around
400
- if (!b) return null;
401
-
402
- i--;
403
- // Find the closest error component up to the previous branch
404
- while (i > last_idx + 1 && page.errors[i] === undefined) i -= 1;
405
- last_idx = i;
406
-
407
- const idx = page.errors[i];
408
- if (idx == null) return undefined;
409
-
410
- return manifest._.nodes[idx]?.()
411
- .then((e) => e.component?.())
412
- .catch(() => undefined);
413
- })
414
- // filter out indexes where there was no branch, but keep indexes where there was a branch but no error component
415
- .filter((e) => e !== null)
416
- );
417
- }
382
+ function load_error_components(ssr, branch, page, manifest) {
383
+ if (!ssr) return undefined;
418
384
 
419
- return error_components;
385
+ return build_error_chain(branch, page.errors, (idx) =>
386
+ manifest._.nodes[idx]?.().then((e) => e.component?.())
387
+ );
420
388
  }
@@ -21,7 +21,7 @@ import { try_get_request_store, with_request_store } from '@sveltejs/kit/interna
21
21
  import { text_encoder } from '../../utils.js';
22
22
  import { count_non_ssi_comments, get_global_name } from '../utils.js';
23
23
  import { handle_error_and_jsonify } from '../errors.js';
24
- import * as env from '__sveltekit/env';
24
+ import * as env from '<sveltekit:generated>/env/config.js';
25
25
  import { collect_remote_data } from '../remote-functions.js';
26
26
  import Root from '../../components/root.svelte';
27
27
  import { render } from 'svelte/server';
@@ -43,7 +43,7 @@ import { has_custom_transporters, uneval } from '#app/internal/transport';
43
43
  * event: import('@sveltejs/kit').RequestEvent;
44
44
  * state: import('types').RequestState;
45
45
  * resolve_opts: import('types').RequiredResolveOptions;
46
- * action_result?: import('$app/forms').ActionResult;
46
+ * action_result?: import('types').ServerActionResult;
47
47
  * data_serializer: import('./types.js').ServerDataSerializer;
48
48
  * error_components?: Array<import('svelte').Component | undefined>
49
49
  * }} opts
@@ -77,7 +77,9 @@ export async function render_response({
77
77
 
78
78
  const modulepreloads = new Set(client?.imports);
79
79
  const stylesheets = new Set(client?.stylesheets);
80
- const fonts = new Set(client?.fonts);
80
+
81
+ /** @type {Map<string, import('types').FontDependency>} */
82
+ const fonts = new Map(client?.fonts.map((font) => [font.file, font]));
81
83
 
82
84
  /**
83
85
  * The value of the Link header that is added to the response when not prerendering
@@ -90,7 +92,7 @@ export async function render_response({
90
92
  const inline_styles = new Map();
91
93
 
92
94
  // TODO `svelte/server` should expose `RenderOutput`
93
- /** @type {{ head: string, body: string, hashes: { script: string[] } }} */
95
+ /** @type {Omit<Awaited<ReturnType<typeof render>>, 'html'>} */
94
96
  let rendered;
95
97
 
96
98
  const form_value =
@@ -156,7 +158,7 @@ export async function render_response({
156
158
  tree: new RenderNode(
157
159
  // TODO tidy up
158
160
  /** @type {Component} */ (await branch[0].node.component?.()),
159
- /** @type {Component} */ (error_components?.[1])
161
+ undefined
160
162
  ),
161
163
  form: form_value,
162
164
  error: error ?? undefined
@@ -176,7 +178,7 @@ export async function render_response({
176
178
  current_node = current_node.child = new RenderNode(
177
179
  // TODO tidy up
178
180
  /** @type {Component} */ (await branch[i + 1].node.component?.()),
179
- /** @type {Component} */ (error_components?.slice(0, i + 2).findLast((x) => x))
181
+ error_components?.[i + 1]
180
182
  );
181
183
  }
182
184
  }
@@ -244,19 +246,12 @@ export async function render_response({
244
246
  }
245
247
 
246
248
  rendered = await with_request_store({ event, state: render_state }, async () => {
247
- // We have to invoke .then eagerly here in order to kick off rendering: it's only starting on access,
248
- // and `await maybe_promise` would eagerly access the .then property but call its function only after a tick, which is too late
249
- // for the paths.reset() below and for any eager getRequestEvent() calls during rendering without AsyncLocalStorage available.
250
- const rendered = render(Root, { ...render_opts, props });
251
-
252
- const { head, body, hashes } = await rendered;
253
-
254
- if (hashes) {
255
- csp.add_script_hashes(hashes.script);
256
- }
257
-
258
- return { head, body, hashes };
249
+ return render(Root, { ...render_opts, props });
259
250
  });
251
+
252
+ if (rendered.hashes) {
253
+ csp.add_script_hashes(rendered.hashes.script);
254
+ }
260
255
  } finally {
261
256
  if (DEV) {
262
257
  globalThis.fetch = fetch;
@@ -269,7 +264,7 @@ export async function render_response({
269
264
  for (const { node } of branch) {
270
265
  for (const url of node.imports) modulepreloads.add(url);
271
266
  for (const url of node.stylesheets) stylesheets.add(url);
272
- for (const url of node.fonts) fonts.add(url);
267
+ for (const font of node.fonts) fonts.set(font.file, font);
273
268
 
274
269
  if (node.inline_styles && !client?.inline) {
275
270
  Object.entries(await node.inline_styles()).forEach(([filename, css]) => {
@@ -342,11 +337,11 @@ export async function render_response({
342
337
  head.add_stylesheet(path, attributes);
343
338
  }
344
339
 
345
- for (const dep of fonts) {
346
- const path = prefixed(dep);
340
+ for (const { file, filename } of fonts.values()) {
341
+ const path = prefixed(file);
347
342
 
348
- if (resolve_opts.preload({ type: 'font', path })) {
349
- const ext = dep.slice(dep.lastIndexOf('.') + 1);
343
+ if (resolve_opts.preload({ type: 'font', path, filename })) {
344
+ const ext = file.slice(file.lastIndexOf('.') + 1);
350
345
 
351
346
  add_preload(path, ['rel="preload"', 'as="font"', `type="font/${ext}"`, 'crossorigin']);
352
347
  }
@@ -1,9 +1,8 @@
1
1
  /** @import { RequestEvent, SSRManifest } from '@sveltejs/kit' */
2
2
  /** @import { RemoteForm } from '$app/server' */
3
- /** @import { ActionResult } from '$app/forms' */
4
- /** @import { RemoteFormInternals, RemoteFunctionData, RemoteFunctionResponse, RemoteInternals, RequestState, SSROptions } from 'types' */
3
+ /** @import { RemoteFormInternals, RemoteFunctionData, RemoteFunctionResponse, RemoteInternals, RequestState, ServerActionResult, SSROptions } from 'types' */
5
4
 
6
- import { json, error } from '@sveltejs/kit';
5
+ import { error } from '@sveltejs/kit';
7
6
  import { Redirect, SvelteKitError } from '@sveltejs/kit/internal';
8
7
  import { with_request_store, merge_tracing, record_span } from '@sveltejs/kit/internal/server';
9
8
  import { app_dir, base } from '#app/paths';
@@ -11,9 +10,11 @@ import { is_form_content_type } from '../../utils/http.js';
11
10
  import { create_remote_key, parse_remote_arg, split_remote_key } from '../shared.js';
12
11
  import { stringify } from '#app/internal/transport';
13
12
  import { handle_error_and_jsonify } from './errors.js';
14
- import { normalize_error } from '../../utils/error.js';
15
- import { check_incorrect_fail_use, get_action_location } from './page/actions.js';
16
- import { DEV } from 'esm-env';
13
+ import {
14
+ action_error_result,
15
+ get_action_location,
16
+ method_not_allowed_result
17
+ } from './page/actions.js';
17
18
  import { deserialize_binary_form } from '../form-utils.js';
18
19
  import { with_version_header } from './utils.js';
19
20
 
@@ -262,7 +263,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
262
263
 
263
264
  if (data._.issues) {
264
265
  // special case — don't serialize refreshes/reconnects
265
- return json(
266
+ return Response.json(
266
267
  /** @type {RemoteFunctionResponse} */ ({
267
268
  type: 'result',
268
269
  data: stringify(data)
@@ -310,7 +311,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
310
311
 
311
312
  await collect_remote_data(data, event, state, options);
312
313
 
313
- return json(
314
+ return Response.json(
314
315
  /** @type {RemoteFunctionResponse} */ ({
315
316
  type: 'result',
316
317
  data: stringify(data)
@@ -321,7 +322,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
321
322
  if (error instanceof Redirect) {
322
323
  const data = await collect_remote_data({ redirect: error.location }, event, state, options);
323
324
 
324
- return json(
325
+ return Response.json(
325
326
  /** @type {RemoteFunctionResponse} */ ({
326
327
  type: 'result',
327
328
  data: stringify(data)
@@ -332,7 +333,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
332
333
 
333
334
  const transformed = await handle_error_and_jsonify(event, state, options, error);
334
335
 
335
- return json(
336
+ return Response.json(
336
337
  /** @type {RemoteFunctionResponse} */ ({
337
338
  type: 'error',
338
339
  error: transformed
@@ -531,7 +532,7 @@ export async function handle_remote_form_post(event, state, manifest, id) {
531
532
  * @param {RequestState} state
532
533
  * @param {SSRManifest} manifest
533
534
  * @param {string} id
534
- * @returns {Promise<ActionResult>}
535
+ * @returns {Promise<ServerActionResult>}
535
536
  */
536
537
  async function handle_remote_form_post_internal(event, state, manifest, id) {
537
538
  const location = get_action_location(event.url);
@@ -547,21 +548,7 @@ async function handle_remote_form_post_internal(event, state, manifest, id) {
547
548
  );
548
549
 
549
550
  if (!form) {
550
- event.setHeaders({
551
- // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/405
552
- // "The server must generate an Allow header field in a 405 status code response"
553
- allow: 'GET'
554
- });
555
- return {
556
- type: 'error',
557
- location,
558
- // We're lying a bit with the types here; this will be transformed into a proper App.Error object later
559
- error: new SvelteKitError(
560
- 405,
561
- 'Method Not Allowed',
562
- `POST method not allowed. No form actions exist for ${DEV ? `the page at ${event.route.id}` : 'this page'}`
563
- )
564
- };
551
+ return method_not_allowed_result(event, location);
565
552
  }
566
553
 
567
554
  if (action_id) {
@@ -591,22 +578,7 @@ async function handle_remote_form_post_internal(event, state, manifest, id) {
591
578
  location
592
579
  };
593
580
  } catch (e) {
594
- const err = normalize_error(e);
595
-
596
- if (err instanceof Redirect) {
597
- return {
598
- type: 'redirect',
599
- status: err.status,
600
- location: err.location
601
- };
602
- }
603
-
604
- return {
605
- type: 'error',
606
- location,
607
- // @ts-expect-error We're lying a bit with the types here; this will be transformed into a proper App.Error object later
608
- error: check_incorrect_fail_use(err)
609
- };
581
+ return action_error_result(e, location);
610
582
  }
611
583
  }
612
584
 
@@ -1,6 +1,6 @@
1
1
  /** @import { SSRNode } from 'types' */
2
2
  import { DEV } from 'esm-env';
3
- import { json, text } from '@sveltejs/kit';
3
+ import { text } from '@sveltejs/kit';
4
4
  import { Redirect, SvelteKitError } from '@sveltejs/kit/internal';
5
5
  import {
6
6
  merge_tracing,
@@ -111,7 +111,7 @@ export async function internal_respond(request, options, manifest, state) {
111
111
  })
112
112
  ) {
113
113
  const message = 'Cross-site remote requests are forbidden';
114
- return json({ message }, { status: 403 });
114
+ return Response.json({ message }, { status: 403 });
115
115
  }
116
116
  } else if (options.csrf_check_origin) {
117
117
  const forbidden = is_csrf_forbidden({
@@ -126,7 +126,7 @@ export async function internal_respond(request, options, manifest, state) {
126
126
  const opts = { status: 403 };
127
127
 
128
128
  if (request.headers.get('accept') === 'application/json') {
129
- return json({ message }, opts);
129
+ return Response.json({ message }, opts);
130
130
  }
131
131
 
132
132
  return text(message, opts);
@@ -754,6 +754,26 @@ export async function internal_respond(request, options, manifest, state) {
754
754
  // if this request came direct from the user, rather than
755
755
  // via our own `fetch`, render a 404 page
756
756
  if (state.depth === 0) {
757
+ // Error-page data requests only invalidate the root layout.
758
+ if (
759
+ !state.prerendering &&
760
+ is_data_request &&
761
+ invalidated_data_nodes?.length === 1 &&
762
+ invalidated_data_nodes[0]
763
+ ) {
764
+ return await render_data(
765
+ event,
766
+ state,
767
+ { page: { layouts: [], leaf: 0 } },
768
+ options,
769
+ manifest,
770
+ invalidated_data_nodes,
771
+ // there is no route to take a trailing slash option from, and the
772
+ // SSR'd error page sees the pathname as-is
773
+ 'ignore'
774
+ );
775
+ }
776
+
757
777
  if (non_html_fetch_destinations.has(event.request.headers.get('sec-fetch-dest') ?? '')) {
758
778
  return text('Not Found', {
759
779
  status: 404,