@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.
Files changed (88) hide show
  1. package/package.json +1 -1
  2. package/src/cli.js +8 -8
  3. package/src/constants.js +3 -1
  4. package/src/core/adapt/builder.js +3 -6
  5. package/src/core/config/index.js +6 -1
  6. package/src/core/config/options.js +54 -104
  7. package/src/core/env.js +25 -11
  8. package/src/core/postbuild/fallback.js +2 -1
  9. package/src/core/postbuild/prerender.js +75 -28
  10. package/src/core/postbuild/queue.js +2 -1
  11. package/src/core/sync/sync.js +11 -14
  12. package/src/core/sync/utils.js +21 -1
  13. package/src/core/sync/{write_non_ambient.js → write_app_types.js} +23 -21
  14. package/src/core/sync/write_client_manifest.js +4 -12
  15. package/src/core/sync/write_env.js +6 -4
  16. package/src/core/sync/write_server.js +12 -17
  17. package/src/core/sync/write_tsconfig/index.js +245 -0
  18. package/src/core/sync/write_tsconfig/utils.js +162 -0
  19. package/src/core/sync/write_types/index.js +80 -88
  20. package/src/core/utils.js +28 -3
  21. package/src/exports/env/index.js +68 -3
  22. package/src/exports/internal/env.js +6 -3
  23. package/src/exports/internal/server/index.js +3 -1
  24. package/src/exports/params.js +9 -4
  25. package/src/exports/public.d.ts +69 -71
  26. package/src/exports/vite/dev/index.js +112 -56
  27. package/src/exports/vite/index.js +483 -258
  28. package/src/exports/vite/module_ids.js +2 -2
  29. package/src/exports/vite/preview/index.js +3 -2
  30. package/src/exports/vite/utils.js +21 -10
  31. package/src/runner.js +13 -0
  32. package/src/runtime/app/forms.js +4 -0
  33. package/src/runtime/app/manifest/index.js +1 -0
  34. package/src/runtime/app/paths/client.js +30 -30
  35. package/src/runtime/app/paths/internal/client.js +26 -0
  36. package/src/runtime/app/paths/server.js +23 -10
  37. package/src/runtime/app/paths/types.d.ts +11 -19
  38. package/src/runtime/app/server/index.js +1 -1
  39. package/src/runtime/app/server/remote/command.js +12 -7
  40. package/src/runtime/app/server/remote/form.js +29 -26
  41. package/src/runtime/app/server/remote/prerender.js +9 -2
  42. package/src/runtime/app/server/remote/query.js +6 -5
  43. package/src/runtime/app/server/remote/shared.js +48 -30
  44. package/src/runtime/app/service-worker/index.js +24 -0
  45. package/src/runtime/app/state/index.js +1 -1
  46. package/src/runtime/client/client.js +46 -9
  47. package/src/runtime/client/ndjson.js +1 -1
  48. package/src/runtime/client/remote-functions/form.svelte.js +43 -51
  49. package/src/runtime/client/remote-functions/query/index.js +2 -2
  50. package/src/runtime/client/remote-functions/query-batch.svelte.js +2 -3
  51. package/src/runtime/client/remote-functions/query-live/iterator.js +5 -2
  52. package/src/runtime/client/remote-functions/shared.svelte.js +4 -1
  53. package/src/runtime/client/state.svelte.js +54 -21
  54. package/src/runtime/client/stream.js +3 -2
  55. package/src/runtime/form-utils.js +89 -54
  56. package/src/runtime/server/cookie.js +1 -1
  57. package/src/runtime/server/data/index.js +32 -29
  58. package/src/runtime/server/errors.js +135 -0
  59. package/src/runtime/server/fetch.js +1 -1
  60. package/src/runtime/server/index.js +20 -10
  61. package/src/runtime/server/internal.js +25 -0
  62. package/src/runtime/server/page/actions.js +4 -3
  63. package/src/runtime/server/page/data_serializer.js +10 -10
  64. package/src/runtime/server/page/index.js +3 -2
  65. package/src/runtime/server/page/load_data.js +1 -1
  66. package/src/runtime/server/page/render.js +22 -35
  67. package/src/runtime/server/page/respond_with_error.js +6 -5
  68. package/src/runtime/server/{remote.js → remote-functions.js} +67 -36
  69. package/src/runtime/server/respond.js +58 -20
  70. package/src/runtime/server/sourcemaps.js +183 -0
  71. package/src/runtime/server/utils.js +12 -157
  72. package/src/types/ambient-private.d.ts +10 -0
  73. package/src/types/ambient.d.ts +22 -27
  74. package/src/types/global-private.d.ts +12 -5
  75. package/src/types/internal.d.ts +19 -9
  76. package/src/types/private.d.ts +8 -0
  77. package/src/utils/escape.js +9 -25
  78. package/src/utils/features.js +1 -1
  79. package/src/utils/fork.js +7 -2
  80. package/src/utils/page_nodes.js +3 -5
  81. package/src/utils/url.js +12 -0
  82. package/src/version.js +1 -1
  83. package/types/index.d.ts +152 -120
  84. package/types/index.d.ts.map +6 -1
  85. package/src/core/sync/write_ambient.js +0 -18
  86. package/src/core/sync/write_tsconfig.js +0 -258
  87. package/src/runtime/shared-server.js +0 -7
  88. /package/src/core/sync/{write_tsconfig_test → write_tsconfig/test-app}/package.json +0 -0
@@ -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 { write_ambient } from './write_ambient.js';
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
- write_non_ambient(config.kit, manifest_data);
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
- write_non_ambient(config.kit, manifest_data);
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
- const cwd = process.cwd();
87
- init(config, cwd);
88
- const manifest_data = create_manifest_data({ config, cwd });
89
- write_all_types(config, manifest_data, cwd);
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(kit, entry, env_config);
100
+ write_env(entry, env_config, root);
104
101
 
105
102
  return env_config;
106
103
  }
@@ -1,6 +1,7 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { mkdirp } from '../../utils/filesystem.js';
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(config.outDir, params_file));
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('/' + asset.file));
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\tPathname(): ${Array.from(pathnames).join(' | ')};`,
252
- '\t\tResolvedPathname(): `${"" | `/${string}`}${ReturnType<AppTypes[\'Pathname\']>}`;',
253
- `\t\tAsset(): ${assets.concat('string & {}').join(' | ')};`,
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 non-ambient declarations to the output directory
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 write_non_ambient(config, manifest_data) {
265
- const app_types = generate_app_types(manifest_data, config);
266
- const content = [template, app_types].join('\n\n');
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(config.outDir, 'non-ambient.d.ts'), content);
270
+ write_if_changed(path.join(dir, 'index.d.ts'), content);
269
271
  }
@@ -1,8 +1,6 @@
1
- import path from 'node:path';
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
- const typo = resolve_entry('src/+hooks.client');
127
- if (typo) {
128
- console.log(
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(kit, entry, env_config) {
17
+ export function write_env(entry, env_config, root) {
18
18
  const content = [];
19
- const out = path.join(kit.outDir, 'env.d.ts');
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(kit.outDir, entry));
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
- const typo = resolve_entry('src/+hooks.server');
101
- if (typo) {
102
- console.log(
103
- styleText(
104
- ['bold', 'yellow'],
105
- `Unexpected + prefix. Did you mean ${typo.split('/').at(-1)?.slice(1)}?` +
106
- ` at ${path.resolve(typo)}`
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
+ }