@sveltejs/kit 3.0.0-next.22 → 3.0.0-next.24

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 (106) hide show
  1. package/package.json +40 -9
  2. package/src/cli.js +3 -3
  3. package/src/constants.js +13 -1
  4. package/src/core/adapt/builder.js +2 -3
  5. package/src/core/env.js +139 -181
  6. package/src/core/postbuild/analyse.js +9 -4
  7. package/src/core/postbuild/prerender.js +22 -23
  8. package/src/core/sync/create_manifest_data/index.js +29 -33
  9. package/src/core/sync/sync.js +23 -40
  10. package/src/core/sync/write_app_manifest.js +83 -0
  11. package/src/core/sync/write_client_manifest.js +6 -4
  12. package/src/core/sync/write_server.js +10 -6
  13. package/src/core/sync/write_types/index.js +2 -2
  14. package/src/core/utils.js +0 -28
  15. package/src/exports/hooks/public.d.ts +9 -1
  16. package/src/exports/index.js +10 -0
  17. package/src/exports/node/index.js +77 -5
  18. package/src/exports/public.d.ts +9 -0
  19. package/src/exports/vite/build/build_server.js +3 -3
  20. package/src/exports/vite/build/utils.js +48 -4
  21. package/src/exports/vite/dev/index.js +11 -22
  22. package/src/exports/vite/index.js +62 -345
  23. package/src/exports/vite/module_ids.js +1 -11
  24. package/src/exports/vite/plugins/env-vars.js +117 -0
  25. package/src/exports/vite/preview/index.js +6 -4
  26. package/src/exports/vite/utils.js +2 -4
  27. package/src/runtime/app/env/{types.d.ts → client.js} +9 -4
  28. package/src/runtime/app/env/index.js +1 -2
  29. package/src/runtime/app/env/private/index.js +1 -0
  30. package/src/runtime/app/env/public/client.js +1 -1
  31. package/src/runtime/app/env/public/server.js +1 -1
  32. package/src/runtime/app/env/{internal.js → server.js} +4 -4
  33. package/src/runtime/app/forms/client.js +263 -0
  34. package/src/runtime/app/forms/index.js +1 -263
  35. package/src/runtime/app/forms/public.d.ts +1 -1
  36. package/src/runtime/app/forms/server.js +6 -0
  37. package/src/runtime/app/forms/shared.js +34 -0
  38. package/src/runtime/app/manifest/index.js +1 -1
  39. package/src/runtime/app/navigation/client.js +15 -0
  40. package/src/runtime/app/navigation/index.js +1 -15
  41. package/src/runtime/app/navigation/public.d.ts +1 -1
  42. package/src/runtime/app/navigation/server.js +15 -0
  43. package/src/runtime/app/paths/server.js +1 -1
  44. package/src/runtime/app/server/public.d.ts +512 -0
  45. package/src/runtime/app/server/remote/command.js +1 -1
  46. package/src/runtime/app/server/remote/form.js +16 -6
  47. package/src/runtime/app/server/remote/prerender.js +2 -3
  48. package/src/runtime/app/server/remote/query.js +2 -2
  49. package/src/runtime/app/server/remote/requested.js +3 -3
  50. package/src/runtime/app/state/client.svelte.js +207 -0
  51. package/src/runtime/app/state/index.js +1 -66
  52. package/src/runtime/app/state/public.d.ts +1 -1
  53. package/src/runtime/client/bundle.js +1 -1
  54. package/src/runtime/client/client.js +206 -274
  55. package/src/runtime/client/fetcher.js +18 -8
  56. package/src/runtime/client/remote-functions/command.svelte.js +1 -1
  57. package/src/runtime/client/remote-functions/form.svelte.js +10 -7
  58. package/src/runtime/client/remote-functions/prerender.svelte.js +2 -2
  59. package/src/runtime/client/remote-functions/query/index.js +1 -1
  60. package/src/runtime/client/remote-functions/query/instance.svelte.js +2 -1
  61. package/src/runtime/client/remote-functions/query-batch.svelte.js +1 -1
  62. package/src/runtime/client/remote-functions/query-live/index.js +1 -1
  63. package/src/runtime/client/remote-functions/query-live/instance.svelte.js +4 -3
  64. package/src/runtime/client/remote-functions/query-live/iterator.js +1 -1
  65. package/src/runtime/client/remote-functions/shared.svelte.js +3 -3
  66. package/src/runtime/client/snapshots.js +1 -3
  67. package/src/runtime/client/stream.js +27 -20
  68. package/src/runtime/client/utils.js +7 -3
  69. package/src/runtime/components/root.svelte +5 -5
  70. package/src/runtime/env/dynamic/private.js +1 -1
  71. package/src/runtime/env/static/private.js +1 -1
  72. package/src/runtime/error-chain.js +54 -0
  73. package/src/runtime/form-utils.js +53 -77
  74. package/src/runtime/invalid-import.js +1 -0
  75. package/src/runtime/props.svelte.js +1 -1
  76. package/src/runtime/server/data/index.js +1 -1
  77. package/src/runtime/server/endpoint.js +8 -3
  78. package/src/runtime/server/env_module.js +1 -1
  79. package/src/runtime/server/errors.js +2 -2
  80. package/src/runtime/server/index.js +2 -2
  81. package/src/runtime/server/page/actions.js +77 -122
  82. package/src/runtime/server/page/index.js +37 -69
  83. package/src/runtime/server/page/render.js +18 -23
  84. package/src/runtime/server/remote-functions.js +15 -43
  85. package/src/runtime/server/respond.js +23 -3
  86. package/src/telemetry.js +1 -33
  87. package/src/types/ambient-private.d.ts +9 -17
  88. package/src/types/internal.d.ts +21 -5
  89. package/src/types/private.d.ts +1 -1
  90. package/src/utils/exports.js +1 -0
  91. package/src/utils/filesystem.js +9 -21
  92. package/src/utils/functions.js +10 -0
  93. package/src/utils/promise.js +25 -0
  94. package/src/utils/routing.js +0 -11
  95. package/src/utils/url.js +0 -11
  96. package/src/version.js +1 -1
  97. package/types/index.d.ts +1134 -1136
  98. package/types/index.d.ts.map +50 -50
  99. package/src/exports/remote/index.js +0 -11
  100. package/src/exports/remote/public.d.ts +0 -519
  101. package/src/runtime/app/env/private.js +0 -1
  102. package/src/runtime/app/env/standard-schema.d.ts +0 -0
  103. package/src/runtime/app/state/client.js +0 -63
  104. package/src/runtime/client/state.svelte.js +0 -98
  105. package/src/runtime/server/ambient.d.ts +0 -4
  106. package/src/utils/path.js +0 -23
