@sveltejs/kit 2.30.1 → 2.31.1
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/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 -5
- package/src/exports/vite/dev/index.js +8 -0
- package/src/exports/vite/index.js +32 -5
- package/src/exports/vite/utils.js +44 -0
- 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/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 +117 -4
- package/types/index.d.ts.map +2 -2
- package/src/runtime/server/event-state.js +0 -40
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sveltejs/kit",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.31.1",
|
|
4
4
|
"description": "SvelteKit is the fastest way to build Svelte apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"framework",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"sirv": "^3.0.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
+
"@opentelemetry/api": "^1.0.0",
|
|
36
37
|
"@playwright/test": "^1.51.1",
|
|
37
38
|
"@sveltejs/vite-plugin-svelte": "^6.0.0-next.3",
|
|
38
39
|
"@types/connect": "^3.4.38",
|
|
@@ -48,9 +49,15 @@
|
|
|
48
49
|
},
|
|
49
50
|
"peerDependencies": {
|
|
50
51
|
"@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0",
|
|
52
|
+
"@opentelemetry/api": "^1.0.0",
|
|
51
53
|
"svelte": "^4.0.0 || ^5.0.0-next.0",
|
|
52
54
|
"vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0"
|
|
53
55
|
},
|
|
56
|
+
"peerDependenciesMeta": {
|
|
57
|
+
"@opentelemetry/api": {
|
|
58
|
+
"optional": true
|
|
59
|
+
}
|
|
60
|
+
},
|
|
54
61
|
"bin": {
|
|
55
62
|
"svelte-kit": "svelte-kit.js"
|
|
56
63
|
},
|
|
@@ -72,6 +79,10 @@
|
|
|
72
79
|
"types": "./types/index.d.ts",
|
|
73
80
|
"import": "./src/exports/internal/index.js"
|
|
74
81
|
},
|
|
82
|
+
"./internal/server": {
|
|
83
|
+
"types": "./types/index.d.ts",
|
|
84
|
+
"import": "./src/exports/internal/server.js"
|
|
85
|
+
},
|
|
75
86
|
"./node": {
|
|
76
87
|
"types": "./types/index.d.ts",
|
|
77
88
|
"import": "./src/exports/node/index.js"
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
/** @import { Builder } from '@sveltejs/kit' */
|
|
2
|
+
/** @import { ResolvedConfig } from 'vite' */
|
|
3
|
+
/** @import { RouteDefinition } from '@sveltejs/kit' */
|
|
4
|
+
/** @import { RouteData, ValidatedConfig, BuildData, ServerMetadata, ServerMetadataRoute, Prerendered, PrerenderMap, Logger } from 'types' */
|
|
1
5
|
import colors from 'kleur';
|
|
2
6
|
import { createReadStream, createWriteStream, existsSync, statSync } from 'node:fs';
|
|
3
|
-
import { extname, resolve } from 'node:path';
|
|
7
|
+
import { extname, resolve, join, dirname, relative } from 'node:path';
|
|
4
8
|
import { pipeline } from 'node:stream';
|
|
5
9
|
import { promisify } from 'node:util';
|
|
6
10
|
import zlib from 'node:zlib';
|
|
@@ -12,6 +16,7 @@ import generate_fallback from '../postbuild/fallback.js';
|
|
|
12
16
|
import { write } from '../sync/utils.js';
|
|
13
17
|
import { list_files } from '../utils.js';
|
|
14
18
|
import { find_server_assets } from '../generate_manifest/find_server_assets.js';
|
|
19
|
+
import { reserved } from '../env.js';
|
|
15
20
|
|
|
16
21
|
const pipe = promisify(pipeline);
|
|
17
22
|
const extensions = ['.html', '.js', '.mjs', '.json', '.css', '.svg', '.xml', '.wasm'];
|
|
@@ -19,16 +24,16 @@ const extensions = ['.html', '.js', '.mjs', '.json', '.css', '.svg', '.xml', '.w
|
|
|
19
24
|
/**
|
|
20
25
|
* Creates the Builder which is passed to adapters for building the application.
|
|
21
26
|
* @param {{
|
|
22
|
-
* config:
|
|
23
|
-
* build_data:
|
|
24
|
-
* server_metadata:
|
|
25
|
-
* route_data:
|
|
26
|
-
* prerendered:
|
|
27
|
-
* prerender_map:
|
|
28
|
-
* log:
|
|
29
|
-
* vite_config:
|
|
27
|
+
* config: ValidatedConfig;
|
|
28
|
+
* build_data: BuildData;
|
|
29
|
+
* server_metadata: ServerMetadata;
|
|
30
|
+
* route_data: RouteData[];
|
|
31
|
+
* prerendered: Prerendered;
|
|
32
|
+
* prerender_map: PrerenderMap;
|
|
33
|
+
* log: Logger;
|
|
34
|
+
* vite_config: ResolvedConfig;
|
|
30
35
|
* }} opts
|
|
31
|
-
* @returns {
|
|
36
|
+
* @returns {Builder}
|
|
32
37
|
*/
|
|
33
38
|
export function create_builder({
|
|
34
39
|
config,
|
|
@@ -40,7 +45,7 @@ export function create_builder({
|
|
|
40
45
|
log,
|
|
41
46
|
vite_config
|
|
42
47
|
}) {
|
|
43
|
-
/** @type {Map<
|
|
48
|
+
/** @type {Map<RouteDefinition, RouteData>} */
|
|
44
49
|
const lookup = new Map();
|
|
45
50
|
|
|
46
51
|
/**
|
|
@@ -48,11 +53,11 @@ export function create_builder({
|
|
|
48
53
|
* we expose a stable type that adapters can use to group/filter routes
|
|
49
54
|
*/
|
|
50
55
|
const routes = route_data.map((route) => {
|
|
51
|
-
const { config, methods, page, api } = /** @type {
|
|
56
|
+
const { config, methods, page, api } = /** @type {ServerMetadataRoute} */ (
|
|
52
57
|
server_metadata.routes.get(route.id)
|
|
53
58
|
);
|
|
54
59
|
|
|
55
|
-
/** @type {
|
|
60
|
+
/** @type {RouteDefinition} */
|
|
56
61
|
const facade = {
|
|
57
62
|
id: route.id,
|
|
58
63
|
api,
|
|
@@ -229,6 +234,53 @@ export function create_builder({
|
|
|
229
234
|
|
|
230
235
|
writeServer(dest) {
|
|
231
236
|
return copy(`${config.kit.outDir}/output/server`, dest);
|
|
237
|
+
},
|
|
238
|
+
|
|
239
|
+
hasServerInstrumentationFile() {
|
|
240
|
+
return existsSync(`${config.kit.outDir}/output/server/instrumentation.server.js`);
|
|
241
|
+
},
|
|
242
|
+
|
|
243
|
+
instrument({
|
|
244
|
+
entrypoint,
|
|
245
|
+
instrumentation,
|
|
246
|
+
start = join(dirname(entrypoint), 'start.js'),
|
|
247
|
+
module = {
|
|
248
|
+
exports: ['default']
|
|
249
|
+
}
|
|
250
|
+
}) {
|
|
251
|
+
if (!existsSync(instrumentation)) {
|
|
252
|
+
throw new Error(
|
|
253
|
+
`Instrumentation file ${instrumentation} not found. This is probably a bug in your adapter.`
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
if (!existsSync(entrypoint)) {
|
|
257
|
+
throw new Error(
|
|
258
|
+
`Entrypoint file ${entrypoint} not found. This is probably a bug in your adapter.`
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
copy(entrypoint, start);
|
|
263
|
+
if (existsSync(`${entrypoint}.map`)) {
|
|
264
|
+
copy(`${entrypoint}.map`, `${start}.map`);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const relative_instrumentation = relative(dirname(entrypoint), instrumentation);
|
|
268
|
+
const relative_start = relative(dirname(entrypoint), start);
|
|
269
|
+
|
|
270
|
+
const facade =
|
|
271
|
+
'generateText' in module
|
|
272
|
+
? module.generateText({
|
|
273
|
+
instrumentation: relative_instrumentation,
|
|
274
|
+
start: relative_start
|
|
275
|
+
})
|
|
276
|
+
: create_instrumentation_facade({
|
|
277
|
+
instrumentation: relative_instrumentation,
|
|
278
|
+
start: relative_start,
|
|
279
|
+
exports: module.exports
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
rimraf(entrypoint);
|
|
283
|
+
write(entrypoint, facade);
|
|
232
284
|
}
|
|
233
285
|
};
|
|
234
286
|
}
|
|
@@ -254,3 +306,60 @@ async function compress_file(file, format = 'gz') {
|
|
|
254
306
|
|
|
255
307
|
await pipe(source, compress, destination);
|
|
256
308
|
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Given a list of exports, generate a facade that:
|
|
312
|
+
* - Imports the instrumentation file
|
|
313
|
+
* - Imports `exports` from the entrypoint (dynamically, if `tla` is true)
|
|
314
|
+
* - Re-exports `exports` from the entrypoint
|
|
315
|
+
*
|
|
316
|
+
* `default` receives special treatment: It will be imported as `default` and exported with `export default`.
|
|
317
|
+
*
|
|
318
|
+
* @param {{ instrumentation: string; start: string; exports: string[] }} opts
|
|
319
|
+
* @returns {string}
|
|
320
|
+
*/
|
|
321
|
+
function create_instrumentation_facade({ instrumentation, start, exports }) {
|
|
322
|
+
const import_instrumentation = `import './${instrumentation}';`;
|
|
323
|
+
|
|
324
|
+
let alias_index = 0;
|
|
325
|
+
const aliases = new Map();
|
|
326
|
+
|
|
327
|
+
for (const name of exports.filter((name) => reserved.has(name))) {
|
|
328
|
+
/*
|
|
329
|
+
* you can do evil things like `export { c as class }`.
|
|
330
|
+
* in order to import these, you need to alias them, and then un-alias them when re-exporting
|
|
331
|
+
* this map will allow us to generate the following:
|
|
332
|
+
* import { class as _1 } from 'entrypoint';
|
|
333
|
+
* export { _1 as class };
|
|
334
|
+
*/
|
|
335
|
+
let alias = `_${alias_index++}`;
|
|
336
|
+
while (exports.includes(alias)) {
|
|
337
|
+
alias = `_${alias_index++}`;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
aliases.set(name, alias);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const import_statements = [];
|
|
344
|
+
const export_statements = [];
|
|
345
|
+
|
|
346
|
+
for (const name of exports) {
|
|
347
|
+
const alias = aliases.get(name);
|
|
348
|
+
if (alias) {
|
|
349
|
+
import_statements.push(`${name}: ${alias}`);
|
|
350
|
+
export_statements.push(`${alias} as ${name}`);
|
|
351
|
+
} else {
|
|
352
|
+
import_statements.push(`${name}`);
|
|
353
|
+
export_statements.push(`${name}`);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const entrypoint_facade = [
|
|
358
|
+
`const { ${import_statements.join(', ')} } = await import('./${start}');`,
|
|
359
|
+
export_statements.length > 0 ? `export { ${export_statements.join(', ')} };` : ''
|
|
360
|
+
]
|
|
361
|
+
.filter(Boolean)
|
|
362
|
+
.join('\n');
|
|
363
|
+
|
|
364
|
+
return `${import_instrumentation}\n${entrypoint_facade}`;
|
|
365
|
+
}
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/** @import { Handle, RequestEvent, ResolveOptions } from '@sveltejs/kit' */
|
|
2
|
+
/** @import { MaybePromise } from 'types' */
|
|
3
|
+
import {
|
|
4
|
+
merge_tracing,
|
|
5
|
+
get_request_store,
|
|
6
|
+
with_request_store
|
|
7
|
+
} from '@sveltejs/kit/internal/server';
|
|
8
|
+
|
|
1
9
|
/**
|
|
2
10
|
* A helper function for sequencing multiple `handle` calls in a middleware-like manner.
|
|
3
11
|
* The behavior for the `handle` options is as follows:
|
|
@@ -66,56 +74,70 @@
|
|
|
66
74
|
* first post-processing
|
|
67
75
|
* ```
|
|
68
76
|
*
|
|
69
|
-
* @param {...
|
|
70
|
-
* @returns {
|
|
77
|
+
* @param {...Handle} handlers The chain of `handle` functions
|
|
78
|
+
* @returns {Handle}
|
|
71
79
|
*/
|
|
72
80
|
export function sequence(...handlers) {
|
|
73
81
|
const length = handlers.length;
|
|
74
82
|
if (!length) return ({ event, resolve }) => resolve(event);
|
|
75
83
|
|
|
76
84
|
return ({ event, resolve }) => {
|
|
85
|
+
const { state } = get_request_store();
|
|
77
86
|
return apply_handle(0, event, {});
|
|
78
87
|
|
|
79
88
|
/**
|
|
80
89
|
* @param {number} i
|
|
81
|
-
* @param {
|
|
82
|
-
* @param {
|
|
83
|
-
* @returns {
|
|
90
|
+
* @param {RequestEvent} event
|
|
91
|
+
* @param {ResolveOptions | undefined} parent_options
|
|
92
|
+
* @returns {MaybePromise<Response>}
|
|
84
93
|
*/
|
|
85
94
|
function apply_handle(i, event, parent_options) {
|
|
86
95
|
const handle = handlers[i];
|
|
87
96
|
|
|
88
|
-
return
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
97
|
+
return state.tracing.record_span({
|
|
98
|
+
name: `sveltekit.handle.sequenced.${handle.name ? handle.name : i}`,
|
|
99
|
+
attributes: {},
|
|
100
|
+
fn: async (current) => {
|
|
101
|
+
const traced_event = merge_tracing(event, current);
|
|
102
|
+
return await with_request_store({ event: traced_event, state }, () =>
|
|
103
|
+
handle({
|
|
104
|
+
event: traced_event,
|
|
105
|
+
resolve: (event, options) => {
|
|
106
|
+
/** @type {ResolveOptions['transformPageChunk']} */
|
|
107
|
+
const transformPageChunk = async ({ html, done }) => {
|
|
108
|
+
if (options?.transformPageChunk) {
|
|
109
|
+
html = (await options.transformPageChunk({ html, done })) ?? '';
|
|
110
|
+
}
|
|
96
111
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
112
|
+
if (parent_options?.transformPageChunk) {
|
|
113
|
+
html = (await parent_options.transformPageChunk({ html, done })) ?? '';
|
|
114
|
+
}
|
|
100
115
|
|
|
101
|
-
|
|
102
|
-
|
|
116
|
+
return html;
|
|
117
|
+
};
|
|
103
118
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
119
|
+
/** @type {ResolveOptions['filterSerializedResponseHeaders']} */
|
|
120
|
+
const filterSerializedResponseHeaders =
|
|
121
|
+
parent_options?.filterSerializedResponseHeaders ??
|
|
122
|
+
options?.filterSerializedResponseHeaders;
|
|
108
123
|
|
|
109
|
-
|
|
110
|
-
|
|
124
|
+
/** @type {ResolveOptions['preload']} */
|
|
125
|
+
const preload = parent_options?.preload ?? options?.preload;
|
|
111
126
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
127
|
+
return i < length - 1
|
|
128
|
+
? apply_handle(i + 1, event, {
|
|
129
|
+
transformPageChunk,
|
|
130
|
+
filterSerializedResponseHeaders,
|
|
131
|
+
preload
|
|
132
|
+
})
|
|
133
|
+
: resolve(event, {
|
|
134
|
+
transformPageChunk,
|
|
135
|
+
filterSerializedResponseHeaders,
|
|
136
|
+
preload
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
);
|
|
119
141
|
}
|
|
120
142
|
});
|
|
121
143
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/** @import { RequestEvent } from '@sveltejs/kit' */
|
|
2
|
+
/** @import { RequestStore } from 'types' */
|
|
3
|
+
/** @import { AsyncLocalStorage } from 'node:async_hooks' */
|
|
2
4
|
|
|
3
|
-
/** @type {
|
|
4
|
-
let
|
|
5
|
+
/** @type {RequestStore | null} */
|
|
6
|
+
let sync_store = null;
|
|
5
7
|
|
|
6
|
-
/** @type {
|
|
8
|
+
/** @type {AsyncLocalStorage<RequestStore | null> | null} */
|
|
7
9
|
let als;
|
|
8
10
|
|
|
9
11
|
import('node:async_hooks')
|
|
@@ -19,10 +21,11 @@ import('node:async_hooks')
|
|
|
19
21
|
*
|
|
20
22
|
* In environments without [`AsyncLocalStorage`](https://nodejs.org/api/async_context.html#class-asynclocalstorage), this must be called synchronously (i.e. not after an `await`).
|
|
21
23
|
* @since 2.20.0
|
|
24
|
+
*
|
|
22
25
|
* @returns {RequestEvent}
|
|
23
26
|
*/
|
|
24
27
|
export function getRequestEvent() {
|
|
25
|
-
const event =
|
|
28
|
+
const event = try_get_request_store()?.event;
|
|
26
29
|
|
|
27
30
|
if (!event) {
|
|
28
31
|
let message =
|
|
@@ -39,16 +42,28 @@ export function getRequestEvent() {
|
|
|
39
42
|
return event;
|
|
40
43
|
}
|
|
41
44
|
|
|
45
|
+
export function get_request_store() {
|
|
46
|
+
const result = try_get_request_store();
|
|
47
|
+
if (!result) {
|
|
48
|
+
throw new Error('Could not get the request store. This is an internal error.');
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function try_get_request_store() {
|
|
54
|
+
return sync_store ?? als?.getStore() ?? null;
|
|
55
|
+
}
|
|
56
|
+
|
|
42
57
|
/**
|
|
43
58
|
* @template T
|
|
44
|
-
* @param {
|
|
59
|
+
* @param {RequestStore | null} store
|
|
45
60
|
* @param {() => T} fn
|
|
46
61
|
*/
|
|
47
|
-
export function
|
|
62
|
+
export function with_request_store(store, fn) {
|
|
48
63
|
try {
|
|
49
|
-
|
|
50
|
-
return als ? als.run(
|
|
64
|
+
sync_store = store;
|
|
65
|
+
return als ? als.run(store, fn) : fn();
|
|
51
66
|
} finally {
|
|
52
|
-
|
|
67
|
+
sync_store = null;
|
|
53
68
|
}
|
|
54
69
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @template {{ tracing: { enabled: boolean, root: import('@opentelemetry/api').Span, current: import('@opentelemetry/api').Span } }} T
|
|
3
|
+
* @param {T} event_like
|
|
4
|
+
* @param {import('@opentelemetry/api').Span} current
|
|
5
|
+
* @returns {T}
|
|
6
|
+
*/
|
|
7
|
+
export function merge_tracing(event_like, current) {
|
|
8
|
+
return {
|
|
9
|
+
...event_like,
|
|
10
|
+
tracing: {
|
|
11
|
+
...event_like.tracing,
|
|
12
|
+
current
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export {
|
|
18
|
+
with_request_store,
|
|
19
|
+
getRequestEvent,
|
|
20
|
+
get_request_store,
|
|
21
|
+
try_get_request_store
|
|
22
|
+
} from './event.js';
|
package/src/exports/public.d.ts
CHANGED
|
@@ -17,13 +17,14 @@ import {
|
|
|
17
17
|
RouteSegment
|
|
18
18
|
} from '../types/private.js';
|
|
19
19
|
import { BuildData, SSRNodeLoader, SSRRoute, ValidatedConfig } from 'types';
|
|
20
|
-
import
|
|
21
|
-
import
|
|
20
|
+
import { SvelteConfig } from '@sveltejs/vite-plugin-svelte';
|
|
21
|
+
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
22
22
|
import {
|
|
23
23
|
RouteId as AppRouteId,
|
|
24
24
|
LayoutParams as AppLayoutParams,
|
|
25
25
|
ResolvedPathname
|
|
26
26
|
} from '$app/types';
|
|
27
|
+
import { Span } from '@opentelemetry/api';
|
|
27
28
|
|
|
28
29
|
export { PrerenderOption } from '../types/private.js';
|
|
29
30
|
|
|
@@ -49,6 +50,12 @@ export interface Adapter {
|
|
|
49
50
|
* @param details.config The merged route config
|
|
50
51
|
*/
|
|
51
52
|
read?: (details: { config: any; route: { id: string } }) => boolean;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Test support for `instrumentation.server.js`. To pass, the adapter must support running `instrumentation.server.js` prior to the application code.
|
|
56
|
+
* @since 2.31.0
|
|
57
|
+
*/
|
|
58
|
+
instrumentation?: () => boolean;
|
|
52
59
|
};
|
|
53
60
|
/**
|
|
54
61
|
* Creates an `Emulator`, which allows the adapter to influence the environment
|
|
@@ -186,6 +193,47 @@ export interface Builder {
|
|
|
186
193
|
}
|
|
187
194
|
) => string[];
|
|
188
195
|
|
|
196
|
+
/**
|
|
197
|
+
* Check if the server instrumentation file exists.
|
|
198
|
+
* @returns true if the server instrumentation file exists, false otherwise
|
|
199
|
+
* @since 2.31.0
|
|
200
|
+
*/
|
|
201
|
+
hasServerInstrumentationFile: () => boolean;
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Instrument `entrypoint` with `instrumentation`.
|
|
205
|
+
*
|
|
206
|
+
* Renames `entrypoint` to `start` and creates a new module at
|
|
207
|
+
* `entrypoint` which imports `instrumentation` and then dynamically imports `start`. This allows
|
|
208
|
+
* the module hooks necessary for instrumentation libraries to be loaded prior to any application code.
|
|
209
|
+
*
|
|
210
|
+
* Caveats:
|
|
211
|
+
* - "Live exports" will not work. If your adapter uses live exports, your users will need to manually import the server instrumentation on startup.
|
|
212
|
+
* - If `tla` is `false`, OTEL auto-instrumentation may not work properly. Use it if your environment supports it.
|
|
213
|
+
* - Use `hasServerInstrumentationFile` to check if the user has a server instrumentation file; if they don't, you shouldn't do this.
|
|
214
|
+
*
|
|
215
|
+
* @param options an object containing the following properties:
|
|
216
|
+
* @param options.entrypoint the path to the entrypoint to trace.
|
|
217
|
+
* @param options.instrumentation the path to the instrumentation file.
|
|
218
|
+
* @param options.start the name of the start file. This is what `entrypoint` will be renamed to.
|
|
219
|
+
* @param options.module configuration for the resulting entrypoint module.
|
|
220
|
+
* @param options.module.exports
|
|
221
|
+
* @param options.module.generateText a function that receives the relative paths to the instrumentation and start files, and generates the text of the module to be traced. If not provided, the default implementation will be used, which uses top-level await.
|
|
222
|
+
* @since 2.31.0
|
|
223
|
+
*/
|
|
224
|
+
instrument: (args: {
|
|
225
|
+
entrypoint: string;
|
|
226
|
+
instrumentation: string;
|
|
227
|
+
start?: string;
|
|
228
|
+
module?:
|
|
229
|
+
| {
|
|
230
|
+
exports: string[];
|
|
231
|
+
}
|
|
232
|
+
| {
|
|
233
|
+
generateText: (args: { instrumentation: string; start: string }) => string;
|
|
234
|
+
};
|
|
235
|
+
}) => void;
|
|
236
|
+
|
|
189
237
|
/**
|
|
190
238
|
* Compress files in `directory` with gzip and brotli, where appropriate. Generates `.gz` and `.br` files alongside the originals.
|
|
191
239
|
* @param {string} directory The directory containing the files to be compressed
|
|
@@ -407,10 +455,34 @@ export interface KitConfig {
|
|
|
407
455
|
*/
|
|
408
456
|
privatePrefix?: string;
|
|
409
457
|
};
|
|
410
|
-
/**
|
|
411
|
-
* Experimental features which are exempt from semantic versioning. These features may be changed or removed at any time.
|
|
412
|
-
*/
|
|
458
|
+
/** Experimental features. Here be dragons. These are not subject to semantic versioning, so breaking changes or removal can happen in any release. */
|
|
413
459
|
experimental?: {
|
|
460
|
+
/**
|
|
461
|
+
* Options for enabling server-side [OpenTelemetry](https://opentelemetry.io/) tracing for SvelteKit operations including the [`handle` hook](https://svelte.dev/docs/kit/hooks#Server-hooks-handle), [`load` functions](https://svelte.dev/docs/kit/load), [form actions](https://svelte.dev/docs/kit/form-actions), and [remote functions](https://svelte.dev/docs/kit/remote-functions).
|
|
462
|
+
* @default { server: false, serverFile: false }
|
|
463
|
+
* @since 2.31.0
|
|
464
|
+
*/
|
|
465
|
+
tracing?: {
|
|
466
|
+
/**
|
|
467
|
+
* Enables server-side [OpenTelemetry](https://opentelemetry.io/) span emission for SvelteKit operations including the [`handle` hook](https://svelte.dev/docs/kit/hooks#Server-hooks-handle), [`load` functions](https://svelte.dev/docs/kit/load), [form actions](https://svelte.dev/docs/kit/form-actions), and [remote functions](https://svelte.dev/docs/kit/remote-functions).
|
|
468
|
+
* @default false
|
|
469
|
+
* @since 2.31.0
|
|
470
|
+
*/
|
|
471
|
+
server?: boolean;
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* @since 2.31.0
|
|
476
|
+
*/
|
|
477
|
+
instrumentation?: {
|
|
478
|
+
/**
|
|
479
|
+
* Enables `instrumentation.server.js` for tracing and observability instrumentation.
|
|
480
|
+
* @default false
|
|
481
|
+
* @since 2.31.0
|
|
482
|
+
*/
|
|
483
|
+
server?: boolean;
|
|
484
|
+
};
|
|
485
|
+
|
|
414
486
|
/**
|
|
415
487
|
* Whether to enable the experimental remote functions feature. This feature is not yet stable and may be changed or removed at any time.
|
|
416
488
|
* @default false
|
|
@@ -1026,6 +1098,19 @@ export interface LoadEvent<
|
|
|
1026
1098
|
* ```
|
|
1027
1099
|
*/
|
|
1028
1100
|
untrack: <T>(fn: () => T) => T;
|
|
1101
|
+
|
|
1102
|
+
/**
|
|
1103
|
+
* Access to spans for tracing. If tracing is not enabled or the function is being run in the browser, these spans will do nothing.
|
|
1104
|
+
* @since 2.31.0
|
|
1105
|
+
*/
|
|
1106
|
+
tracing: {
|
|
1107
|
+
/** Whether tracing is enabled. */
|
|
1108
|
+
enabled: boolean;
|
|
1109
|
+
/** The root span for the request. This span is named `sveltekit.handle.root`. */
|
|
1110
|
+
root: Span;
|
|
1111
|
+
/** The span associated with the current `load` function. */
|
|
1112
|
+
current: Span;
|
|
1113
|
+
};
|
|
1029
1114
|
}
|
|
1030
1115
|
|
|
1031
1116
|
export interface NavigationEvent<
|
|
@@ -1304,6 +1389,20 @@ export interface RequestEvent<
|
|
|
1304
1389
|
* `true` for `+server.js` calls coming from SvelteKit without the overhead of actually making an HTTP request. This happens when you make same-origin `fetch` requests on the server.
|
|
1305
1390
|
*/
|
|
1306
1391
|
isSubRequest: boolean;
|
|
1392
|
+
|
|
1393
|
+
/**
|
|
1394
|
+
* Access to spans for tracing. If tracing is not enabled, these spans will do nothing.
|
|
1395
|
+
* @since 2.31.0
|
|
1396
|
+
*/
|
|
1397
|
+
tracing: {
|
|
1398
|
+
/** Whether tracing is enabled. */
|
|
1399
|
+
enabled: boolean;
|
|
1400
|
+
/** The root span for the request. This span is named `sveltekit.handle.root`. */
|
|
1401
|
+
root: Span;
|
|
1402
|
+
/** The span associated with the current `handle` hook, `load` function, or form action. */
|
|
1403
|
+
current: Span;
|
|
1404
|
+
};
|
|
1405
|
+
|
|
1307
1406
|
/**
|
|
1308
1407
|
* `true` if the request comes from the client via a remote function. The `url` property will be stripped of the internal information
|
|
1309
1408
|
* related to the data request in this case. Use this property instead if the distinction is important to you.
|
|
@@ -1467,6 +1566,19 @@ export interface ServerLoadEvent<
|
|
|
1467
1566
|
* ```
|
|
1468
1567
|
*/
|
|
1469
1568
|
untrack: <T>(fn: () => T) => T;
|
|
1569
|
+
|
|
1570
|
+
/**
|
|
1571
|
+
* Access to spans for tracing. If tracing is not enabled, these spans will do nothing.
|
|
1572
|
+
* @since 2.31.0
|
|
1573
|
+
*/
|
|
1574
|
+
tracing: {
|
|
1575
|
+
/** Whether tracing is enabled. */
|
|
1576
|
+
enabled: boolean;
|
|
1577
|
+
/** The root span for the request. This span is named `sveltekit.handle.root`. */
|
|
1578
|
+
root: Span;
|
|
1579
|
+
/** The span associated with the current server `load` function. */
|
|
1580
|
+
current: Span;
|
|
1581
|
+
};
|
|
1470
1582
|
}
|
|
1471
1583
|
|
|
1472
1584
|
/**
|
|
@@ -501,6 +501,14 @@ export async function dev(vite, vite_config, svelte_config) {
|
|
|
501
501
|
return;
|
|
502
502
|
}
|
|
503
503
|
|
|
504
|
+
const resolved_instrumentation = resolve_entry(
|
|
505
|
+
path.join(svelte_config.kit.files.src, 'instrumentation.server')
|
|
506
|
+
);
|
|
507
|
+
|
|
508
|
+
if (resolved_instrumentation) {
|
|
509
|
+
await vite.ssrLoadModule(resolved_instrumentation);
|
|
510
|
+
}
|
|
511
|
+
|
|
504
512
|
// we have to import `Server` before calling `set_assets`
|
|
505
513
|
const { Server } = /** @type {import('types').ServerModule} */ (
|
|
506
514
|
await vite.ssrLoadModule(`${runtime_base}/server/index.js`, { fixStacktrace: true })
|