@sveltejs/kit 3.0.0-next.23 → 3.0.0-next.25
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 +51 -8
- package/src/cli.js +3 -3
- package/src/constants.js +19 -1
- package/src/core/adapt/builder.js +3 -5
- package/src/core/env.js +137 -182
- package/src/core/postbuild/analyse.js +9 -4
- package/src/core/postbuild/prerender.js +5 -6
- 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 +12 -22
- package/src/core/sync/write_types/index.js +2 -2
- package/src/core/utils.js +10 -28
- package/src/exports/adapter.js +22 -0
- package/src/exports/hooks/public.d.ts +9 -1
- package/src/exports/node/index.js +77 -5
- package/src/exports/public.d.ts +1 -1
- package/src/exports/vite/build/build_server.js +3 -3
- package/src/exports/vite/build/service-worker.js +98 -0
- package/src/exports/vite/build/utils.js +48 -4
- package/src/exports/vite/dev/index.js +28 -25
- package/src/exports/vite/index.js +94 -747
- package/src/exports/vite/module_ids.js +1 -11
- package/src/exports/vite/plugins/env-vars.js +159 -0
- package/src/exports/vite/plugins/guard.js +205 -0
- package/src/exports/vite/preview/index.js +6 -4
- package/src/exports/vite/utils.js +99 -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/remote/form.js +11 -1
- package/src/runtime/app/server/remote/prerender.js +1 -2
- package/src/runtime/app/server/remote/query.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 +210 -278
- package/src/runtime/client/fetcher.js +18 -8
- package/src/runtime/client/remote-functions/form.svelte.js +9 -6
- package/src/runtime/client/remote-functions/prerender.svelte.js +1 -1
- package/src/runtime/client/remote-functions/query-live/iterator.js +1 -1
- package/src/runtime/client/remote-functions/shared.svelte.js +2 -2
- 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 +55 -87
- package/src/runtime/invalid-import.js +1 -0
- package/src/runtime/props.svelte.js +1 -1
- package/src/runtime/server/data/index.js +12 -27
- package/src/runtime/server/endpoint.js +8 -3
- package/src/runtime/server/env_module.js +1 -1
- package/src/runtime/server/errors.js +9 -12
- package/src/runtime/server/fetch.js +14 -16
- package/src/runtime/server/index.js +30 -27
- package/src/runtime/server/internal.js +34 -4
- package/src/runtime/server/page/actions.js +77 -124
- package/src/runtime/server/page/data_serializer.js +6 -10
- package/src/runtime/server/page/index.js +45 -82
- package/src/runtime/server/page/render.js +34 -52
- package/src/runtime/server/page/respond_with_error.js +7 -9
- package/src/runtime/server/remote-functions.js +138 -166
- package/src/runtime/server/respond.js +75 -30
- package/src/runtime/server/state.js +1 -0
- package/src/runtime/server/utils.js +0 -7
- package/src/runtime/utils.js +41 -0
- package/src/telemetry.js +1 -33
- package/src/types/ambient-private.d.ts +9 -17
- package/src/types/global-private.d.ts +8 -0
- package/src/types/internal.d.ts +27 -15
- package/src/types/private.d.ts +1 -1
- package/src/utils/exports.js +1 -0
- package/src/utils/filesystem.js +10 -22
- package/src/utils/functions.js +10 -0
- package/src/utils/routing.js +0 -11
- package/src/utils/streaming.js +5 -15
- package/src/utils/url.js +0 -11
- package/src/version.js +1 -1
- package/types/index.d.ts +54 -29
- package/types/index.d.ts.map +10 -5
- 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,9 +1,8 @@
|
|
|
1
1
|
/** @import { RequestEvent, SSRManifest } from '@sveltejs/kit' */
|
|
2
2
|
/** @import { RemoteForm } from '$app/server' */
|
|
3
|
-
/** @import {
|
|
4
|
-
/** @import { RemoteFormInternals, RemoteFunctionData, RemoteFunctionResponse, RemoteInternals, RequestState, SSROptions } from 'types' */
|
|
3
|
+
/** @import { RemoteFormInternals, RemoteFunctionData, RemoteFunctionResponse, RemoteInternals, RequestState, ServerActionResult } 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,10 +10,13 @@ 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';
|
|
19
|
+
import { text_encoder } from '../utils.js';
|
|
18
20
|
import { with_version_header } from './utils.js';
|
|
19
21
|
|
|
20
22
|
/**
|
|
@@ -24,8 +26,121 @@ import { with_version_header } from './utils.js';
|
|
|
24
26
|
*/
|
|
25
27
|
const KEEP_ALIVE_INTERVAL = 30_000;
|
|
26
28
|
|
|
29
|
+
/**
|
|
30
|
+
* @param {RequestEvent} event
|
|
31
|
+
* @param {RequestState} state
|
|
32
|
+
* @param {import('types').RemoteQueryLiveInternals} internals
|
|
33
|
+
* @param {any} arg
|
|
34
|
+
*/
|
|
35
|
+
export function create_live_query_response(event, state, internals, arg) {
|
|
36
|
+
const cancellation = new AbortController();
|
|
37
|
+
const live_event = {
|
|
38
|
+
...event,
|
|
39
|
+
request: new Request(event.request, {
|
|
40
|
+
signal: AbortSignal.any([event.request.signal, cancellation.signal])
|
|
41
|
+
})
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const generator = internals.run(live_event, state, arg);
|
|
45
|
+
|
|
46
|
+
let open = true;
|
|
47
|
+
let pulling = false;
|
|
48
|
+
/** @type {ReadableStreamDefaultController<Uint8Array>} */
|
|
49
|
+
let stream_controller;
|
|
50
|
+
/** @type {ReturnType<typeof setTimeout> | undefined} */
|
|
51
|
+
let keep_alive;
|
|
52
|
+
/** @type {string | undefined} */
|
|
53
|
+
let result;
|
|
54
|
+
|
|
55
|
+
function schedule_keep_alive() {
|
|
56
|
+
clearTimeout(keep_alive);
|
|
57
|
+
keep_alive = setTimeout(() => {
|
|
58
|
+
if (!open) return;
|
|
59
|
+
if ((stream_controller.desiredSize ?? 0) > 0) {
|
|
60
|
+
stream_controller.enqueue(text_encoder.encode(': keep-alive\n\n'));
|
|
61
|
+
}
|
|
62
|
+
schedule_keep_alive();
|
|
63
|
+
}, KEEP_ALIVE_INTERVAL);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** @param {any} data */
|
|
67
|
+
function send(data) {
|
|
68
|
+
if (!open) return;
|
|
69
|
+
stream_controller.enqueue(text_encoder.encode('data: ' + JSON.stringify(data) + '\n\n'));
|
|
70
|
+
schedule_keep_alive();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** @param {boolean} cancelled */
|
|
74
|
+
function teardown(cancelled) {
|
|
75
|
+
if (!open) return;
|
|
76
|
+
open = false;
|
|
77
|
+
clearTimeout(keep_alive);
|
|
78
|
+
cancellation.abort();
|
|
79
|
+
if (!cancelled) stream_controller.close();
|
|
80
|
+
// AsyncGenerator.return() cannot interrupt a pending next(). Cleanup is
|
|
81
|
+
// cooperative via request.signal, so stream cancellation must not await it.
|
|
82
|
+
void generator.return(undefined).catch(() => {});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
event.request.signal.addEventListener('abort', () => teardown(true), { once: true });
|
|
86
|
+
|
|
87
|
+
return new Response(
|
|
88
|
+
new ReadableStream({
|
|
89
|
+
start(controller) {
|
|
90
|
+
stream_controller = controller;
|
|
91
|
+
schedule_keep_alive();
|
|
92
|
+
},
|
|
93
|
+
async pull() {
|
|
94
|
+
if (!open || pulling) return;
|
|
95
|
+
pulling = true;
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
while (open) {
|
|
99
|
+
const { value, done } = await generator.next();
|
|
100
|
+
|
|
101
|
+
if (!open) return;
|
|
102
|
+
|
|
103
|
+
if (done) {
|
|
104
|
+
teardown(false);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (result !== (result = stringify(value))) {
|
|
109
|
+
send({ type: 'result', result });
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
} catch (error) {
|
|
114
|
+
if (!open) return;
|
|
115
|
+
|
|
116
|
+
if (error instanceof Redirect) {
|
|
117
|
+
send({ type: 'redirect', location: error.location });
|
|
118
|
+
} else {
|
|
119
|
+
const transformed = await handle_error_and_jsonify(event, state, error);
|
|
120
|
+
|
|
121
|
+
send({ type: 'error', error: transformed });
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
teardown(false);
|
|
125
|
+
} finally {
|
|
126
|
+
pulling = false;
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
cancel() {
|
|
130
|
+
teardown(true);
|
|
131
|
+
}
|
|
132
|
+
}),
|
|
133
|
+
{
|
|
134
|
+
headers: {
|
|
135
|
+
'cache-control': 'private, no-store',
|
|
136
|
+
'content-type': 'text/event-stream'
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
27
142
|
/** @type {typeof handle_remote_call_internal} */
|
|
28
|
-
export async function handle_remote_call(event, state,
|
|
143
|
+
export async function handle_remote_call(event, state, manifest, id) {
|
|
29
144
|
return record_span({
|
|
30
145
|
name: 'sveltekit.remote.call',
|
|
31
146
|
attributes: {
|
|
@@ -34,7 +149,7 @@ export async function handle_remote_call(event, state, options, manifest, id) {
|
|
|
34
149
|
fn: async (current) => {
|
|
35
150
|
const traced_event = merge_tracing(event, current);
|
|
36
151
|
const response = await with_request_store({ event: traced_event, state }, () =>
|
|
37
|
-
handle_remote_call_internal(traced_event, state,
|
|
152
|
+
handle_remote_call_internal(traced_event, state, manifest, id)
|
|
38
153
|
);
|
|
39
154
|
return with_version_header(response);
|
|
40
155
|
}
|
|
@@ -44,11 +159,10 @@ export async function handle_remote_call(event, state, options, manifest, id) {
|
|
|
44
159
|
/**
|
|
45
160
|
* @param {RequestEvent} event
|
|
46
161
|
* @param {RequestState} state
|
|
47
|
-
* @param {SSROptions} options
|
|
48
162
|
* @param {SSRManifest} manifest
|
|
49
163
|
* @param {string} id
|
|
50
164
|
*/
|
|
51
|
-
async function handle_remote_call_internal(event, state,
|
|
165
|
+
async function handle_remote_call_internal(event, state, manifest, id) {
|
|
52
166
|
const [hash, name, additional_args] = id.split('/');
|
|
53
167
|
const remotes = manifest._.remotes;
|
|
54
168
|
|
|
@@ -88,119 +202,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
|
|
|
88
202
|
new URL(event.request.url).searchParams.get('payload')
|
|
89
203
|
);
|
|
90
204
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const encoder = new TextEncoder();
|
|
94
|
-
|
|
95
|
-
let closed = false;
|
|
96
|
-
|
|
97
|
-
/** @type {ReturnType<typeof setTimeout> | undefined} */
|
|
98
|
-
let keep_alive;
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* (Re)schedule the keep-alive comment. Called whenever a message is sent, so
|
|
102
|
-
* that a keep-alive is only emitted once `KEEP_ALIVE_INTERVAL` has elapsed
|
|
103
|
-
* without any other activity.
|
|
104
|
-
* @param {ReadableStreamDefaultController} controller
|
|
105
|
-
*/
|
|
106
|
-
function schedule_keep_alive(controller) {
|
|
107
|
-
clearTimeout(keep_alive);
|
|
108
|
-
keep_alive = setTimeout(() => {
|
|
109
|
-
if (closed || event.request.signal.aborted) return;
|
|
110
|
-
// SSE comments (lines starting with `:`) are ignored by the client
|
|
111
|
-
controller.enqueue(encoder.encode(': keep-alive\n\n'));
|
|
112
|
-
schedule_keep_alive(controller);
|
|
113
|
-
}, KEEP_ALIVE_INTERVAL);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* @param {ReadableStreamDefaultController} controller
|
|
118
|
-
* @param {any} payload
|
|
119
|
-
*/
|
|
120
|
-
function send(controller, payload) {
|
|
121
|
-
controller.enqueue(encoder.encode('data: ' + JSON.stringify(payload) + '\n\n'));
|
|
122
|
-
schedule_keep_alive(controller);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/** @type {string | undefined} */
|
|
126
|
-
let result = undefined;
|
|
127
|
-
|
|
128
|
-
async function cancel() {
|
|
129
|
-
if (closed) return;
|
|
130
|
-
closed = true;
|
|
131
|
-
clearTimeout(keep_alive);
|
|
132
|
-
await generator.return(undefined);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
event.request.signal.addEventListener('abort', cancel, { once: true });
|
|
136
|
-
|
|
137
|
-
return new Response(
|
|
138
|
-
new ReadableStream({
|
|
139
|
-
start(controller) {
|
|
140
|
-
schedule_keep_alive(controller);
|
|
141
|
-
},
|
|
142
|
-
async pull(controller) {
|
|
143
|
-
if (event.request.signal.aborted) {
|
|
144
|
-
await cancel();
|
|
145
|
-
controller.close();
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
try {
|
|
150
|
-
while (true) {
|
|
151
|
-
const { value, done } = await generator.next();
|
|
152
|
-
|
|
153
|
-
if (done) {
|
|
154
|
-
await cancel();
|
|
155
|
-
controller.close();
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// only send changed data
|
|
160
|
-
if (result !== (result = stringify(value))) {
|
|
161
|
-
send(controller, {
|
|
162
|
-
type: 'result',
|
|
163
|
-
result
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
} catch (error) {
|
|
170
|
-
if (!event.request.signal.aborted) {
|
|
171
|
-
if (error instanceof Redirect) {
|
|
172
|
-
send(controller, {
|
|
173
|
-
type: 'redirect',
|
|
174
|
-
location: error.location
|
|
175
|
-
});
|
|
176
|
-
} else {
|
|
177
|
-
const transformed = await handle_error_and_jsonify(
|
|
178
|
-
event,
|
|
179
|
-
state,
|
|
180
|
-
options,
|
|
181
|
-
error
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
send(controller, {
|
|
185
|
-
type: 'error',
|
|
186
|
-
error: transformed
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
await cancel();
|
|
192
|
-
controller.close();
|
|
193
|
-
}
|
|
194
|
-
},
|
|
195
|
-
cancel
|
|
196
|
-
}),
|
|
197
|
-
{
|
|
198
|
-
headers: {
|
|
199
|
-
'cache-control': 'private, no-store',
|
|
200
|
-
'content-type': 'text/event-stream'
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
);
|
|
205
|
+
return create_live_query_response(event, state, internals, parse_remote_arg(payload));
|
|
204
206
|
}
|
|
205
207
|
|
|
206
208
|
case 'query_batch': {
|
|
@@ -217,7 +219,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
|
|
|
217
219
|
|
|
218
220
|
const args = await Promise.all(payloads.map((payload) => parse_remote_arg(payload)));
|
|
219
221
|
|
|
220
|
-
data._ = await with_request_store({ event, state }, () => internals.run(args
|
|
222
|
+
data._ = await with_request_store({ event, state }, () => internals.run(args));
|
|
221
223
|
|
|
222
224
|
break;
|
|
223
225
|
}
|
|
@@ -262,7 +264,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
|
|
|
262
264
|
|
|
263
265
|
if (data._.issues) {
|
|
264
266
|
// special case — don't serialize refreshes/reconnects
|
|
265
|
-
return json(
|
|
267
|
+
return Response.json(
|
|
266
268
|
/** @type {RemoteFunctionResponse} */ ({
|
|
267
269
|
type: 'result',
|
|
268
270
|
data: stringify(data)
|
|
@@ -308,9 +310,9 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
|
|
|
308
310
|
}
|
|
309
311
|
}
|
|
310
312
|
|
|
311
|
-
await collect_remote_data(data, event, state
|
|
313
|
+
await collect_remote_data(data, event, state);
|
|
312
314
|
|
|
313
|
-
return json(
|
|
315
|
+
return Response.json(
|
|
314
316
|
/** @type {RemoteFunctionResponse} */ ({
|
|
315
317
|
type: 'result',
|
|
316
318
|
data: stringify(data)
|
|
@@ -319,9 +321,9 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
|
|
|
319
321
|
);
|
|
320
322
|
} catch (error) {
|
|
321
323
|
if (error instanceof Redirect) {
|
|
322
|
-
const data = await collect_remote_data({ redirect: error.location }, event, state
|
|
324
|
+
const data = await collect_remote_data({ redirect: error.location }, event, state);
|
|
323
325
|
|
|
324
|
-
return json(
|
|
326
|
+
return Response.json(
|
|
325
327
|
/** @type {RemoteFunctionResponse} */ ({
|
|
326
328
|
type: 'result',
|
|
327
329
|
data: stringify(data)
|
|
@@ -330,9 +332,9 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
|
|
|
330
332
|
);
|
|
331
333
|
}
|
|
332
334
|
|
|
333
|
-
const transformed = await handle_error_and_jsonify(event, state,
|
|
335
|
+
const transformed = await handle_error_and_jsonify(event, state, error);
|
|
334
336
|
|
|
335
|
-
return json(
|
|
337
|
+
return Response.json(
|
|
336
338
|
/** @type {RemoteFunctionResponse} */ ({
|
|
337
339
|
type: 'error',
|
|
338
340
|
error: transformed
|
|
@@ -355,9 +357,8 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
|
|
|
355
357
|
* @param {RemoteFunctionData} data
|
|
356
358
|
* @param {RequestEvent} event
|
|
357
359
|
* @param {RequestState} state
|
|
358
|
-
* @param {SSROptions} options
|
|
359
360
|
*/
|
|
360
|
-
export async function collect_remote_data(data, event, state
|
|
361
|
+
export async function collect_remote_data(data, event, state) {
|
|
361
362
|
/**
|
|
362
363
|
*
|
|
363
364
|
* @param {unknown} error
|
|
@@ -365,7 +366,7 @@ export async function collect_remote_data(data, event, state, options) {
|
|
|
365
366
|
*/
|
|
366
367
|
function convert_error(error) {
|
|
367
368
|
// TODO 4.0 remove the `Promise.resolve(...)`
|
|
368
|
-
return Promise.resolve(handle_error_and_jsonify(event, state,
|
|
369
|
+
return Promise.resolve(handle_error_and_jsonify(event, state, error));
|
|
369
370
|
}
|
|
370
371
|
|
|
371
372
|
/** @type {Promise<any>[]} */
|
|
@@ -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
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** @import { SSRNode } from 'types' */
|
|
2
2
|
import { DEV } from 'esm-env';
|
|
3
|
-
import {
|
|
3
|
+
import { text } from '@sveltejs/kit';
|
|
4
4
|
import { Redirect, SvelteKitError } from '@sveltejs/kit/internal';
|
|
5
5
|
import {
|
|
6
6
|
merge_tracing,
|
|
@@ -45,6 +45,7 @@ import {
|
|
|
45
45
|
} from '../pathname.js';
|
|
46
46
|
import { server_data_serializer } from './page/data_serializer.js';
|
|
47
47
|
import { get_remote_id, handle_remote_call } from './remote-functions.js';
|
|
48
|
+
import { hooks, options } from './internal.js';
|
|
48
49
|
|
|
49
50
|
/** @type {import('types').RequiredResolveOptions['transformPageChunk']} */
|
|
50
51
|
const default_transform = ({ html }) => html;
|
|
@@ -85,12 +86,11 @@ export const respond = propagate_context(internal_respond);
|
|
|
85
86
|
|
|
86
87
|
/**
|
|
87
88
|
* @param {Request} request
|
|
88
|
-
* @param {import('types').SSROptions} options
|
|
89
89
|
* @param {import('@sveltejs/kit').SSRManifest} manifest
|
|
90
90
|
* @param {import('types').RequestState} state
|
|
91
91
|
* @returns {Promise<Response>}
|
|
92
92
|
*/
|
|
93
|
-
export async function internal_respond(request,
|
|
93
|
+
export async function internal_respond(request, manifest, state) {
|
|
94
94
|
/** URL but stripped from the potential `/__data.json` suffix and its search param */
|
|
95
95
|
const url = new URL(request.url);
|
|
96
96
|
|
|
@@ -100,7 +100,7 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
100
100
|
|
|
101
101
|
if (!__SVELTEKIT_DEV__) {
|
|
102
102
|
const request_origin = request.headers.get('origin');
|
|
103
|
-
const self_origin = get_self_origin(
|
|
103
|
+
const self_origin = get_self_origin(__SVELTEKIT_PATHS_ORIGIN__, url.origin);
|
|
104
104
|
|
|
105
105
|
if (remote_id) {
|
|
106
106
|
if (
|
|
@@ -111,9 +111,9 @@ 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
|
-
} else if (
|
|
116
|
+
} else if (__SVELTEKIT_CSRF_CHECK_ORIGIN__) {
|
|
117
117
|
const forbidden = is_csrf_forbidden({
|
|
118
118
|
request,
|
|
119
119
|
request_origin,
|
|
@@ -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);
|
|
@@ -134,7 +134,7 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
if (
|
|
137
|
+
if (__SVELTEKIT_HASH_ROUTING__ && url.pathname !== base + '/' && url.pathname !== '/[fallback]') {
|
|
138
138
|
return text('Not found', { status: 404 });
|
|
139
139
|
}
|
|
140
140
|
|
|
@@ -243,7 +243,6 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
243
243
|
// @ts-expect-error this has to be assigned lazily
|
|
244
244
|
event.fetch = create_fetch({
|
|
245
245
|
event,
|
|
246
|
-
options,
|
|
247
246
|
manifest,
|
|
248
247
|
state,
|
|
249
248
|
get_cookie_header,
|
|
@@ -263,7 +262,16 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
263
262
|
|
|
264
263
|
// reroute could alter the given URL, so we pass a copy
|
|
265
264
|
resolved_path =
|
|
266
|
-
(await
|
|
265
|
+
(await hooks.reroute({ url: new URL(url), fetch: event.fetch })) ?? url.pathname;
|
|
266
|
+
|
|
267
|
+
if (!manifest._.routes.length && resolved_path !== url.pathname) {
|
|
268
|
+
state.rerouted_url = denormalise_url({
|
|
269
|
+
request_url: request.url,
|
|
270
|
+
resolved_path,
|
|
271
|
+
is_data_request,
|
|
272
|
+
is_route_resolution_request
|
|
273
|
+
}).toString();
|
|
274
|
+
}
|
|
267
275
|
} catch {
|
|
268
276
|
return text('Internal Server Error', {
|
|
269
277
|
status: 500
|
|
@@ -300,12 +308,12 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
300
308
|
!state.prerendering?.fallback &&
|
|
301
309
|
has_prerendered_path(manifest, resolved_path)
|
|
302
310
|
) {
|
|
303
|
-
const url =
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
311
|
+
const url = denormalise_url({
|
|
312
|
+
request_url: request.url,
|
|
313
|
+
resolved_path,
|
|
314
|
+
is_data_request,
|
|
315
|
+
is_route_resolution_request
|
|
316
|
+
});
|
|
309
317
|
|
|
310
318
|
try {
|
|
311
319
|
// `fetch` automatically decodes the body, so we need to delete the related headers to not break the response
|
|
@@ -323,7 +331,7 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
323
331
|
statusText: response.statusText
|
|
324
332
|
});
|
|
325
333
|
} catch (error) {
|
|
326
|
-
return await handle_fatal_error(event, state,
|
|
334
|
+
return await handle_fatal_error(event, state, error);
|
|
327
335
|
}
|
|
328
336
|
}
|
|
329
337
|
|
|
@@ -369,7 +377,7 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
369
377
|
event.params = result.params;
|
|
370
378
|
}
|
|
371
379
|
} catch (e) {
|
|
372
|
-
return await handle_fatal_error(event, state,
|
|
380
|
+
return await handle_fatal_error(event, state, e);
|
|
373
381
|
}
|
|
374
382
|
}
|
|
375
383
|
|
|
@@ -452,10 +460,10 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
452
460
|
add_cookies_to_headers(response.headers, new_cookies.values());
|
|
453
461
|
return response;
|
|
454
462
|
} catch (err) {
|
|
455
|
-
return await handle_fatal_error(event, state,
|
|
463
|
+
return await handle_fatal_error(event, state, err);
|
|
456
464
|
}
|
|
457
465
|
}
|
|
458
|
-
return await handle_fatal_error(event, state,
|
|
466
|
+
return await handle_fatal_error(event, state, e);
|
|
459
467
|
}
|
|
460
468
|
|
|
461
469
|
async function handle() {
|
|
@@ -485,7 +493,7 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
485
493
|
};
|
|
486
494
|
|
|
487
495
|
return await with_request_store({ event: traced_event, state }, () =>
|
|
488
|
-
|
|
496
|
+
hooks.handle({
|
|
489
497
|
event: traced_event,
|
|
490
498
|
resolve: (event, opts) => {
|
|
491
499
|
return record_span({
|
|
@@ -592,7 +600,6 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
592
600
|
return await respond_with_error({
|
|
593
601
|
event,
|
|
594
602
|
state,
|
|
595
|
-
options,
|
|
596
603
|
manifest,
|
|
597
604
|
error: new SvelteKitError(
|
|
598
605
|
400,
|
|
@@ -603,11 +610,10 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
603
610
|
});
|
|
604
611
|
}
|
|
605
612
|
|
|
606
|
-
if (
|
|
613
|
+
if (__SVELTEKIT_HASH_ROUTING__ || state.prerendering?.fallback) {
|
|
607
614
|
return await render_response({
|
|
608
615
|
event,
|
|
609
616
|
state,
|
|
610
|
-
options,
|
|
611
617
|
manifest,
|
|
612
618
|
page_config: { ssr: false, csr: true },
|
|
613
619
|
status: 200,
|
|
@@ -622,12 +628,12 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
622
628
|
],
|
|
623
629
|
fetched: [],
|
|
624
630
|
resolve_opts,
|
|
625
|
-
data_serializer: server_data_serializer(event, state
|
|
631
|
+
data_serializer: server_data_serializer(event, state)
|
|
626
632
|
});
|
|
627
633
|
}
|
|
628
634
|
|
|
629
635
|
if (remote_id) {
|
|
630
|
-
return await handle_remote_call(event, state,
|
|
636
|
+
return await handle_remote_call(event, state, manifest, remote_id);
|
|
631
637
|
}
|
|
632
638
|
|
|
633
639
|
if (route) {
|
|
@@ -641,7 +647,6 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
641
647
|
event,
|
|
642
648
|
state,
|
|
643
649
|
route,
|
|
644
|
-
options,
|
|
645
650
|
manifest,
|
|
646
651
|
invalidated_data_nodes,
|
|
647
652
|
trailing_slash
|
|
@@ -676,7 +681,6 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
676
681
|
event,
|
|
677
682
|
state,
|
|
678
683
|
route.page,
|
|
679
|
-
options,
|
|
680
684
|
manifest,
|
|
681
685
|
page_nodes,
|
|
682
686
|
resolve_opts
|
|
@@ -754,6 +758,25 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
754
758
|
// if this request came direct from the user, rather than
|
|
755
759
|
// via our own `fetch`, render a 404 page
|
|
756
760
|
if (state.depth === 0) {
|
|
761
|
+
// Error-page data requests only invalidate the root layout.
|
|
762
|
+
if (
|
|
763
|
+
!state.prerendering &&
|
|
764
|
+
is_data_request &&
|
|
765
|
+
invalidated_data_nodes?.length === 1 &&
|
|
766
|
+
invalidated_data_nodes[0]
|
|
767
|
+
) {
|
|
768
|
+
return await render_data(
|
|
769
|
+
event,
|
|
770
|
+
state,
|
|
771
|
+
{ page: { layouts: [], leaf: 0 } },
|
|
772
|
+
manifest,
|
|
773
|
+
invalidated_data_nodes,
|
|
774
|
+
// there is no route to take a trailing slash option from, and the
|
|
775
|
+
// SSR'd error page sees the pathname as-is
|
|
776
|
+
'ignore'
|
|
777
|
+
);
|
|
778
|
+
}
|
|
779
|
+
|
|
757
780
|
if (non_html_fetch_destinations.has(event.request.headers.get('sec-fetch-dest') ?? '')) {
|
|
758
781
|
return text('Not Found', {
|
|
759
782
|
status: 404,
|
|
@@ -764,7 +787,6 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
764
787
|
return await respond_with_error({
|
|
765
788
|
event,
|
|
766
789
|
state,
|
|
767
|
-
options,
|
|
768
790
|
manifest,
|
|
769
791
|
error: new SvelteKitError(404, 'Not Found', `Not found: ${event.url.pathname}`),
|
|
770
792
|
resolve_opts
|
|
@@ -786,7 +808,7 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
786
808
|
// and I don't even know how to describe it. need to investigate at some point
|
|
787
809
|
|
|
788
810
|
// HttpError from endpoint can end up here - TODO should it be handled there instead?
|
|
789
|
-
return await handle_fatal_error(event, state,
|
|
811
|
+
return await handle_fatal_error(event, state, e);
|
|
790
812
|
} finally {
|
|
791
813
|
event.cookies.set = () => {
|
|
792
814
|
throw new Error('Cannot use `cookies.set(...)` after the response has been generated');
|
|
@@ -833,3 +855,26 @@ function propagate_context(fn) {
|
|
|
833
855
|
});
|
|
834
856
|
};
|
|
835
857
|
}
|
|
858
|
+
|
|
859
|
+
/**
|
|
860
|
+
* @param {object} opts
|
|
861
|
+
* @param {string} opts.request_url - The original request URL
|
|
862
|
+
* @param {string} opts.resolved_path - The resolved pathname
|
|
863
|
+
* @param {boolean} opts.is_data_request - Whether the request is a data request
|
|
864
|
+
* @param {boolean} opts.is_route_resolution_request -
|
|
865
|
+
* @returns {URL}
|
|
866
|
+
*/
|
|
867
|
+
function denormalise_url({
|
|
868
|
+
request_url,
|
|
869
|
+
resolved_path,
|
|
870
|
+
is_data_request,
|
|
871
|
+
is_route_resolution_request
|
|
872
|
+
}) {
|
|
873
|
+
const url = new URL(request_url);
|
|
874
|
+
url.pathname = is_data_request
|
|
875
|
+
? add_data_suffix(resolved_path)
|
|
876
|
+
: is_route_resolution_request
|
|
877
|
+
? add_resolution_suffix(resolved_path)
|
|
878
|
+
: resolved_path;
|
|
879
|
+
return url;
|
|
880
|
+
}
|