@sveltejs/kit 3.0.0-next.10 → 3.0.0-next.12
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 +1 -1
- package/src/cli.js +8 -8
- package/src/constants.js +3 -1
- package/src/core/adapt/builder.js +3 -6
- package/src/core/config/index.js +6 -1
- package/src/core/config/options.js +54 -104
- package/src/core/env.js +25 -11
- package/src/core/postbuild/fallback.js +2 -1
- package/src/core/postbuild/prerender.js +75 -28
- package/src/core/postbuild/queue.js +2 -1
- package/src/core/sync/sync.js +11 -14
- package/src/core/sync/utils.js +21 -1
- package/src/core/sync/{write_non_ambient.js → write_app_types.js} +23 -21
- package/src/core/sync/write_client_manifest.js +4 -12
- package/src/core/sync/write_env.js +6 -4
- package/src/core/sync/write_server.js +12 -17
- package/src/core/sync/write_tsconfig/index.js +245 -0
- package/src/core/sync/write_tsconfig/utils.js +162 -0
- package/src/core/sync/write_types/index.js +80 -88
- package/src/core/utils.js +28 -3
- package/src/exports/env/index.js +68 -3
- package/src/exports/internal/env.js +6 -3
- package/src/exports/internal/server/index.js +3 -1
- package/src/exports/params.js +9 -4
- package/src/exports/public.d.ts +69 -71
- package/src/exports/vite/dev/index.js +112 -56
- package/src/exports/vite/index.js +483 -258
- package/src/exports/vite/module_ids.js +2 -2
- package/src/exports/vite/preview/index.js +3 -2
- package/src/exports/vite/utils.js +21 -10
- package/src/runner.js +13 -0
- package/src/runtime/app/forms.js +4 -0
- package/src/runtime/app/manifest/index.js +1 -0
- package/src/runtime/app/paths/client.js +30 -30
- package/src/runtime/app/paths/internal/client.js +26 -0
- package/src/runtime/app/paths/server.js +23 -10
- package/src/runtime/app/paths/types.d.ts +11 -19
- package/src/runtime/app/server/index.js +1 -1
- package/src/runtime/app/server/remote/command.js +12 -7
- package/src/runtime/app/server/remote/form.js +29 -26
- package/src/runtime/app/server/remote/prerender.js +9 -2
- package/src/runtime/app/server/remote/query.js +6 -5
- package/src/runtime/app/server/remote/shared.js +48 -30
- package/src/runtime/app/service-worker/index.js +24 -0
- package/src/runtime/app/state/index.js +1 -1
- package/src/runtime/client/client.js +46 -9
- package/src/runtime/client/ndjson.js +1 -1
- package/src/runtime/client/remote-functions/form.svelte.js +43 -51
- package/src/runtime/client/remote-functions/query/index.js +2 -2
- package/src/runtime/client/remote-functions/query-batch.svelte.js +2 -3
- package/src/runtime/client/remote-functions/query-live/iterator.js +5 -2
- package/src/runtime/client/remote-functions/shared.svelte.js +4 -1
- package/src/runtime/client/state.svelte.js +54 -21
- package/src/runtime/client/stream.js +3 -2
- package/src/runtime/form-utils.js +89 -54
- package/src/runtime/server/cookie.js +1 -1
- package/src/runtime/server/data/index.js +32 -29
- package/src/runtime/server/errors.js +135 -0
- package/src/runtime/server/fetch.js +1 -1
- package/src/runtime/server/index.js +20 -10
- package/src/runtime/server/internal.js +25 -0
- package/src/runtime/server/page/actions.js +4 -3
- package/src/runtime/server/page/data_serializer.js +10 -10
- package/src/runtime/server/page/index.js +3 -2
- package/src/runtime/server/page/load_data.js +1 -1
- package/src/runtime/server/page/render.js +22 -35
- package/src/runtime/server/page/respond_with_error.js +6 -5
- package/src/runtime/server/{remote.js → remote-functions.js} +67 -36
- package/src/runtime/server/respond.js +58 -20
- package/src/runtime/server/sourcemaps.js +183 -0
- package/src/runtime/server/utils.js +12 -157
- package/src/types/ambient-private.d.ts +10 -0
- package/src/types/ambient.d.ts +22 -27
- package/src/types/global-private.d.ts +12 -5
- package/src/types/internal.d.ts +19 -9
- package/src/types/private.d.ts +8 -0
- package/src/utils/escape.js +9 -25
- package/src/utils/features.js +1 -1
- package/src/utils/fork.js +7 -2
- package/src/utils/page_nodes.js +3 -5
- package/src/utils/url.js +12 -0
- package/src/version.js +1 -1
- package/types/index.d.ts +152 -120
- package/types/index.d.ts.map +6 -1
- package/src/core/sync/write_ambient.js +0 -18
- package/src/core/sync/write_tsconfig.js +0 -258
- package/src/runtime/shared-server.js +0 -7
- /package/src/core/sync/{write_tsconfig_test → write_tsconfig/test-app}/package.json +0 -0
package/src/core/sync/sync.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import process from 'node:process';
|
|
3
2
|
import create_manifest_data from './create_manifest_data/index.js';
|
|
4
3
|
import { write_client_manifest } from './write_client_manifest.js';
|
|
5
|
-
import { write_tsconfig } from './write_tsconfig.js';
|
|
4
|
+
import { write_tsconfig } from './write_tsconfig/index.js';
|
|
6
5
|
import { write_types, write_all_types } from './write_types/index.js';
|
|
7
|
-
import {
|
|
8
|
-
import { write_non_ambient } from './write_non_ambient.js';
|
|
6
|
+
import { write_app_types } from './write_app_types.js';
|
|
9
7
|
import { write_server } from './write_server.js';
|
|
10
8
|
import {
|
|
11
9
|
create_node_analyser,
|
|
@@ -21,7 +19,6 @@ import { write_env } from './write_env.js';
|
|
|
21
19
|
*/
|
|
22
20
|
export function init(config, root) {
|
|
23
21
|
write_tsconfig(config.kit, root);
|
|
24
|
-
write_ambient(config.kit);
|
|
25
22
|
}
|
|
26
23
|
|
|
27
24
|
/**
|
|
@@ -37,7 +34,7 @@ export function create(config, root) {
|
|
|
37
34
|
write_client_manifest(config.kit, manifest_data, `${output}/client`);
|
|
38
35
|
write_server(config, output, root);
|
|
39
36
|
write_all_types(config, manifest_data, root);
|
|
40
|
-
|
|
37
|
+
write_app_types(config.kit, manifest_data, root);
|
|
41
38
|
|
|
42
39
|
return { manifest_data };
|
|
43
40
|
}
|
|
@@ -65,7 +62,7 @@ export function update(config, manifest_data, file, root) {
|
|
|
65
62
|
}
|
|
66
63
|
|
|
67
64
|
write_types(config, manifest_data, file, root);
|
|
68
|
-
|
|
65
|
+
write_app_types(config.kit, manifest_data, root);
|
|
69
66
|
}
|
|
70
67
|
|
|
71
68
|
/**
|
|
@@ -81,13 +78,13 @@ export function all(config, root) {
|
|
|
81
78
|
/**
|
|
82
79
|
* Run sync.init and then generate all type files.
|
|
83
80
|
* @param {import('types').ValidatedConfig} config
|
|
81
|
+
* @param {string} root
|
|
84
82
|
*/
|
|
85
|
-
export function all_types(config) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
write_non_ambient(config.kit, manifest_data);
|
|
83
|
+
export function all_types(config, root) {
|
|
84
|
+
init(config, root);
|
|
85
|
+
const manifest_data = create_manifest_data({ config, cwd: root });
|
|
86
|
+
write_all_types(config, manifest_data, root);
|
|
87
|
+
write_app_types(config.kit, manifest_data, root);
|
|
91
88
|
}
|
|
92
89
|
|
|
93
90
|
/**
|
|
@@ -100,7 +97,7 @@ export function all_types(config) {
|
|
|
100
97
|
export async function env(kit, entry, root, mode) {
|
|
101
98
|
const env_config = await load_explicit_env(kit, entry, root, mode);
|
|
102
99
|
|
|
103
|
-
write_env(
|
|
100
|
+
write_env(entry, env_config, root);
|
|
104
101
|
|
|
105
102
|
return env_config;
|
|
106
103
|
}
|
package/src/core/sync/utils.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
3
|
+
import { styleText } from 'node:util';
|
|
4
|
+
import { mkdirp, resolve_entry } from '../../utils/filesystem.js';
|
|
4
5
|
|
|
5
6
|
/** @type {Map<string, string>} */
|
|
6
7
|
const previous_contents = new Map();
|
|
@@ -68,3 +69,22 @@ export function dedent(strings, ...values) {
|
|
|
68
69
|
|
|
69
70
|
return str;
|
|
70
71
|
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @param {string} original
|
|
75
|
+
* @param {string} typo The common misspelling to check for
|
|
76
|
+
* @param {string} description What was wrong with the filename
|
|
77
|
+
*/
|
|
78
|
+
export function check_spelling(original, typo, description) {
|
|
79
|
+
const misspelled = resolve_entry(typo);
|
|
80
|
+
if (!misspelled) return;
|
|
81
|
+
|
|
82
|
+
const corrected = path.basename(misspelled).replace(path.basename(typo), path.basename(original));
|
|
83
|
+
|
|
84
|
+
console.warn(
|
|
85
|
+
styleText(
|
|
86
|
+
['bold', 'yellow'],
|
|
87
|
+
`${description}. Did you mean ${corrected}?` + ` at ${path.resolve(misspelled)}`
|
|
88
|
+
)
|
|
89
|
+
);
|
|
90
|
+
}
|
|
@@ -22,10 +22,6 @@ const remove_group_segments = (/** @type {string} */ id) => {
|
|
|
22
22
|
* @returns {string[]}
|
|
23
23
|
*/
|
|
24
24
|
function get_pathnames_for_trailing_slash(pathname, route) {
|
|
25
|
-
if (pathname === '/') {
|
|
26
|
-
return [pathname];
|
|
27
|
-
}
|
|
28
|
-
|
|
29
25
|
/** @type {Set<string>} */
|
|
30
26
|
const pathnames = new Set();
|
|
31
27
|
|
|
@@ -55,8 +51,6 @@ function get_pathnames_for_trailing_slash(pathname, route) {
|
|
|
55
51
|
// people could use to type their own components.
|
|
56
52
|
// The T generic is needed or else there's a "all declarations must have identical type parameters" error.
|
|
57
53
|
const template = `
|
|
58
|
-
${GENERATED_COMMENT}
|
|
59
|
-
|
|
60
54
|
declare module "svelte/elements" {
|
|
61
55
|
export interface HTMLAttributes<T> {
|
|
62
56
|
'data-sveltekit-keepfocus'?: true | false | '' | undefined | null;
|
|
@@ -76,16 +70,15 @@ declare module "svelte/elements" {
|
|
|
76
70
|
'data-sveltekit-replacestate'?: true | false | '' | undefined | null;
|
|
77
71
|
}
|
|
78
72
|
}
|
|
79
|
-
|
|
80
|
-
export {};
|
|
81
73
|
`;
|
|
82
74
|
|
|
83
75
|
/**
|
|
84
76
|
* Generate app types interface extension
|
|
85
77
|
* @param {import('types').ManifestData} manifest_data
|
|
86
78
|
* @param {import('types').ValidatedKitConfig} config
|
|
79
|
+
* @param {string} dir
|
|
87
80
|
*/
|
|
88
|
-
function generate_app_types(manifest_data, config) {
|
|
81
|
+
function generate_app_types(manifest_data, config, dir) {
|
|
89
82
|
/** @type {Map<string, string>} */
|
|
90
83
|
const matcher_types = new Map();
|
|
91
84
|
|
|
@@ -100,7 +93,7 @@ function generate_app_types(manifest_data, config) {
|
|
|
100
93
|
resolve_entry(config.files.params) ??
|
|
101
94
|
config.files.params.replace(/\.(js|ts)$/, '') + '.js';
|
|
102
95
|
|
|
103
|
-
return posixify(path.relative(
|
|
96
|
+
return posixify(path.relative(dir, params_file));
|
|
104
97
|
};
|
|
105
98
|
|
|
106
99
|
type = `import('@sveltejs/kit').MatcherParam<(typeof import('${path_to_params()}').params)[${JSON.stringify(matcher)}]>`;
|
|
@@ -201,7 +194,7 @@ function generate_app_types(manifest_data, config) {
|
|
|
201
194
|
|
|
202
195
|
for (const route of manifest_data.routes) {
|
|
203
196
|
const pathname = remove_group_segments(route.id);
|
|
204
|
-
let normalized_pathname = pathname;
|
|
197
|
+
let normalized_pathname = pathname.slice(1);
|
|
205
198
|
|
|
206
199
|
/** @type {(path: string) => string} */
|
|
207
200
|
let serialise = s;
|
|
@@ -215,7 +208,7 @@ function generate_app_types(manifest_data, config) {
|
|
|
215
208
|
|
|
216
209
|
dynamic_routes.push(route_type);
|
|
217
210
|
|
|
218
|
-
normalized_pathname = replace_required_params(replace_optional_params(pathname));
|
|
211
|
+
normalized_pathname = replace_required_params(replace_optional_params(pathname)).slice(1);
|
|
219
212
|
serialise = (p) => `\`${p}\` & {}`;
|
|
220
213
|
}
|
|
221
214
|
|
|
@@ -240,7 +233,7 @@ function generate_app_types(manifest_data, config) {
|
|
|
240
233
|
layouts.push(`${s(route.id)}: ${layout_type}`);
|
|
241
234
|
}
|
|
242
235
|
|
|
243
|
-
const assets = manifest_data.assets.map((asset) => s(
|
|
236
|
+
const assets = manifest_data.assets.map((asset) => s(asset.file));
|
|
244
237
|
|
|
245
238
|
return [
|
|
246
239
|
'declare module "$app/types" {',
|
|
@@ -248,22 +241,31 @@ function generate_app_types(manifest_data, config) {
|
|
|
248
241
|
`\t\tRouteId(): ${manifest_data.routes.map((r) => s(r.id)).join(' | ')};`,
|
|
249
242
|
`\t\tRouteParams(): {\n\t\t\t${dynamic_routes.join(';\n\t\t\t')}\n\t\t};`,
|
|
250
243
|
`\t\tLayoutParams(): {\n\t\t\t${layouts.join(';\n\t\t\t')}\n\t\t};`,
|
|
251
|
-
`\t\
|
|
252
|
-
'\t\tResolvedPathname(): `${"" | `/${string}
|
|
253
|
-
`\t\
|
|
244
|
+
`\t\tPath(): ${Array.from(pathnames).join(' | ')};`,
|
|
245
|
+
'\t\tResolvedPathname(): `${"/" | `/${string}/`}${ReturnType<AppTypes[\'Path\']>}`;',
|
|
246
|
+
`\t\tAssetPath(): ${assets.join(' | ') || 'never'};`,
|
|
254
247
|
'\t}',
|
|
255
248
|
'}'
|
|
256
249
|
].join('\n');
|
|
257
250
|
}
|
|
258
251
|
|
|
259
252
|
/**
|
|
260
|
-
* Writes
|
|
253
|
+
* Writes `node_modules/$app/types/index.d.ts`. This file contains
|
|
254
|
+
* declarations for `$app/types` and `svelte/elements`, and
|
|
255
|
+
* imports `env.ts` which declares `$app/env/(public|private)`
|
|
261
256
|
* @param {import('types').ValidatedKitConfig} config
|
|
262
257
|
* @param {import('types').ManifestData} manifest_data
|
|
258
|
+
* @param {string} root
|
|
263
259
|
*/
|
|
264
|
-
export function
|
|
265
|
-
const
|
|
266
|
-
|
|
260
|
+
export function write_app_types(config, manifest_data, root) {
|
|
261
|
+
const dir = path.join(root, 'node_modules/$app/types');
|
|
262
|
+
|
|
263
|
+
const content = [
|
|
264
|
+
GENERATED_COMMENT,
|
|
265
|
+
`import '@sveltejs/kit';\nimport './env';`,
|
|
266
|
+
generate_app_types(manifest_data, config, dir),
|
|
267
|
+
template.trim()
|
|
268
|
+
].join('\n\n');
|
|
267
269
|
|
|
268
|
-
write_if_changed(path.join(
|
|
270
|
+
write_if_changed(path.join(dir, 'index.d.ts'), content);
|
|
269
271
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { styleText } from 'node:util';
|
|
1
|
+
import { check_spelling, dedent, write_if_changed } from './utils.js';
|
|
3
2
|
import { relative_path, resolve_entry } from '../../utils/filesystem.js';
|
|
4
3
|
import { s } from '../../utils/misc.js';
|
|
5
|
-
import { dedent, write_if_changed } from './utils.js';
|
|
6
4
|
|
|
7
5
|
/**
|
|
8
6
|
* Writes the client manifest to disk. The manifest is used to power the router. It contains the
|
|
@@ -123,15 +121,9 @@ export function write_client_manifest(kit, manifest_data, output, metadata) {
|
|
|
123
121
|
const client_hooks_file = resolve_entry(kit.files.hooks.client);
|
|
124
122
|
const universal_hooks_file = resolve_entry(kit.files.hooks.universal);
|
|
125
123
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
styleText(
|
|
130
|
-
['bold', 'yellow'],
|
|
131
|
-
`Unexpected + prefix. Did you mean ${typo.split('/').at(-1)?.slice(1)}?` +
|
|
132
|
-
` at ${path.resolve(typo)}`
|
|
133
|
-
)
|
|
134
|
-
);
|
|
124
|
+
if (!client_hooks_file) {
|
|
125
|
+
check_spelling('src/hooks.client', 'src/+hooks.client', 'Unexpected + prefix');
|
|
126
|
+
check_spelling('src/hooks.client', 'src/hook.client', 'Missing s suffix');
|
|
135
127
|
}
|
|
136
128
|
|
|
137
129
|
// Stringified version of
|
|
@@ -10,16 +10,18 @@ const DOCS = '// See https://svelte.dev/docs/kit/environment-variables for more
|
|
|
10
10
|
* Writes ambient declarations including types reference to @sveltejs/kit,
|
|
11
11
|
* and the existing environment variables in process.env to
|
|
12
12
|
* $env/static/private and $env/static/public
|
|
13
|
-
* @param {import('types').ValidatedKitConfig} kit
|
|
14
13
|
* @param {string | null} entry
|
|
15
14
|
* @param {Record<string, EnvVarConfig<any>> | null} env_config
|
|
15
|
+
* @param {string} root
|
|
16
16
|
*/
|
|
17
|
-
export function write_env(
|
|
17
|
+
export function write_env(entry, env_config, root) {
|
|
18
18
|
const content = [];
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
const dir = path.join(root, 'node_modules/$app/types');
|
|
21
|
+
const out = path.join(dir, 'env.d.ts');
|
|
20
22
|
|
|
21
23
|
if (entry && env_config) {
|
|
22
|
-
const relative = posixify(path.relative(
|
|
24
|
+
const relative = posixify(path.relative(dir, entry));
|
|
23
25
|
content.push(
|
|
24
26
|
`// This file is generated from ${relative}.\n${DOCS}`,
|
|
25
27
|
create_explicit_env_types(env_config, relative, 'private'),
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import { styleText } from 'node:util';
|
|
3
2
|
import { hash } from '../../utils/hash.js';
|
|
4
3
|
import { resolve_entry } from '../../utils/filesystem.js';
|
|
5
4
|
import { posixify } from '../../utils/os.js';
|
|
6
5
|
import { s } from '../../utils/misc.js';
|
|
7
6
|
import { load_error_page, load_template } from '../config/index.js';
|
|
8
|
-
import { write_if_changed } from './utils.js';
|
|
7
|
+
import { check_spelling, write_if_changed } from './utils.js';
|
|
9
8
|
import { escape_html } from '../../utils/escape.js';
|
|
10
9
|
|
|
11
10
|
/**
|
|
@@ -26,7 +25,7 @@ const server_template = ({
|
|
|
26
25
|
}) => `
|
|
27
26
|
import { set_building, set_prerendering } from '$app/env/internal';
|
|
28
27
|
import { set_assets } from '$app/paths/internal/server';
|
|
29
|
-
import { set_manifest, set_read_implementation } from '__sveltekit/server';
|
|
28
|
+
import { set_fix_stack_trace, set_manifest, set_read_implementation } from '__sveltekit/server';
|
|
30
29
|
import error from '../shared/error-template.js';
|
|
31
30
|
|
|
32
31
|
export const options = {
|
|
@@ -54,6 +53,7 @@ export const options = {
|
|
|
54
53
|
)},
|
|
55
54
|
error
|
|
56
55
|
},
|
|
56
|
+
version: ${s(config.kit.version.name)},
|
|
57
57
|
version_hash: ${s(hash(config.kit.version.name))}
|
|
58
58
|
};
|
|
59
59
|
|
|
@@ -80,13 +80,9 @@ export async function get_hooks() {
|
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
export { set_assets, set_building, set_manifest, set_prerendering, set_read_implementation };
|
|
83
|
+
export { set_assets, set_building, set_fix_stack_trace, set_manifest, set_prerendering, set_read_implementation };
|
|
84
84
|
`;
|
|
85
85
|
|
|
86
|
-
// TODO need to re-run this whenever src/app.html or src/error.html are
|
|
87
|
-
// created or changed, or src/service-worker.js is created or deleted.
|
|
88
|
-
// Also, need to check that updating hooks.server.js works
|
|
89
|
-
|
|
90
86
|
/**
|
|
91
87
|
* Write server configuration to disk
|
|
92
88
|
* @param {import('types').ValidatedConfig} config
|
|
@@ -97,15 +93,14 @@ export function write_server(config, output, root) {
|
|
|
97
93
|
const server_hooks_file = resolve_entry(config.kit.files.hooks.server);
|
|
98
94
|
const universal_hooks_file = resolve_entry(config.kit.files.hooks.universal);
|
|
99
95
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
);
|
|
96
|
+
if (!server_hooks_file) {
|
|
97
|
+
check_spelling('src/hooks.server', 'src/+hooks.server', 'Unexpected + prefix');
|
|
98
|
+
check_spelling('src/hooks.server', 'src/hook.server', 'Missing s suffix');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (!universal_hooks_file) {
|
|
102
|
+
check_spelling('src/hooks', 'src/+hooks', 'Unexpected + prefix');
|
|
103
|
+
check_spelling('src/hooks', 'src/hook', 'Missing s suffix');
|
|
109
104
|
}
|
|
110
105
|
|
|
111
106
|
/** @param {string} file */
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/** @import { ValidatedKitConfig } from 'types' */
|
|
2
|
+
import process from 'node:process';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import ts from 'typescript';
|
|
6
|
+
import { styleText } from 'node:util';
|
|
7
|
+
import { write_if_changed } from '../utils.js';
|
|
8
|
+
import {
|
|
9
|
+
ESSENTIAL_OPTIONS,
|
|
10
|
+
extends_id,
|
|
11
|
+
get_subpath_imports,
|
|
12
|
+
normalize_config,
|
|
13
|
+
RECOMMENDED_OPTIONS,
|
|
14
|
+
remove_trailing_slashstar,
|
|
15
|
+
validate_resolved_config
|
|
16
|
+
} from './utils.js';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Generates the tsconfig that the user's tsconfig inherits from.
|
|
20
|
+
* @param {import('types').ValidatedKitConfig} kit
|
|
21
|
+
* @param {string} root
|
|
22
|
+
*/
|
|
23
|
+
export function write_tsconfig(kit, root) {
|
|
24
|
+
const paths = get_paths(kit, root);
|
|
25
|
+
|
|
26
|
+
write_parent_tsconfig(
|
|
27
|
+
root,
|
|
28
|
+
root,
|
|
29
|
+
'$app/tsconfig',
|
|
30
|
+
{
|
|
31
|
+
compilerOptions: {
|
|
32
|
+
paths,
|
|
33
|
+
rootDirs: ['.', `${kit.outDir}/types`],
|
|
34
|
+
types: ['$app/types'],
|
|
35
|
+
|
|
36
|
+
// This is required for svelte-package to work as expected
|
|
37
|
+
// Can be overwritten
|
|
38
|
+
lib: ['ESNext', 'DOM', 'DOM.Iterable'],
|
|
39
|
+
|
|
40
|
+
...ESSENTIAL_OPTIONS,
|
|
41
|
+
...RECOMMENDED_OPTIONS
|
|
42
|
+
},
|
|
43
|
+
exclude: [kit.files.serviceWorker]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
extends: '$app/tsconfig',
|
|
47
|
+
include: ['src']
|
|
48
|
+
},
|
|
49
|
+
kit.typescript.config
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
write_parent_tsconfig(
|
|
53
|
+
root,
|
|
54
|
+
kit.files.serviceWorker,
|
|
55
|
+
'$app/tsconfig/service-worker',
|
|
56
|
+
{
|
|
57
|
+
compilerOptions: {
|
|
58
|
+
paths,
|
|
59
|
+
types: ['$app/types'],
|
|
60
|
+
lib: ['ESNext', 'WebWorker'],
|
|
61
|
+
...ESSENTIAL_OPTIONS
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
extends: '$app/tsconfig/service-worker'
|
|
66
|
+
}
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Write a generated `tsconfig.json` inside `node_modules`, for the
|
|
72
|
+
* user config to extend
|
|
73
|
+
* @param {string} root The project root
|
|
74
|
+
* @param {string} dir The directory to resolve a user config from
|
|
75
|
+
* @param {string} id The id of the generated config
|
|
76
|
+
* @param {any} config The contents of the generated tsconfig, with paths relative to `root`
|
|
77
|
+
* @param {any} example What to print if the user config does _not_ extend the generated config
|
|
78
|
+
* @param {ValidatedKitConfig['typescript']['config']} [transform] TODO get rid of this
|
|
79
|
+
*/
|
|
80
|
+
function write_parent_tsconfig(root, dir, id, config, example, transform) {
|
|
81
|
+
const out_file = path.join(root, `node_modules/${id}/tsconfig.json`);
|
|
82
|
+
|
|
83
|
+
let normalized = normalize_config(out_file, config);
|
|
84
|
+
normalized = transform?.(normalized) ?? normalized;
|
|
85
|
+
|
|
86
|
+
write_if_changed(out_file, JSON.stringify(normalized, null, '\t'));
|
|
87
|
+
|
|
88
|
+
const user_config = load_user_tsconfig(dir);
|
|
89
|
+
|
|
90
|
+
if (user_config && modified_since_last_check(user_config.file)) {
|
|
91
|
+
// now that we've written the parent config, we can resolve the
|
|
92
|
+
// user config and validate that nothing important was overwritten
|
|
93
|
+
if (!extends_id(user_config.options, id)) {
|
|
94
|
+
console.warn(
|
|
95
|
+
styleText(
|
|
96
|
+
['bold', 'yellow'],
|
|
97
|
+
`${path.relative(process.cwd(), user_config.file)} should extend SvelteKit's built-in configuration:`
|
|
98
|
+
)
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
console.warn(JSON.stringify(example, null, ' '));
|
|
102
|
+
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const resolved = ts.parseJsonConfigFileContent(user_config.options, ts.sys, dir).options;
|
|
107
|
+
const warnings = validate_resolved_config(resolved, config.compilerOptions);
|
|
108
|
+
|
|
109
|
+
if (warnings.length > 0) {
|
|
110
|
+
console.warn(
|
|
111
|
+
styleText(
|
|
112
|
+
['bold', 'yellow'],
|
|
113
|
+
`Found issues while validating ${path.relative(process.cwd(), user_config.file)}`
|
|
114
|
+
)
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
for (const warning of warnings) {
|
|
118
|
+
console.warn(` - ${warning}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** @type {Map<string, number>} */
|
|
125
|
+
const mtimes = new Map();
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Returns true if the file was modified since we last got here,
|
|
129
|
+
* otherwise we can skip warnings
|
|
130
|
+
* @param {string} file
|
|
131
|
+
*/
|
|
132
|
+
function modified_since_last_check(file) {
|
|
133
|
+
const a = mtimes.get(file) ?? -1;
|
|
134
|
+
const b = fs.statSync(file).mtimeMs;
|
|
135
|
+
mtimes.set(file, b);
|
|
136
|
+
|
|
137
|
+
return b > a;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @param {string} cwd
|
|
142
|
+
* @param {string} file
|
|
143
|
+
*/
|
|
144
|
+
function maybe_file(cwd, file) {
|
|
145
|
+
const resolved = path.resolve(cwd, file);
|
|
146
|
+
if (fs.existsSync(resolved)) {
|
|
147
|
+
return resolved;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** @param {string} cwd */
|
|
152
|
+
function load_user_tsconfig(cwd) {
|
|
153
|
+
const file = maybe_file(cwd, 'tsconfig.json') || maybe_file(cwd, 'jsconfig.json');
|
|
154
|
+
if (!file) return;
|
|
155
|
+
|
|
156
|
+
const options = load_tsconfig(file);
|
|
157
|
+
|
|
158
|
+
return {
|
|
159
|
+
file,
|
|
160
|
+
kind: path.basename(file),
|
|
161
|
+
options
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* @param {string} file
|
|
167
|
+
*/
|
|
168
|
+
function load_tsconfig(file) {
|
|
169
|
+
const options = ts.readConfigFile(file, ts.sys.readFile);
|
|
170
|
+
|
|
171
|
+
if (options.error) {
|
|
172
|
+
let message = `Failed to parse TypeScript config`;
|
|
173
|
+
|
|
174
|
+
if (typeof options.error.messageText === 'string') {
|
|
175
|
+
message += `: ${options.error.messageText}`;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const error = new Error(message);
|
|
179
|
+
error.stack = '';
|
|
180
|
+
|
|
181
|
+
if (options.error.file && options.error.start !== undefined) {
|
|
182
|
+
const line_start = options.error.file.text.lastIndexOf('\n', options.error.start);
|
|
183
|
+
|
|
184
|
+
const line =
|
|
185
|
+
line_start === -1
|
|
186
|
+
? 0
|
|
187
|
+
: options.error.file.text.slice(0, options.error.start).split('\n').length;
|
|
188
|
+
const column = options.error.start - line_start;
|
|
189
|
+
|
|
190
|
+
error.stack = `${error.message}\n at ${path.relative(process.cwd(), file)}:${line}:${column}`;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return options.config;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** Matches anything (except the empty string/string with newline), and separates any trailing `/*` */
|
|
200
|
+
const alias_key = /^(.+?)(\/\*)?$/;
|
|
201
|
+
|
|
202
|
+
/** Matches anything (except the empty string/string with newline), and separates any trailing `/*` or file extension */
|
|
203
|
+
const alias_value = /^(.+?)((\/\*)|(\.\w+))?$/;
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Generates tsconfig path aliases from kit's aliases and the package.json `imports` field.
|
|
207
|
+
* Related to vite alias creation.
|
|
208
|
+
*
|
|
209
|
+
* @param {import('types').ValidatedKitConfig} config
|
|
210
|
+
* @param {string} root
|
|
211
|
+
* @returns {Record<string, string[]>}
|
|
212
|
+
*/
|
|
213
|
+
function get_paths(config, root) {
|
|
214
|
+
const alias = {
|
|
215
|
+
...config.alias,
|
|
216
|
+
...get_subpath_imports(root)
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
/** @type {Record<string, string[]>} */
|
|
220
|
+
const paths = {};
|
|
221
|
+
|
|
222
|
+
for (const [key, value] of Object.entries(alias)) {
|
|
223
|
+
const key_match = alias_key.exec(key);
|
|
224
|
+
if (!key_match) throw new Error(`Invalid alias key: ${key}`);
|
|
225
|
+
|
|
226
|
+
const value_match = alias_value.exec(value);
|
|
227
|
+
if (!value_match) throw new Error(`Invalid alias value: ${value}`);
|
|
228
|
+
|
|
229
|
+
const resolved = path.resolve(root, remove_trailing_slashstar(value));
|
|
230
|
+
const slashstar = key_match[2];
|
|
231
|
+
|
|
232
|
+
if (slashstar) {
|
|
233
|
+
paths[key] = [resolved + '/*'];
|
|
234
|
+
} else {
|
|
235
|
+
paths[key] = [resolved];
|
|
236
|
+
const fileending = value_match[4];
|
|
237
|
+
|
|
238
|
+
if (!fileending && !(key + '/*' in alias)) {
|
|
239
|
+
paths[key + '/*'] = [resolved + '/*'];
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return paths;
|
|
245
|
+
}
|