@@ -1,10 +1,8 @@
1
1
  import process from 'node:process';
2
2
  import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
3
3
  import { dirname, join } from 'node:path';
4
- import { clearLine, moveCursor } from 'node:readline';
5
4
  import { pathToFileURL } from 'node:url';
6
5
  import { walk } from '../../utils/filesystem.js';
7
- import { posixify } from '../../utils/os.js';
8
6
  import { noop } from '../../utils/functions.js';
9
7
  import { decode_uri, is_root_relative, resolve } from '../../utils/url.js';
10
8
  import { escape_html } from '../../utils/escape.js';
@@ -64,7 +62,7 @@ async function prerender({
64
62
 
65
63
  // `set_env` and `Server` live in modules that import the user's `src/env` config. We import them
66
64
  // *after* `set_building()` so that `building`-dependent expressions resolve correctly
67
- /** @type {typeof import('__sveltekit/env')} */
65
+ /** @type {typeof import('<sveltekit:generated>/env/config.js')} */
68
66
  const { set_env } = await import(pathToFileURL(`${out}/server/env.js`).href);
69
67
  set_env(env);
70
68
 
@@ -257,13 +255,13 @@ async function prerender({
257
255
  return file;
258
256
  }
259
257
 
260
- const files = new Set(walk(`${out}/client`).map(posixify));
258
+ const files = new Set(walk(`${out}/client`));
261
259
  files.add(`${config.appDir}/env.js`);
262
260
 
263
261
  const immutable = `${config.appDir}/immutable`;
264
262
  if (existsSync(`${out}/server/${immutable}`)) {
265
263
  for (const file of walk(`${out}/server/${immutable}`)) {
266
- files.add(posixify(`${config.appDir}/immutable/${file}`));
264
+ files.add(`${config.appDir}/immutable/${file}`);
267
265
  }
268
266
  }
269
267
 
@@ -283,26 +281,31 @@ async function prerender({
283
281
  // currently requesting, then clearing the line once the response comes in.
284
282
  // This avoids the wall of text that happens when you prerender
285
283
  // many pages and log each response
284
+ const { stdout, stderr } = process;
285
+
286
286
  let current = false;
287
- let mid_line = false;
288
- const stdout_write = process.stdout.write;
289
- const stderr_write = process.stderr.write;
287
+ let needs_newline = true;
288
+
289
+ const write = stdout.write;
290
+
291
+ /** @param {string} value */
292
+ const print = (value) => write.call(stdout, value);
290
293
 
291
- /** @type {ProxyHandler<typeof stdout_write>} */
292
- const track_output = {
294
+ /** @type {ProxyHandler<typeof stdout.write>} */
295
+ const intercept = {
293
296
  apply(target, this_arg, args) {
294
297
  const chunk = args[0];
295
298
  if (chunk.length > 0) {
296
299
  current = false;
297
- mid_line =
300
+ needs_newline =
298
301
  typeof chunk === 'string' ? !chunk.endsWith('\n') : chunk[chunk.length - 1] !== 10;
299
302
  }
300
303
  return Reflect.apply(target, this_arg, args);
301
304
  }
302
305
  };
303
306
 
304
- process.stdout.write = new Proxy(stdout_write, track_output);
305
- process.stderr.write = new Proxy(stderr_write, track_output);
307
+ stdout.write = new Proxy(stdout.write, intercept);
308
+ stderr.write = new Proxy(stderr.write, intercept);
306
309
 
307
310
  progress = {
308
311
  clear: () => {
@@ -310,25 +313,21 @@ async function prerender({
310
313
  // the previous progress log, because that will corrupt things
311
314
  if (!current) return;
312
315
 
313
- moveCursor(process.stdout, 0, -1);
314
- clearLine(process.stdout, 0);
316
+ print('\x1B[1A'); // move cursor to start of progress update
317
+ print('\x1B[2K'); // clear current line
315
318
  },
316
319
 
317
320
  update: (path) => {
318
- if (mid_line) {
319
- // app output ended mid-line — start a fresh one rather than appending to it
320
- stdout_write.call(process.stdout, '\n');
321
- }
321
+ // if we're in the middle of a line, start a new one
322
+ if (needs_newline) print('\n');
322
323
 
323
- stdout_write.call(process.stdout, `crawling ${path}\n`);
324
+ print(`crawling ${path}\n`);
324
325
  current = true;
325
- mid_line = false;
326
+ needs_newline = false;
326
327
  },
327
328
 
328
329
  updated: 0
329
330
  };
330
-
331
- console.log('');
332
331
  }
333
332
 
334
333
  /** @type {Set<string>} */
@@ -1,11 +1,12 @@
1
+ /** @import { ValidatedConfig } from 'types' */
1
2
  import { lookup } from '../../../utils/mime.js';
2
3
  import fs from 'node:fs';
3
4
  import path from 'node:path';
4
5
  import { styleText } from 'node:util';
5
- import { resolve_entry } from '../../../utils/filesystem.js';
6
+ import { resolve_entry, walk } from '../../../utils/filesystem.js';
6
7
  import { posixify } from '../../../utils/os.js';
7
8
  import { parse_route_id } from '../../../utils/routing.js';
8
- import { list_files, runtime_directory } from '../../utils.js';
9
+ import { runtime_directory } from '../../utils.js';
9
10
  import { prevent_conflicts } from './conflict.js';
10
11
  import { sort_routes } from './sort.js';
11
12
  import {
@@ -13,24 +14,27 @@ import {
13
14
  get_page_options
14
15
  } from '../../../exports/vite/static_analysis/index.js';
15
16
 
17
+ const component_name_pattern = /^\+(?:(page(?:@(.*))?)|(layout(?:@(.*))?)|(error))$/;
18
+
19
+ const module_name_pattern =
20
+ /^\+(?:(server)|(page(?:(@[a-zA-Z0-9_-]*))?(\.server)?)|(layout(?:(@[a-zA-Z0-9_-]*))?(\.server)?))$/;
21
+
16
22
  /**
17
23
  * Generates the manifest data used for the client-side manifest and types generation.
18
- * @param {{
19
- * config: import('types').ValidatedConfig;
20
- * fallback?: string;
21
- * cwd: string;
22
- * }} opts
24
+ * @param {ValidatedConfig} config
25
+ * @param {string} root
26
+ * @param {string} [fallback] Where to look for fallback components
23
27
  * @returns {import('types').ManifestData}
24
28
  */
25
- export default function create_manifest_data({
29
+ export default function create_manifest_data(
26
30
  config,
27
- fallback = `${runtime_directory}/components`,
28
- cwd
29
- }) {
31
+ root,
32
+ fallback = `${runtime_directory}/components`
33
+ ) {
30
34
  const assets = create_assets(config);
31
- const hooks = create_hooks(config, cwd);
32
- const params = resolve_params(config, cwd);
33
- const { nodes, routes } = create_routes_and_nodes(cwd, config, fallback);
35
+ const hooks = create_hooks(config, root);
36
+ const params = resolve_params(config, root);
37
+ const { nodes, routes } = create_routes_and_nodes(root, config, fallback);
34
38
 
35
39
  return {
36
40
  assets,
@@ -74,7 +78,9 @@ export function is_app_route(route) {
74
78
  * @param {import('types').ValidatedConfig} config
75
79
  */
76
80
  export function create_assets(config) {
77
- return list_files(config.files.assets).map((file) => ({
81
+ if (!fs.existsSync(config.files.assets)) return [];
82
+
83
+ return [...walk(config.files.assets)].map((file) => ({
78
84
  file,
79
85
  size: fs.statSync(path.resolve(config.files.assets, file)).size,
80
86
  type: lookup(file) || null
@@ -232,13 +238,12 @@ function create_routes_and_nodes(cwd, config, fallback) {
232
238
 
233
239
  if (!file.name.startsWith('+')) {
234
240
  const name = file.name.slice(0, -ext.length);
241
+ const pattern = config.extensions.includes(ext)
242
+ ? component_name_pattern
243
+ : module_name_pattern;
244
+
235
245
  // check if it is a valid route filename but missing the + prefix
236
- const typo =
237
- /^(?:(page(?:@(.*))?)|(layout(?:@(.*))?)|(error))$/.test(name) ||
238
- /^(?:(server)|(page(?:(@[a-zA-Z0-9_-]*))?(\.server)?)|(layout(?:(@[a-zA-Z0-9_-]*))?(\.server)?))$/.test(
239
- name
240
- );
241
- if (typo) {
246
+ if (pattern.test(`+${name}`)) {
242
247
  console.log(
243
248
  styleText(
244
249
  ['bold', 'yellow'],
@@ -265,13 +270,7 @@ function create_routes_and_nodes(cwd, config, fallback) {
265
270
  const ext = valid_extensions.find((ext) => name.endsWith(ext));
266
271
  if (ext) name = name.slice(0, -ext.length);
267
272
 
268
- const valid =
269
- /^\+(?:(page(?:@(.*))?)|(layout(?:@(.*))?)|(error))$/.test(name) ||
270
- /^\+(?:(server)|(page(?:(@[a-zA-Z0-9_-]*))?(\.server)?)|(layout(?:(@[a-zA-Z0-9_-]*))?(\.server)?))$/.test(
271
- name
272
- );
273
-
274
- if (valid) continue;
273
+ if (component_name_pattern.test(name) || module_name_pattern.test(name)) continue;
275
274
  }
276
275
 
277
276
  const project_relative = posixify(path.relative(cwd, path.join(dir, file.name)));
@@ -535,8 +534,7 @@ function analyze(project_relative, file, component_extensions, module_extensions
535
534
  const component_extension = component_extensions.find((ext) => file.endsWith(ext));
536
535
  if (component_extension) {
537
536
  const name = file.slice(0, -component_extension.length);
538
- const pattern = /^\+(?:(page(?:@(.*))?)|(layout(?:@(.*))?)|(error))$/;
539
- const match = pattern.exec(name);
537
+ const match = component_name_pattern.exec(name);
540
538
  if (!match) {
541
539
  throw new Error(`Files prefixed with + are reserved (saw ${project_relative})`);
542
540
  }
@@ -553,9 +551,7 @@ function analyze(project_relative, file, component_extensions, module_extensions
553
551
  const module_extension = module_extensions.find((ext) => file.endsWith(ext));
554
552
  if (module_extension) {
555
553
  const name = file.slice(0, -module_extension.length);
556
- const pattern =
557
- /^\+(?:(server)|(page(?:(@[a-zA-Z0-9_-]*))?(\.server)?)|(layout(?:(@[a-zA-Z0-9_-]*))?(\.server)?))$/;
558
- const match = pattern.exec(name);
554
+ const match = module_name_pattern.exec(name);
559
555
  if (!match) {
560
556
  throw new Error(`Files prefixed with + are reserved (saw ${project_relative})`);
561
557
  } else if (match[3] || match[6]) {
@@ -1,3 +1,4 @@
1
+ /** @import { ValidatedConfig, ManifestData } from 'types' */
1
2
  import path from 'node:path';
2
3
  import create_manifest_data from './create_manifest_data/index.js';
3
4
  import { write_client_manifest } from './write_client_manifest.js';
@@ -11,39 +12,30 @@ import {
11
12
  } from '../../exports/vite/static_analysis/index.js';
12
13
  import { load_explicit_env } from '../env.js';
13
14
  import { write_env } from './write_env.js';
14
-
15
- /**
16
- * Initialize SvelteKit's generated files that only depend on the config and mode.
17
- * @param {import('types').ValidatedConfig} config
18
- * @param {string} root The project root directory
19
- */
20
- export function init(config, root) {
21
- write_tsconfig(config, root);
22
- }
15
+ import { write_app_manifest } from './write_app_manifest.js';
23
16
 
24
17
  /**
25
18
  * Update SvelteKit's generated files
26
- * @param {import('types').ValidatedConfig} config
19
+ * @param {ValidatedConfig} config
27
20
  * @param {string} root The project root directory
21
+ * @param {ManifestData} manifest_data
22
+ * @param {boolean} is_build
28
23
  */
29
- export function create(config, root) {
30
- const manifest_data = create_manifest_data({ config, cwd: root });
24
+ export function create(config, root, manifest_data, is_build) {
25
+ const output = path.join(config.outDir, `generated/${is_build ? 'build' : 'dev'}`);
31
26
 
32
- const output = path.join(config.outDir, 'generated');
33
-
34
- write_client_manifest(config, manifest_data, `${output}/client`);
27
+ write_app_manifest(output, manifest_data, is_build);
28
+ write_client_manifest(config, manifest_data, `${output}/client`, root);
35
29
  write_server(config, output, root);
36
30
  write_all_types(config, manifest_data, root);
37
31
  write_app_types(config, manifest_data, root);
38
-
39
- return { manifest_data };
40
32
  }
41
33
 
42
34
  /**
43
35
  * Update SvelteKit's generated files in response to a single file content update.
44
36
  * Do not call this when the file in question was created/deleted.
45
37
  *
46
- * @param {import('types').ValidatedConfig} config
38
+ * @param {ValidatedConfig} config
47
39
  * @param {import('types').ManifestData} manifest_data
48
40
  * @param {string} file
49
41
  * @param {string} root The project root directory
@@ -79,48 +71,39 @@ export function update(config, manifest_data, file, root) {
79
71
  }
80
72
 
81
73
  /**
82
- * Run sync.init and sync.create in series, returning the result from sync.create.
83
- * @param {import('types').ValidatedConfig} config
74
+ * Run write_tsconfig and sync.create in series during build
75
+ * @param {ValidatedConfig} config
84
76
  * @param {string} root The project root directory
77
+ * @param {ManifestData} manifest_data
85
78
  */
86
- export function all(config, root) {
87
- init(config, root);
88
- return create(config, root);
79
+ export function all(config, root, manifest_data) {
80
+ write_tsconfig(config, root);
81
+ create(config, root, manifest_data, true);
89
82
  }
90
83
 
91
84
  /**
92
85
  * Run sync.init and then generate all type files.
93
- * @param {import('types').ValidatedConfig} config
86
+ * @param {ValidatedConfig} config
94
87
  * @param {string} root
95
88
  */
96
89
  export function all_types(config, root) {
97
- init(config, root);
98
- const manifest_data = create_manifest_data({ config, cwd: root });
90
+ write_tsconfig(config, root);
91
+ const manifest_data = create_manifest_data(config, root);
99
92
  write_all_types(config, manifest_data, root);
100
93
  write_app_types(config, manifest_data, root);
101
94
  }
102
95
 
103
96
  /**
104
97
  * Generate modules and types for explicit env vars
105
- * @param {typeof import('vite')} vite
106
- * @param {import('types').ValidatedConfig} kit
98
+ * @param {ValidatedConfig} kit
107
99
  * @param {string | null} entry
108
100
  * @param {string} root The Vite root
109
101
  * @param {string} mode The Vite mode
110
102
  */
111
- export async function env(vite, kit, entry, root, mode) {
112
- const env_config = await load_explicit_env(vite, kit, entry, root, mode);
103
+ export async function env(kit, entry, root, mode) {
104
+ const env_config = await load_explicit_env(kit, entry, root, mode);
113
105
 
114
- write_env(entry, env_config, root);
106
+ write_env(entry, env_config.variables, root);
115
107
 
116
108
  return env_config;
117
109
  }
118
-
119
- /**
120
- * Regenerate __SERVER__/internal.js in response to src/{app.html,error.html,service-worker.js} changing
121
- * @param {import('types').ValidatedConfig} config
122
- * @param {string} root The project root directory
123
- */
124
- export function server(config, root) {
125
- write_server(config, path.join(config.outDir, 'generated'), root);
126
- }
@@ -0,0 +1,83 @@
1
+ /** @import { Asset, ManifestData, RouteData } from 'types' */
2
+
3
+ import { s } from '../../utils/misc.js';
4
+ import { is_app_route, is_endpoint_route, is_page_route } from './create_manifest_data/index.js';
5
+ import { dedent, write_if_changed } from './utils.js';
6
+
7
+ /**
8
+ * Creates the `$app/manifest` data module. During development, real values
9
+ * are emitted for `assets` and `routes` (the only data known at that point).
10
+ *
11
+ * During build, bare identifier placeholders (fake globals) are emitted.
12
+ * The bundler leaves these as unresolved global references in the output,
13
+ * which are then replaced with real values by scanning the output chunks
14
+ * after each build completes. This avoids the content-hash feedback loop:
15
+ * the manifest data lives in its own chunk with a fixed filename, so
16
+ * importers' hashes are stable regardless of the manifest content.
17
+ *
18
+ * @param {string} out
19
+ * @param {ManifestData | undefined} manifest_data
20
+ * @param {boolean} is_build
21
+ */
22
+ export function write_app_manifest(out, manifest_data, is_build) {
23
+ const code = is_build
24
+ ? // Bare identifiers (fake globals) — the bundler leaves these as
25
+ // unresolved global references in the output. They are replaced
26
+ // with real values by `replace_manifest_placeholder_variables`
27
+ // after each build completes.
28
+ dedent`
29
+ export const immutable = __SVELTEKIT_MANIFEST_IMMUTABLE__;
30
+ export const assets = __SVELTEKIT_MANIFEST_ASSETS__;
31
+ export const prerendered = __SVELTEKIT_MANIFEST_PRERENDERED__;
32
+ export const routes = __SVELTEKIT_MANIFEST_ROUTES__;
33
+ `
34
+ : // In dev, an empty manifest is written before dependency scanning starts.
35
+ // `configureServer` replaces it with the full manifest before modules are served.
36
+ dedent`
37
+ // empty during dev
38
+ export const immutable = [];
39
+ export const prerendered = [];
40
+
41
+ export const assets = [
42
+ ${stringify_assets(manifest_data?.assets)}
43
+ ];
44
+
45
+ export const routes = [
46
+ ${stringify_routes(manifest_data?.routes)}
47
+ ];
48
+ `;
49
+
50
+ write_if_changed(`${out}/app-manifest.js`, code);
51
+ }
52
+
53
+ /**
54
+ * @param {Asset[] | undefined} assets
55
+ * @returns {string}
56
+ */
57
+ function stringify_assets(assets) {
58
+ return assets?.map((asset) => s({ path: asset.file })).join(',\n') ?? '';
59
+ }
60
+
61
+ /**
62
+ * @param {RouteData[] | undefined} routes
63
+ * @returns {Array<{ id: string; page: boolean; endpoint: boolean }>}
64
+ */
65
+ export function get_manifest_routes(routes) {
66
+ return (
67
+ routes?.filter(is_app_route).map((route) => ({
68
+ id: route.id,
69
+ page: is_page_route(route),
70
+ endpoint: is_endpoint_route(route)
71
+ })) ?? []
72
+ );
73
+ }
74
+
75
+ /**
76
+ * @param {RouteData[] | undefined} routes
77
+ * @returns {string}
78
+ */
79
+ function stringify_routes(routes) {
80
+ return get_manifest_routes(routes)
81
+ .map((route) => s(route))
82
+ .join(',\n');
83
+ }
@@ -1,3 +1,4 @@
1
+ import path from 'node:path';
1
2
  import { check_spelling, dedent, write_if_changed } from './utils.js';
2
3
  import { relative_path, resolve_entry } from '../../utils/filesystem.js';
3
4
  import { s } from '../../utils/misc.js';
@@ -8,9 +9,10 @@ import { s } from '../../utils/misc.js';
8
9
  * @param {import('types').ValidatedConfig} kit
9
10
  * @param {import('types').ManifestData} manifest_data
10
11
  * @param {string} output
12
+ * @param {string} root The project root directory
11
13
  * @param {import('types').ServerMetadata['nodes']} [metadata] If this is omitted, we have to assume that all routes with a `+layout/page.server.js` file have a server load function
12
14
  */
13
- export function write_client_manifest(kit, manifest_data, output, metadata) {
15
+ export function write_client_manifest(kit, manifest_data, output, root, metadata) {
14
16
  const client_routing = kit.router.resolution === 'client';
15
17
 
16
18
  /**
@@ -22,7 +24,7 @@ export function write_client_manifest(kit, manifest_data, output, metadata) {
22
24
 
23
25
  if (node.universal) {
24
26
  declarations.push(
25
- `import * as universal from ${s(relative_path(`${output}/nodes`, node.universal))};`,
27
+ `import * as universal from ${s(relative_path(`${output}/nodes`, path.resolve(root, node.universal)))};`,
26
28
  'export { universal };'
27
29
  );
28
30
  }
@@ -30,7 +32,7 @@ export function write_client_manifest(kit, manifest_data, output, metadata) {
30
32
  if (node.component) {
31
33
  declarations.push(
32
34
  `export { default as component } from ${s(
33
- relative_path(`${output}/nodes`, node.component)
35
+ relative_path(`${output}/nodes`, path.resolve(root, node.component))
34
36
  )};`
35
37
  );
36
38
  }
@@ -180,7 +182,7 @@ export function write_client_manifest(kit, manifest_data, output, metadata) {
180
182
  const module =
181
183
  !manifest_data.params || !uses_matchers
182
184
  ? 'export const matchers = {};'
183
- : `import { params as matchers } from ${s(relative_path(output, manifest_data.params))};\n\nexport { matchers };`;
185
+ : `import { params as matchers } from ${s(relative_path(output, path.resolve(root, manifest_data.params)))};\n\nexport { matchers };`;
184
186
 
185
187
  write_if_changed(`${output}/matchers.js`, module);
186
188
  }
@@ -6,6 +6,7 @@ import { s } from '../../utils/misc.js';
6
6
  import { load_error_page, load_template } from '../config/index.js';
7
7
  import { check_spelling, write_if_changed } from './utils.js';
8
8
  import { escape_html } from '../../utils/escape.js';
9
+ import { runtime_directory } from '../utils.js';
9
10
 
10
11
  /**
11
12
  * @param {{
@@ -14,6 +15,7 @@ import { escape_html } from '../../utils/escape.js';
14
15
  * config: import('types').ValidatedConfig;
15
16
  * has_service_worker: boolean;
16
17
  * template: string;
18
+ * runtime_directory: string;
17
19
  * }} opts
18
20
  */
19
21
  const server_template = ({
@@ -21,12 +23,13 @@ const server_template = ({
21
23
  server_hooks,
22
24
  universal_hooks,
23
25
  has_service_worker,
24
- template
26
+ template,
27
+ runtime_directory
25
28
  }) => `
26
- import { set_building, set_prerendering } from '$app/env/internal';
29
+ import { set_building, set_prerendering } from '$app/env/server';
27
30
  import { set_assets } from '$app/paths/internal/server';
28
- import { set_fix_stack_trace, set_manifest, set_read_implementation, log_response } from '__sveltekit/server';
29
- import error from '../shared/error-template.js';
31
+ import { set_fix_stack_trace, set_manifest, set_read_implementation, log_response } from '${runtime_directory}/server/internal.js';
32
+ import error from './shared/error-template.js';
30
33
 
31
34
  export const options = {
32
35
  app_template_contains_nonce: ${template.includes('%sveltekit.nonce%')},
@@ -103,7 +106,7 @@ export function write_server(config, output, root) {
103
106
 
104
107
  /** @param {string} file */
105
108
  function relative(file) {
106
- return posixify(path.relative(`${output}/server`, file));
109
+ return posixify(path.relative(output, file));
107
110
  }
108
111
 
109
112
  write_if_changed(
@@ -116,9 +119,10 @@ export function write_server(config, output, root) {
116
119
  // Contains the stringified version of
117
120
  /** @type {import('types').SSROptions} */
118
121
  write_if_changed(
119
- `${output}/server/internal.js`,
122
+ `${output}/server.js`,
120
123
  server_template({
121
124
  config,
125
+ runtime_directory: relative(runtime_directory),
122
126
  server_hooks: server_hooks_file ? relative(server_hooks_file) : null,
123
127
  universal_hooks: universal_hooks_file ? relative(universal_hooks_file) : null,
124
128
  has_service_worker:
@@ -42,12 +42,12 @@ export function write_all_types(config, manifest_data, root) {
42
42
  posixify(path.relative(root, config.files.routes))
43
43
  );
44
44
  const expected_directories = new Set(
45
- manifest_data.routes.map((route) => path.join(routes_dir, route.id))
45
+ manifest_data.routes.map((route) => path.posix.join(routes_dir, route.id))
46
46
  );
47
47
 
48
48
  if (fs.existsSync(types_dir)) {
49
49
  for (const file of walk(types_dir)) {
50
- const dir = path.dirname(file);
50
+ const dir = path.posix.dirname(file);
51
51
  if (!expected_directories.has(dir)) {
52
52
  fs.rmSync(path.join(types_dir, file), { force: true, recursive: true });
53
53
  }
package/src/core/utils.js CHANGED
@@ -1,4 +1,3 @@
1
- import fs from 'node:fs';
2
1
  import path from 'node:path';
3
2
  import { fileURLToPath } from 'node:url';
4
3
  import { styleText } from 'node:util';
@@ -85,30 +84,3 @@ export function get_mime_lookup(manifest_data) {
85
84
 
86
85
  return mime;
87
86
  }
88
-
89
- /**
90
- * @param {string} dir
91
- * @param {(file: string) => boolean} [filter]
92
- */
93
- export function list_files(dir, filter) {
94
- /** @type {string[]} */
95
- const files = [];
96
-
97
- /** @param {string} current */
98
- function walk(current) {
99
- for (const file of fs.readdirSync(path.resolve(dir, current))) {
100
- const child = path.posix.join(current, file);
101
- if (fs.statSync(path.resolve(dir, child)).isDirectory()) {
102
- walk(child);
103
- } else {
104
- if (!filter || filter(child)) {
105
- files.push(child);
106
- }
107
- }
108
- }
109
- }
110
-
111
- if (fs.existsSync(dir)) walk('');
112
-
113
- return files;
114
- }
@@ -170,9 +170,17 @@ export interface ResolveOptions {
170
170
  * `<head>` tag; if `output.linkHeaderPreload` is enabled, dynamically rendered pages use the
171
171
  * [`Link` response header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Link) instead.
172
172
  * By default, `js` and `css` files will be preloaded.
173
+ *
174
+ * For `font` files, `input` also has a `filename` property, the source file's pathname relative
175
+ * to the project root, so that a filter can match on it instead of the hashed path. `js` and
176
+ * `css` files are bundled and have no single source file name.
173
177
  * @param input the type of the file and its path
174
178
  */
175
- preload?: (input: { type: 'font' | 'css' | 'js' | 'asset'; path: string }) => boolean;
179
+ preload?: (
180
+ input:
181
+ | { type: 'css' | 'js' | 'asset'; path: string }
182
+ | { type: 'font'; path: string; filename: string }
183
+ ) => boolean;
176
184
  }
177
185
 
178
186
  type AppErrorWithOptionalDefaults = Omit<App.Error, 'status' | 'message'> & {
@@ -270,6 +270,16 @@ export function invalid(...issues) {
270
270
  );
271
271
  }
272
272
 
273
+ /**
274
+ * Checks whether this is a validation error thrown by {@link invalid}.
275
+ * @param {unknown} e The object to check.
276
+ * @return {e is import('./public.js').ValidationError}
277
+ * @since 2.47.3
278
+ */
279
+ export function isValidationError(e) {
280
+ return e instanceof ValidationError;
281
+ }
282
+
273
283
  /**
274
284
  * Strips possible SvelteKit-internal suffixes and trailing slashes from the URL pathname.
275
285
  * Returns the normalized URL as well as a method for adding the potential suffix back