@sveltejs/kit 3.0.0-next.0 → 3.0.0-next.10

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 (127) hide show
  1. package/package.json +33 -21
  2. package/src/core/adapt/builder.js +29 -43
  3. package/src/core/adapt/index.js +1 -4
  4. package/src/core/config/index.js +132 -71
  5. package/src/core/config/options.js +294 -244
  6. package/src/core/config/types.d.ts +1 -1
  7. package/src/core/env.js +121 -5
  8. package/src/core/generate_manifest/index.js +12 -15
  9. package/src/core/postbuild/analyse.js +7 -19
  10. package/src/core/postbuild/crawl.js +22 -6
  11. package/src/core/postbuild/prerender.js +42 -23
  12. package/src/core/sync/create_manifest_data/index.js +53 -50
  13. package/src/core/sync/sync.js +0 -2
  14. package/src/core/sync/write_client_manifest.js +8 -15
  15. package/src/core/sync/write_env.js +2 -1
  16. package/src/core/sync/write_non_ambient.js +12 -9
  17. package/src/core/sync/write_server.js +13 -14
  18. package/src/core/sync/write_tsconfig.js +16 -8
  19. package/src/core/sync/write_tsconfig_test/package.json +7 -0
  20. package/src/core/sync/write_types/index.js +28 -24
  21. package/src/core/utils.js +2 -2
  22. package/src/exports/env/index.js +12 -0
  23. package/src/exports/hooks/index.js +3 -9
  24. package/src/exports/hooks/sequence.js +3 -2
  25. package/src/exports/index.js +35 -13
  26. package/src/exports/internal/client.js +5 -0
  27. package/src/exports/internal/env.js +2 -2
  28. package/src/exports/internal/index.js +1 -90
  29. package/src/exports/internal/{event.js → server/event.js} +1 -2
  30. package/src/exports/internal/server/index.js +33 -0
  31. package/src/exports/internal/shared.js +89 -0
  32. package/src/exports/node/index.js +62 -15
  33. package/src/exports/params.js +63 -0
  34. package/src/exports/public.d.ts +323 -170
  35. package/src/exports/url.js +86 -0
  36. package/src/exports/vite/build/build_server.js +53 -59
  37. package/src/exports/vite/build/remote.js +18 -11
  38. package/src/exports/vite/build/utils.js +0 -8
  39. package/src/exports/vite/dev/index.js +42 -44
  40. package/src/exports/vite/index.js +810 -593
  41. package/src/exports/vite/preview/index.js +29 -22
  42. package/src/exports/vite/static_analysis/index.js +2 -4
  43. package/src/exports/vite/static_analysis/types.d.ts +14 -0
  44. package/src/exports/vite/utils.js +21 -36
  45. package/src/runtime/app/env/internal.js +4 -4
  46. package/src/runtime/app/env/types.d.ts +1 -1
  47. package/src/runtime/app/environment/index.js +6 -0
  48. package/src/runtime/app/forms.js +24 -7
  49. package/src/runtime/app/paths/client.js +4 -10
  50. package/src/runtime/app/paths/internal/client.js +4 -2
  51. package/src/runtime/app/paths/internal/server.js +2 -23
  52. package/src/runtime/app/paths/public.d.ts +0 -28
  53. package/src/runtime/app/paths/server.js +9 -5
  54. package/src/runtime/app/server/remote/command.js +0 -3
  55. package/src/runtime/app/server/remote/form.js +27 -15
  56. package/src/runtime/app/server/remote/prerender.js +29 -36
  57. package/src/runtime/app/server/remote/query.js +101 -99
  58. package/src/runtime/app/server/remote/requested.js +22 -14
  59. package/src/runtime/app/server/remote/shared.js +30 -26
  60. package/src/runtime/app/state/client.js +1 -2
  61. package/src/runtime/app/stores.js +13 -76
  62. package/src/runtime/client/bundle.js +1 -1
  63. package/src/runtime/client/client-entry.js +3 -0
  64. package/src/runtime/client/client.js +411 -318
  65. package/src/runtime/client/entry.js +24 -3
  66. package/src/runtime/client/fetcher.js +3 -2
  67. package/src/runtime/client/ndjson.js +6 -33
  68. package/src/runtime/client/payload.js +17 -0
  69. package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
  70. package/src/runtime/client/remote-functions/command.svelte.js +7 -32
  71. package/src/runtime/client/remote-functions/form.svelte.js +183 -112
  72. package/src/runtime/client/remote-functions/prerender.svelte.js +29 -8
  73. package/src/runtime/client/remote-functions/query/index.js +7 -14
  74. package/src/runtime/client/remote-functions/query/instance.svelte.js +63 -18
  75. package/src/runtime/client/remote-functions/query/proxy.js +3 -3
  76. package/src/runtime/client/remote-functions/query-batch.svelte.js +60 -68
  77. package/src/runtime/client/remote-functions/query-live/instance.svelte.js +60 -18
  78. package/src/runtime/client/remote-functions/query-live/iterator.js +36 -55
  79. package/src/runtime/client/remote-functions/shared.svelte.js +88 -62
  80. package/src/runtime/client/sse.js +32 -0
  81. package/src/runtime/client/state.svelte.js +65 -49
  82. package/src/runtime/client/stream.js +38 -0
  83. package/src/runtime/client/types.d.ts +11 -7
  84. package/src/runtime/client/utils.js +0 -96
  85. package/src/runtime/components/root.svelte +66 -0
  86. package/src/runtime/env/dynamic/private.js +7 -0
  87. package/src/runtime/env/dynamic/public.js +7 -0
  88. package/src/runtime/env/static/private.js +6 -0
  89. package/src/runtime/env/static/public.js +6 -0
  90. package/src/runtime/form-utils.js +100 -22
  91. package/src/runtime/server/cookie.js +69 -52
  92. package/src/runtime/server/csrf.js +65 -0
  93. package/src/runtime/server/data/index.js +14 -18
  94. package/src/runtime/server/env_module.js +0 -5
  95. package/src/runtime/server/index.js +2 -2
  96. package/src/runtime/server/page/actions.js +41 -26
  97. package/src/runtime/server/page/index.js +9 -15
  98. package/src/runtime/server/page/load_data.js +1 -1
  99. package/src/runtime/server/page/render.js +112 -187
  100. package/src/runtime/server/page/respond_with_error.js +7 -8
  101. package/src/runtime/server/page/server_routing.js +27 -18
  102. package/src/runtime/server/remote.js +355 -216
  103. package/src/runtime/server/respond.js +97 -61
  104. package/src/runtime/server/utils.js +32 -9
  105. package/src/runtime/shared.js +83 -13
  106. package/src/runtime/telemetry/otel.js +1 -1
  107. package/src/runtime/types.d.ts +8 -0
  108. package/src/types/ambient.d.ts +10 -5
  109. package/src/types/global-private.d.ts +15 -22
  110. package/src/types/internal.d.ts +89 -74
  111. package/src/types/private.d.ts +33 -1
  112. package/src/utils/error.js +24 -4
  113. package/src/utils/import.js +6 -1
  114. package/src/utils/imports.js +83 -0
  115. package/src/utils/mime.js +9 -0
  116. package/src/utils/params.js +66 -0
  117. package/src/utils/routing.js +90 -44
  118. package/src/utils/shared-iterator.js +5 -0
  119. package/src/utils/streaming.js +14 -4
  120. package/src/utils/url.js +20 -2
  121. package/src/version.js +1 -1
  122. package/types/index.d.ts +467 -537
  123. package/types/index.d.ts.map +22 -39
  124. package/src/core/sync/write_root.js +0 -148
  125. package/src/exports/internal/server.js +0 -22
  126. package/src/types/synthetic/$lib.md +0 -5
  127. /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
