@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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sveltejs/kit",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.31.0",
|
|
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
|
+
}
|
package/src/core/sync/sync.js
CHANGED
|
@@ -9,14 +9,13 @@ import { write_non_ambient } from './write_non_ambient.js';
|
|
|
9
9
|
import { write_server } from './write_server.js';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* Initialize SvelteKit's generated files.
|
|
12
|
+
* Initialize SvelteKit's generated files that only depend on the config and mode.
|
|
13
13
|
* @param {import('types').ValidatedConfig} config
|
|
14
14
|
* @param {string} mode
|
|
15
15
|
*/
|
|
16
16
|
export function init(config, mode) {
|
|
17
17
|
write_tsconfig(config.kit);
|
|
18
18
|
write_ambient(config.kit, mode);
|
|
19
|
-
write_non_ambient(config.kit);
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
/**
|
|
@@ -32,6 +31,7 @@ export function create(config) {
|
|
|
32
31
|
write_server(config, output);
|
|
33
32
|
write_root(manifest_data, output);
|
|
34
33
|
write_all_types(config, manifest_data);
|
|
34
|
+
write_non_ambient(config.kit, manifest_data);
|
|
35
35
|
|
|
36
36
|
return { manifest_data };
|
|
37
37
|
}
|
|
@@ -67,6 +67,7 @@ export function all_types(config, mode) {
|
|
|
67
67
|
init(config, mode);
|
|
68
68
|
const manifest_data = create_manifest_data({ config });
|
|
69
69
|
write_all_types(config, manifest_data);
|
|
70
|
+
write_non_ambient(config.kit, manifest_data);
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
/**
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { GENERATED_COMMENT } from '../../constants.js';
|
|
3
3
|
import { write_if_changed } from './utils.js';
|
|
4
|
+
import { s } from '../../utils/misc.js';
|
|
5
|
+
import { get_route_segments } from '../../utils/routing.js';
|
|
6
|
+
|
|
7
|
+
const replace_optional_params = (/** @type {string} */ id) =>
|
|
8
|
+
id.replace(/\/\[\[[^\]]+\]\]/g, '${string}');
|
|
9
|
+
const replace_required_params = (/** @type {string} */ id) =>
|
|
10
|
+
id.replace(/\/\[[^\]]+\]/g, '/${string}');
|
|
11
|
+
/** Convert route ID to pathname by removing layout groups */
|
|
12
|
+
const remove_group_segments = (/** @type {string} */ id) => {
|
|
13
|
+
return '/' + get_route_segments(id).join('/');
|
|
14
|
+
};
|
|
4
15
|
|
|
5
16
|
// `declare module "svelte/elements"` needs to happen in a non-ambient module, and dts-buddy generates one big ambient module,
|
|
6
17
|
// so we can't add it there - therefore generate the typings ourselves here.
|
|
@@ -33,10 +44,75 @@ declare module "svelte/elements" {
|
|
|
33
44
|
export {};
|
|
34
45
|
`;
|
|
35
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Generate app types interface extension
|
|
49
|
+
* @param {import('types').ManifestData} manifest_data
|
|
50
|
+
*/
|
|
51
|
+
function generate_app_types(manifest_data) {
|
|
52
|
+
/** @type {Set<string>} */
|
|
53
|
+
const pathnames = new Set();
|
|
54
|
+
|
|
55
|
+
/** @type {string[]} */
|
|
56
|
+
const dynamic_routes = [];
|
|
57
|
+
|
|
58
|
+
/** @type {string[]} */
|
|
59
|
+
const layouts = [];
|
|
60
|
+
|
|
61
|
+
for (const route of manifest_data.routes) {
|
|
62
|
+
if (route.params.length > 0) {
|
|
63
|
+
const params = route.params.map((p) => `${p.name}${p.optional ? '?:' : ':'} string`);
|
|
64
|
+
const route_type = `${s(route.id)}: { ${params.join('; ')} }`;
|
|
65
|
+
|
|
66
|
+
dynamic_routes.push(route_type);
|
|
67
|
+
|
|
68
|
+
const pathname = remove_group_segments(route.id);
|
|
69
|
+
pathnames.add(`\`${replace_required_params(replace_optional_params(pathname))}\` & {}`);
|
|
70
|
+
} else {
|
|
71
|
+
const pathname = remove_group_segments(route.id);
|
|
72
|
+
pathnames.add(s(pathname));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** @type {Map<string, boolean>} */
|
|
76
|
+
const child_params = new Map(route.params.map((p) => [p.name, p.optional]));
|
|
77
|
+
|
|
78
|
+
for (const child of manifest_data.routes.filter((r) => r.id.startsWith(route.id))) {
|
|
79
|
+
for (const p of child.params) {
|
|
80
|
+
if (!child_params.has(p.name)) {
|
|
81
|
+
child_params.set(p.name, true); // always optional
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const layout_params = Array.from(child_params)
|
|
87
|
+
.map(([name, optional]) => `${name}${optional ? '?:' : ':'} string`)
|
|
88
|
+
.join('; ');
|
|
89
|
+
|
|
90
|
+
const layout_type = `${s(route.id)}: ${layout_params.length > 0 ? `{ ${layout_params} }` : 'Record<string, never>'}`;
|
|
91
|
+
layouts.push(layout_type);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return [
|
|
95
|
+
'declare module "$app/types" {',
|
|
96
|
+
'\texport interface AppTypes {',
|
|
97
|
+
`\t\tRouteId(): ${manifest_data.routes.map((r) => s(r.id)).join(' | ')};`,
|
|
98
|
+
`\t\tRouteParams(): {\n\t\t\t${dynamic_routes.join(';\n\t\t\t')}\n\t\t};`,
|
|
99
|
+
`\t\tLayoutParams(): {\n\t\t\t${layouts.join(';\n\t\t\t')}\n\t\t};`,
|
|
100
|
+
`\t\tPathname(): ${Array.from(pathnames).join(' | ')};`,
|
|
101
|
+
'\t\tResolvedPathname(): `${"" | `/${string}`}${ReturnType<AppTypes[\'Pathname\']>}`;',
|
|
102
|
+
`\t\tAsset(): ${manifest_data.assets.map((asset) => s('/' + asset.file)).join(' | ') || 'never'};`,
|
|
103
|
+
'\t}',
|
|
104
|
+
'}'
|
|
105
|
+
].join('\n');
|
|
106
|
+
}
|
|
107
|
+
|
|
36
108
|
/**
|
|
37
109
|
* Writes non-ambient declarations to the output directory
|
|
38
110
|
* @param {import('types').ValidatedKitConfig} config
|
|
111
|
+
* @param {import('types').ManifestData} manifest_data
|
|
39
112
|
*/
|
|
40
|
-
export function write_non_ambient(config) {
|
|
41
|
-
|
|
113
|
+
export function write_non_ambient(config, manifest_data) {
|
|
114
|
+
const app_types = generate_app_types(manifest_data);
|
|
115
|
+
const content = [template, app_types].join('\n\n');
|
|
116
|
+
|
|
117
|
+
write_if_changed(path.join(config.outDir, 'non-ambient.d.ts'), content);
|
|
42
118
|
}
|
|
@@ -5,19 +5,8 @@ import MagicString from 'magic-string';
|
|
|
5
5
|
import { posixify, rimraf, walk } from '../../../utils/filesystem.js';
|
|
6
6
|
import { compact } from '../../../utils/array.js';
|
|
7
7
|
import { ts } from '../ts.js';
|
|
8
|
-
import { s } from '../../../utils/misc.js';
|
|
9
|
-
import { get_route_segments } from '../../../utils/routing.js';
|
|
10
|
-
|
|
11
8
|
const remove_relative_parent_traversals = (/** @type {string} */ path) =>
|
|
12
9
|
path.replace(/\.\.\//g, '');
|
|
13
|
-
const replace_optional_params = (/** @type {string} */ id) =>
|
|
14
|
-
id.replace(/\/\[\[[^\]]+\]\]/g, '${string}');
|
|
15
|
-
const replace_required_params = (/** @type {string} */ id) =>
|
|
16
|
-
id.replace(/\/\[[^\]]+\]/g, '/${string}');
|
|
17
|
-
/** Convert route ID to pathname by removing layout groups */
|
|
18
|
-
const remove_group_segments = (/** @type {string} */ id) => {
|
|
19
|
-
return '/' + get_route_segments(id).join('/');
|
|
20
|
-
};
|
|
21
10
|
const is_whitespace = (/** @type {string} */ char) => /\s/.test(char);
|
|
22
11
|
|
|
23
12
|
/**
|
|
@@ -65,67 +54,6 @@ export function write_all_types(config, manifest_data) {
|
|
|
65
54
|
}
|
|
66
55
|
}
|
|
67
56
|
|
|
68
|
-
/** @type {Set<string>} */
|
|
69
|
-
const pathnames = new Set();
|
|
70
|
-
|
|
71
|
-
/** @type {string[]} */
|
|
72
|
-
const dynamic_routes = [];
|
|
73
|
-
|
|
74
|
-
/** @type {string[]} */
|
|
75
|
-
const layouts = [];
|
|
76
|
-
|
|
77
|
-
for (const route of manifest_data.routes) {
|
|
78
|
-
if (route.params.length > 0) {
|
|
79
|
-
const params = route.params.map((p) => `${p.name}${p.optional ? '?:' : ':'} string`);
|
|
80
|
-
const route_type = `${s(route.id)}: { ${params.join('; ')} }`;
|
|
81
|
-
|
|
82
|
-
dynamic_routes.push(route_type);
|
|
83
|
-
|
|
84
|
-
const pathname = remove_group_segments(route.id);
|
|
85
|
-
pathnames.add(`\`${replace_required_params(replace_optional_params(pathname))}\` & {}`);
|
|
86
|
-
} else {
|
|
87
|
-
const pathname = remove_group_segments(route.id);
|
|
88
|
-
pathnames.add(s(pathname));
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/** @type {Map<string, boolean>} */
|
|
92
|
-
const child_params = new Map(route.params.map((p) => [p.name, p.optional]));
|
|
93
|
-
|
|
94
|
-
for (const child of manifest_data.routes.filter((r) => r.id.startsWith(route.id))) {
|
|
95
|
-
for (const p of child.params) {
|
|
96
|
-
if (!child_params.has(p.name)) {
|
|
97
|
-
child_params.set(p.name, true); // always optional
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const layout_params = Array.from(child_params)
|
|
103
|
-
.map(([name, optional]) => `${name}${optional ? '?:' : ':'} string`)
|
|
104
|
-
.join('; ');
|
|
105
|
-
|
|
106
|
-
const layout_type = `${s(route.id)}: ${layout_params.length > 0 ? `{ ${layout_params} }` : 'undefined'}`;
|
|
107
|
-
layouts.push(layout_type);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
try {
|
|
111
|
-
fs.mkdirSync(types_dir, { recursive: true });
|
|
112
|
-
} catch {}
|
|
113
|
-
|
|
114
|
-
fs.writeFileSync(
|
|
115
|
-
`${types_dir}/index.d.ts`,
|
|
116
|
-
[
|
|
117
|
-
`type DynamicRoutes = {\n\t${dynamic_routes.join(';\n\t')}\n};`,
|
|
118
|
-
`type Layouts = {\n\t${layouts.join(';\n\t')}\n};`,
|
|
119
|
-
// we enumerate these rather than doing `keyof Routes` so that the list is visible on hover
|
|
120
|
-
`export type RouteId = ${manifest_data.routes.map((r) => s(r.id)).join(' | ')};`,
|
|
121
|
-
'export type RouteParams<T extends RouteId> = T extends keyof DynamicRoutes ? DynamicRoutes[T] : Record<string, never>;',
|
|
122
|
-
'export type LayoutParams<T extends RouteId> = Layouts[T] | Record<string, never>;',
|
|
123
|
-
`export type Pathname = ${Array.from(pathnames).join(' | ')};`,
|
|
124
|
-
'export type ResolvedPathname = `${"" | `/${string}`}${Pathname}`;',
|
|
125
|
-
`export type Asset = ${manifest_data.assets.map((asset) => s('/' + asset.file)).join(' | ') || 'never'};`
|
|
126
|
-
].join('\n\n')
|
|
127
|
-
);
|
|
128
|
-
|
|
129
57
|
// Read/write meta data on each invocation, not once per node process,
|
|
130
58
|
// it could be invoked by another process in the meantime.
|
|
131
59
|
const meta_data_file = `${types_dir}/route_meta_data.json`;
|
|
@@ -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';
|