@sveltejs/kit 3.0.0-next.22 → 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.
- package/package.json +40 -9
- package/src/cli.js +3 -3
- package/src/constants.js +13 -1
- package/src/core/adapt/builder.js +2 -3
- package/src/core/env.js +139 -181
- package/src/core/postbuild/analyse.js +9 -4
- package/src/core/postbuild/prerender.js +22 -23
- package/src/core/sync/create_manifest_data/index.js +29 -33
- package/src/core/sync/sync.js +23 -40
- package/src/core/sync/write_app_manifest.js +83 -0
- package/src/core/sync/write_client_manifest.js +6 -4
- package/src/core/sync/write_server.js +10 -6
- package/src/core/sync/write_types/index.js +2 -2
- package/src/core/utils.js +0 -28
- package/src/exports/hooks/public.d.ts +9 -1
- package/src/exports/index.js +10 -0
- package/src/exports/node/index.js +77 -5
- package/src/exports/public.d.ts +9 -0
- package/src/exports/vite/build/build_server.js +3 -3
- package/src/exports/vite/build/utils.js +48 -4
- package/src/exports/vite/dev/index.js +11 -22
- package/src/exports/vite/index.js +62 -345
- package/src/exports/vite/module_ids.js +1 -11
- package/src/exports/vite/plugins/env-vars.js +117 -0
- package/src/exports/vite/preview/index.js +6 -4
- package/src/exports/vite/utils.js +2 -4
- package/src/runtime/app/env/{types.d.ts → client.js} +9 -4
- package/src/runtime/app/env/index.js +1 -2
- package/src/runtime/app/env/private/index.js +1 -0
- package/src/runtime/app/env/public/client.js +1 -1
- package/src/runtime/app/env/public/server.js +1 -1
- package/src/runtime/app/env/{internal.js → server.js} +4 -4
- package/src/runtime/app/forms/client.js +263 -0
- package/src/runtime/app/forms/index.js +1 -263
- package/src/runtime/app/forms/public.d.ts +1 -1
- package/src/runtime/app/forms/server.js +6 -0
- package/src/runtime/app/forms/shared.js +34 -0
- package/src/runtime/app/manifest/index.js +1 -1
- package/src/runtime/app/navigation/client.js +15 -0
- package/src/runtime/app/navigation/index.js +1 -15
- package/src/runtime/app/navigation/public.d.ts +1 -1
- package/src/runtime/app/navigation/server.js +15 -0
- package/src/runtime/app/paths/server.js +1 -1
- package/src/runtime/app/server/public.d.ts +512 -0
- package/src/runtime/app/server/remote/command.js +1 -1
- package/src/runtime/app/server/remote/form.js +16 -6
- package/src/runtime/app/server/remote/prerender.js +2 -3
- package/src/runtime/app/server/remote/query.js +2 -2
- package/src/runtime/app/server/remote/requested.js +3 -3
- package/src/runtime/app/state/client.svelte.js +207 -0
- package/src/runtime/app/state/index.js +1 -66
- package/src/runtime/app/state/public.d.ts +1 -1
- package/src/runtime/client/bundle.js +1 -1
- package/src/runtime/client/client.js +206 -274
- package/src/runtime/client/fetcher.js +18 -8
- package/src/runtime/client/remote-functions/command.svelte.js +1 -1
- package/src/runtime/client/remote-functions/form.svelte.js +10 -7
- package/src/runtime/client/remote-functions/prerender.svelte.js +2 -2
- package/src/runtime/client/remote-functions/query/index.js +1 -1
- package/src/runtime/client/remote-functions/query/instance.svelte.js +2 -1
- package/src/runtime/client/remote-functions/query-batch.svelte.js +1 -1
- package/src/runtime/client/remote-functions/query-live/index.js +1 -1
- package/src/runtime/client/remote-functions/query-live/instance.svelte.js +4 -3
- package/src/runtime/client/remote-functions/query-live/iterator.js +1 -1
- package/src/runtime/client/remote-functions/shared.svelte.js +3 -3
- package/src/runtime/client/snapshots.js +1 -3
- package/src/runtime/client/stream.js +27 -20
- package/src/runtime/client/utils.js +7 -3
- package/src/runtime/components/root.svelte +5 -5
- package/src/runtime/env/dynamic/private.js +1 -1
- package/src/runtime/env/static/private.js +1 -1
- package/src/runtime/error-chain.js +54 -0
- package/src/runtime/form-utils.js +53 -77
- package/src/runtime/invalid-import.js +1 -0
- package/src/runtime/props.svelte.js +1 -1
- package/src/runtime/server/data/index.js +1 -1
- package/src/runtime/server/endpoint.js +8 -3
- package/src/runtime/server/env_module.js +1 -1
- package/src/runtime/server/errors.js +2 -2
- package/src/runtime/server/index.js +2 -2
- package/src/runtime/server/page/actions.js +77 -122
- package/src/runtime/server/page/index.js +37 -69
- package/src/runtime/server/page/render.js +18 -23
- package/src/runtime/server/remote-functions.js +15 -43
- package/src/runtime/server/respond.js +23 -3
- package/src/telemetry.js +1 -33
- package/src/types/ambient-private.d.ts +9 -17
- package/src/types/internal.d.ts +21 -5
- package/src/types/private.d.ts +1 -1
- package/src/utils/exports.js +1 -0
- package/src/utils/filesystem.js +9 -21
- package/src/utils/functions.js +10 -0
- package/src/utils/promise.js +25 -0
- package/src/utils/routing.js +0 -11
- package/src/utils/url.js +0 -11
- package/src/version.js +1 -1
- package/types/index.d.ts +1134 -1136
- package/types/index.d.ts.map +50 -50
- package/src/exports/remote/index.js +0 -11
- package/src/exports/remote/public.d.ts +0 -519
- package/src/runtime/app/env/private.js +0 -1
- package/src/runtime/app/env/standard-schema.d.ts +0 -0
- package/src/runtime/app/state/client.js +0 -63
- package/src/runtime/client/state.svelte.js +0 -98
- package/src/runtime/server/ambient.d.ts +0 -4
- package/src/utils/path.js +0 -23
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Redirect } from '@sveltejs/kit/internal';
|
|
2
2
|
import { with_request_store } from '@sveltejs/kit/internal/server';
|
|
3
|
-
import { ENDPOINT_METHODS, PAGE_METHODS } from '../../constants.js';
|
|
3
|
+
import { BODY_DEPENDENT_METHODS, ENDPOINT_METHODS, PAGE_METHODS } from '../../constants.js';
|
|
4
4
|
import { negotiate } from '../../utils/http.js';
|
|
5
5
|
import { method_not_allowed } from './utils.js';
|
|
6
6
|
|
|
@@ -25,8 +25,13 @@ export async function render_endpoint(event, state, mod) {
|
|
|
25
25
|
|
|
26
26
|
const prerender = mod.prerender ?? state.prerender_default;
|
|
27
27
|
|
|
28
|
-
if (
|
|
29
|
-
|
|
28
|
+
if (
|
|
29
|
+
prerender &&
|
|
30
|
+
/** @type {import('types').HttpMethod[]} */ (BODY_DEPENDENT_METHODS).some(
|
|
31
|
+
(method) => mod[method]
|
|
32
|
+
)
|
|
33
|
+
) {
|
|
34
|
+
throw new Error('Cannot prerender endpoints with body-dependent methods');
|
|
30
35
|
}
|
|
31
36
|
|
|
32
37
|
if (state.prerendering && !state.prerendering.inside_reroute && !prerender) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { text } from '@sveltejs/kit';
|
|
2
2
|
import {
|
|
3
3
|
HandledHttpError,
|
|
4
4
|
HttpError,
|
|
@@ -28,7 +28,7 @@ export async function handle_fatal_error(event, state, options, error) {
|
|
|
28
28
|
]);
|
|
29
29
|
|
|
30
30
|
if (event.isDataRequest || type === 'application/json') {
|
|
31
|
-
return json(body, {
|
|
31
|
+
return Response.json(body, {
|
|
32
32
|
status
|
|
33
33
|
});
|
|
34
34
|
}
|
|
@@ -2,9 +2,9 @@ import { noop } from '../../utils/functions.js';
|
|
|
2
2
|
import { IN_WEBCONTAINER } from '../../constants.js';
|
|
3
3
|
import { respond } from './respond.js';
|
|
4
4
|
import { create_request_state } from './state.js';
|
|
5
|
-
import { options, get_hooks } from '
|
|
5
|
+
import { options, get_hooks } from '<sveltekit:generated>/server.js';
|
|
6
6
|
import { set_read_implementation, set_manifest, fix_stack_trace } from './internal.js';
|
|
7
|
-
import { set_env } from '
|
|
7
|
+
import { set_env } from '<sveltekit:generated>/env/config.js';
|
|
8
8
|
import { init_tracing } from '@sveltejs/kit/internal/server';
|
|
9
9
|
import { DEV } from 'esm-env';
|
|
10
10
|
import { init_transport } from '#app/internal/transport';
|
|
@@ -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
|
|
32
|
-
|
|
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
|
-
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
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
|
-
|
|
116
|
-
error
|
|
117
|
-
|
|
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 {
|
|
88
|
+
* @param {RequestEvent} event
|
|
89
|
+
* @param {string} location
|
|
90
|
+
* @returns {Extract<ServerActionResult, { type: 'error' }>}
|
|
144
91
|
*/
|
|
145
|
-
export function
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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<
|
|
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
|
|
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
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
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 {
|
|
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
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
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
|
-
|
|
390
|
-
|
|
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
|
|
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 '
|
|
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('
|
|
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
|
-
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
346
|
-
const path = prefixed(
|
|
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 =
|
|
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
|
-
/** @import { RemoteForm } from '
|
|
3
|
-
/** @import {
|
|
4
|
-
/** @import { RemoteFormInternals, RemoteFunctionData, RemoteFunctionResponse, RemoteInternals, RequestState, SSROptions } from 'types' */
|
|
2
|
+
/** @import { RemoteForm } from '$app/server' */
|
|
3
|
+
/** @import { RemoteFormInternals, RemoteFunctionData, RemoteFunctionResponse, RemoteInternals, RequestState, ServerActionResult, SSROptions } from 'types' */
|
|
5
4
|
|
|
6
|
-
import {
|
|
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 {
|
|
15
|
-
|
|
16
|
-
|
|
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<
|
|
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
|
|
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
|
-
|
|
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
|
|