@@ -1,4 +1,4 @@
1
- import { lookup } from 'mrmime';
1
+ import { lookup } from '../../../utils/mime.js';
2
2
  import fs from 'node:fs';
3
3
  import path from 'node:path';
4
4
  import { styleText } from 'node:util';
@@ -29,27 +29,20 @@ export default function create_manifest_data({
29
29
  }) {
30
30
  const assets = create_assets(config);
31
31
  const hooks = create_hooks(config, cwd);
32
- const matchers = create_matchers(config, cwd);
32
+ const params = resolve_params(config, cwd);
33
33
  const { nodes, routes } = create_routes_and_nodes(cwd, config, fallback);
34
34
 
35
- for (const route of routes) {
36
- for (const param of route.params) {
37
- if (param.matcher && !matchers[param.matcher]) {
38
- throw new Error(`No matcher found for parameter '${param.matcher}' in route ${route.id}`);
39
- }
40
- }
41
- }
42
-
43
35
  return {
44
36
  assets,
45
37
  hooks,
46
- matchers,
38
+ params,
47
39
  nodes,
48
40
  routes
49
41
  };
50
42
  }
51
43
 
52
44
  /**
45
+ * Returns a list of files in the `static` directory.
53
46
  * @param {import('types').ValidatedConfig} config
54
47
  */
