@sveltejs/kit 1.18.0 → 1.19.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 +6 -1
- package/src/core/adapt/builder.js +3 -3
- package/src/core/config/index.js +2 -2
- package/src/core/config/options.js +3 -3
- package/src/core/env.js +1 -1
- package/src/core/generate_manifest/index.js +2 -2
- package/src/core/postbuild/analyse.js +3 -3
- package/src/core/postbuild/fallback.js +1 -1
- package/src/core/postbuild/prerender.js +1 -1
- package/src/core/sync/create_manifest_data/index.js +2 -2
- package/src/core/sync/write_ambient.js +1 -1
- package/src/core/sync/write_client_manifest.js +1 -1
- package/src/core/sync/write_server.js +1 -1
- package/src/core/sync/write_types/index.js +24 -24
- package/src/exports/hooks/sequence.js +71 -7
- package/src/exports/index.js +88 -12
- package/src/exports/node/index.js +14 -3
- package/src/exports/node/polyfills.js +8 -0
- package/src/exports/public.d.ts +1264 -0
- package/src/exports/vite/build/build_server.js +2 -2
- package/src/exports/vite/build/build_service_worker.js +1 -1
- package/src/exports/vite/dev/index.js +3 -3
- package/src/exports/vite/index.js +11 -6
- package/src/runtime/app/environment.js +3 -4
- package/src/runtime/app/forms.js +63 -7
- package/src/runtime/app/navigation.js +95 -0
- package/src/runtime/app/stores.js +28 -7
- package/src/runtime/client/client.js +26 -14
- package/src/runtime/client/singletons.js +6 -4
- package/src/runtime/client/start.js +1 -1
- package/src/runtime/client/types.d.ts +4 -12
- package/src/runtime/client/utils.js +29 -10
- package/src/runtime/control.js +12 -9
- package/src/runtime/server/ambient.d.ts +3 -3
- package/src/runtime/server/cookie.js +3 -3
- package/src/runtime/server/data/index.js +3 -3
- package/src/runtime/server/endpoint.js +11 -4
- package/src/runtime/server/fetch.js +4 -6
- package/src/runtime/server/index.js +2 -2
- package/src/runtime/server/page/actions.js +13 -13
- package/src/runtime/server/page/csp.js +7 -2
- package/src/runtime/server/page/index.js +4 -4
- package/src/runtime/server/page/load_data.js +7 -7
- package/src/runtime/server/page/render.js +11 -11
- package/src/runtime/server/page/respond_with_error.js +2 -2
- package/src/runtime/server/respond.js +6 -6
- package/src/runtime/server/utils.js +7 -7
- package/src/types/ambient-private.d.ts +11 -0
- package/src/types/ambient.d.ts +108 -0
- package/{types → src/types}/internal.d.ts +3 -13
- package/{types → src/types}/private.d.ts +1 -10
- package/src/utils/error.js +3 -3
- package/src/utils/exports.js +2 -2
- package/src/utils/routing.js +1 -39
- package/src/utils/streaming.js +2 -2
- package/types/index.d.ts +2079 -1108
- package/types/index.d.ts.map +165 -0
- package/src/internal.d.ts +0 -16
- package/types/ambient.d.ts +0 -486
- /package/{types → src/types}/synthetic/$env+dynamic+private.md +0 -0
- /package/{types → src/types}/synthetic/$env+dynamic+public.md +0 -0
- /package/{types → src/types}/synthetic/$env+static+private.md +0 -0
- /package/{types → src/types}/synthetic/$env+static+public.md +0 -0
- /package/{types → src/types}/synthetic/$lib.md +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sveltejs/kit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.0",
|
|
4
4
|
"description": "The fastest way to build Svelte apps",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"@types/node": "^16.18.6",
|
|
34
34
|
"@types/sade": "^1.7.4",
|
|
35
35
|
"@types/set-cookie-parser": "^2.4.2",
|
|
36
|
+
"dts-buddy": "^0.0.9",
|
|
36
37
|
"marked": "^4.2.3",
|
|
37
38
|
"rollup": "^3.7.0",
|
|
38
39
|
"svelte": "^3.56.0",
|
|
@@ -64,15 +65,19 @@
|
|
|
64
65
|
"import": "./src/exports/index.js"
|
|
65
66
|
},
|
|
66
67
|
"./node": {
|
|
68
|
+
"types": "./types/index.d.ts",
|
|
67
69
|
"import": "./src/exports/node/index.js"
|
|
68
70
|
},
|
|
69
71
|
"./node/polyfills": {
|
|
72
|
+
"types": "./types/index.d.ts",
|
|
70
73
|
"import": "./src/exports/node/polyfills.js"
|
|
71
74
|
},
|
|
72
75
|
"./hooks": {
|
|
76
|
+
"types": "./types/index.d.ts",
|
|
73
77
|
"import": "./src/exports/hooks/index.js"
|
|
74
78
|
},
|
|
75
79
|
"./vite": {
|
|
80
|
+
"types": "./types/index.d.ts",
|
|
76
81
|
"import": "./src/exports/vite/index.js"
|
|
77
82
|
}
|
|
78
83
|
},
|
|
@@ -24,7 +24,7 @@ const pipe = promisify(pipeline);
|
|
|
24
24
|
* prerender_map: import('types').PrerenderMap;
|
|
25
25
|
* log: import('types').Logger;
|
|
26
26
|
* }} opts
|
|
27
|
-
* @returns {import('
|
|
27
|
+
* @returns {import('@sveltejs/kit').Builder}
|
|
28
28
|
*/
|
|
29
29
|
export function create_builder({
|
|
30
30
|
config,
|
|
@@ -35,7 +35,7 @@ export function create_builder({
|
|
|
35
35
|
prerender_map,
|
|
36
36
|
log
|
|
37
37
|
}) {
|
|
38
|
-
/** @type {Map<import('
|
|
38
|
+
/** @type {Map<import('@sveltejs/kit').RouteDefinition, import('types').RouteData>} */
|
|
39
39
|
const lookup = new Map();
|
|
40
40
|
|
|
41
41
|
/**
|
|
@@ -47,7 +47,7 @@ export function create_builder({
|
|
|
47
47
|
server_metadata.routes.get(route.id)
|
|
48
48
|
);
|
|
49
49
|
|
|
50
|
-
/** @type {import('
|
|
50
|
+
/** @type {import('@sveltejs/kit').RouteDefinition} */
|
|
51
51
|
const facade = {
|
|
52
52
|
id: route.id,
|
|
53
53
|
api,
|
package/src/core/config/index.js
CHANGED
|
@@ -73,7 +73,7 @@ export async function load_config({ cwd = process.cwd() } = {}) {
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
/**
|
|
76
|
-
* @param {import('
|
|
76
|
+
* @param {import('@sveltejs/kit').Config} config
|
|
77
77
|
* @returns {import('types').ValidatedConfig}
|
|
78
78
|
*/
|
|
79
79
|
function process_config(config, { cwd = process.cwd() } = {}) {
|
|
@@ -95,7 +95,7 @@ function process_config(config, { cwd = process.cwd() } = {}) {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
/**
|
|
98
|
-
* @param {import('
|
|
98
|
+
* @param {import('@sveltejs/kit').Config} config
|
|
99
99
|
* @returns {import('types').ValidatedConfig}
|
|
100
100
|
*/
|
|
101
101
|
export function validate_config(config) {
|
|
@@ -210,7 +210,7 @@ const options = object(
|
|
|
210
210
|
(/** @type {any} */ { message }) => {
|
|
211
211
|
throw new Error(
|
|
212
212
|
message +
|
|
213
|
-
|
|
213
|
+
'\nTo suppress or handle this error, implement `handleHttpError` in https://kit.svelte.dev/docs/configuration#prerender'
|
|
214
214
|
);
|
|
215
215
|
},
|
|
216
216
|
(input, keypath) => {
|
|
@@ -224,7 +224,7 @@ const options = object(
|
|
|
224
224
|
(/** @type {any} */ { message }) => {
|
|
225
225
|
throw new Error(
|
|
226
226
|
message +
|
|
227
|
-
|
|
227
|
+
'\nTo suppress or handle this error, implement `handleMissingId` in https://kit.svelte.dev/docs/configuration#prerender'
|
|
228
228
|
);
|
|
229
229
|
},
|
|
230
230
|
(input, keypath) => {
|
|
@@ -238,7 +238,7 @@ const options = object(
|
|
|
238
238
|
(/** @type {any} */ { message }) => {
|
|
239
239
|
throw new Error(
|
|
240
240
|
message +
|
|
241
|
-
|
|
241
|
+
'\nTo suppress or handle this error, implement `handleEntryGeneratorMismatch` in https://kit.svelte.dev/docs/configuration#prerender'
|
|
242
242
|
);
|
|
243
243
|
},
|
|
244
244
|
(input, keypath) => {
|
package/src/core/env.js
CHANGED
|
@@ -75,7 +75,7 @@ export function create_dynamic_types(id, env, prefix) {
|
|
|
75
75
|
|
|
76
76
|
if (id === 'private') {
|
|
77
77
|
properties.push(`${prefixed}: undefined;`);
|
|
78
|
-
properties.push(
|
|
78
|
+
properties.push('[key: string]: string | undefined;');
|
|
79
79
|
} else {
|
|
80
80
|
properties.push(`${prefixed}: string | undefined;`);
|
|
81
81
|
}
|
|
@@ -55,7 +55,7 @@ export function generate_manifest({ build_data, relative_path, routes }) {
|
|
|
55
55
|
|
|
56
56
|
/** @param {Array<number | undefined>} indexes */
|
|
57
57
|
function get_nodes(indexes) {
|
|
58
|
-
|
|
58
|
+
const string = indexes.map((n) => reindexed.get(n) ?? '').join(',');
|
|
59
59
|
|
|
60
60
|
// since JavaScript ignores trailing commas, we need to insert a dummy
|
|
61
61
|
// comma so that the array has the correct length if the last item
|
|
@@ -65,7 +65,7 @@ export function generate_manifest({ build_data, relative_path, routes }) {
|
|
|
65
65
|
|
|
66
66
|
// prettier-ignore
|
|
67
67
|
// String representation of
|
|
68
|
-
/** @type {import('
|
|
68
|
+
/** @type {import('@sveltejs/kit').SSRManifest} */
|
|
69
69
|
return dedent`
|
|
70
70
|
{
|
|
71
71
|
appDir: ${s(build_data.app_dir)},
|
|
@@ -12,7 +12,7 @@ import { load_config } from '../config/index.js';
|
|
|
12
12
|
import { forked } from '../../utils/fork.js';
|
|
13
13
|
import { should_polyfill } from '../../utils/platform.js';
|
|
14
14
|
import { installPolyfills } from '../../exports/node/polyfills.js';
|
|
15
|
-
import {
|
|
15
|
+
import { resolvePath } from '../../exports/index.js';
|
|
16
16
|
|
|
17
17
|
export default forked(import.meta.url, analyse);
|
|
18
18
|
|
|
@@ -23,7 +23,7 @@ export default forked(import.meta.url, analyse);
|
|
|
23
23
|
* }} opts
|
|
24
24
|
*/
|
|
25
25
|
async function analyse({ manifest_path, env }) {
|
|
26
|
-
/** @type {import('
|
|
26
|
+
/** @type {import('@sveltejs/kit').SSRManifest} */
|
|
27
27
|
const manifest = (await import(pathToFileURL(manifest_path).href)).manifest;
|
|
28
28
|
|
|
29
29
|
/** @type {import('types').ValidatedKitConfig} */
|
|
@@ -145,7 +145,7 @@ async function analyse({ manifest_path, env }) {
|
|
|
145
145
|
},
|
|
146
146
|
prerender,
|
|
147
147
|
entries:
|
|
148
|
-
entries && (await entries()).map((entry_object) =>
|
|
148
|
+
entries && (await entries()).map((entry_object) => resolvePath(route.id, entry_object))
|
|
149
149
|
});
|
|
150
150
|
}
|
|
151
151
|
|
|
@@ -27,7 +27,7 @@ async function generate_fallback({ manifest_path, env }) {
|
|
|
27
27
|
/** @type {import('types').ServerModule} */
|
|
28
28
|
const { Server } = await import(pathToFileURL(`${server_root}/server/index.js`).href);
|
|
29
29
|
|
|
30
|
-
/** @type {import('
|
|
30
|
+
/** @type {import('@sveltejs/kit').SSRManifest} */
|
|
31
31
|
const manifest = (await import(pathToFileURL(manifest_path).href)).manifest;
|
|
32
32
|
|
|
33
33
|
set_building(true);
|
|
@@ -26,7 +26,7 @@ export default forked(import.meta.url, prerender);
|
|
|
26
26
|
* }} opts
|
|
27
27
|
*/
|
|
28
28
|
async function prerender({ out, manifest_path, metadata, verbose, env }) {
|
|
29
|
-
/** @type {import('
|
|
29
|
+
/** @type {import('@sveltejs/kit').SSRManifest} */
|
|
30
30
|
const manifest = (await import(pathToFileURL(manifest_path).href)).manifest;
|
|
31
31
|
|
|
32
32
|
/** @type {import('types').ServerInternalModule} */
|
|
@@ -456,7 +456,7 @@ function analyze(project_relative, file, component_extensions, module_extensions
|
|
|
456
456
|
);
|
|
457
457
|
}
|
|
458
458
|
|
|
459
|
-
const kind =
|
|
459
|
+
const kind = match[1] || match[4] || match[7] ? 'server' : 'universal';
|
|
460
460
|
|
|
461
461
|
return {
|
|
462
462
|
kind,
|
|
@@ -513,7 +513,7 @@ function prevent_conflicts(routes) {
|
|
|
513
513
|
const normalized = normalize_route_id(route.id);
|
|
514
514
|
|
|
515
515
|
// find all permutations created by optional parameters
|
|
516
|
-
const split = normalized.split(/<\?(.+?)
|
|
516
|
+
const split = normalized.split(/<\?(.+?)>/g);
|
|
517
517
|
|
|
518
518
|
let permutations = [/** @type {string} */ (split[0])];
|
|
519
519
|
|
|
@@ -8,7 +8,7 @@ import { write_if_changed } from './utils.js';
|
|
|
8
8
|
|
|
9
9
|
// TODO these types should be described in a neutral place, rather than
|
|
10
10
|
// inside either `packages/kit` or `kit.svelte.dev`
|
|
11
|
-
const descriptions_dir = fileURLToPath(new URL('../../../types/synthetic', import.meta.url));
|
|
11
|
+
const descriptions_dir = fileURLToPath(new URL('../../../src/types/synthetic', import.meta.url));
|
|
12
12
|
|
|
13
13
|
/** @param {string} filename */
|
|
14
14
|
function read_description(filename) {
|
|
@@ -21,7 +21,7 @@ export function write_client_manifest(kit, manifest_data, output, metadata) {
|
|
|
21
21
|
if (node.universal) {
|
|
22
22
|
declarations.push(
|
|
23
23
|
`import * as universal from ${s(relative_path(`${output}/nodes`, node.universal))};`,
|
|
24
|
-
|
|
24
|
+
'export { universal };'
|
|
25
25
|
);
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -75,7 +75,7 @@ export { set_assets, set_building, set_private_env, set_public_env };
|
|
|
75
75
|
* @param {string} output
|
|
76
76
|
*/
|
|
77
77
|
export function write_server(config, output) {
|
|
78
|
-
// TODO the casting shouldn't be necessary —
|
|
78
|
+
// TODO the casting shouldn't be necessary — investigate
|
|
79
79
|
const hooks_file = /** @type {string} */ (resolve_entry(config.kit.files.hooks.server));
|
|
80
80
|
|
|
81
81
|
/** @param {string} file */
|
|
@@ -52,7 +52,7 @@ export async function write_all_types(config, manifest_data) {
|
|
|
52
52
|
// it could be invoked by another process in the meantime.
|
|
53
53
|
const meta_data_file = `${types_dir}/route_meta_data.json`;
|
|
54
54
|
const has_meta_data = fs.existsSync(meta_data_file);
|
|
55
|
-
|
|
55
|
+
const meta_data = has_meta_data
|
|
56
56
|
? /** @type {Record<string, string[]>} */ (JSON.parse(fs.readFileSync(meta_data_file, 'utf-8')))
|
|
57
57
|
: {};
|
|
58
58
|
const routes_map = create_routes_map(manifest_data);
|
|
@@ -177,7 +177,7 @@ function update_types(config, routes, route, to_delete = new Set()) {
|
|
|
177
177
|
const outdir = path.join(config.kit.outDir, 'types', routes_dir, route.id);
|
|
178
178
|
|
|
179
179
|
// now generate new types
|
|
180
|
-
const imports = [
|
|
180
|
+
const imports = ["import type * as Kit from '@sveltejs/kit';"];
|
|
181
181
|
|
|
182
182
|
/** @type {string[]} */
|
|
183
183
|
const declarations = [];
|
|
@@ -196,7 +196,7 @@ function update_types(config, routes, route, to_delete = new Set()) {
|
|
|
196
196
|
|
|
197
197
|
if (route.params.length > 0) {
|
|
198
198
|
exports.push(
|
|
199
|
-
|
|
199
|
+
'export type EntryGenerator = () => Promise<Array<RouteParams>> | Array<RouteParams>;'
|
|
200
200
|
);
|
|
201
201
|
}
|
|
202
202
|
|
|
@@ -206,24 +206,24 @@ function update_types(config, routes, route, to_delete = new Set()) {
|
|
|
206
206
|
if (route.layout || route.leaf) {
|
|
207
207
|
declarations.push(
|
|
208
208
|
// If T extends the empty object, void is also allowed as a return type
|
|
209
|
-
|
|
209
|
+
'type MaybeWithVoid<T> = {} extends T ? T | void : T;',
|
|
210
210
|
|
|
211
211
|
// Returns the key of the object whose values are required.
|
|
212
|
-
|
|
212
|
+
'export type RequiredKeys<T> = { [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; }[keyof T];',
|
|
213
213
|
|
|
214
214
|
// Helper type to get the correct output type for load functions. It should be passed the parent type to check what types from App.PageData are still required.
|
|
215
215
|
// If none, void is also allowed as a return type.
|
|
216
|
-
|
|
216
|
+
'type OutputDataShape<T> = MaybeWithVoid<Omit<App.PageData, RequiredKeys<T>> & Partial<Pick<App.PageData, keyof T & keyof App.PageData>> & Record<string, any>>',
|
|
217
217
|
|
|
218
218
|
// null & {} == null, we need to prevent that in some situations
|
|
219
|
-
|
|
219
|
+
'type EnsureDefined<T> = T extends null | undefined ? {} : T;',
|
|
220
220
|
|
|
221
221
|
// Takes a union type and returns a union type where each type also has all properties
|
|
222
222
|
// of all possible types (typed as undefined), making accessing them more ergonomic
|
|
223
|
-
|
|
223
|
+
'type OptionalUnion<U extends Record<string, any>, A extends keyof U = U extends U ? keyof U : never> = U extends unknown ? { [P in Exclude<A, keyof U>]?: never } & U : never;',
|
|
224
224
|
|
|
225
225
|
// Re-export `Snapshot` from @sveltejs/kit — in future we could use this to infer <T> from the return type of `snapshot.capture`
|
|
226
|
-
|
|
226
|
+
'export type Snapshot<T = any> = Kit.Snapshot<T>;'
|
|
227
227
|
);
|
|
228
228
|
}
|
|
229
229
|
|
|
@@ -255,10 +255,10 @@ function update_types(config, routes, route, to_delete = new Set()) {
|
|
|
255
255
|
|
|
256
256
|
if (route.leaf.server) {
|
|
257
257
|
exports.push(
|
|
258
|
-
|
|
258
|
+
'export type Action<OutputData extends Record<string, any> | void = Record<string, any> | void> = Kit.Action<RouteParams, OutputData, RouteId>'
|
|
259
259
|
);
|
|
260
260
|
exports.push(
|
|
261
|
-
|
|
261
|
+
'export type Actions<OutputData extends Record<string, any> | void = Record<string, any> | void> = Kit.Actions<RouteParams, OutputData, RouteId>'
|
|
262
262
|
);
|
|
263
263
|
}
|
|
264
264
|
}
|
|
@@ -326,11 +326,11 @@ function update_types(config, routes, route, to_delete = new Set()) {
|
|
|
326
326
|
}
|
|
327
327
|
|
|
328
328
|
if (route.endpoint) {
|
|
329
|
-
exports.push(
|
|
329
|
+
exports.push('export type RequestHandler = Kit.RequestHandler<RouteParams, RouteId>;');
|
|
330
330
|
}
|
|
331
331
|
|
|
332
332
|
if (route.leaf?.server || route.layout?.server || route.endpoint) {
|
|
333
|
-
exports.push(
|
|
333
|
+
exports.push('export type RequestEvent = Kit.RequestEvent<RouteParams, RouteId>;');
|
|
334
334
|
}
|
|
335
335
|
|
|
336
336
|
const output = [imports.join('\n'), declarations.join('\n'), exports.join('\n')]
|
|
@@ -386,7 +386,7 @@ function process_node(node, outdir, is_page, proxies, all_pages_have_load = true
|
|
|
386
386
|
// +page.js load present -> server can return all-optional data
|
|
387
387
|
const output_data_shape =
|
|
388
388
|
node.universal || (!is_page && all_pages_have_load)
|
|
389
|
-
?
|
|
389
|
+
? 'Partial<App.PageData> & Record<string, any> | void'
|
|
390
390
|
: `OutputDataShape<${parent_type}>`;
|
|
391
391
|
exports.push(
|
|
392
392
|
`export type ${prefix}ServerLoad<OutputData extends ${output_data_shape} = ${output_data_shape}> = Kit.ServerLoad<${params}, ${parent_type}, OutputData, ${route_id}>;`
|
|
@@ -404,15 +404,15 @@ function process_node(node, outdir, is_page, proxies, all_pages_have_load = true
|
|
|
404
404
|
: path_to_original(outdir, node.server);
|
|
405
405
|
|
|
406
406
|
exports.push(
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
407
|
+
'type ExcludeActionFailure<T> = T extends Kit.ActionFailure<any> ? never : T extends void ? never : T;',
|
|
408
|
+
'type ActionsSuccess<T extends Record<string, (...args: any) => any>> = { [Key in keyof T]: ExcludeActionFailure<Awaited<ReturnType<T[Key]>>>; }[keyof T];',
|
|
409
|
+
'type ExtractActionFailure<T> = T extends Kit.ActionFailure<infer X> ? X extends void ? never : X : never;',
|
|
410
|
+
'type ActionsFailure<T extends Record<string, (...args: any) => any>> = { [Key in keyof T]: Exclude<ExtractActionFailure<Awaited<ReturnType<T[Key]>>>, void>; }[keyof T];',
|
|
411
411
|
`type ActionsExport = typeof import('${from}').actions`,
|
|
412
|
-
|
|
412
|
+
'export type SubmitFunction = Kit.SubmitFunction<Expand<ActionsSuccess<ActionsExport>>, Expand<ActionsFailure<ActionsExport>>>'
|
|
413
413
|
);
|
|
414
414
|
|
|
415
|
-
type =
|
|
415
|
+
type = 'Expand<Kit.AwaitedActions<ActionsExport>> | null';
|
|
416
416
|
}
|
|
417
417
|
exports.push(`export type ActionData = ${type};`);
|
|
418
418
|
}
|
|
@@ -440,7 +440,7 @@ function process_node(node, outdir, is_page, proxies, all_pages_have_load = true
|
|
|
440
440
|
|
|
441
441
|
const output_data_shape =
|
|
442
442
|
!is_page && all_pages_have_load
|
|
443
|
-
?
|
|
443
|
+
? 'Partial<App.PageData> & Record<string, any> | void'
|
|
444
444
|
: `OutputDataShape<${parent_type}>`;
|
|
445
445
|
exports.push(
|
|
446
446
|
`export type ${prefix}Load<OutputData extends ${output_data_shape} = ${output_data_shape}> = Kit.Load<${params}, ${prefix}ServerData, ${parent_type}, OutputData, ${route_id}>;`
|
|
@@ -688,7 +688,7 @@ export function tweak_types(content, is_server) {
|
|
|
688
688
|
// remove type from `export const load: Load ...`
|
|
689
689
|
if (declaration.type) {
|
|
690
690
|
let a = declaration.type.pos;
|
|
691
|
-
|
|
691
|
+
const b = declaration.type.end;
|
|
692
692
|
while (/\s/.test(content[a])) a += 1;
|
|
693
693
|
|
|
694
694
|
const type = content.slice(a, b);
|
|
@@ -760,7 +760,7 @@ export function tweak_types(content, is_server) {
|
|
|
760
760
|
// remove type from `export const actions: Actions ...`
|
|
761
761
|
if (declaration.type) {
|
|
762
762
|
let a = declaration.type.pos;
|
|
763
|
-
|
|
763
|
+
const b = declaration.type.end;
|
|
764
764
|
while (/\s/.test(content[a])) a += 1;
|
|
765
765
|
|
|
766
766
|
const type = content.slice(a, b);
|
|
@@ -788,7 +788,7 @@ export function tweak_types(content, is_server) {
|
|
|
788
788
|
if (arg && !arg.type) {
|
|
789
789
|
code.appendLeft(
|
|
790
790
|
arg.name.end,
|
|
791
|
-
|
|
791
|
+
": import('./$types').RequestEvent" + (add_parens ? ')' : '')
|
|
792
792
|
);
|
|
793
793
|
}
|
|
794
794
|
}
|
|
@@ -1,6 +1,70 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* A helper function for sequencing multiple `handle` calls in a middleware-like manner.
|
|
3
|
+
* The behavior for the `handle` options is as follows:
|
|
4
|
+
* - `transformPageChunk` is applied in reverse order and merged
|
|
5
|
+
* - `preload` is applied in forward order, the first option "wins" and no `preload` options after it are called
|
|
6
|
+
* - `filterSerializedResponseHeaders` behaves the same as `preload`
|
|
7
|
+
*
|
|
8
|
+
* ```js
|
|
9
|
+
* /// file: src/hooks.server.js
|
|
10
|
+
* import { sequence } from '@sveltejs/kit/hooks';
|
|
11
|
+
*
|
|
12
|
+
* /// type: import('@sveltejs/kit').Handle
|
|
13
|
+
* async function first({ event, resolve }) {
|
|
14
|
+
* console.log('first pre-processing');
|
|
15
|
+
* const result = await resolve(event, {
|
|
16
|
+
* transformPageChunk: ({ html }) => {
|
|
17
|
+
* // transforms are applied in reverse order
|
|
18
|
+
* console.log('first transform');
|
|
19
|
+
* return html;
|
|
20
|
+
* },
|
|
21
|
+
* preload: () => {
|
|
22
|
+
* // this one wins as it's the first defined in the chain
|
|
23
|
+
* console.log('first preload');
|
|
24
|
+
* }
|
|
25
|
+
* });
|
|
26
|
+
* console.log('first post-processing');
|
|
27
|
+
* return result;
|
|
28
|
+
* }
|
|
29
|
+
*
|
|
30
|
+
* /// type: import('@sveltejs/kit').Handle
|
|
31
|
+
* async function second({ event, resolve }) {
|
|
32
|
+
* console.log('second pre-processing');
|
|
33
|
+
* const result = await resolve(event, {
|
|
34
|
+
* transformPageChunk: ({ html }) => {
|
|
35
|
+
* console.log('second transform');
|
|
36
|
+
* return html;
|
|
37
|
+
* },
|
|
38
|
+
* preload: () => {
|
|
39
|
+
* console.log('second preload');
|
|
40
|
+
* },
|
|
41
|
+
* filterSerializedResponseHeaders: () => {
|
|
42
|
+
* // this one wins as it's the first defined in the chain
|
|
43
|
+
* console.log('second filterSerializedResponseHeaders');
|
|
44
|
+
* }
|
|
45
|
+
* });
|
|
46
|
+
* console.log('second post-processing');
|
|
47
|
+
* return result;
|
|
48
|
+
* }
|
|
49
|
+
*
|
|
50
|
+
* export const handle = sequence(first, second);
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* The example above would print:
|
|
54
|
+
*
|
|
55
|
+
* ```
|
|
56
|
+
* first pre-processing
|
|
57
|
+
* first preload
|
|
58
|
+
* second pre-processing
|
|
59
|
+
* second filterSerializedResponseHeaders
|
|
60
|
+
* second transform
|
|
61
|
+
* first transform
|
|
62
|
+
* second post-processing
|
|
63
|
+
* first post-processing
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* @param {...import('@sveltejs/kit').Handle} handlers The chain of `handle` functions
|
|
67
|
+
* @returns {import('@sveltejs/kit').Handle}
|
|
4
68
|
*/
|
|
5
69
|
export function sequence(...handlers) {
|
|
6
70
|
const length = handlers.length;
|
|
@@ -11,8 +75,8 @@ export function sequence(...handlers) {
|
|
|
11
75
|
|
|
12
76
|
/**
|
|
13
77
|
* @param {number} i
|
|
14
|
-
* @param {import('
|
|
15
|
-
* @param {import('
|
|
78
|
+
* @param {import('@sveltejs/kit').RequestEvent} event
|
|
79
|
+
* @param {import('@sveltejs/kit').ResolveOptions | undefined} parent_options
|
|
16
80
|
* @returns {import('types').MaybePromise<Response>}
|
|
17
81
|
*/
|
|
18
82
|
function apply_handle(i, event, parent_options) {
|
|
@@ -21,7 +85,7 @@ export function sequence(...handlers) {
|
|
|
21
85
|
return handle({
|
|
22
86
|
event,
|
|
23
87
|
resolve: (event, options) => {
|
|
24
|
-
/** @type {import('
|
|
88
|
+
/** @type {import('@sveltejs/kit').ResolveOptions['transformPageChunk']} */
|
|
25
89
|
const transformPageChunk = async ({ html, done }) => {
|
|
26
90
|
if (options?.transformPageChunk) {
|
|
27
91
|
html = (await options.transformPageChunk({ html, done })) ?? '';
|
|
@@ -34,12 +98,12 @@ export function sequence(...handlers) {
|
|
|
34
98
|
return html;
|
|
35
99
|
};
|
|
36
100
|
|
|
37
|
-
/** @type {import('
|
|
101
|
+
/** @type {import('@sveltejs/kit').ResolveOptions['filterSerializedResponseHeaders']} */
|
|
38
102
|
const filterSerializedResponseHeaders =
|
|
39
103
|
parent_options?.filterSerializedResponseHeaders ??
|
|
40
104
|
options?.filterSerializedResponseHeaders;
|
|
41
105
|
|
|
42
|
-
/** @type {import('
|
|
106
|
+
/** @type {import('@sveltejs/kit').ResolveOptions['preload']} */
|
|
43
107
|
const preload = parent_options?.preload ?? options?.preload;
|
|
44
108
|
|
|
45
109
|
return i < length - 1
|
package/src/exports/index.js
CHANGED
|
@@ -1,22 +1,43 @@
|
|
|
1
1
|
import { HttpError, Redirect, ActionFailure } from '../runtime/control.js';
|
|
2
2
|
import { BROWSER, DEV } from 'esm-env';
|
|
3
|
+
import { get_route_segments } from '../utils/routing.js';
|
|
3
4
|
|
|
4
|
-
// For some reason we need to type the params as well here,
|
|
5
|
-
// JSdoc doesn't seem to like @type with function overloads
|
|
6
5
|
/**
|
|
7
|
-
* @
|
|
6
|
+
* @overload
|
|
8
7
|
* @param {number} status
|
|
9
|
-
* @param {
|
|
8
|
+
* @param {App.Error} body
|
|
9
|
+
* @return {HttpError}
|
|
10
10
|
*/
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @overload
|
|
14
|
+
* @param {number} status
|
|
15
|
+
* @param {{ message: string } extends App.Error ? App.Error | string | undefined : never} [body]
|
|
16
|
+
* @return {HttpError}
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Creates an `HttpError` object with an HTTP status code and an optional message.
|
|
21
|
+
* This object, if thrown during request handling, will cause SvelteKit to
|
|
22
|
+
* return an error response without invoking `handleError`.
|
|
23
|
+
* Make sure you're not catching the thrown error, which would prevent SvelteKit from handling it.
|
|
24
|
+
* @param {number} status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599.
|
|
25
|
+
* @param {{ message: string } extends App.Error ? App.Error | string | undefined : never} body An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
|
|
26
|
+
*/
|
|
27
|
+
export function error(status, body) {
|
|
12
28
|
if ((!BROWSER || DEV) && (isNaN(status) || status < 400 || status > 599)) {
|
|
13
29
|
throw new Error(`HTTP error status codes must be between 400 and 599 — ${status} is invalid`);
|
|
14
30
|
}
|
|
15
31
|
|
|
16
|
-
return new HttpError(status,
|
|
32
|
+
return new HttpError(status, body);
|
|
17
33
|
}
|
|
18
34
|
|
|
19
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* Create a `Redirect` object. If thrown during request handling, SvelteKit will return a redirect response.
|
|
37
|
+
* Make sure you're not catching the thrown redirect, which would prevent SvelteKit from handling it.
|
|
38
|
+
* @param {300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308} status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages). Must be in the range 300-308.
|
|
39
|
+
* @param {string} location The location to redirect to.
|
|
40
|
+
*/
|
|
20
41
|
export function redirect(status, location) {
|
|
21
42
|
if ((!BROWSER || DEV) && (isNaN(status) || status < 300 || status > 308)) {
|
|
22
43
|
throw new Error('Invalid status code');
|
|
@@ -25,7 +46,11 @@ export function redirect(status, location) {
|
|
|
25
46
|
return new Redirect(status, location);
|
|
26
47
|
}
|
|
27
48
|
|
|
28
|
-
/**
|
|
49
|
+
/**
|
|
50
|
+
* Create a JSON `Response` object from the supplied data.
|
|
51
|
+
* @param {any} data The value that will be serialized as JSON.
|
|
52
|
+
* @param {ResponseInit} [init] Options such as `status` and `headers` that will be added to the response. `Content-Type: application/json` and `Content-Length` headers will be added automatically.
|
|
53
|
+
*/
|
|
29
54
|
export function json(data, init) {
|
|
30
55
|
// TODO deprecate this in favour of `Response.json` when it's
|
|
31
56
|
// more widely supported
|
|
@@ -51,7 +76,11 @@ export function json(data, init) {
|
|
|
51
76
|
|
|
52
77
|
const encoder = new TextEncoder();
|
|
53
78
|
|
|
54
|
-
/**
|
|
79
|
+
/**
|
|
80
|
+
* Create a `Response` object from the supplied body.
|
|
81
|
+
* @param {string} body The value that will be used as-is.
|
|
82
|
+
* @param {ResponseInit} [init] Options such as `status` and `headers` that will be added to the response. A `Content-Length` header will be added automatically.
|
|
83
|
+
*/
|
|
55
84
|
export function text(body, init) {
|
|
56
85
|
const headers = new Headers(init?.headers);
|
|
57
86
|
if (!headers.has('content-length')) {
|
|
@@ -65,10 +94,57 @@ export function text(body, init) {
|
|
|
65
94
|
}
|
|
66
95
|
|
|
67
96
|
/**
|
|
68
|
-
*
|
|
69
|
-
* @
|
|
70
|
-
* @param {
|
|
97
|
+
* Create an `ActionFailure` object.
|
|
98
|
+
* @template {Record<string, unknown> | undefined} [T=undefined]
|
|
99
|
+
* @param {number} status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599.
|
|
100
|
+
* @param {T} [data] Data associated with the failure (e.g. validation errors)
|
|
101
|
+
* @returns {ActionFailure<T>}
|
|
71
102
|
*/
|
|
72
103
|
export function fail(status, data) {
|
|
73
104
|
return new ActionFailure(status, data);
|
|
74
105
|
}
|
|
106
|
+
|
|
107
|
+
const basic_param_pattern = /\[(\[)?(?:\.\.\.)?(\w+?)(?:=(\w+))?\]\]?/g;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Populate a route ID with params to resolve a pathname.
|
|
111
|
+
* @example
|
|
112
|
+
* ```js
|
|
113
|
+
* resolvePath(
|
|
114
|
+
* `/blog/[slug]/[...somethingElse]`,
|
|
115
|
+
* {
|
|
116
|
+
* slug: 'hello-world',
|
|
117
|
+
* somethingElse: 'something/else'
|
|
118
|
+
* }
|
|
119
|
+
* ); // `/blog/hello-world/something/else`
|
|
120
|
+
* ```
|
|
121
|
+
* @param {string} id
|
|
122
|
+
* @param {Record<string, string | undefined>} params
|
|
123
|
+
* @returns {string}
|
|
124
|
+
*/
|
|
125
|
+
export function resolvePath(id, params) {
|
|
126
|
+
const segments = get_route_segments(id);
|
|
127
|
+
return (
|
|
128
|
+
'/' +
|
|
129
|
+
segments
|
|
130
|
+
.map((segment) =>
|
|
131
|
+
segment.replace(basic_param_pattern, (_, optional, name) => {
|
|
132
|
+
const param_value = params[name];
|
|
133
|
+
|
|
134
|
+
// This is nested so TS correctly narrows the type
|
|
135
|
+
if (!param_value) {
|
|
136
|
+
if (optional) return '';
|
|
137
|
+
throw new Error(`Missing parameter '${name}' in route ${id}`);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (param_value.startsWith('/') || param_value.endsWith('/'))
|
|
141
|
+
throw new Error(
|
|
142
|
+
`Parameter '${name}' in route ${id} cannot start or end with a slash -- this would cause an invalid route like foo//bar`
|
|
143
|
+
);
|
|
144
|
+
return param_value;
|
|
145
|
+
})
|
|
146
|
+
)
|
|
147
|
+
.filter(Boolean)
|
|
148
|
+
.join('/')
|
|
149
|
+
);
|
|
150
|
+
}
|