@sveltejs/kit 2.30.0 → 2.31.0
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 -1
- package/src/core/adapt/builder.js +122 -13
- package/src/core/config/options.js +6 -0
- package/src/core/sync/sync.js +3 -2
- package/src/core/sync/write_non_ambient.js +78 -2
- package/src/core/sync/write_types/index.js +0 -72
- package/src/exports/hooks/sequence.js +53 -31
- package/src/{runtime/app/server → exports/internal}/event.js +24 -9
- package/src/exports/internal/server.js +22 -0
- package/src/exports/public.d.ts +117 -6
- package/src/exports/vite/dev/index.js +8 -0
- package/src/exports/vite/index.js +30 -3
- package/src/exports/vite/utils.js +44 -0
- package/src/runtime/app/paths/index.js +3 -1
- package/src/runtime/app/paths/types.d.ts +0 -1
- package/src/runtime/app/server/index.js +1 -1
- package/src/runtime/app/server/remote/command.js +4 -5
- package/src/runtime/app/server/remote/form.js +5 -7
- package/src/runtime/app/server/remote/prerender.js +5 -7
- package/src/runtime/app/server/remote/query.js +6 -8
- package/src/runtime/app/server/remote/shared.js +9 -13
- package/src/runtime/client/client.js +9 -14
- package/src/runtime/server/data/index.js +10 -5
- package/src/runtime/server/endpoint.js +4 -3
- package/src/runtime/server/page/actions.js +55 -24
- package/src/runtime/server/page/index.js +22 -5
- package/src/runtime/server/page/load_data.js +131 -121
- package/src/runtime/server/page/render.js +15 -7
- package/src/runtime/server/page/respond_with_error.js +7 -2
- package/src/runtime/server/remote.js +59 -13
- package/src/runtime/server/respond.js +110 -34
- package/src/runtime/server/utils.js +20 -5
- package/src/runtime/shared.js +20 -0
- package/src/runtime/telemetry/noop.js +81 -0
- package/src/runtime/telemetry/otel.js +21 -0
- package/src/runtime/telemetry/record_span.js +65 -0
- package/src/types/ambient.d.ts +54 -0
- package/src/types/global-private.d.ts +2 -0
- package/src/types/internal.d.ts +28 -0
- package/src/types/synthetic/$env+dynamic+private.md +1 -1
- package/src/version.js +1 -1
- package/types/index.d.ts +171 -4
- package/types/index.d.ts.map +2 -2
- package/src/runtime/server/event-state.js +0 -40
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
import { DEV } from 'esm-env';
|
|
2
2
|
import { disable_search, make_trackable } from '../../../utils/url.js';
|
|
3
|
-
import { validate_depends } from '../../shared.js';
|
|
3
|
+
import { validate_depends, validate_load_response } from '../../shared.js';
|
|
4
|
+
import { with_request_store, merge_tracing } from '@sveltejs/kit/internal/server';
|
|
5
|
+
import { record_span } from '../../telemetry/record_span.js';
|
|
6
|
+
import { get_node_type } from '../utils.js';
|
|
4
7
|
import { base64_encode, text_decoder } from '../../utils.js';
|
|
5
|
-
import { with_event } from '../../app/server/event.js';
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* Calls the user's server `load` function.
|
|
9
11
|
* @param {{
|
|
10
12
|
* event: import('@sveltejs/kit').RequestEvent;
|
|
13
|
+
* event_state: import('types').RequestState;
|
|
11
14
|
* state: import('types').SSRState;
|
|
12
15
|
* node: import('types').SSRNode | undefined;
|
|
13
16
|
* parent: () => Promise<Record<string, any>>;
|
|
14
17
|
* }} opts
|
|
15
18
|
* @returns {Promise<import('types').ServerDataNode | null>}
|
|
16
19
|
*/
|
|
17
|
-
export async function load_server_data({ event, state, node, parent }) {
|
|
20
|
+
export async function load_server_data({ event, event_state, state, node, parent }) {
|
|
18
21
|
if (!node?.server) return null;
|
|
19
22
|
|
|
20
23
|
let is_tracking = true;
|
|
@@ -68,97 +71,111 @@ export async function load_server_data({ event, state, node, parent }) {
|
|
|
68
71
|
|
|
69
72
|
let done = false;
|
|
70
73
|
|
|
71
|
-
const result = await
|
|
72
|
-
load
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
for (const dep of deps) {
|
|
89
|
-
const { href } = new URL(dep, event.url);
|
|
90
|
-
|
|
91
|
-
if (DEV) {
|
|
92
|
-
validate_depends(node.server_id || 'missing route ID', dep);
|
|
93
|
-
|
|
94
|
-
if (done && !uses.dependencies.has(href)) {
|
|
74
|
+
const result = await record_span({
|
|
75
|
+
name: 'sveltekit.load',
|
|
76
|
+
attributes: {
|
|
77
|
+
'sveltekit.load.node_id': node.server_id || 'unknown',
|
|
78
|
+
'sveltekit.load.node_type': get_node_type(node.server_id),
|
|
79
|
+
'sveltekit.load.environment': 'server',
|
|
80
|
+
'http.route': event.route.id || 'unknown'
|
|
81
|
+
},
|
|
82
|
+
fn: async (current) => {
|
|
83
|
+
const traced_event = merge_tracing(event, current);
|
|
84
|
+
const result = await with_request_store({ event: traced_event, state: event_state }, () =>
|
|
85
|
+
load.call(null, {
|
|
86
|
+
...traced_event,
|
|
87
|
+
fetch: (info, init) => {
|
|
88
|
+
const url = new URL(info instanceof Request ? info.url : info, event.url);
|
|
89
|
+
|
|
90
|
+
if (DEV && done && !uses.dependencies.has(url.href)) {
|
|
95
91
|
console.warn(
|
|
96
|
-
`${node.server_id}: Calling \`
|
|
92
|
+
`${node.server_id}: Calling \`event.fetch(...)\` in a promise handler after \`load(...)\` has returned will not cause the function to re-run when the dependency is invalidated`
|
|
97
93
|
);
|
|
98
94
|
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
uses.dependencies.add(href);
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
|
-
params: new Proxy(event.params, {
|
|
105
|
-
get: (target, key) => {
|
|
106
|
-
if (DEV && done && typeof key === 'string' && !uses.params.has(key)) {
|
|
107
|
-
console.warn(
|
|
108
|
-
`${node.server_id}: Accessing \`params.${String(
|
|
109
|
-
key
|
|
110
|
-
)}\` in a promise handler after \`load(...)\` has returned will not cause the function to re-run when the param changes`
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
95
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
96
|
+
// Note: server fetches are not added to uses.depends due to security concerns
|
|
97
|
+
return event.fetch(info, init);
|
|
98
|
+
},
|
|
99
|
+
/** @param {string[]} deps */
|
|
100
|
+
depends: (...deps) => {
|
|
101
|
+
for (const dep of deps) {
|
|
102
|
+
const { href } = new URL(dep, event.url);
|
|
103
|
+
|
|
104
|
+
if (DEV) {
|
|
105
|
+
validate_depends(node.server_id || 'missing route ID', dep);
|
|
106
|
+
|
|
107
|
+
if (done && !uses.dependencies.has(href)) {
|
|
108
|
+
console.warn(
|
|
109
|
+
`${node.server_id}: Calling \`depends(...)\` in a promise handler after \`load(...)\` has returned will not cause the function to re-run when the dependency is invalidated`
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
uses.dependencies.add(href);
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
params: new Proxy(event.params, {
|
|
118
|
+
get: (target, key) => {
|
|
119
|
+
if (DEV && done && typeof key === 'string' && !uses.params.has(key)) {
|
|
120
|
+
console.warn(
|
|
121
|
+
`${node.server_id}: Accessing \`params.${String(
|
|
122
|
+
key
|
|
123
|
+
)}\` in a promise handler after \`load(...)\` has returned will not cause the function to re-run when the param changes`
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (is_tracking) {
|
|
128
|
+
uses.params.add(key);
|
|
129
|
+
}
|
|
130
|
+
return target[/** @type {string} */ (key)];
|
|
131
|
+
}
|
|
132
|
+
}),
|
|
133
|
+
parent: async () => {
|
|
134
|
+
if (DEV && done && !uses.parent) {
|
|
135
|
+
console.warn(
|
|
136
|
+
`${node.server_id}: Calling \`parent(...)\` in a promise handler after \`load(...)\` has returned will not cause the function to re-run when parent data changes`
|
|
137
|
+
);
|
|
138
|
+
}
|
|
126
139
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
+
if (is_tracking) {
|
|
141
|
+
uses.parent = true;
|
|
142
|
+
}
|
|
143
|
+
return parent();
|
|
144
|
+
},
|
|
145
|
+
route: new Proxy(event.route, {
|
|
146
|
+
get: (target, key) => {
|
|
147
|
+
if (DEV && done && typeof key === 'string' && !uses.route) {
|
|
148
|
+
console.warn(
|
|
149
|
+
`${node.server_id}: Accessing \`route.${String(
|
|
150
|
+
key
|
|
151
|
+
)}\` in a promise handler after \`load(...)\` has returned will not cause the function to re-run when the route changes`
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (is_tracking) {
|
|
156
|
+
uses.route = true;
|
|
157
|
+
}
|
|
158
|
+
return target[/** @type {'id'} */ (key)];
|
|
159
|
+
}
|
|
160
|
+
}),
|
|
161
|
+
url,
|
|
162
|
+
untrack(fn) {
|
|
163
|
+
is_tracking = false;
|
|
164
|
+
try {
|
|
165
|
+
return fn();
|
|
166
|
+
} finally {
|
|
167
|
+
is_tracking = true;
|
|
168
|
+
}
|
|
140
169
|
}
|
|
170
|
+
})
|
|
171
|
+
);
|
|
141
172
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
return target[/** @type {'id'} */ (key)];
|
|
146
|
-
}
|
|
147
|
-
}),
|
|
148
|
-
url,
|
|
149
|
-
untrack(fn) {
|
|
150
|
-
is_tracking = false;
|
|
151
|
-
try {
|
|
152
|
-
return fn();
|
|
153
|
-
} finally {
|
|
154
|
-
is_tracking = true;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
})
|
|
158
|
-
);
|
|
173
|
+
return result;
|
|
174
|
+
}
|
|
175
|
+
});
|
|
159
176
|
|
|
160
177
|
if (__SVELTEKIT_DEV__) {
|
|
161
|
-
validate_load_response(result, node.server_id);
|
|
178
|
+
validate_load_response(result, `in ${node.server_id}`);
|
|
162
179
|
}
|
|
163
180
|
|
|
164
181
|
done = true;
|
|
@@ -175,6 +192,7 @@ export async function load_server_data({ event, state, node, parent }) {
|
|
|
175
192
|
* Calls the user's `load` function.
|
|
176
193
|
* @param {{
|
|
177
194
|
* event: import('@sveltejs/kit').RequestEvent;
|
|
195
|
+
* event_state: import('types').RequestState;
|
|
178
196
|
* fetched: import('./types.js').Fetched[];
|
|
179
197
|
* node: import('types').SSRNode | undefined;
|
|
180
198
|
* parent: () => Promise<Record<string, any>>;
|
|
@@ -187,6 +205,7 @@ export async function load_server_data({ event, state, node, parent }) {
|
|
|
187
205
|
*/
|
|
188
206
|
export async function load_data({
|
|
189
207
|
event,
|
|
208
|
+
event_state,
|
|
190
209
|
fetched,
|
|
191
210
|
node,
|
|
192
211
|
parent,
|
|
@@ -203,24 +222,35 @@ export async function load_data({
|
|
|
203
222
|
return server_data_node?.data ?? null;
|
|
204
223
|
}
|
|
205
224
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
225
|
+
const result = await record_span({
|
|
226
|
+
name: 'sveltekit.load',
|
|
227
|
+
attributes: {
|
|
228
|
+
'sveltekit.load.node_id': node.universal_id || 'unknown',
|
|
229
|
+
'sveltekit.load.node_type': get_node_type(node.universal_id),
|
|
230
|
+
'sveltekit.load.environment': 'server',
|
|
231
|
+
'http.route': event.route.id || 'unknown'
|
|
232
|
+
},
|
|
233
|
+
fn: async (current) => {
|
|
234
|
+
const traced_event = merge_tracing(event, current);
|
|
235
|
+
return await with_request_store({ event: traced_event, state: event_state }, () =>
|
|
236
|
+
load.call(null, {
|
|
237
|
+
url: event.url,
|
|
238
|
+
params: event.params,
|
|
239
|
+
data: server_data_node?.data ?? null,
|
|
240
|
+
route: event.route,
|
|
241
|
+
fetch: create_universal_fetch(event, state, fetched, csr, resolve_opts),
|
|
242
|
+
setHeaders: event.setHeaders,
|
|
243
|
+
depends: () => {},
|
|
244
|
+
parent,
|
|
245
|
+
untrack: (fn) => fn(),
|
|
246
|
+
tracing: traced_event.tracing
|
|
247
|
+
})
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
});
|
|
221
251
|
|
|
222
252
|
if (__SVELTEKIT_DEV__) {
|
|
223
|
-
validate_load_response(result, node.universal_id);
|
|
253
|
+
validate_load_response(result, `in ${node.universal_id}`);
|
|
224
254
|
}
|
|
225
255
|
|
|
226
256
|
return result ?? null;
|
|
@@ -405,23 +435,3 @@ async function stream_to_string(stream) {
|
|
|
405
435
|
}
|
|
406
436
|
return result;
|
|
407
437
|
}
|
|
408
|
-
|
|
409
|
-
/**
|
|
410
|
-
* @param {any} data
|
|
411
|
-
* @param {string} [id]
|
|
412
|
-
*/
|
|
413
|
-
function validate_load_response(data, id) {
|
|
414
|
-
if (data != null && Object.getPrototypeOf(data) !== Object.prototype) {
|
|
415
|
-
throw new Error(
|
|
416
|
-
`a load function in ${id} returned ${
|
|
417
|
-
typeof data !== 'object'
|
|
418
|
-
? `a ${typeof data}`
|
|
419
|
-
: data instanceof Response
|
|
420
|
-
? 'a Response object'
|
|
421
|
-
: Array.isArray(data)
|
|
422
|
-
? 'an array'
|
|
423
|
-
: 'a non-plain object'
|
|
424
|
-
}, but must return a plain object at the top level (i.e. \`return {...}\`)`
|
|
425
|
-
);
|
|
426
|
-
}
|
|
427
|
-
}
|
|
@@ -15,8 +15,7 @@ import { SVELTE_KIT_ASSETS } from '../../../constants.js';
|
|
|
15
15
|
import { SCHEME } from '../../../utils/url.js';
|
|
16
16
|
import { create_server_routing_response, generate_route_object } from './server_routing.js';
|
|
17
17
|
import { add_resolution_suffix } from '../../pathname.js';
|
|
18
|
-
import {
|
|
19
|
-
import { get_event_state } from '../event-state.js';
|
|
18
|
+
import { with_request_store } from '@sveltejs/kit/internal/server';
|
|
20
19
|
import { text_encoder } from '../../utils.js';
|
|
21
20
|
|
|
22
21
|
// TODO rename this function/module
|
|
@@ -38,6 +37,7 @@ const updated = {
|
|
|
38
37
|
* status: number;
|
|
39
38
|
* error: App.Error | null;
|
|
40
39
|
* event: import('@sveltejs/kit').RequestEvent;
|
|
40
|
+
* event_state: import('types').RequestState;
|
|
41
41
|
* resolve_opts: import('types').RequiredResolveOptions;
|
|
42
42
|
* action_result?: import('@sveltejs/kit').ActionResult;
|
|
43
43
|
* }} opts
|
|
@@ -52,6 +52,7 @@ export async function render_response({
|
|
|
52
52
|
status,
|
|
53
53
|
error = null,
|
|
54
54
|
event,
|
|
55
|
+
event_state,
|
|
55
56
|
resolve_opts,
|
|
56
57
|
action_result
|
|
57
58
|
}) {
|
|
@@ -190,14 +191,18 @@ export async function render_response({
|
|
|
190
191
|
};
|
|
191
192
|
|
|
192
193
|
try {
|
|
193
|
-
rendered =
|
|
194
|
+
rendered = with_request_store({ event, state: event_state }, () =>
|
|
195
|
+
options.root.render(props, render_opts)
|
|
196
|
+
);
|
|
194
197
|
} finally {
|
|
195
198
|
globalThis.fetch = fetch;
|
|
196
199
|
paths.reset();
|
|
197
200
|
}
|
|
198
201
|
} else {
|
|
199
202
|
try {
|
|
200
|
-
rendered =
|
|
203
|
+
rendered = with_request_store({ event, state: event_state }, () =>
|
|
204
|
+
options.root.render(props, render_opts)
|
|
205
|
+
);
|
|
201
206
|
} finally {
|
|
202
207
|
paths.reset();
|
|
203
208
|
}
|
|
@@ -288,6 +293,7 @@ export async function render_response({
|
|
|
288
293
|
|
|
289
294
|
const { data, chunks } = get_data(
|
|
290
295
|
event,
|
|
296
|
+
event_state,
|
|
291
297
|
options,
|
|
292
298
|
branch.map((b) => b.server_data),
|
|
293
299
|
csp,
|
|
@@ -377,7 +383,7 @@ export async function render_response({
|
|
|
377
383
|
}`);
|
|
378
384
|
}
|
|
379
385
|
|
|
380
|
-
const { remote_data } =
|
|
386
|
+
const { remote_data } = event_state;
|
|
381
387
|
|
|
382
388
|
if (remote_data) {
|
|
383
389
|
/** @type {Record<string, any>} */
|
|
@@ -611,13 +617,14 @@ export async function render_response({
|
|
|
611
617
|
* If the serialized data contains promises, `chunks` will be an
|
|
612
618
|
* async iterable containing their resolutions
|
|
613
619
|
* @param {import('@sveltejs/kit').RequestEvent} event
|
|
620
|
+
* @param {import('types').RequestState} event_state
|
|
614
621
|
* @param {import('types').SSROptions} options
|
|
615
622
|
* @param {Array<import('types').ServerDataNode | null>} nodes
|
|
616
623
|
* @param {import('./csp.js').Csp} csp
|
|
617
624
|
* @param {string} global
|
|
618
625
|
* @returns {{ data: string, chunks: AsyncIterable<string> | null }}
|
|
619
626
|
*/
|
|
620
|
-
function get_data(event, options, nodes, csp, global) {
|
|
627
|
+
function get_data(event, event_state, options, nodes, csp, global) {
|
|
621
628
|
let promise_id = 1;
|
|
622
629
|
let count = 0;
|
|
623
630
|
|
|
@@ -633,7 +640,7 @@ function get_data(event, options, nodes, csp, global) {
|
|
|
633
640
|
.then(/** @param {any} data */ (data) => ({ data }))
|
|
634
641
|
.catch(
|
|
635
642
|
/** @param {any} error */ async (error) => ({
|
|
636
|
-
error: await handle_error_and_jsonify(event, options, error)
|
|
643
|
+
error: await handle_error_and_jsonify(event, event_state, options, error)
|
|
637
644
|
})
|
|
638
645
|
)
|
|
639
646
|
.then(
|
|
@@ -649,6 +656,7 @@ function get_data(event, options, nodes, csp, global) {
|
|
|
649
656
|
} catch {
|
|
650
657
|
error = await handle_error_and_jsonify(
|
|
651
658
|
event,
|
|
659
|
+
event_state,
|
|
652
660
|
options,
|
|
653
661
|
new Error(`Failed to serialize promise while rendering ${event.route.id}`)
|
|
654
662
|
);
|
|
@@ -12,6 +12,7 @@ import { PageNodes } from '../../../utils/page_nodes.js';
|
|
|
12
12
|
/**
|
|
13
13
|
* @param {{
|
|
14
14
|
* event: import('@sveltejs/kit').RequestEvent;
|
|
15
|
+
* event_state: import('types').RequestState;
|
|
15
16
|
* options: import('types').SSROptions;
|
|
16
17
|
* manifest: import('@sveltejs/kit').SSRManifest;
|
|
17
18
|
* state: import('types').SSRState;
|
|
@@ -22,6 +23,7 @@ import { PageNodes } from '../../../utils/page_nodes.js';
|
|
|
22
23
|
*/
|
|
23
24
|
export async function respond_with_error({
|
|
24
25
|
event,
|
|
26
|
+
event_state,
|
|
25
27
|
options,
|
|
26
28
|
manifest,
|
|
27
29
|
state,
|
|
@@ -49,6 +51,7 @@ export async function respond_with_error({
|
|
|
49
51
|
|
|
50
52
|
const server_data_promise = load_server_data({
|
|
51
53
|
event,
|
|
54
|
+
event_state,
|
|
52
55
|
state,
|
|
53
56
|
node: default_layout,
|
|
54
57
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
@@ -59,6 +62,7 @@ export async function respond_with_error({
|
|
|
59
62
|
|
|
60
63
|
const data = await load_data({
|
|
61
64
|
event,
|
|
65
|
+
event_state,
|
|
62
66
|
fetched,
|
|
63
67
|
node: default_layout,
|
|
64
68
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
@@ -92,10 +96,11 @@ export async function respond_with_error({
|
|
|
92
96
|
csr
|
|
93
97
|
},
|
|
94
98
|
status,
|
|
95
|
-
error: await handle_error_and_jsonify(event, options, error),
|
|
99
|
+
error: await handle_error_and_jsonify(event, event_state, options, error),
|
|
96
100
|
branch,
|
|
97
101
|
fetched,
|
|
98
102
|
event,
|
|
103
|
+
event_state,
|
|
99
104
|
resolve_opts
|
|
100
105
|
});
|
|
101
106
|
} catch (e) {
|
|
@@ -108,7 +113,7 @@ export async function respond_with_error({
|
|
|
108
113
|
return static_error_page(
|
|
109
114
|
options,
|
|
110
115
|
get_status(e),
|
|
111
|
-
(await handle_error_and_jsonify(event, options, e)).message
|
|
116
|
+
(await handle_error_and_jsonify(event, event_state, options, e)).message
|
|
112
117
|
);
|
|
113
118
|
}
|
|
114
119
|
}
|
|
@@ -1,25 +1,42 @@
|
|
|
1
1
|
/** @import { ActionResult, RemoteForm, RequestEvent, SSRManifest } from '@sveltejs/kit' */
|
|
2
|
-
/** @import { RemoteFunctionResponse, RemoteInfo, SSROptions } from 'types' */
|
|
2
|
+
/** @import { RemoteFunctionResponse, RemoteInfo, RequestState, SSROptions } from 'types' */
|
|
3
3
|
|
|
4
4
|
import { json, error } from '@sveltejs/kit';
|
|
5
5
|
import { HttpError, Redirect, SvelteKitError } from '@sveltejs/kit/internal';
|
|
6
|
+
import { with_request_store, merge_tracing } from '@sveltejs/kit/internal/server';
|
|
6
7
|
import { app_dir, base } from '__sveltekit/paths';
|
|
7
|
-
import { with_event } from '../app/server/event.js';
|
|
8
8
|
import { is_form_content_type } from '../../utils/http.js';
|
|
9
9
|
import { parse_remote_arg, stringify } from '../shared.js';
|
|
10
10
|
import { handle_error_and_jsonify } from './utils.js';
|
|
11
11
|
import { normalize_error } from '../../utils/error.js';
|
|
12
12
|
import { check_incorrect_fail_use } from './page/actions.js';
|
|
13
13
|
import { DEV } from 'esm-env';
|
|
14
|
-
import {
|
|
14
|
+
import { record_span } from '../telemetry/record_span.js';
|
|
15
|
+
|
|
16
|
+
/** @type {typeof handle_remote_call_internal} */
|
|
17
|
+
export async function handle_remote_call(event, state, options, manifest, id) {
|
|
18
|
+
return record_span({
|
|
19
|
+
name: 'sveltekit.remote.call',
|
|
20
|
+
attributes: {
|
|
21
|
+
'sveltekit.remote.call.id': id
|
|
22
|
+
},
|
|
23
|
+
fn: (current) => {
|
|
24
|
+
const traced_event = merge_tracing(event, current);
|
|
25
|
+
return with_request_store({ event: traced_event, state }, () =>
|
|
26
|
+
handle_remote_call_internal(traced_event, state, options, manifest, id)
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
15
31
|
|
|
16
32
|
/**
|
|
17
33
|
* @param {RequestEvent} event
|
|
34
|
+
* @param {RequestState} state
|
|
18
35
|
* @param {SSROptions} options
|
|
19
36
|
* @param {SSRManifest} manifest
|
|
20
37
|
* @param {string} id
|
|
21
38
|
*/
|
|
22
|
-
|
|
39
|
+
async function handle_remote_call_internal(event, state, options, manifest, id) {
|
|
23
40
|
const [hash, name, prerender_args] = id.split('/');
|
|
24
41
|
const remotes = manifest._.remotes;
|
|
25
42
|
|
|
@@ -34,6 +51,11 @@ export async function handle_remote_call(event, options, manifest, id) {
|
|
|
34
51
|
const info = fn.__;
|
|
35
52
|
const transport = options.hooks.transport;
|
|
36
53
|
|
|
54
|
+
event.tracing.current.setAttributes({
|
|
55
|
+
'sveltekit.remote.call.type': info.type,
|
|
56
|
+
'sveltekit.remote.call.name': info.name
|
|
57
|
+
});
|
|
58
|
+
|
|
37
59
|
/** @type {string[] | undefined} */
|
|
38
60
|
let form_client_refreshes;
|
|
39
61
|
|
|
@@ -56,7 +78,7 @@ export async function handle_remote_call(event, options, manifest, id) {
|
|
|
56
78
|
form_data.delete('sveltekit:remote_refreshes');
|
|
57
79
|
|
|
58
80
|
const fn = info.fn;
|
|
59
|
-
const data = await
|
|
81
|
+
const data = await with_request_store({ event, state }, () => fn(form_data));
|
|
60
82
|
|
|
61
83
|
return json(
|
|
62
84
|
/** @type {RemoteFunctionResponse} */ ({
|
|
@@ -71,7 +93,7 @@ export async function handle_remote_call(event, options, manifest, id) {
|
|
|
71
93
|
/** @type {{ payload: string, refreshes: string[] }} */
|
|
72
94
|
const { payload, refreshes } = await event.request.json();
|
|
73
95
|
const arg = parse_remote_arg(payload, transport);
|
|
74
|
-
const data = await
|
|
96
|
+
const data = await with_request_store({ event, state }, () => fn(arg));
|
|
75
97
|
|
|
76
98
|
return json(
|
|
77
99
|
/** @type {RemoteFunctionResponse} */ ({
|
|
@@ -90,7 +112,9 @@ export async function handle_remote_call(event, options, manifest, id) {
|
|
|
90
112
|
new URL(event.request.url).searchParams.get('payload')
|
|
91
113
|
);
|
|
92
114
|
|
|
93
|
-
const data = await
|
|
115
|
+
const data = await with_request_store({ event, state }, () =>
|
|
116
|
+
fn(parse_remote_arg(payload, transport))
|
|
117
|
+
);
|
|
94
118
|
|
|
95
119
|
return json(
|
|
96
120
|
/** @type {RemoteFunctionResponse} */ ({
|
|
@@ -110,7 +134,7 @@ export async function handle_remote_call(event, options, manifest, id) {
|
|
|
110
134
|
return json(
|
|
111
135
|
/** @type {RemoteFunctionResponse} */ ({
|
|
112
136
|
type: 'error',
|
|
113
|
-
error: await handle_error_and_jsonify(event, options, error),
|
|
137
|
+
error: await handle_error_and_jsonify(event, state, options, error),
|
|
114
138
|
status: error instanceof HttpError || error instanceof SvelteKitError ? error.status : 500
|
|
115
139
|
}),
|
|
116
140
|
{
|
|
@@ -126,7 +150,7 @@ export async function handle_remote_call(event, options, manifest, id) {
|
|
|
126
150
|
*/
|
|
127
151
|
async function serialize_refreshes(client_refreshes) {
|
|
128
152
|
const refreshes = {
|
|
129
|
-
...
|
|
153
|
+
...state.refreshes,
|
|
130
154
|
...Object.fromEntries(
|
|
131
155
|
await Promise.all(
|
|
132
156
|
client_refreshes.map(async (key) => {
|
|
@@ -141,7 +165,12 @@ export async function handle_remote_call(event, options, manifest, id) {
|
|
|
141
165
|
|
|
142
166
|
if (!fn) error(400, 'Bad Request');
|
|
143
167
|
|
|
144
|
-
return [
|
|
168
|
+
return [
|
|
169
|
+
key,
|
|
170
|
+
await with_request_store({ event, state }, () =>
|
|
171
|
+
fn(parse_remote_arg(payload, transport))
|
|
172
|
+
)
|
|
173
|
+
];
|
|
145
174
|
})
|
|
146
175
|
)
|
|
147
176
|
)
|
|
@@ -151,13 +180,30 @@ export async function handle_remote_call(event, options, manifest, id) {
|
|
|
151
180
|
}
|
|
152
181
|
}
|
|
153
182
|
|
|
183
|
+
/** @type {typeof handle_remote_form_post_internal} */
|
|
184
|
+
export async function handle_remote_form_post(event, state, manifest, id) {
|
|
185
|
+
return record_span({
|
|
186
|
+
name: 'sveltekit.remote.form.post',
|
|
187
|
+
attributes: {
|
|
188
|
+
'sveltekit.remote.form.post.id': id
|
|
189
|
+
},
|
|
190
|
+
fn: (current) => {
|
|
191
|
+
const traced_event = merge_tracing(event, current);
|
|
192
|
+
return with_request_store({ event: traced_event, state }, () =>
|
|
193
|
+
handle_remote_form_post_internal(traced_event, state, manifest, id)
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
154
199
|
/**
|
|
155
200
|
* @param {RequestEvent} event
|
|
201
|
+
* @param {RequestState} state
|
|
156
202
|
* @param {SSRManifest} manifest
|
|
157
203
|
* @param {string} id
|
|
158
204
|
* @returns {Promise<ActionResult>}
|
|
159
205
|
*/
|
|
160
|
-
|
|
206
|
+
async function handle_remote_form_post_internal(event, state, manifest, id) {
|
|
161
207
|
const [hash, name, action_id] = id.split('/');
|
|
162
208
|
const remotes = manifest._.remotes;
|
|
163
209
|
const module = await remotes[hash]?.();
|
|
@@ -182,14 +228,14 @@ export async function handle_remote_form_post(event, manifest, id) {
|
|
|
182
228
|
|
|
183
229
|
if (action_id) {
|
|
184
230
|
// @ts-expect-error
|
|
185
|
-
form =
|
|
231
|
+
form = with_request_store({ event, state }, () => form.for(JSON.parse(action_id)));
|
|
186
232
|
}
|
|
187
233
|
|
|
188
234
|
try {
|
|
189
235
|
const form_data = await event.request.formData();
|
|
190
236
|
const fn = /** @type {RemoteInfo & { type: 'form' }} */ (/** @type {any} */ (form).__).fn;
|
|
191
237
|
|
|
192
|
-
await
|
|
238
|
+
await with_request_store({ event, state }, () => fn(form_data));
|
|
193
239
|
|
|
194
240
|
// We don't want the data to appear on `let { form } = $props()`, which is why we're not returning it.
|
|
195
241
|
// It is instead available on `myForm.result`, setting of which happens within the remote `form` function.
|