55
48
  export function create_assets(config) {
@@ -80,38 +73,9 @@ function create_hooks(config, cwd) {
80
73
  * @param {import('types').ValidatedConfig} config
81
74
  * @param {string} cwd
82
75
  */
83
- function create_matchers(config, cwd) {
84
- const params_base = path.relative(cwd, config.kit.files.params);
85
-
86
- /** @type {Record<string, string>} */
87
- const matchers = {};
88
- if (fs.existsSync(config.kit.files.params)) {
89
- for (const file of fs.readdirSync(config.kit.files.params)) {
90
- const ext = path.extname(file);
91
- if (!config.kit.moduleExtensions.includes(ext)) continue;
92
- const type = file.slice(0, -ext.length);
93
-
94
- if (/^\w+$/.test(type)) {
95
- const matcher_file = path.join(params_base, file);
96
-
97
- // Disallow same matcher with different extensions
98
- if (matchers[type]) {
99
- throw new Error(`Duplicate matchers: ${matcher_file} and ${matchers[type]}`);
100
- } else {
101
- matchers[type] = matcher_file;
102
- }
103
- } else {
104
- // Allow for matcher test collocation
105
- if (type.endsWith('.test') || type.endsWith('.spec')) continue;
106
-
107
- throw new Error(
108
- `Matcher names can only have underscores and alphanumeric characters — "${file}" is invalid`
109
- );
110
- }
111
- }
112
- }
113
-
114
- return matchers;
76
+ function resolve_params(config, cwd) {
77
+ const params_file = resolve_entry(config.kit.files.params);
78
+ return params_file ? posixify(path.relative(cwd, params_file)) : null;
115
79
  }
116
80
 
117
81
  /**
@@ -130,6 +94,7 @@ function create_routes_and_nodes(cwd, config, fallback) {
130
94
  /** @type {import('types').PageNode[]} */
131
95
  const nodes = [];
132
96
 
97
+ // create route data by processing files in `src/routes`
133
98
  if (fs.existsSync(config.kit.files.routes)) {
134
99
  /**
135
100
  * @param {number} depth
@@ -177,7 +142,7 @@ function create_routes_and_nodes(cwd, config, fallback) {
177
142
  throw new Error(`Route ${id} should be renamed to ${id.replace(/#/g, '[x+23]')}`);
178
143
  }
179
144
 
180
- if (/\[\.\.\.\w+\]\/\[\[/.test(id)) {
145
+ if (/\[\.\.\.[\w-]+\]\/\[\[/.test(id)) {
181
146
  throw new Error(
182
147
  `Invalid route ${id} — an [[optional]] route segment cannot follow a [...rest] route segment`
183
148
  );
@@ -218,10 +183,17 @@ function create_routes_and_nodes(cwd, config, fallback) {
218
183
 
219
184
  // We can't use withFileTypes because of a NodeJs bug which returns wrong results
220
185
  // with isDirectory() in case of symlinks: https://github.com/nodejs/node/issues/30646
221
- const files = fs.readdirSync(dir).map((name) => ({
222
- is_dir: fs.statSync(path.join(dir, name)).isDirectory(),
223
- name
224
- }));
186
+ // We sort the entries because `readdirSync` order is not guaranteed and differs
187
+ // between runtimes (e.g. Node returns entries alphabetically, Bun in directory
188
+ // order). Node indices are assigned from this traversal order, so without sorting
189
+ // the SSR and client manifests can disagree, causing hydration mismatches.
190
+ const files = fs
191
+ .readdirSync(dir)
192
+ .sort()
193
+ .map((name) => ({
194
+ is_dir: fs.statSync(path.join(dir, name)).isDirectory(),
195
+ name
196
+ }));
225
197
 
226
198
  // process files first
227
199
  for (const file of files) {
@@ -365,7 +337,7 @@ function create_routes_and_nodes(cwd, config, fallback) {
365
337
  const root = routes[0];
366
338
  if (!root.leaf && !root.error && !root.layout && !root.endpoint) {
367
339
  throw new Error(
368
- 'No routes found. If you are using a custom src/routes directory, make sure it is specified in your Svelte config file'
340
+ 'No routes found. If you are using a custom src/routes directory, make sure it is specified in your SvelteKit Vite plugin options'
369
341
  );
370
342
  }
371
343
  }
@@ -388,6 +360,7 @@ function create_routes_and_nodes(cwd, config, fallback) {
388
360
 
389
361
  prevent_conflicts(routes);
390
362
 
363
+ // fallback root layout and root error components
391
364
  const root = routes[0];
392
365
 
393
366
  if (!root.layout?.component) {
@@ -396,10 +369,11 @@ function create_routes_and_nodes(cwd, config, fallback) {
396
369
  }
397
370
 
398
371
  if (!root.error?.component) {
399
- if (!root.error) root.error = { depth: 0 };
372
+ if (!root.error) root.error = { depth: 0, parent: root.layout };
400
373
  root.error.component = posixify(path.relative(cwd, `${fallback}/error.svelte`));
401
374
  }
402
375
 
376
+ // populate the page nodes list
403
377
  // we do layouts/errors first as they are more likely to be reused,
404
378
  // and smaller indexes take fewer bytes. also, this guarantees that
405
379
  // the default error/layout are 0/1
@@ -421,6 +395,7 @@ function create_routes_and_nodes(cwd, config, fallback) {
421
395
 
422
396
  const node_analyser = create_node_analyser(cwd);
423
397
 
398
+ // add the related layout, page, and error nodes for a route
424
399
  for (const route of routes) {
425
400
  if (!route.leaf) continue;
426
401
 
@@ -465,6 +440,22 @@ function create_routes_and_nodes(cwd, config, fallback) {
465
440
  }
466
441
  }
467
442
 
443
+ // add parents to error nodes so that we can compute which page options apply to them
444
+ for (const route of routes) {
445
+ if (!route.error) continue;
446
+
447
+ /** @type {import('types').RouteData | null} */
448
+ let current_route = route;
449
+ while (current_route) {
450
+ if (current_route.layout) {
451
+ route.error.parent = current_route.layout;
452
+ break;
453
+ }
454
+ current_route = current_route.parent;
455
+ }
456
+ }
457
+
458
+ // compute the final page options for each page node
468
459
  for (const node of nodes) {
469
460
  node.page_options = node_analyser.get_page_options(node);
470
461
  }
@@ -473,6 +464,17 @@ function create_routes_and_nodes(cwd, config, fallback) {
473
464
  if (route.endpoint) {
474
465
  route.endpoint.page_options = get_page_options(route.endpoint.file, cwd);
475
466
  }
467
+
468
+ if (route.page && route.endpoint) {
469
+ const page = nodes[route.page.leaf];
470
+ if (page.page_options?.prerender || route.endpoint.page_options?.prerender) {
471
+ const endpoint_file = route.endpoint.file.split('/').pop();
472
+
473
+ throw new Error(
474
+ `Cannot prerender a route (${route.id}) with both a \`+page.svelte\` and a \`${endpoint_file}\``
475
+ );
476
+ }
477
+ }
476
478
  }
477
479
 
478
480
  return {
@@ -482,6 +484,7 @@ function create_routes_and_nodes(cwd, config, fallback) {
482
484
  }
483
485
 
484
486
  /**
487
+ * Determine if and how the file is relevant to the routing system.
485
488
  * @param {string} project_relative
486
489
  * @param {string} file
487
490
  * @param {string[]} component_extensions
@@ -2,7 +2,6 @@ import path from 'node:path';
2
2
  import process from 'node:process';
3
3
  import create_manifest_data from './create_manifest_data/index.js';
4
4
  import { write_client_manifest } from './write_client_manifest.js';
5
- import { write_root } from './write_root.js';
6
5
  import { write_tsconfig } from './write_tsconfig.js';
7
6
  import { write_types, write_all_types } from './write_types/index.js';
8
7
  import { write_ambient } from './write_ambient.js';
@@ -37,7 +36,6 @@ export function create(config, root) {
37
36
 
38
37
  write_client_manifest(config.kit, manifest_data, `${output}/client`);
39
38
  write_server(config, output, root);
40
- write_root(manifest_data, config, output);
41
39
  write_all_types(config, manifest_data, root);
42
40
  write_non_ambient(config.kit, manifest_data);
43
41
 
@@ -176,26 +176,19 @@ export function write_client_manifest(kit, manifest_data, output, metadata) {
176
176
 
177
177
  export const decode = (type, value) => decoders[type](value);
178
178
 
179
- export { default as root } from '../root.js';
179
+ export const get_error_template = () => import('../shared/error-template.js').then(m => m.default);
180
180
  `
181
181
  );
182
182
 
183
183
  if (client_routing) {
184
- // write matchers to a separate module so that we don't
185
- // need to worry about name conflicts
186
- const imports = [];
187
- const matchers = [];
188
-
189
- for (const key in manifest_data.matchers) {
190
- const src = manifest_data.matchers[key];
191
-
192
- imports.push(`import { match as ${key} } from ${s(relative_path(output, src))};`);
193
- matchers.push(key);
194
- }
184
+ const uses_matchers = manifest_data.routes.some((route) =>
185
+ route.params.some((param) => param.matcher)
186
+ );
195
187
 
196
- const module = imports.length
197
- ? `${imports.join('\n')}\n\nexport const matchers = { ${matchers.join(', ')} };`
198
- : 'export const matchers = {};';
188
+ const module =
189
+ !manifest_data.params || !uses_matchers
190
+ ? 'export const matchers = {};'
191
+ : `import { params as matchers } from ${s(relative_path(output, manifest_data.params))};\n\nexport { matchers };`;
199
192
 
200
193
  write_if_changed(`${output}/matchers.js`, module);
201
194
  }
@@ -2,6 +2,7 @@
2
2
  import path from 'node:path';
3
3
  import { create_explicit_env_types } from '../env.js';
4
4
  import { write_if_changed } from './utils.js';
5
+ import { posixify } from '../../utils/os.js';
5
6
 
6
7
  const DOCS = '// See https://svelte.dev/docs/kit/environment-variables for more information';
7
8
 
@@ -18,7 +19,7 @@ export function write_env(kit, entry, env_config) {
18
19
  const out = path.join(kit.outDir, 'env.d.ts');
19
20
 
20
21
  if (entry && env_config) {
21
- const relative = path.relative(kit.outDir, entry);
22
+ const relative = posixify(path.relative(kit.outDir, entry));
22
23
  content.push(
23
24
  `// This file is generated from ${relative}.\n${DOCS}`,
24
25
  create_explicit_env_types(env_config, relative, 'private'),
@@ -1,5 +1,6 @@
1
1
  import path from 'node:path';
2
2
  import { GENERATED_COMMENT } from '../../constants.js';
3
+ import { resolve_entry } from '../../utils/filesystem.js';
3
4
  import { posixify } from '../../utils/os.js';
4
5
  import { write_if_changed } from './utils.js';
5
6
  import { s } from '../../utils/misc.js';
@@ -85,10 +86,6 @@ export {};
85
86
  * @param {import('types').ValidatedKitConfig} config
86
87
  */
87
88
  function generate_app_types(manifest_data, config) {
88
- /** @param {string} matcher */
89
- const path_to_matcher = (matcher) =>
90
- posixify(path.relative(config.outDir, path.join(config.files.params, matcher + '.js')));
91
-
92
89
  /** @type {Map<string, string>} */
93
90
  const matcher_types = new Map();
94
91
 
@@ -98,7 +95,15 @@ function generate_app_types(manifest_data, config) {
98
95
 
99
96
  let type = matcher_types.get(matcher);
100
97
  if (!type) {
101
- type = `MatcherParam<typeof import('${path_to_matcher(matcher)}').match>`;
98
+ const path_to_params = () => {
99
+ const params_file =
100
+ resolve_entry(config.files.params) ??
101
+ config.files.params.replace(/\.(js|ts)$/, '') + '.js';
102
+
103
+ return posixify(path.relative(config.outDir, params_file));
104
+ };
105
+
106
+ type = `import('@sveltejs/kit').MatcherParam<(typeof import('${path_to_params()}').params)[${JSON.stringify(matcher)}]>`;
102
107
  matcher_types.set(matcher, type);
103
108
  }
104
109
 
@@ -204,7 +209,7 @@ function generate_app_types(manifest_data, config) {
204
209
  if (route.params.length > 0) {
205
210
  const params = route.params.map((p) => {
206
211
  const type = get_matcher_type(p.matcher);
207
- return `${p.name}${p.optional ? '?:' : ':'} ${type}${p.optional ? ' | undefined' : ''}`;
212
+ return `${/^\w+$/.test(p.name) ? p.name : `'${p.name}'`}${p.optional ? '?:' : ':'} ${type}${p.optional ? ' | undefined' : ''}`;
208
213
  });
209
214
  const route_type = `${s(route.id)}: { ${params.join('; ')} }`;
210
215
 
@@ -225,7 +230,7 @@ function generate_app_types(manifest_data, config) {
225
230
  const params = Array.from(layout_params)
226
231
  .map(([name, { optional, matchers }]) => {
227
232
  const type = get_matchers_type(matchers);
228
- return `${name}${optional ? '?:' : ':'} ${type}${optional ? ' | undefined' : ''}`;
233
+ return `${/^\w+$/.test(name) ? name : `'${name}'`}${optional ? '?:' : ':'} ${type}${optional ? ' | undefined' : ''}`;
229
234
  })
230
235
  .join('; ');
231
236
 
@@ -239,8 +244,6 @@ function generate_app_types(manifest_data, config) {
239
244
 
240
245
  return [
241
246
  'declare module "$app/types" {',
242
- '\ttype MatcherParam<M> = M extends (param : string) => param is (infer U extends string) ? U : string;',
243
- '',
244
247
  '\texport interface AppTypes {',
245
248
  `\t\tRouteId(): ${manifest_data.routes.map((r) => s(r.id)).join(' | ')};`,
246
249
  `\t\tRouteParams(): {\n\t\t\t${dynamic_routes.join(';\n\t\t\t')}\n\t\t};`,
@@ -15,7 +15,6 @@ import { escape_html } from '../../utils/escape.js';
15
15
  * config: import('types').ValidatedConfig;
16
16
  * has_service_worker: boolean;
17
17
  * template: string;
18
- * error_page: string;
19
18
  * }} opts
20
19
  */
21
20
  const server_template = ({
@@ -23,18 +22,15 @@ const server_template = ({
23
22
  server_hooks,
24
23
  universal_hooks,
25
24
  has_service_worker,
26
- template,
27
- error_page
25
+ template
28
26
  }) => `
29
- import root from '../root.js';
30
27
  import { set_building, set_prerendering } from '$app/env/internal';
31
28
  import { set_assets } from '$app/paths/internal/server';
32
29
  import { set_manifest, set_read_implementation } from '__sveltekit/server';
33
- import { set_env } from '__sveltekit/env';
30
+ import error from '../shared/error-template.js';
34
31
 
35
32
  export const options = {
36
33
  app_template_contains_nonce: ${template.includes('%sveltekit.nonce%')},
37
- async: ${s(!!config.compilerOptions?.experimental?.async)},
38
34
  csp: ${s(config.kit.csp)},
39
35
  csrf_check_origin: ${s(!config.kit.csrf.trustedOrigins.includes('*'))},
40
36
  csrf_trusted_origins: ${s(config.kit.csrf.trustedOrigins)},
@@ -42,10 +38,9 @@ export const options = {
42
38
  hash_routing: ${s(config.kit.router.type === 'hash')},
43
39
  hooks: null, // added lazily, via \`get_hooks\`
44
40
  link_header_preload: ${s(config.kit.output.linkHeaderPreload)},
45
- root,
41
+ paths_origin: ${s(config.kit.paths.origin)},
46
42
  service_worker: ${has_service_worker},
47
43
  service_worker_options: ${config.kit.serviceWorker.register ? s(config.kit.serviceWorker.options) : 'null'},
48
- server_error_boundaries: ${s(!!config.kit.experimental.handleRenderingErrors)},
49
44
  templates: {
50
45
  app: ({ head, body, assets, nonce, env }) => ${s(template)
51
46
  .replace('%sveltekit.head%', '" + head + "')
@@ -57,9 +52,7 @@ export const options = {
57
52
  /%sveltekit\.env\.([^%]+)%/g,
58
53
  (_match, capture) => `" + (env[${s(capture)}] ?? "") + "`
59
54
  )},
60
- error: ({ status, message }) => ${s(error_page)
61
- .replace(/%sveltekit\.status%/g, '" + status + "')
62
- .replace(/%sveltekit\.error\.message%/g, '" + message + "')}
55
+ error
63
56
  },
64
57
  version_hash: ${s(hash(config.kit.version.name))}
65
58
  };
@@ -87,7 +80,7 @@ export async function get_hooks() {
87
80
  };
88
81
  }
89
82
 
90
- export { set_assets, set_building, set_env, set_manifest, set_prerendering, set_read_implementation };
83
+ export { set_assets, set_building, set_manifest, set_prerendering, set_read_implementation };
91
84
  `;
92
85
 
93
86
  // TODO need to re-run this whenever src/app.html or src/error.html are
@@ -120,6 +113,13 @@ export function write_server(config, output, root) {
120
113
  return posixify(path.relative(`${output}/server`, file));
121
114
  }
122
115
 
116
+ write_if_changed(
117
+ `${output}/shared/error-template.js`,
118
+ `export default ({ status, message }) => ${s(load_error_page(config))
119
+ .replace(/%sveltekit\.status%/g, '" + status + "')
120
+ .replace(/%sveltekit\.error\.message%/g, '" + message + "')};`
121
+ );
122
+
123
123
  // Contains the stringified version of
124
124
  /** @type {import('types').SSROptions} */
125
125
  write_if_changed(
@@ -130,8 +130,7 @@ export function write_server(config, output, root) {
130
130
  universal_hooks: universal_hooks_file ? relative(universal_hooks_file) : null,
131
131
  has_service_worker:
132
132
  config.kit.serviceWorker.register && !!resolve_entry(config.kit.files.serviceWorker),
133
- template: load_template(root, config),
134
- error_page: load_error_page(config)
133
+ template: load_template(root, config)
135
134
  })
136
135
  );
137
136
  }
@@ -2,6 +2,7 @@ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { styleText } from 'node:util';
4
4
  import { posixify } from '../../utils/os.js';
5
+ import { read_package_imports, normalize_import_value } from '../../utils/imports.js';
5
6
  import { write_if_changed } from './utils.js';
6
7
 
7
8
  /**
@@ -62,11 +63,10 @@ export function get_tsconfig(kit, cwd) {
62
63
  'env.d.ts',
63
64
  'non-ambient.d.ts',
64
65
  './types/**/$types.d.ts',
65
- config_relative('svelte.config.js'),
66
66
  config_relative('vite.config.js'),
67
67
  config_relative('vite.config.ts')
68
68
  ]);
69
- const src_includes = [kit.files.routes, kit.files.lib, kit.files.src].filter((dir) => {
69
+ const src_includes = [kit.files.routes, kit.files.src].filter((dir) => {
70
70
  const relative = path.relative(kit.files.src, dir);
71
71
  return !relative || relative.startsWith('..');
72
72
  });
@@ -125,8 +125,7 @@ export function get_tsconfig(kit, cwd) {
125
125
  moduleResolution: 'bundler',
126
126
  module: 'esnext',
127
127
  noEmit: true, // prevent tsconfig error "overwriting input files" - Vite handles the build and ignores this
128
- target: 'esnext',
129
- types: ['node']
128
+ target: 'esnext'
130
129
  },
131
130
  include: [...include],
132
131
  exclude
@@ -176,7 +175,7 @@ function validate_user_config(cwd, out, config) {
176
175
  styleText(
177
176
  ['bold', 'yellow'],
178
177
  `You have specified a baseUrl and/or paths in your ${config.kind} which interferes with SvelteKit's auto-generated tsconfig.json. ` +
179
- 'Remove it to avoid problems with intellisense. For path aliases, use `kit.alias` instead: https://svelte.dev/docs/kit/configuration#alias'
178
+ 'Remove it to avoid problems with intellisense. For path aliases, use `config.alias` instead: https://svelte.dev/docs/kit/configuration#alias'
180
179
  )
181
180
  );
182
181
  }
@@ -200,7 +199,7 @@ const alias_regex = /^(.+?)(\/\*)?$/;
200
199
  const value_regex = /^(.*?)((\/\*)|(\.\w+))?$/;
201
200
 
202
201
  /**
203
- * Generates tsconfig path aliases from kit's aliases.
202
+ * Generates tsconfig path aliases from kit's aliases and the package.json `imports` field.
204
203
  * Related to vite alias creation.
205
204
  *
206
205
  * @param {import('types').ValidatedKitConfig} config
@@ -217,8 +216,17 @@ function get_tsconfig_paths(config, cwd) {
217
216
  };
218
217
 
219
218
  const alias = { ...config.alias };
220
- if (fs.existsSync(project_relative(cwd, config.files.lib))) {
221
- alias['$lib'] = project_relative(cwd, config.files.lib);
219
+
220
+ // Add all `#`-prefixed imports from package.json as path aliases
221
+ const imports = read_package_imports(cwd);
222
+ if (imports) {
223
+ for (const [key, raw_value] of Object.entries(imports)) {
224
+ if (!key.startsWith('#')) continue;
225
+ const value = normalize_import_value(raw_value);
226
+ if (value) {
227
+ alias[key] = value;
228
+ }
229
+ }
222
230
  }
223
231
 
224
232
  /** @type {Record<string, string[]>} */
@@ -0,0 +1,7 @@
1
+ {
2
+ "private": true,
3
+ "imports": {
4
+ "#lib": "./src/lib",
5
+ "#lib/*": "./src/lib/*"
6
+ }
7
+ }
@@ -1,7 +1,7 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import MagicString from 'magic-string';
4
- import { rimraf, walk } from '../../../utils/filesystem.js';
4
+ import { rimraf, walk, resolve_entry } from '../../../utils/filesystem.js';
5
5
  import { compact } from '../../../utils/array.js';
6
6
  import { posixify } from '../../../utils/os.js';
7
7
  import { ts } from '../ts.js';
@@ -198,11 +198,6 @@ function update_types(config, routes, route, root, to_delete = new Set()) {
198
198
  // Makes sure a type is "repackaged" and therefore more readable
199
199
  declarations.push('type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;');
200
200
 
201
- // returns the predicate of a matcher's type guard - or string if there is no type guard
202
- declarations.push(
203
- 'type MatcherParam<M> = M extends (param : string) => param is (infer U extends string) ? U : string;'
204
- );
205
-
206
201
  declarations.push(
207
202
  'type RouteParams = ' + generate_params_type(route.params, outdir, config) + ';'
208
203
  );
@@ -236,7 +231,9 @@ function update_types(config, routes, route, root, to_delete = new Set()) {
236
231
  '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;',
237
232
 
238
233
  // Re-export `Snapshot` from @sveltejs/kit — in future we could use this to infer <T> from the return type of `snapshot.capture`
239
- 'export type Snapshot<T = any> = Kit.Snapshot<T>;'
234
+ 'export type Snapshot<T = any> = Kit.Snapshot<T>;',
235
+
236
+ 'export type ErrorProps = { error: App.Error };'
240
237
  );
241
238
  }
242
239
 
@@ -268,15 +265,8 @@ function update_types(config, routes, route, root, to_delete = new Set()) {
268
265
 
269
266
  if (route.leaf.server) {
270
267
  exports.push(
271
- 'export type Action<OutputData extends Record<string, any> | void = Record<string, any> | void> = Kit.Action<RouteParams, OutputData, RouteId>'
272
- );
273
- exports.push(
274
- 'export type Actions<OutputData extends Record<string, any> | void = Record<string, any> | void> = Kit.Actions<RouteParams, OutputData, RouteId>'
275
- );
276
- }
277
-
278
- if (route.leaf.server) {
279
- exports.push(
268
+ 'export type Action<OutputData extends Record<string, any> | void = Record<string, any> | void> = Kit.Action<RouteParams, OutputData, RouteId>',
269
+ 'export type Actions<OutputData extends Record<string, any> | void = Record<string, any> | void> = Kit.Actions<RouteParams, OutputData, RouteId>',
280
270
  'export type PageProps = { params: RouteParams; data: PageData; form: ActionData }'
281
271
  );
282
272
  } else {
@@ -604,16 +594,22 @@ function replace_ext_with_js(file_path) {
604
594
  * @param {import('types').ValidatedConfig} config
605
595
  */
606
596
  function generate_params_type(params, outdir, config) {
607
- /** @param {string} matcher */
608
- const path_to_matcher = (matcher) =>
609
- posixify(path.relative(outdir, path.join(config.kit.files.params, matcher + '.js')));
597
+ const path_to_params = () => {
598
+ const params_file =
599
+ resolve_entry(config.kit.files.params) ??
600
+ config.kit.files.params.replace(/\.(js|ts)$/, '') + '.js';
601
+
602
+ return posixify(path.relative(outdir, params_file));
603
+ };
604
+
605
+ const params_import = path_to_params();
610
606
 
611
607
  return `{ ${params
612
608
  .map(
613
609
  (param) =>
614
- `${param.name}${param.optional ? '?' : ''}: ${
610
+ `${/^\w+$/.test(param.name) ? param.name : `'${param.name}'`}${param.optional ? '?' : ''}: ${
615
611
  param.matcher
616
- ? `MatcherParam<typeof import('${path_to_matcher(param.matcher)}').match>`
612
+ ? `import('@sveltejs/kit').MatcherParam<(typeof import('${params_import}').params)[${JSON.stringify(param.matcher)}]>`
617
613
  : 'string'
618
614
  }${param.optional ? ' | undefined' : ''}`
619
615
  )
@@ -642,6 +638,16 @@ export function tweak_types(content, is_server) {
642
638
  const code = new MagicString(content);
643
639
 
644
640
  const exports = new Map();
641
+ /** @param {import('typescript').BindingName} name */
642
+ function add_export(name) {
643
+ if (ts.isIdentifier(name)) {
644
+ if (names.has(name.text)) exports.set(name.text, name.text);
645
+ } else {
646
+ for (const element of name.elements) {
647
+ if (ts.isBindingElement(element)) add_export(element.name);
648
+ }
649
+ }
650
+ }
645
651
 
646
652
  ast.forEachChild((node) => {
647
653
  if (
@@ -668,9 +674,7 @@ export function tweak_types(content, is_server) {
668
674
 
669
675
  if (ts.isVariableStatement(node)) {
670
676
  node.declarationList.declarations.forEach((declaration) => {
671
- if (ts.isIdentifier(declaration.name) && names.has(declaration.name.text)) {
672
- exports.set(declaration.name.text, declaration.name.text);
673
- }
677
+ add_export(declaration.name);
674
678
  });
675
679
  }
676
680
  }
package/src/core/utils.js CHANGED
@@ -7,7 +7,7 @@ import { noop } from '../utils/functions.js';
7
7
  import { posixify } from '../utils/os.js';
8
8
 
9
9
  /**
10
- * Resolved path of the `runtime` directory
10
+ * Resolved path of the `runtime` directory posix-ified
11
11
  *
12
12
  * TODO Windows issue:
13
13
  * Vite or sth else somehow sets the driver letter inconsistently to lower or upper case depending on the run environment.
@@ -25,7 +25,7 @@ export const runtime_directory = posixify(fileURLToPath(new URL('../runtime', im
25
25
  */
26
26
  export function get_runtime_base(root) {
27
27
  return runtime_directory.startsWith(root)
28
- ? `/${path.relative(root, runtime_directory)}`
28
+ ? `/${posixify(path.relative(root, runtime_directory))}`
29
29
  : to_fs(runtime_directory);
30
30
  }
31
31
 
@@ -0,0 +1,12 @@
1
+ /** @import { EnvVarConfig } from '@sveltejs/kit' */
2
+
3
+ /**
4
+ * Utility for defining [environment variables](https://svelte.dev/docs/kit/environment-variables),
5
+ * which are made available via `$app/env/public` and `$app/env/private`.
6
+ * @template {Record<string, EnvVarConfig<any>>} T
7
+ * @param {T} variables
8
+ * @returns {T}
9
+ */
10
+ export function defineEnvVars(variables) {
11
+ return variables;
12
+ }
@@ -1,14 +1,8 @@
1
- /** @import { EnvVarConfig } from '@sveltejs/kit' */
2
-
3
1
  export { sequence } from './sequence.js';
4
2
 
5
3
  /**
6
- * Utility for defining [environment variables](https://svelte.dev/docs/kit/environment-variables),
7
- * which are made available via `$app/env/public` and `$app/env/private`.
8
- * @template {Record<string, EnvVarConfig<any>>} T
9
- * @param {T} variables
10
- * @returns {T}
4
+ * @internal
11
5
  */
12
- export function defineEnvVars(variables) {
13
- return variables;
6
+ export function defineEnvVars() {
7
+ throw new Error(`\`defineEnvVars\` has moved — import it from \`@sveltejs/kit/env\` instead`);
14
8
  }
@@ -1,5 +1,4 @@
1
1
  /** @import { Handle, RequestEvent, ResolveOptions } from '@sveltejs/kit' */
2
- /** @import { MaybePromise } from 'types' */
3
2
  import {
4
3
  merge_tracing,
5
4
  get_request_store,
@@ -74,6 +73,8 @@ import {
74
73
  * first post-processing
75
74
  * ```
76
75
  *
76
+ * Calling `resolve` invokes the next handler in the sequence (or SvelteKit itself, if it is the last one). To pass data between handlers, use `event.locals`.
77
+ *
77
78
  * @param {...Handle} handlers The chain of `handle` functions
78
79
  * @returns {Handle}
79
80
  */
@@ -89,7 +90,7 @@ export function sequence(...handlers) {
89
90
  * @param {number} i
90
91
  * @param {RequestEvent} event
91
92
  * @param {ResolveOptions | undefined} parent_options
92
- * @returns {MaybePromise<Response>}
93
+ * @returns {Promise<Response>}
93
94
  */
94
95
  function apply_handle(i, event, parent_options) {
95
96
  const handle = handlers[i];