@sveltejs/kit 3.0.0-next.2 → 3.0.0-next.21
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 +62 -36
- package/src/cli.js +15 -12
- package/src/constants.js +6 -1
- package/src/core/adapt/builder.js +66 -72
- package/src/core/adapt/index.js +17 -6
- package/src/core/config/index.js +134 -80
- package/src/core/config/options.js +295 -273
- package/src/core/config/types.d.ts +1 -1
- package/src/core/env.js +146 -16
- package/src/core/generate_manifest/index.js +18 -15
- package/src/core/postbuild/analyse.js +8 -20
- package/src/core/postbuild/crawl.js +22 -6
- package/src/core/postbuild/entities.js +8 -2
- package/src/core/postbuild/fallback.js +4 -2
- package/src/core/postbuild/prerender.js +222 -70
- package/src/core/postbuild/queue.js +2 -1
- package/src/core/sync/create_manifest_data/conflict.js +1 -1
- package/src/core/sync/create_manifest_data/index.js +82 -62
- package/src/core/sync/sync.js +40 -31
- package/src/core/sync/ts.js +1 -1
- package/src/core/sync/utils.js +22 -2
- package/src/core/sync/{write_non_ambient.js → write_app_types.js} +107 -58
- package/src/core/sync/write_client_manifest.js +14 -29
- package/src/core/sync/write_env.js +7 -5
- package/src/core/sync/write_server.js +37 -45
- package/src/core/sync/write_tsconfig/index.js +274 -0
- package/src/core/sync/write_tsconfig/test-app/package.json +7 -0
- package/src/core/sync/write_tsconfig/utils.js +77 -0
- package/src/core/sync/write_tsconfig/validate.js +128 -0
- package/src/core/sync/write_types/index.js +127 -123
- package/src/core/utils.js +30 -5
- package/src/exports/env/index.js +77 -0
- package/src/exports/env/public.d.ts +55 -0
- package/src/exports/hooks/index.js +3 -9
- package/src/exports/hooks/public.d.ts +195 -0
- package/src/exports/hooks/sequence.js +9 -6
- package/src/exports/index.js +52 -29
- package/src/exports/internal/client.js +5 -0
- package/src/exports/internal/env.js +8 -5
- package/src/exports/internal/index.js +1 -90
- package/src/exports/internal/{event.js → server/event.js} +2 -3
- package/src/exports/internal/server/index.js +37 -0
- package/src/exports/internal/server/telemetry.js +95 -0
- package/src/exports/internal/shared.js +90 -0
- package/src/exports/node/index.js +64 -22
- package/src/exports/params/index.js +70 -0
- package/src/exports/params/public.d.ts +63 -0
- package/src/exports/public.d.ts +50 -1733
- package/src/exports/remote/index.js +11 -0
- package/src/exports/remote/public.d.ts +519 -0
- package/src/exports/url.js +86 -0
- package/src/exports/vite/build/build_server.js +54 -65
- package/src/exports/vite/build/remote.js +24 -19
- package/src/exports/vite/build/utils.js +0 -8
- package/src/exports/vite/dev/index.js +218 -146
- package/src/exports/vite/index.js +1590 -858
- package/src/exports/vite/module_ids.js +2 -2
- package/src/exports/vite/preview/index.js +40 -32
- package/src/exports/vite/public.d.ts +588 -0
- package/src/exports/vite/utils.js +84 -46
- package/src/pathname.js +55 -0
- package/src/runner.js +15 -0
- package/src/runtime/app/env/internal.js +4 -4
- package/src/runtime/app/env/types.d.ts +1 -1
- package/src/runtime/app/environment/index.js +3 -3
- package/src/runtime/app/{forms.js → forms/index.js} +73 -42
- package/src/runtime/app/forms/public.d.ts +2 -0
- package/src/runtime/app/forms/types.d.ts +56 -0
- package/src/runtime/app/internal/transport.js +53 -0
- package/src/runtime/app/manifest/index.js +1 -0
- package/src/runtime/app/{navigation.js → navigation/index.js} +2 -1
- package/src/runtime/app/navigation/public.d.ts +237 -0
- package/src/runtime/app/paths/client.js +37 -37
- package/src/runtime/app/paths/index.js +1 -1
- package/src/runtime/app/paths/internal/client.js +34 -2
- package/src/runtime/app/paths/internal/server.js +6 -23
- package/src/runtime/app/paths/internal.d.ts +3 -0
- package/src/runtime/app/paths/public.d.ts +1 -29
- package/src/runtime/app/paths/server.js +36 -17
- package/src/runtime/app/paths/types.d.ts +11 -19
- package/src/runtime/app/server/index.js +2 -2
- package/src/runtime/app/server/public.d.ts +201 -0
- package/src/runtime/app/server/remote/command.js +13 -11
- package/src/runtime/app/server/remote/form.js +61 -39
- package/src/runtime/app/server/remote/prerender.js +45 -45
- package/src/runtime/app/server/remote/query.js +106 -108
- package/src/runtime/app/server/remote/requested.js +27 -19
- package/src/runtime/app/server/remote/shared.js +76 -76
- package/src/runtime/app/service-worker/index.js +24 -0
- package/src/runtime/app/state/client.js +4 -2
- package/src/runtime/app/state/index.js +7 -5
- package/src/runtime/app/state/public.d.ts +72 -0
- package/src/runtime/app/state/server.js +3 -0
- package/src/runtime/app/stores.js +15 -78
- package/src/runtime/client/bundle.js +1 -1
- package/src/runtime/client/client-entry.js +3 -0
- package/src/runtime/client/client.js +1336 -648
- package/src/runtime/client/constants.js +3 -6
- package/src/runtime/client/entry.js +24 -3
- package/src/runtime/client/fetcher.js +25 -25
- package/src/runtime/client/ndjson.js +1 -1
- package/src/runtime/client/parse.js +1 -1
- package/src/runtime/client/payload.js +17 -0
- package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
- package/src/runtime/client/remote-functions/command.svelte.js +37 -61
- package/src/runtime/client/remote-functions/form.svelte.js +267 -178
- package/src/runtime/client/remote-functions/prerender.svelte.js +32 -11
- package/src/runtime/client/remote-functions/query/index.js +10 -17
- package/src/runtime/client/remote-functions/query/instance.svelte.js +64 -18
- package/src/runtime/client/remote-functions/query/proxy.js +5 -5
- package/src/runtime/client/remote-functions/query-batch.svelte.js +61 -70
- package/src/runtime/client/remote-functions/query-live/index.js +1 -1
- package/src/runtime/client/remote-functions/query-live/instance.svelte.js +63 -21
- package/src/runtime/client/remote-functions/query-live/iterator.js +15 -12
- package/src/runtime/client/remote-functions/query-live/proxy.js +2 -12
- package/src/runtime/client/remote-functions/shared.svelte.js +90 -65
- package/src/runtime/client/snapshots.js +147 -0
- package/src/runtime/client/state.svelte.js +94 -55
- package/src/runtime/client/stream.js +3 -2
- package/src/runtime/client/types.d.ts +13 -9
- package/src/runtime/client/utils.js +22 -110
- package/src/runtime/components/root.svelte +56 -0
- package/src/runtime/env/dynamic/private.js +7 -0
- package/src/runtime/env/dynamic/public.js +7 -0
- package/src/runtime/env/static/private.js +6 -0
- package/src/runtime/env/static/public.js +6 -0
- package/src/runtime/form-utils.js +172 -61
- package/src/runtime/pathname.js +20 -32
- package/src/runtime/props.svelte.js +72 -0
- package/src/runtime/server/constants.js +0 -3
- package/src/runtime/server/cookie.js +72 -55
- package/src/runtime/server/csrf.js +65 -0
- package/src/runtime/server/data/index.js +49 -53
- package/src/runtime/server/dev.js +22 -0
- package/src/runtime/server/endpoint.js +6 -7
- package/src/runtime/server/env_module.js +0 -5
- package/src/runtime/server/errors.js +160 -0
- package/src/runtime/server/fetch.js +32 -39
- package/src/runtime/server/index.js +90 -64
- package/src/runtime/server/internal.js +71 -0
- package/src/runtime/server/page/actions.js +85 -64
- package/src/runtime/server/page/crypto.js +2 -2
- package/src/runtime/server/page/csp.js +88 -104
- package/src/runtime/server/page/data_serializer.js +24 -25
- package/src/runtime/server/page/index.js +36 -53
- package/src/runtime/server/page/load_data.js +50 -57
- package/src/runtime/server/page/render.js +173 -239
- package/src/runtime/server/page/respond_with_error.js +17 -31
- package/src/runtime/server/page/serialize_data.js +2 -13
- package/src/runtime/server/page/server_routing.js +85 -26
- package/src/runtime/server/remote-functions.js +640 -0
- package/src/runtime/server/respond.js +190 -131
- package/src/runtime/server/sourcemaps.js +183 -0
- package/src/runtime/server/state.js +53 -0
- package/src/runtime/server/utils.js +13 -155
- package/src/runtime/shared.js +20 -40
- package/src/runtime/utils.js +3 -0
- package/src/types/ambient-private.d.ts +11 -1
- package/src/types/ambient.d.ts +87 -36
- package/src/types/global-private.d.ts +25 -25
- package/src/types/internal.d.ts +163 -157
- package/src/types/private.d.ts +41 -1
- package/src/utils/error.js +28 -4
- package/src/utils/escape.js +9 -25
- package/src/utils/features.js +1 -1
- package/src/utils/filesystem.js +1 -23
- package/src/utils/fork.js +7 -2
- package/src/utils/hash.js +21 -0
- package/src/utils/http.js +8 -7
- package/src/utils/import.js +9 -2
- package/src/utils/imports.js +83 -0
- package/src/utils/mime.js +9 -0
- package/src/utils/page_nodes.js +6 -7
- package/src/utils/params.js +67 -0
- package/src/utils/regex.js +9 -0
- package/src/utils/routing.js +145 -73
- package/src/utils/shared-iterator.js +5 -0
- package/src/utils/streaming.js +14 -4
- package/src/utils/url.js +33 -2
- package/src/version.js +1 -1
- package/types/index.d.ts +2616 -2433
- package/types/index.d.ts.map +120 -106
- package/src/core/sync/write_ambient.js +0 -18
- package/src/core/sync/write_root.js +0 -148
- package/src/core/sync/write_tsconfig.js +0 -250
- package/src/exports/internal/server.js +0 -22
- package/src/exports/node/polyfills.js +0 -30
- package/src/runtime/server/app.js +0 -9
- package/src/runtime/server/remote.js +0 -457
- package/src/runtime/shared-server.js +0 -7
- package/src/runtime/telemetry/otel.js +0 -21
- package/src/runtime/telemetry/record_span.js +0 -65
- package/src/types/synthetic/$lib.md +0 -5
- /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
- /package/src/{runtime/telemetry/noop.js → telemetry.js} +0 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/** @import { ValidatedConfig } from 'types' */
|
|
2
|
+
import process from 'node:process';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { styleText } from 'node:util';
|
|
6
|
+
import { write_if_changed } from '../utils.js';
|
|
7
|
+
import {
|
|
8
|
+
ESSENTIAL_OPTIONS,
|
|
9
|
+
normalize_config,
|
|
10
|
+
RECOMMENDED_OPTIONS,
|
|
11
|
+
remove_trailing_slashstar
|
|
12
|
+
} from './utils.js';
|
|
13
|
+
import { extends_id, validate_resolved_config } from './validate.js';
|
|
14
|
+
|
|
15
|
+
/** @type {typeof import('typescript')} */
|
|
16
|
+
let ts;
|
|
17
|
+
try {
|
|
18
|
+
ts = await import('typescript');
|
|
19
|
+
} catch {
|
|
20
|
+
// The user has not installed TypeScript.
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Generates the tsconfig that the user's tsconfig inherits from.
|
|
25
|
+
* @param {ValidatedConfig} kit
|
|
26
|
+
* @param {string} root
|
|
27
|
+
*/
|
|
28
|
+
export function write_tsconfig(kit, root) {
|
|
29
|
+
const paths = get_paths(kit, root);
|
|
30
|
+
const types = ['$app/types'];
|
|
31
|
+
|
|
32
|
+
write_parent_tsconfig(
|
|
33
|
+
root,
|
|
34
|
+
'$app/tsconfig',
|
|
35
|
+
{
|
|
36
|
+
compilerOptions: {
|
|
37
|
+
paths,
|
|
38
|
+
rootDirs: ['.', `${kit.outDir}/types`],
|
|
39
|
+
types,
|
|
40
|
+
|
|
41
|
+
// This is required for svelte-package to work as expected
|
|
42
|
+
// Can be overwritten
|
|
43
|
+
lib: ['ESNext', 'DOM', 'DOM.Iterable'],
|
|
44
|
+
|
|
45
|
+
...ESSENTIAL_OPTIONS,
|
|
46
|
+
...RECOMMENDED_OPTIONS
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
kit.typescript.config
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
validate_config(root, {
|
|
53
|
+
paths,
|
|
54
|
+
types,
|
|
55
|
+
exclusions: [kit.files.serviceWorker],
|
|
56
|
+
example: {
|
|
57
|
+
extends: '$app/tsconfig'
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
write_parent_tsconfig(root, '$app/tsconfig/service-worker', {
|
|
62
|
+
compilerOptions: {
|
|
63
|
+
paths,
|
|
64
|
+
types,
|
|
65
|
+
lib: ['ESNext', 'WebWorker'],
|
|
66
|
+
...ESSENTIAL_OPTIONS,
|
|
67
|
+
...RECOMMENDED_OPTIONS
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
validate_config(kit.files.serviceWorker, {
|
|
72
|
+
paths,
|
|
73
|
+
types,
|
|
74
|
+
example: {
|
|
75
|
+
extends: '$app/tsconfig/service-worker'
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Write a generated `tsconfig.json` inside `node_modules`, for the
|
|
82
|
+
* user config to extend
|
|
83
|
+
* @param {string} root The project root
|
|
84
|
+
* @param {string} id The id of the generated config
|
|
85
|
+
* @param {any} config The contents of the generated tsconfig, with paths relative to `root`
|
|
86
|
+
* @param {ValidatedConfig['typescript']['config']} [transform] TODO get rid of this
|
|
87
|
+
*/
|
|
88
|
+
function write_parent_tsconfig(root, id, config, transform) {
|
|
89
|
+
// simplified tsconfig resolvers (e.g. Playwright's) only find `${id}.json`, not `${id}/tsconfig.json`
|
|
90
|
+
const out_file = path.join(root, `node_modules/${id}.json`);
|
|
91
|
+
|
|
92
|
+
let normalized = normalize_config(out_file, config);
|
|
93
|
+
normalized = transform?.(normalized) ?? normalized;
|
|
94
|
+
|
|
95
|
+
write_if_changed(out_file, JSON.stringify(normalized, null, '\t'));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* @param {string} dir The directory to resolve a user config from
|
|
100
|
+
* @param {Object} options
|
|
101
|
+
* @param {Record<string, string[]>} options.paths The expected paths
|
|
102
|
+
* @param {string[]} options.types The expected types
|
|
103
|
+
* @param {string[]} [options.exclusions] Files that should be excluded
|
|
104
|
+
* @param {any} options.example What to print if the user config does _not_ extend the generated config
|
|
105
|
+
*/
|
|
106
|
+
function validate_config(dir, options) {
|
|
107
|
+
if (!ts) {
|
|
108
|
+
// The user has not installed TypeScript. Skip validation of config.
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const user_config = load_user_tsconfig(dir);
|
|
113
|
+
if (!user_config || !modified_since_last_check(user_config.file)) return;
|
|
114
|
+
|
|
115
|
+
// now that we've written the parent config, we can resolve the
|
|
116
|
+
// user config and validate that nothing important was overwritten
|
|
117
|
+
if (!extends_id(user_config.options, options.example.extends)) {
|
|
118
|
+
console.warn(
|
|
119
|
+
styleText(
|
|
120
|
+
['bold', 'yellow'],
|
|
121
|
+
`${path.relative(process.cwd(), user_config.file)} should extend SvelteKit's built-in configuration:`
|
|
122
|
+
)
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
console.warn(JSON.stringify(options.example, null, ' '));
|
|
126
|
+
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const resolved = ts.parseJsonConfigFileContent(user_config.options, ts.sys, dir);
|
|
131
|
+
|
|
132
|
+
const warnings = validate_resolved_config(
|
|
133
|
+
dir,
|
|
134
|
+
resolved,
|
|
135
|
+
options.paths,
|
|
136
|
+
options.types,
|
|
137
|
+
options.exclusions
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
if (warnings.length > 0) {
|
|
141
|
+
console.warn(
|
|
142
|
+
styleText(
|
|
143
|
+
['bold', 'yellow'],
|
|
144
|
+
`Found issues while validating ${path.relative(process.cwd(), user_config.file)}`
|
|
145
|
+
)
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
for (const warning of warnings) {
|
|
149
|
+
console.warn(` - ${warning}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** @type {Map<string, number>} */
|
|
155
|
+
const mtimes = new Map();
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Returns true if the file was modified since we last got here,
|
|
159
|
+
* otherwise we can skip warnings
|
|
160
|
+
* @param {string} file
|
|
161
|
+
*/
|
|
162
|
+
function modified_since_last_check(file) {
|
|
163
|
+
const a = mtimes.get(file) ?? -1;
|
|
164
|
+
const b = fs.statSync(file).mtimeMs;
|
|
165
|
+
mtimes.set(file, b);
|
|
166
|
+
|
|
167
|
+
return b > a;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* @param {string} cwd
|
|
172
|
+
* @param {string} file
|
|
173
|
+
*/
|
|
174
|
+
function maybe_file(cwd, file) {
|
|
175
|
+
const resolved = path.resolve(cwd, file);
|
|
176
|
+
if (fs.existsSync(resolved)) {
|
|
177
|
+
return resolved;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** @param {string} cwd */
|
|
182
|
+
function load_user_tsconfig(cwd) {
|
|
183
|
+
const file = maybe_file(cwd, 'tsconfig.json') || maybe_file(cwd, 'jsconfig.json');
|
|
184
|
+
if (!file) return;
|
|
185
|
+
|
|
186
|
+
const options = load_tsconfig(file);
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
file,
|
|
190
|
+
kind: path.basename(file),
|
|
191
|
+
options
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* @param {string} file
|
|
197
|
+
*/
|
|
198
|
+
function load_tsconfig(file) {
|
|
199
|
+
const options = ts.readConfigFile(file, ts.sys.readFile);
|
|
200
|
+
|
|
201
|
+
if (options.error) {
|
|
202
|
+
let message = `Failed to parse TypeScript config`;
|
|
203
|
+
|
|
204
|
+
if (typeof options.error.messageText === 'string') {
|
|
205
|
+
message += `: ${options.error.messageText}`;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const error = new Error(message);
|
|
209
|
+
error.stack = '';
|
|
210
|
+
|
|
211
|
+
if (options.error.file && options.error.start !== undefined) {
|
|
212
|
+
const line_start = options.error.file.text.lastIndexOf('\n', options.error.start);
|
|
213
|
+
|
|
214
|
+
const line =
|
|
215
|
+
line_start === -1
|
|
216
|
+
? 0
|
|
217
|
+
: options.error.file.text.slice(0, options.error.start).split('\n').length;
|
|
218
|
+
const column = options.error.start - line_start;
|
|
219
|
+
|
|
220
|
+
error.stack = `${error.message}\n at ${path.relative(process.cwd(), file)}:${line}:${column}`;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
throw error;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return options.config;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** Matches anything (except the empty string/string with newline), and separates any trailing `/*` */
|
|
230
|
+
const alias_key = /^(.+?)(\/\*)?$/;
|
|
231
|
+
|
|
232
|
+
/** Matches anything (except the empty string/string with newline), and separates any trailing `/*` or file extension */
|
|
233
|
+
const alias_value = /^(.+?)((\/\*)|(\.\w+))?$/;
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Generates tsconfig path aliases from kit's aliases and the package.json `imports` field.
|
|
237
|
+
* Related to vite alias creation.
|
|
238
|
+
*
|
|
239
|
+
* @param {import('types').ValidatedConfig} config
|
|
240
|
+
* @param {string} root
|
|
241
|
+
* @returns {Record<string, string[]>}
|
|
242
|
+
*/
|
|
243
|
+
function get_paths(config, root) {
|
|
244
|
+
const alias = {
|
|
245
|
+
...config.alias
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
/** @type {Record<string, string[]>} */
|
|
249
|
+
const paths = {};
|
|
250
|
+
|
|
251
|
+
for (const [key, value] of Object.entries(alias)) {
|
|
252
|
+
const key_match = alias_key.exec(key);
|
|
253
|
+
if (!key_match) throw new Error(`Invalid alias key: ${key}`);
|
|
254
|
+
|
|
255
|
+
const value_match = alias_value.exec(value);
|
|
256
|
+
if (!value_match) throw new Error(`Invalid alias value: ${value}`);
|
|
257
|
+
|
|
258
|
+
const resolved = path.resolve(root, remove_trailing_slashstar(value));
|
|
259
|
+
const slashstar = key_match[2];
|
|
260
|
+
|
|
261
|
+
if (slashstar) {
|
|
262
|
+
paths[key] = [resolved + '/*'];
|
|
263
|
+
} else {
|
|
264
|
+
paths[key] = [resolved];
|
|
265
|
+
const fileending = value_match[4];
|
|
266
|
+
|
|
267
|
+
if (!fileending && !(key + '/*' in alias)) {
|
|
268
|
+
paths[key + '/*'] = [resolved + '/*'];
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return paths;
|
|
274
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { posixify } from '../../../utils/os.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Without these, compilation will fail
|
|
6
|
+
* @type {Record<string, any>}
|
|
7
|
+
*/
|
|
8
|
+
export const ESSENTIAL_OPTIONS = {
|
|
9
|
+
// svelte-preprocess cannot figure out whether you have a value or a type, so tell TypeScript
|
|
10
|
+
// to enforce using \`import type\` instead of \`import\` for Types.
|
|
11
|
+
// Also, TypeScript doesn't know about import usages in the template because it only sees the
|
|
12
|
+
// script of a Svelte file. Therefore preserve all value imports.
|
|
13
|
+
verbatimModuleSyntax: true,
|
|
14
|
+
// Vite compiles modules one at a time
|
|
15
|
+
isolatedModules: true
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Options that are strongly recommended, either because not having them is silly or
|
|
20
|
+
* because the align TypeScript's behaviour with Vite's, but which can be overwritten
|
|
21
|
+
* @type {Record<string, any>}
|
|
22
|
+
*/
|
|
23
|
+
export const RECOMMENDED_OPTIONS = {
|
|
24
|
+
allowJs: true,
|
|
25
|
+
checkJs: true,
|
|
26
|
+
forceConsistentCasingInFileNames: true,
|
|
27
|
+
resolveJsonModule: true,
|
|
28
|
+
moduleDetection: 'force',
|
|
29
|
+
moduleResolution: 'bundler',
|
|
30
|
+
allowImportingTsExtensions: true,
|
|
31
|
+
module: 'esnext',
|
|
32
|
+
target: 'esnext',
|
|
33
|
+
skipLibCheck: true,
|
|
34
|
+
esModuleInterop: true,
|
|
35
|
+
noEmit: true // prevent tsconfig error "overwriting input files" - Vite handles the build and ignores this
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Makes paths relative to the output file
|
|
40
|
+
* @param {string} out
|
|
41
|
+
* @param {any} config
|
|
42
|
+
* @param {(input: any) => any} [transform] TODO get rid of this option
|
|
43
|
+
*/
|
|
44
|
+
export function normalize_config(out, config, transform) {
|
|
45
|
+
const dir = path.dirname(out);
|
|
46
|
+
const relative = (/** @type {string} */ file) => posixify(path.relative(dir, file));
|
|
47
|
+
|
|
48
|
+
const paths =
|
|
49
|
+
config.compilerOptions?.paths &&
|
|
50
|
+
Object.fromEntries(
|
|
51
|
+
Object.entries(config.compilerOptions?.paths).map(([k, v]) => [k, v.map(relative)])
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
const normalized = {
|
|
55
|
+
...config,
|
|
56
|
+
compilerOptions: {
|
|
57
|
+
...config.compilerOptions,
|
|
58
|
+
paths,
|
|
59
|
+
rootDirs: config.compilerOptions?.rootDirs?.map(relative)
|
|
60
|
+
},
|
|
61
|
+
include: config.include?.map(relative),
|
|
62
|
+
exclude: config.exclude?.map(relative)
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
return transform?.(normalized) ?? normalized;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @param {string} file
|
|
70
|
+
*/
|
|
71
|
+
export function remove_trailing_slashstar(file) {
|
|
72
|
+
if (file.endsWith('/*')) {
|
|
73
|
+
return file.slice(0, -2);
|
|
74
|
+
} else {
|
|
75
|
+
return file;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/** @import ts from 'typescript' */
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { ESSENTIAL_OPTIONS, remove_trailing_slashstar } from './utils.js';
|
|
4
|
+
import { posixify } from '../../../utils/os.js';
|
|
5
|
+
|
|
6
|
+
const formatter = new Intl.ListFormat('en-gb', { type: 'conjunction' });
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {string[]} things
|
|
10
|
+
*/
|
|
11
|
+
function join(things) {
|
|
12
|
+
return formatter.format(things.map((thing) => JSON.stringify(thing)));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @param {string} dir
|
|
17
|
+
* @param {ts.ParsedCommandLine} resolved
|
|
18
|
+
* @param {Record<string, string[]>} paths
|
|
19
|
+
* @param {string[]} types
|
|
20
|
+
* @param {string[]} [exclusions]
|
|
21
|
+
*/
|
|
22
|
+
export function validate_resolved_config(dir, resolved, paths, types, exclusions) {
|
|
23
|
+
/** @type {string[]} */
|
|
24
|
+
const warnings = [];
|
|
25
|
+
|
|
26
|
+
if (resolved.options.types) {
|
|
27
|
+
validate_types(warnings, types, resolved.options.types);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (resolved.options.paths) {
|
|
31
|
+
validate_paths(
|
|
32
|
+
warnings,
|
|
33
|
+
/** @type {string} */ (resolved.options.pathsBasePath),
|
|
34
|
+
paths,
|
|
35
|
+
resolved.options.paths
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (exclusions) {
|
|
40
|
+
validate_exclusions(warnings, dir, exclusions, resolved.fileNames);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
for (const key in ESSENTIAL_OPTIONS) {
|
|
44
|
+
if (resolved.options[key] !== ESSENTIAL_OPTIONS[key]) {
|
|
45
|
+
warnings.push(
|
|
46
|
+
`"${key}" was overwritten. It should be ${JSON.stringify(ESSENTIAL_OPTIONS[key])}`
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return warnings;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @param {string[]} warnings
|
|
56
|
+
* @param {string[]} expected
|
|
57
|
+
* @param {string[]} actual
|
|
58
|
+
*/
|
|
59
|
+
export function validate_types(warnings, expected, actual) {
|
|
60
|
+
const missing_types = expected.filter((/** @type {string} */ type) => !actual.includes(type));
|
|
61
|
+
|
|
62
|
+
if (missing_types.length > 0) {
|
|
63
|
+
warnings.push(`"types" was overwritten. It must include ${join(missing_types)}`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return warnings;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @param {string[]} warnings
|
|
71
|
+
* @param {string} base
|
|
72
|
+
* @param {Record<string, string[]>} expected
|
|
73
|
+
* @param {ts.MapLike<string[]>} actual
|
|
74
|
+
*/
|
|
75
|
+
export function validate_paths(warnings, base, expected, actual) {
|
|
76
|
+
/** @type {Set<string>} */
|
|
77
|
+
const mismatch = new Set();
|
|
78
|
+
|
|
79
|
+
for (const [k, e] of Object.entries(expected)) {
|
|
80
|
+
const a = actual[k]?.map((/** @type {string} */ x) =>
|
|
81
|
+
path.resolve(/** @type {string} */ (base), x)
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
if (JSON.stringify(e) !== JSON.stringify(a)) {
|
|
85
|
+
mismatch.add(remove_trailing_slashstar(k));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (mismatch.size > 0) {
|
|
90
|
+
const joined = join([...mismatch]);
|
|
91
|
+
|
|
92
|
+
warnings.push(`"paths" was overwritten. Imports from ${joined} may not typecheck`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return warnings;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* @param {string[]} warnings
|
|
100
|
+
* @param {string} dir
|
|
101
|
+
* @param {string[]} exclusions
|
|
102
|
+
* @param {string[]} files
|
|
103
|
+
*/
|
|
104
|
+
export function validate_exclusions(warnings, dir, exclusions, files) {
|
|
105
|
+
const missing_exclusions = exclusions.map(posixify).filter((exclusion) => {
|
|
106
|
+
return files.some(
|
|
107
|
+
(f) => f === exclusion || f.startsWith(exclusion + '/') || f.startsWith(exclusion + '.')
|
|
108
|
+
);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
if (missing_exclusions.length > 0) {
|
|
112
|
+
warnings.push(
|
|
113
|
+
`${join(missing_exclusions.map((file) => posixify(path.relative(dir, file))))} should be added to the "exclude" array`
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return warnings;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Validates that a tsconfig contains `"extends": "<id>"`
|
|
122
|
+
* @param {any} options
|
|
123
|
+
* @param {string} id
|
|
124
|
+
*/
|
|
125
|
+
export function extends_id(options, id) {
|
|
126
|
+
const o = options.extends;
|
|
127
|
+
return Array.isArray(o) ? o.includes(id) : o === id;
|
|
128
|
+
}
|