@sveltejs/kit 3.0.0-next.24 → 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 +12 -4
- package/src/constants.js +6 -0
- package/src/core/adapt/builder.js +1 -2
- package/src/core/env.js +3 -6
- package/src/core/postbuild/prerender.js +2 -2
- package/src/core/sync/write_server.js +3 -17
- package/src/core/utils.js +10 -0
- package/src/exports/adapter.js +22 -0
- package/src/exports/public.d.ts +1 -1
- package/src/exports/vite/build/service-worker.js +98 -0
- package/src/exports/vite/dev/index.js +17 -3
- package/src/exports/vite/index.js +41 -411
- package/src/exports/vite/plugins/env-vars.js +42 -0
- package/src/exports/vite/plugins/guard.js +205 -0
- package/src/exports/vite/utils.js +97 -0
- package/src/runtime/app/server/remote/query.js +2 -2
- package/src/runtime/client/client.js +4 -4
- package/src/runtime/form-utils.js +11 -19
- package/src/runtime/server/data/index.js +11 -26
- package/src/runtime/server/errors.js +7 -10
- package/src/runtime/server/fetch.js +14 -16
- package/src/runtime/server/index.js +28 -25
- package/src/runtime/server/internal.js +34 -4
- package/src/runtime/server/page/actions.js +6 -8
- package/src/runtime/server/page/data_serializer.js +6 -10
- package/src/runtime/server/page/index.js +9 -14
- package/src/runtime/server/page/render.js +16 -29
- package/src/runtime/server/page/respond_with_error.js +7 -9
- package/src/runtime/server/remote-functions.js +125 -125
- package/src/runtime/server/respond.js +53 -28
- 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/types/global-private.d.ts +8 -0
- package/src/types/internal.d.ts +7 -11
- package/src/utils/filesystem.js +1 -1
- package/src/utils/streaming.js +5 -15
- package/src/version.js +1 -1
- package/types/index.d.ts +20 -1
- package/types/index.d.ts.map +4 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** @import { RequestEvent, SSRManifest } from '@sveltejs/kit' */
|
|
2
2
|
/** @import { RemoteForm } from '$app/server' */
|
|
3
|
-
/** @import { RemoteFormInternals, RemoteFunctionData, RemoteFunctionResponse, RemoteInternals, RequestState, ServerActionResult
|
|
3
|
+
/** @import { RemoteFormInternals, RemoteFunctionData, RemoteFunctionResponse, RemoteInternals, RequestState, ServerActionResult } from 'types' */
|
|
4
4
|
|
|
5
5
|
import { error } from '@sveltejs/kit';
|
|
6
6
|
import { Redirect, SvelteKitError } from '@sveltejs/kit/internal';
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
method_not_allowed_result
|
|
17
17
|
} from './page/actions.js';
|
|
18
18
|
import { deserialize_binary_form } from '../form-utils.js';
|
|
19
|
+
import { text_encoder } from '../utils.js';
|
|
19
20
|
import { with_version_header } from './utils.js';
|
|
20
21
|
|
|
21
22
|
/**
|
|
@@ -25,8 +26,121 @@ import { with_version_header } from './utils.js';
|
|
|
25
26
|
*/
|
|
26
27
|
const KEEP_ALIVE_INTERVAL = 30_000;
|
|
27
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
|
+
|
|
28
142
|
/** @type {typeof handle_remote_call_internal} */
|
|
29
|
-
export async function handle_remote_call(event, state,
|
|
143
|
+
export async function handle_remote_call(event, state, manifest, id) {
|
|
30
144
|
return record_span({
|
|
31
145
|
name: 'sveltekit.remote.call',
|
|
32
146
|
attributes: {
|
|
@@ -35,7 +149,7 @@ export async function handle_remote_call(event, state, options, manifest, id) {
|
|
|
35
149
|
fn: async (current) => {
|
|
36
150
|
const traced_event = merge_tracing(event, current);
|
|
37
151
|
const response = await with_request_store({ event: traced_event, state }, () =>
|
|
38
|
-
handle_remote_call_internal(traced_event, state,
|
|
152
|
+
handle_remote_call_internal(traced_event, state, manifest, id)
|
|
39
153
|
);
|
|
40
154
|
return with_version_header(response);
|
|
41
155
|
}
|
|
@@ -45,11 +159,10 @@ export async function handle_remote_call(event, state, options, manifest, id) {
|
|
|
45
159
|
/**
|
|
46
160
|
* @param {RequestEvent} event
|
|
47
161
|
* @param {RequestState} state
|
|
48
|
-
* @param {SSROptions} options
|
|
49
162
|
* @param {SSRManifest} manifest
|
|
50
163
|
* @param {string} id
|
|
51
164
|
*/
|
|
52
|
-
async function handle_remote_call_internal(event, state,
|
|
165
|
+
async function handle_remote_call_internal(event, state, manifest, id) {
|
|
53
166
|
const [hash, name, additional_args] = id.split('/');
|
|
54
167
|
const remotes = manifest._.remotes;
|
|
55
168
|
|
|
@@ -89,119 +202,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
|
|
|
89
202
|
new URL(event.request.url).searchParams.get('payload')
|
|
90
203
|
);
|
|
91
204
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const encoder = new TextEncoder();
|
|
95
|
-
|
|
96
|
-
let closed = false;
|
|
97
|
-
|
|
98
|
-
/** @type {ReturnType<typeof setTimeout> | undefined} */
|
|
99
|
-
let keep_alive;
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* (Re)schedule the keep-alive comment. Called whenever a message is sent, so
|
|
103
|
-
* that a keep-alive is only emitted once `KEEP_ALIVE_INTERVAL` has elapsed
|
|
104
|
-
* without any other activity.
|
|
105
|
-
* @param {ReadableStreamDefaultController} controller
|
|
106
|
-
*/
|
|
107
|
-
function schedule_keep_alive(controller) {
|
|
108
|
-
clearTimeout(keep_alive);
|
|
109
|
-
keep_alive = setTimeout(() => {
|
|
110
|
-
if (closed || event.request.signal.aborted) return;
|
|
111
|
-
// SSE comments (lines starting with `:`) are ignored by the client
|
|
112
|
-
controller.enqueue(encoder.encode(': keep-alive\n\n'));
|
|
113
|
-
schedule_keep_alive(controller);
|
|
114
|
-
}, KEEP_ALIVE_INTERVAL);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* @param {ReadableStreamDefaultController} controller
|
|
119
|
-
* @param {any} payload
|
|
120
|
-
*/
|
|
121
|
-
function send(controller, payload) {
|
|
122
|
-
controller.enqueue(encoder.encode('data: ' + JSON.stringify(payload) + '\n\n'));
|
|
123
|
-
schedule_keep_alive(controller);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/** @type {string | undefined} */
|
|
127
|
-
let result = undefined;
|
|
128
|
-
|
|
129
|
-
async function cancel() {
|
|
130
|
-
if (closed) return;
|
|
131
|
-
closed = true;
|
|
132
|
-
clearTimeout(keep_alive);
|
|
133
|
-
await generator.return(undefined);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
event.request.signal.addEventListener('abort', cancel, { once: true });
|
|
137
|
-
|
|
138
|
-
return new Response(
|
|
139
|
-
new ReadableStream({
|
|
140
|
-
start(controller) {
|
|
141
|
-
schedule_keep_alive(controller);
|
|
142
|
-
},
|
|
143
|
-
async pull(controller) {
|
|
144
|
-
if (event.request.signal.aborted) {
|
|
145
|
-
await cancel();
|
|
146
|
-
controller.close();
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
try {
|
|
151
|
-
while (true) {
|
|
152
|
-
const { value, done } = await generator.next();
|
|
153
|
-
|
|
154
|
-
if (done) {
|
|
155
|
-
await cancel();
|
|
156
|
-
controller.close();
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// only send changed data
|
|
161
|
-
if (result !== (result = stringify(value))) {
|
|
162
|
-
send(controller, {
|
|
163
|
-
type: 'result',
|
|
164
|
-
result
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
} catch (error) {
|
|
171
|
-
if (!event.request.signal.aborted) {
|
|
172
|
-
if (error instanceof Redirect) {
|
|
173
|
-
send(controller, {
|
|
174
|
-
type: 'redirect',
|
|
175
|
-
location: error.location
|
|
176
|
-
});
|
|
177
|
-
} else {
|
|
178
|
-
const transformed = await handle_error_and_jsonify(
|
|
179
|
-
event,
|
|
180
|
-
state,
|
|
181
|
-
options,
|
|
182
|
-
error
|
|
183
|
-
);
|
|
184
|
-
|
|
185
|
-
send(controller, {
|
|
186
|
-
type: 'error',
|
|
187
|
-
error: transformed
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
await cancel();
|
|
193
|
-
controller.close();
|
|
194
|
-
}
|
|
195
|
-
},
|
|
196
|
-
cancel
|
|
197
|
-
}),
|
|
198
|
-
{
|
|
199
|
-
headers: {
|
|
200
|
-
'cache-control': 'private, no-store',
|
|
201
|
-
'content-type': 'text/event-stream'
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
);
|
|
205
|
+
return create_live_query_response(event, state, internals, parse_remote_arg(payload));
|
|
205
206
|
}
|
|
206
207
|
|
|
207
208
|
case 'query_batch': {
|
|
@@ -218,7 +219,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
|
|
|
218
219
|
|
|
219
220
|
const args = await Promise.all(payloads.map((payload) => parse_remote_arg(payload)));
|
|
220
221
|
|
|
221
|
-
data._ = await with_request_store({ event, state }, () => internals.run(args
|
|
222
|
+
data._ = await with_request_store({ event, state }, () => internals.run(args));
|
|
222
223
|
|
|
223
224
|
break;
|
|
224
225
|
}
|
|
@@ -309,7 +310,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
|
|
|
309
310
|
}
|
|
310
311
|
}
|
|
311
312
|
|
|
312
|
-
await collect_remote_data(data, event, state
|
|
313
|
+
await collect_remote_data(data, event, state);
|
|
313
314
|
|
|
314
315
|
return Response.json(
|
|
315
316
|
/** @type {RemoteFunctionResponse} */ ({
|
|
@@ -320,7 +321,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
|
|
|
320
321
|
);
|
|
321
322
|
} catch (error) {
|
|
322
323
|
if (error instanceof Redirect) {
|
|
323
|
-
const data = await collect_remote_data({ redirect: error.location }, event, state
|
|
324
|
+
const data = await collect_remote_data({ redirect: error.location }, event, state);
|
|
324
325
|
|
|
325
326
|
return Response.json(
|
|
326
327
|
/** @type {RemoteFunctionResponse} */ ({
|
|
@@ -331,7 +332,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
|
|
|
331
332
|
);
|
|
332
333
|
}
|
|
333
334
|
|
|
334
|
-
const transformed = await handle_error_and_jsonify(event, state,
|
|
335
|
+
const transformed = await handle_error_and_jsonify(event, state, error);
|
|
335
336
|
|
|
336
337
|
return Response.json(
|
|
337
338
|
/** @type {RemoteFunctionResponse} */ ({
|
|
@@ -356,9 +357,8 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
|
|
|
356
357
|
* @param {RemoteFunctionData} data
|
|
357
358
|
* @param {RequestEvent} event
|
|
358
359
|
* @param {RequestState} state
|
|
359
|
-
* @param {SSROptions} options
|
|
360
360
|
*/
|
|
361
|
-
export async function collect_remote_data(data, event, state
|
|
361
|
+
export async function collect_remote_data(data, event, state) {
|
|
362
362
|
/**
|
|
363
363
|
*
|
|
364
364
|
* @param {unknown} error
|
|
@@ -366,7 +366,7 @@ export async function collect_remote_data(data, event, state, options) {
|
|
|
366
366
|
*/
|
|
367
367
|
function convert_error(error) {
|
|
368
368
|
// TODO 4.0 remove the `Promise.resolve(...)`
|
|
369
|
-
return Promise.resolve(handle_error_and_jsonify(event, state,
|
|
369
|
+
return Promise.resolve(handle_error_and_jsonify(event, state, error));
|
|
370
370
|
}
|
|
371
371
|
|
|
372
372
|
/** @type {Promise<any>[]} */
|
|
@@ -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 (
|
|
@@ -113,7 +113,7 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
113
113
|
const message = 'Cross-site remote requests are forbidden';
|
|
114
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,
|
|
@@ -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
|
|
@@ -765,7 +769,6 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
765
769
|
event,
|
|
766
770
|
state,
|
|
767
771
|
{ page: { layouts: [], leaf: 0 } },
|
|
768
|
-
options,
|
|
769
772
|
manifest,
|
|
770
773
|
invalidated_data_nodes,
|
|
771
774
|
// there is no route to take a trailing slash option from, and the
|
|
@@ -784,7 +787,6 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
784
787
|
return await respond_with_error({
|
|
785
788
|
event,
|
|
786
789
|
state,
|
|
787
|
-
options,
|
|
788
790
|
manifest,
|
|
789
791
|
error: new SvelteKitError(404, 'Not Found', `Not found: ${event.url.pathname}`),
|
|
790
792
|
resolve_opts
|
|
@@ -806,7 +808,7 @@ export async function internal_respond(request, options, manifest, state) {
|
|
|
806
808
|
// and I don't even know how to describe it. need to investigate at some point
|
|
807
809
|
|
|
808
810
|
// HttpError from endpoint can end up here - TODO should it be handled there instead?
|
|
809
|
-
return await handle_fatal_error(event, state,
|
|
811
|
+
return await handle_fatal_error(event, state, e);
|
|
810
812
|
} finally {
|
|
811
813
|
event.cookies.set = () => {
|
|
812
814
|
throw new Error('Cannot use `cookies.set(...)` after the response has been generated');
|
|
@@ -853,3 +855,26 @@ function propagate_context(fn) {
|
|
|
853
855
|
});
|
|
854
856
|
};
|
|
855
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
|
+
}
|
|
@@ -29,13 +29,6 @@ export function allowed_methods(mod) {
|
|
|
29
29
|
return allowed;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
/**
|
|
33
|
-
* @param {import('types').SSROptions} options
|
|
34
|
-
*/
|
|
35
|
-
export function get_global_name(options) {
|
|
36
|
-
return __SVELTEKIT_DEV__ ? '__sveltekit_dev' : `__sveltekit_${options.version_hash}`;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
32
|
/**
|
|
40
33
|
* @param {number} status
|
|
41
34
|
* @param {string} location
|
package/src/runtime/utils.js
CHANGED
|
@@ -1,6 +1,47 @@
|
|
|
1
1
|
import { BROWSER } from 'esm-env';
|
|
2
2
|
|
|
3
3
|
export const text_encoder = new TextEncoder();
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `ReadableStream.from`, for runtimes that don't support it (as of writing, every Bun release)
|
|
7
|
+
* @template T
|
|
8
|
+
* @param {AsyncIterable<T>} iterable
|
|
9
|
+
* @returns {ReadableStream<T>}
|
|
10
|
+
*/
|
|
11
|
+
export function stream_from_iterable(iterable) {
|
|
12
|
+
// TODO remove the casts once TypeScript's lib includes `ReadableStream.from`
|
|
13
|
+
if (/** @type {any} */ (ReadableStream).from) {
|
|
14
|
+
return /** @type {any} */ (ReadableStream).from(iterable);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const iterator = iterable[Symbol.asyncIterator]();
|
|
18
|
+
return new ReadableStream({
|
|
19
|
+
async pull(controller) {
|
|
20
|
+
const { value, done } = await iterator.next();
|
|
21
|
+
if (done) controller.close();
|
|
22
|
+
else controller.enqueue(value);
|
|
23
|
+
},
|
|
24
|
+
async cancel(reason) {
|
|
25
|
+
await iterator.return?.(reason);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {string} head
|
|
32
|
+
* @param {AsyncIterable<string>} chunks
|
|
33
|
+
* @returns {ReadableStream<Uint8Array>} `head` followed by each non-empty chunk, encoded
|
|
34
|
+
*/
|
|
35
|
+
export function stream_text(head, chunks) {
|
|
36
|
+
return stream_from_iterable(
|
|
37
|
+
(async function* () {
|
|
38
|
+
yield text_encoder.encode(head);
|
|
39
|
+
for await (const chunk of chunks) {
|
|
40
|
+
if (chunk) yield text_encoder.encode(chunk);
|
|
41
|
+
}
|
|
42
|
+
})()
|
|
43
|
+
);
|
|
44
|
+
}
|
|
4
45
|
export const text_decoder = new TextDecoder();
|
|
5
46
|
|
|
6
47
|
/**
|
|
@@ -13,7 +13,15 @@ declare global {
|
|
|
13
13
|
* it is influenced by `NODE_ENV` which can still be true during `vite preview`
|
|
14
14
|
*/
|
|
15
15
|
const __SVELTEKIT_DEV__: boolean;
|
|
16
|
+
const __SVELTEKIT_CSRF_CHECK_ORIGIN__: boolean;
|
|
16
17
|
const __SVELTEKIT_EMBEDDED__: boolean;
|
|
18
|
+
/** True if `config.output.linkHeaderPreload` is `true` */
|
|
19
|
+
const __SVELTEKIT_LINK_HEADER_PRELOAD__: boolean;
|
|
20
|
+
const __SVELTEKIT_PATHS_ORIGIN__: string | undefined;
|
|
21
|
+
/** True if the app has a service worker and `config.serviceWorker.register` is `true` */
|
|
22
|
+
const __SVELTEKIT_SERVICE_WORKER__: boolean;
|
|
23
|
+
/** The `__sveltekit_xxx` name the payload object is attached to, without `globalThis.` */
|
|
24
|
+
const __SVELTEKIT_GLOBAL_NAME__: string;
|
|
17
25
|
const __SVELTEKIT_PATHS_ASSETS__: string;
|
|
18
26
|
const __SVELTEKIT_PATHS_BASE__: string;
|
|
19
27
|
const __SVELTEKIT_PATHS_RELATIVE__: boolean;
|