@sveltejs/kit 3.0.0-next.13 → 3.0.0-next.16

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 (86) hide show
  1. package/package.json +7 -4
  2. package/src/cli.js +8 -5
  3. package/src/core/adapt/builder.js +20 -10
  4. package/src/core/config/index.js +4 -5
  5. package/src/core/env.js +3 -3
  6. package/src/core/generate_manifest/index.js +6 -0
  7. package/src/core/postbuild/entities.js +8 -2
  8. package/src/core/postbuild/fallback.js +2 -1
  9. package/src/core/postbuild/prerender.js +18 -13
  10. package/src/core/sync/create_manifest_data/conflict.js +1 -1
  11. package/src/core/sync/create_manifest_data/index.js +33 -2
  12. package/src/core/sync/sync.js +3 -2
  13. package/src/core/sync/utils.js +2 -2
  14. package/src/core/sync/write_app_types.js +72 -27
  15. package/src/core/sync/write_tsconfig/index.js +73 -54
  16. package/src/core/sync/write_tsconfig/utils.js +0 -61
  17. package/src/core/sync/write_tsconfig/validate.js +128 -0
  18. package/src/core/sync/write_types/index.js +7 -4
  19. package/src/exports/node/index.js +2 -7
  20. package/src/exports/public.d.ts +25 -18
  21. package/src/exports/vite/build/build_server.js +2 -3
  22. package/src/exports/vite/dev/index.js +44 -36
  23. package/src/exports/vite/index.js +91 -16
  24. package/src/exports/vite/utils.js +62 -15
  25. package/src/runner.js +4 -2
  26. package/src/runtime/app/forms.js +4 -7
  27. package/src/runtime/app/internal/transport.js +53 -0
  28. package/src/runtime/app/paths/client.js +2 -2
  29. package/src/runtime/app/paths/internal/client.js +2 -2
  30. package/src/runtime/app/server/remote/prerender.js +6 -10
  31. package/src/runtime/app/server/remote/query.js +3 -9
  32. package/src/runtime/app/server/remote/requested.js +2 -2
  33. package/src/runtime/app/server/remote/shared.js +1 -16
  34. package/src/runtime/client/client.js +177 -63
  35. package/src/runtime/client/fetcher.js +2 -13
  36. package/src/runtime/client/parse.js +1 -1
  37. package/src/runtime/client/remote-functions/command.svelte.js +1 -2
  38. package/src/runtime/client/remote-functions/form.svelte.js +3 -7
  39. package/src/runtime/client/remote-functions/prerender.svelte.js +2 -2
  40. package/src/runtime/client/remote-functions/query/index.js +1 -1
  41. package/src/runtime/client/remote-functions/query/proxy.js +2 -2
  42. package/src/runtime/client/remote-functions/query-batch.svelte.js +1 -1
  43. package/src/runtime/client/remote-functions/query-live/proxy.js +2 -12
  44. package/src/runtime/client/remote-functions/shared.svelte.js +1 -1
  45. package/src/runtime/client/utils.js +1 -0
  46. package/src/runtime/form-utils.js +4 -6
  47. package/src/runtime/pathname.js +44 -1
  48. package/src/runtime/server/data/index.js +5 -8
  49. package/src/runtime/server/dev.js +22 -0
  50. package/src/runtime/server/endpoint.js +3 -4
  51. package/src/runtime/server/fetch.js +25 -30
  52. package/src/runtime/server/index.js +64 -46
  53. package/src/runtime/server/internal.js +12 -5
  54. package/src/runtime/server/page/actions.js +18 -43
  55. package/src/runtime/server/page/crypto.js +2 -2
  56. package/src/runtime/server/page/csp.js +2 -1
  57. package/src/runtime/server/page/data_serializer.js +12 -13
  58. package/src/runtime/server/page/index.js +16 -32
  59. package/src/runtime/server/page/load_data.js +28 -44
  60. package/src/runtime/server/page/render.js +28 -12
  61. package/src/runtime/server/page/respond_with_error.js +8 -20
  62. package/src/runtime/server/page/serialize_data.js +2 -13
  63. package/src/runtime/server/page/server_routing.js +58 -9
  64. package/src/runtime/server/remote-functions.js +11 -15
  65. package/src/runtime/server/respond.js +44 -56
  66. package/src/runtime/server/state.js +60 -0
  67. package/src/runtime/server/utils.js +0 -20
  68. package/src/runtime/shared.js +20 -40
  69. package/src/runtime/utils.js +3 -0
  70. package/src/types/ambient-private.d.ts +1 -1
  71. package/src/types/ambient.d.ts +58 -7
  72. package/src/types/global-private.d.ts +1 -1
  73. package/src/types/internal.d.ts +47 -53
  74. package/src/utils/filesystem.js +1 -23
  75. package/src/utils/hash.js +21 -0
  76. package/src/utils/http.js +8 -7
  77. package/src/utils/import.js +2 -1
  78. package/src/utils/params.js +1 -1
  79. package/src/utils/regex.js +9 -0
  80. package/src/utils/routing.js +52 -27
  81. package/src/utils/url.js +1 -0
  82. package/src/version.js +1 -1
  83. package/types/index.d.ts +98 -28
  84. package/types/index.d.ts.map +1 -1
  85. package/src/exports/node/polyfills.js +0 -30
  86. package/src/runtime/server/app.js +0 -9
@@ -8,7 +8,6 @@ import { URL } from 'node:url';
8
8
  import { AsyncLocalStorage } from 'node:async_hooks';
9
9
  import { styleText } from 'node:util';
10
10
  import sirv from 'sirv';
11
- import { isCSSRequest, loadEnv, buildErrorMessage } from 'vite';
12
11
  import { createReadableStream, getRequest, setResponse } from '../../../exports/node/index.js';
13
12
  import { coalesce_to_error } from '../../../utils/error.js';
14
13
  import { resolve_entry } from '../../../utils/filesystem.js';
@@ -21,12 +20,7 @@ import * as sync from '../../../core/sync/sync.js';
21
20
  import { get_mime_lookup, get_runtime_base } from '../../../core/utils.js';
22
21
  import '../../../utils/mime.js'; // extend mrmime with additional types (affects sirv too)
23
22
  import { compact } from '../../../utils/array.js';
24
- import {
25
- is_chrome_devtools_request,
26
- log_response,
27
- not_found,
28
- remote_module_pattern
29
- } from '../utils.js';
23
+ import { is_chrome_devtools_request, is_remote_module, log_response, not_found } from '../utils.js';
30
24
  import { SCHEME } from '../../../utils/url.js';
31
25
  import { check_feature } from '../../../utils/features.js';
32
26
  import { escape_html } from '../../../utils/escape.js';
@@ -36,7 +30,8 @@ import { get_runner } from '../../../runner.js';
36
30
  const vite_css_query_regex = /(?:\?|&)(?:raw|url|inline)(?:&|$)/;
37
31
 
38
32
  /**
39
- * @param {ViteDevServer} vite
33
+ * @param {typeof import('vite')} vite the peer resolved vite module
34
+ * @param {ViteDevServer} vite_dev_server
40
35
  * @param {ResolvedConfig} vite_config
41
36
  * @param {ValidatedConfig} svelte_config
42
37
  * @param {() => RemoteChunk[]} get_remotes
@@ -44,7 +39,15 @@ const vite_css_query_regex = /(?:\?|&)(?:raw|url|inline)(?:&|$)/;
44
39
  * @param {(manifest_data: ManifestData) => void} set_manifest_data
45
40
  * @return {Promise<Promise<() => void>>}
46
41
  */
47
- export async function dev(vite, vite_config, svelte_config, get_remotes, root, set_manifest_data) {
42
+ export async function dev(
43
+ vite,
44
+ vite_dev_server,
45
+ vite_config,
46
+ svelte_config,
47
+ get_remotes,
48
+ root,
49
+ set_manifest_data
50
+ ) {
48
51
  /** @type {AsyncLocalStorage<{ event: RequestEvent, config: any, prerender: PrerenderOption }>} */
49
52
  const async_local_storage = new AsyncLocalStorage();
50
53
 
@@ -81,7 +84,7 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, s
81
84
  /** @type {Error | null} */
82
85
  let manifest_error = null;
83
86
 
84
- const runner = get_runner(vite);
87
+ const runner = get_runner(vite, vite_dev_server);
85
88
 
86
89
  /**
87
90
  * @param {string} url
@@ -91,19 +94,19 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, s
91
94
  try {
92
95
  return await runner.import(url);
93
96
  } catch (/** @type {any} */ err) {
94
- const msg = buildErrorMessage(err, [
97
+ const msg = vite.buildErrorMessage(err, [
95
98
  styleText('red', `Internal server error: ${err.message}`)
96
99
  ]);
97
100
 
98
- if (!vite.config.logger.hasErrorLogged(err)) {
99
- vite.config.logger.error(msg, { error: err });
101
+ if (!vite_dev_server.config.logger.hasErrorLogged(err)) {
102
+ vite_dev_server.config.logger.error(msg, { error: err });
100
103
  }
101
104
 
102
105
  // TODO this is inadequate — it doesn't reliably show the overlay on every page load,
103
106
  // and when it does appear it may immediately vanish. `vite.hot.send` broadcasts
104
107
  // to all connected clients, even ones that are unaffected by the error.
105
108
  // we need a more considered approach
106
- vite.hot.send({
109
+ vite_dev_server.hot.send({
107
110
  type: 'error',
108
111
  err: /** @type {ErrorPayload['err']} */ ({
109
112
  ...err,
@@ -124,7 +127,7 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, s
124
127
 
125
128
  const module = await loud_ssr_load_module(url);
126
129
 
127
- const module_node = await vite.environments.ssr.moduleGraph.getModuleByUrl(url);
130
+ const module_node = await vite_dev_server.environments.ssr.moduleGraph.getModuleByUrl(url);
128
131
  if (!module_node) throw new Error(`Could not find node for ${url}`);
129
132
 
130
133
  return { module, module_node, url };
@@ -144,13 +147,13 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, s
144
147
 
145
148
  if (manifest_error) {
146
149
  manifest_error = null;
147
- vite.hot.send({ type: 'full-reload' });
150
+ vite_dev_server.hot.send({ type: 'full-reload' });
148
151
  }
149
152
  } catch (error) {
150
153
  manifest_error = /** @type {Error} */ (error);
151
154
 
152
155
  console.error(styleText(['bold', 'red'], manifest_error.message));
153
- vite.hot.send({
156
+ vite_dev_server.hot.send({
154
157
  type: 'error',
155
158
  err: {
156
159
  message: manifest_error.message ?? 'Invalid routes',
@@ -261,14 +264,14 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, s
261
264
  const deps = new Set();
262
265
 
263
266
  for (const module_node of module_nodes) {
264
- await find_deps(vite, module_node, deps);
267
+ await find_deps(vite_dev_server, module_node, deps);
265
268
  }
266
269
 
267
270
  /** @type {Record<string, string>} */
268
271
  const styles = {};
269
272
 
270
273
  for (const dep of deps) {
271
- if (isCSSRequest(dep.url) && !vite_css_query_regex.test(dep.url)) {
274
+ if (vite.isCSSRequest(dep.url) && !vite_css_query_regex.test(dep.url)) {
272
275
  const inlineCssUrl = dep.url.includes('?')
273
276
  ? dep.url.replace('?', '?inline&')
274
277
  : dep.url + '?inline';
@@ -343,14 +346,17 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, s
343
346
  return;
344
347
  }
345
348
 
349
+ let prelude = '';
350
+ let start = -1;
346
351
  let end = 0;
347
352
 
348
- error.stack = error.stack
353
+ const lines = error.stack
349
354
  .replaceAll('\0', '') // remove null bytes from e.g. virtual module IDs, or the response will fail
350
355
  .split('\n')
351
356
  .map((line, i) => {
352
- const match = /^ {4}at (?:[^ ]+ \((.+)\)|(.+))$/.exec(line);
357
+ const match = /^ {4}at (?:[^(]+ \((.+)\)|(.+))$/.exec(line);
353
358
  if (!match) {
359
+ prelude += line + '\n';
354
360
  end = i + 1;
355
361
  return line;
356
362
  }
@@ -360,6 +366,7 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, s
360
366
 
361
367
  if (fs.existsSync(file)) {
362
368
  if (!file.includes('node_modules') && !file.includes(SRC_ROOT)) {
369
+ if (start === -1) start = i;
363
370
  end = i + 1;
364
371
  }
365
372
 
@@ -368,10 +375,11 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, s
368
375
 
369
376
  return line;
370
377
  })
371
- .slice(0, end)
372
- .join('\n');
378
+ // if no user-code frame was found, keep only the prelude (message/header)
379
+ // lines and drop everything else so the message isn't duplicated
380
+ .slice(start === -1 ? end : start, end);
373
381
 
374
- return error.stack;
382
+ return (error.stack = prelude + lines.join('\n'));
375
383
  }
376
384
 
377
385
  const params_file = resolve_entry(svelte_config.kit.files.params);
@@ -381,12 +389,12 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, s
381
389
  * @param {(file: string) => void} cb
382
390
  */
383
391
  const watch = (event, cb) => {
384
- vite.watcher.on(event, (file) => {
392
+ vite_dev_server.watcher.on(event, (file) => {
385
393
  if (
386
394
  file.startsWith(svelte_config.kit.files.routes + path.sep) ||
387
395
  file.startsWith(svelte_config.kit.files.assets + path.sep) ||
388
396
  (params_file && file === params_file) ||
389
- remote_module_pattern.test(file) ||
397
+ is_remote_module(file) ||
390
398
  // in contrast to server hooks, client hooks are written to the client manifest
391
399
  // and therefore need rebuilding when they are added/removed
392
400
  file.startsWith(svelte_config.kit.files.hooks.client)
@@ -429,14 +437,14 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, s
429
437
  // kit defaults to src/app.html, so unless user changed that to index.html
430
438
  // send the vite client a full-reload event without path being set
431
439
  if (appTemplate !== 'index.html') {
432
- vite.watcher.on('change', (file) => {
440
+ vite_dev_server.watcher.on('change', (file) => {
433
441
  if (file === appTemplate) {
434
- vite.hot.send({ type: 'full-reload' });
442
+ vite_dev_server.hot.send({ type: 'full-reload' });
435
443
  }
436
444
  });
437
445
  }
438
446
 
439
- vite.watcher.on('all', (_, file) => {
447
+ vite_dev_server.watcher.on('all', (_, file) => {
440
448
  if (
441
449
  file === appTemplate ||
442
450
  file === errorTemplate ||
@@ -455,8 +463,8 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, s
455
463
  extensions: []
456
464
  });
457
465
 
458
- vite.middlewares.use((req, res, next) => {
459
- const base = `${vite.config.server.https ? 'https' : 'http'}://${
466
+ vite_dev_server.middlewares.use((req, res, next) => {
467
+ const base = `${vite_dev_server.config.server.https ? 'https' : 'http'}://${
460
468
  req.headers[':authority'] || req.headers.host
461
469
  }`;
462
470
 
@@ -478,23 +486,23 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, s
478
486
  next();
479
487
  });
480
488
 
481
- const env = loadEnv(vite_config.mode, svelte_config.kit.env.dir, '');
489
+ const env = vite.loadEnv(vite_config.mode, svelte_config.kit.env.dir, '');
482
490
  const emulator = await svelte_config.kit.adapter?.emulate?.();
483
491
 
484
492
  /** @type {Promise<void> | undefined} */
485
493
  let init_manifest;
486
494
 
487
495
  return () => {
488
- const serve_static_middleware = vite.middlewares.stack.find(
496
+ const serve_static_middleware = vite_dev_server.middlewares.stack.find(
489
497
  (middleware) =>
490
498
  /** @type {Function} */ (middleware.handle).name === 'viteServeStaticMiddleware'
491
499
  );
492
500
 
493
501
  // Vite will give a 403 on URLs like /test, /static, and /package.json preventing us from
494
502
  // serving routes with those names. See https://github.com/vitejs/vite/issues/7363
495
- remove_static_middlewares(vite.middlewares);
503
+ remove_static_middlewares(vite_dev_server.middlewares);
496
504
 
497
- vite.middlewares.use(async (req, res) => {
505
+ vite_dev_server.middlewares.use(async (req, res) => {
498
506
  // Vite throws a Cannot read properties of undefined (reading 'wrapDynamicImport')
499
507
  // if you try to run ssr.runner.import before the server has started so
500
508
  // we do it inside here to avoid that
@@ -504,7 +512,7 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, s
504
512
  const original_url = req.url;
505
513
  req.url = req.originalUrl;
506
514
  try {
507
- const base = `${vite.config.server.https ? 'https' : 'http'}://${
515
+ const base = `${vite_dev_server.config.server.https ? 'https' : 'http'}://${
508
516
  req.headers[':authority'] || req.headers.host
509
517
  }`;
510
518
 
@@ -1,7 +1,7 @@
1
1
  /** @import { EnvVarConfig, KitConfig } from '@sveltejs/kit' */
2
2
  /** @import { Options, SvelteConfig } from '@sveltejs/vite-plugin-svelte' */
3
3
  /** @import { PreprocessorGroup } from 'svelte/compiler' */
4
- /** @import { BuildData, ManifestData, Prerendered, RemoteChunk, RemoteInternals, ServerMetadata, ValidatedConfig, ValidatedKitConfig } from 'types' */
4
+ /** @import { Asset, BuildData, ManifestData, Prerendered, RemoteChunk, RemoteInternals, RouteData, ServerMetadata, ValidatedConfig, ValidatedKitConfig } from 'types' */
5
5
  /** @import { Manifest, Plugin, ResolvedConfig, Rolldown, UserConfig, ViteDevServer } from 'vite' */
6
6
  import fs from 'node:fs';
7
7
  import path from 'node:path';
@@ -11,7 +11,7 @@ import MagicString from 'magic-string';
11
11
  import { loadEnv } from 'vite';
12
12
  import { exactRegex, prefixRegex } from 'rolldown/filter';
13
13
 
14
- import { copy, mkdirp, read, resolve_entry, rimraf } from '../../utils/filesystem.js';
14
+ import { copy, read, resolve_entry } from '../../utils/filesystem.js';
15
15
  import { posixify } from '../../utils/os.js';
16
16
  import { to_fs } from '../../utils/vite.js';
17
17
  import {
@@ -34,6 +34,7 @@ import { preview } from './preview/index.js';
34
34
  import {
35
35
  error_for_missing_config,
36
36
  get_config_aliases,
37
+ is_remote_module,
37
38
  normalize_id,
38
39
  remote_module_pattern,
39
40
  server_only_directory_pattern,
@@ -46,6 +47,11 @@ import analyse from '../../core/postbuild/analyse.js';
46
47
  import { s } from '../../utils/misc.js';
47
48
  import { hash } from '../../utils/hash.js';
48
49
  import { dedent } from '../../core/sync/utils.js';
50
+ import {
51
+ is_app_route,
52
+ is_endpoint_route,
53
+ is_page_route
54
+ } from '../../core/sync/create_manifest_data/index.js';
49
55
  import { get_import_aliases, get_hash_import_keys } from '../../utils/imports.js';
50
56
  import {
51
57
  app_env_private,
@@ -101,6 +107,21 @@ const enforced_config = {
101
107
 
102
108
  const options_regex = /(export\s+const\s+(prerender|csr|ssr|trailingSlash))\s*=/s;
103
109
 
110
+ const removed_modules = [
111
+ {
112
+ name: '$lib',
113
+ pattern: /^\$lib(?:\/.*|\?.*)?$/,
114
+ message:
115
+ "`$lib` has been removed. Use `#lib` instead: https://svelte.dev/docs/kit/$lib. To keep using `$lib`, add `alias: { '$lib': 'src/lib' }` to your SvelteKit config."
116
+ },
117
+ {
118
+ name: '$service-worker',
119
+ pattern: /^\$service-worker(?:\?.*)?$/,
120
+ message:
121
+ '`$service-worker` has been removed. Use `immutable`, `assets` and `prerendered` from `$app/manifest`, `version` from `$app/env`, and `resolve(...)` from `$app/paths` instead: https://svelte.dev/docs/kit/$service-worker'
122
+ }
123
+ ];
124
+
104
125
  /** @type {Set<string>} */
105
126
  const warned = new Set();
106
127
 
@@ -311,6 +332,26 @@ function kit({ svelte_config }) {
311
332
  api: {
312
333
  options: svelte_config
313
334
  },
335
+ resolveId: {
336
+ filter: { id: removed_modules.map(({ pattern }) => pattern) },
337
+ async handler(id, importer, options) {
338
+ const resolved = await this.resolve(id, importer, { ...options, skipSelf: true });
339
+ if (resolved) return resolved;
340
+
341
+ const aliases = svelte_config.kit.alias;
342
+ for (const { name, pattern, message } of removed_modules) {
343
+ if (!pattern.test(id)) continue;
344
+
345
+ // If the user re-added an alias for this module (as the migration message
346
+ // suggests), a failed resolution means a genuine missing file rather than
347
+ // use of the removed module. Let Vite report the real "not found" error
348
+ // instead of the misleading migration message.
349
+ if (name in aliases || `${name}/*` in aliases) return;
350
+
351
+ throw stackless(message);
352
+ }
353
+ }
354
+ },
314
355
 
315
356
  /**
316
357
  * Build the SvelteKit-provided Vite config to be merged with the user's vite.config.js file.
@@ -467,6 +508,7 @@ function kit({ svelte_config }) {
467
508
  async handler(id, importer) {
468
509
  const resolved = await this.resolve(id, importer, { skipSelf: true });
469
510
  if (!resolved) return { id, external: true };
511
+ if (!is_remote_module(resolved.id)) return;
470
512
  // a servable /@fs url; 'absolute' stops rolldown relativizing it in the deps bundle
471
513
  return { id: to_fs(resolved.id), external: 'absolute' };
472
514
  }
@@ -577,7 +619,7 @@ function kit({ svelte_config }) {
577
619
 
578
620
  async configResolved(config) {
579
621
  explicit_env_entry = resolve_explicit_env_entry(kit);
580
- explicit_env_config = await sync.env(kit, explicit_env_entry, config.root, config.mode);
622
+ explicit_env_config = await sync.env(vite, kit, explicit_env_entry, config.root, config.mode);
581
623
  },
582
624
 
583
625
  configureServer(server) {
@@ -591,6 +633,7 @@ function kit({ svelte_config }) {
591
633
  if (file === explicit_env_entry || file === resolved) {
592
634
  explicit_env_entry = resolved;
593
635
  explicit_env_config = await sync.env(
636
+ vite,
594
637
  kit,
595
638
  explicit_env_entry,
596
639
  vite_config.root,
@@ -889,6 +932,8 @@ function kit({ svelte_config }) {
889
932
  id: remote_module_pattern
890
933
  },
891
934
  async handler(code, id) {
935
+ if (!is_remote_module(id)) return;
936
+
892
937
  const file = posixify(path.relative(root, id));
893
938
  const remote = {
894
939
  hash: hash(file),
@@ -951,7 +996,7 @@ function kit({ svelte_config }) {
951
996
  // being called again with `opts.ssr === true` if the module isn't
952
997
  // already loaded) so we can determine what it exports
953
998
  if (dev_server) {
954
- const module = await get_runner(dev_server).import(id);
999
+ const module = await get_runner(vite, dev_server).import(id);
955
1000
 
956
1001
  for (const [name, value] of Object.entries(module)) {
957
1002
  const type = value?.__?.type;
@@ -1121,7 +1166,7 @@ function kit({ svelte_config }) {
1121
1166
  ];
1122
1167
 
1123
1168
  export const assets = [
1124
- ${manifest_data.assets.map((asset) => s({ path: asset.file })).join(',\n')}
1169
+ ${stringify_assets(manifest_data.assets)}
1125
1170
  ];
1126
1171
 
1127
1172
  export const prerendered = [
@@ -1129,7 +1174,7 @@ function kit({ svelte_config }) {
1129
1174
  ];
1130
1175
 
1131
1176
  export const routes = [
1132
- ${manifest_data.routes.map((route) => s({ id: route.id })).join(',\n')}
1177
+ ${stringify_routes(manifest_data.routes)}
1133
1178
  ];
1134
1179
  `;
1135
1180
  }
@@ -1498,6 +1543,7 @@ function kit({ svelte_config }) {
1498
1543
  */
1499
1544
  async configureServer(server) {
1500
1545
  return await dev(
1546
+ vite,
1501
1547
  server,
1502
1548
  vite_config,
1503
1549
  svelte_config,
@@ -1550,9 +1596,9 @@ function kit({ svelte_config }) {
1550
1596
  async buildApp(builder) {
1551
1597
  // clears the output directories
1552
1598
  if (!builder.config.build.watch) {
1553
- rimraf(out);
1599
+ fs.rmSync(out, { force: true, recursive: true });
1554
1600
  }
1555
- mkdirp(out);
1601
+ fs.mkdirSync(out, { recursive: true });
1556
1602
 
1557
1603
  await load_and_validate_params({
1558
1604
  routes: manifest_data.routes,
@@ -1570,7 +1616,7 @@ function kit({ svelte_config }) {
1570
1616
  // the client build and after prerendering respectively.
1571
1617
  replace_manifest_placeholder_variables(server_chunks, `${out}/server`, {
1572
1618
  assets: manifest_data.assets.map((asset) => ({ path: asset.file })),
1573
- routes: manifest_data.routes.map((route) => ({ id: route.id }))
1619
+ routes: get_manifest_routes(manifest_data.routes)
1574
1620
  });
1575
1621
 
1576
1622
  const verbose = builder.config.logLevel === 'info';
@@ -1732,7 +1778,7 @@ function kit({ svelte_config }) {
1732
1778
  replace_manifest_placeholder_variables(client_chunks, `${out}/client`, {
1733
1779
  immutable,
1734
1780
  assets: manifest_data.assets.map((asset) => ({ path: asset.file })),
1735
- routes: manifest_data.routes.map((route) => ({ id: route.id }))
1781
+ routes: get_manifest_routes(manifest_data.routes)
1736
1782
  });
1737
1783
 
1738
1784
  // Now that the client build is done, replace the `build` sentinel
@@ -2112,6 +2158,38 @@ function comparable(value) {
2112
2158
  return process.platform === 'win32' ? normalized.toLowerCase() : normalized;
2113
2159
  }
2114
2160
 
2161
+ /**
2162
+ * @param {Asset[] | undefined} assets
2163
+ * @returns {string}
2164
+ */
2165
+ function stringify_assets(assets) {
2166
+ return assets?.map((asset) => s({ path: asset.file })).join(',\n') ?? '';
2167
+ }
2168
+
2169
+ /**
2170
+ * @param {RouteData[] | undefined} routes
2171
+ * @returns {Array<{ id: string; page: boolean; endpoint: boolean }>}
2172
+ */
2173
+ function get_manifest_routes(routes) {
2174
+ return (
2175
+ routes?.filter(is_app_route).map((route) => ({
2176
+ id: route.id,
2177
+ page: is_page_route(route),
2178
+ endpoint: is_endpoint_route(route)
2179
+ })) ?? []
2180
+ );
2181
+ }
2182
+
2183
+ /**
2184
+ * @param {RouteData[] | undefined} routes
2185
+ * @returns {string}
2186
+ */
2187
+ function stringify_routes(routes) {
2188
+ return get_manifest_routes(routes)
2189
+ .map((route) => s(route))
2190
+ .join(',\n');
2191
+ }
2192
+
2115
2193
  /**
2116
2194
  * Creates the `$app/manifest` data module. During development, real values
2117
2195
  * are emitted for `assets` and `routes` (the only data known at that point).
@@ -2144,20 +2222,17 @@ const create_manifest_data_module = (is_build, manifest_data) => {
2144
2222
  // In dev, `manifest_data` may not be set yet on the very first load,
2145
2223
  // but `configureServer` (which calls `sync.create`) runs before any
2146
2224
  // module is served, so it will be set by the time this is called.
2147
- const routes = manifest_data?.routes.map((route) => s({ id: route.id })).join(',\n') ?? '';
2148
- const assets = manifest_data?.assets.map((asset) => s({ path: asset.file })).join(',\n') ?? '';
2149
-
2150
2225
  return dedent`
2151
2226
  // empty during dev
2152
2227
  export const immutable = [];
2153
2228
  export const prerendered = [];
2154
2229
 
2155
2230
  export const assets = [
2156
- ${assets}
2231
+ ${stringify_assets(manifest_data?.assets)}
2157
2232
  ];
2158
2233
 
2159
2234
  export const routes = [
2160
- ${routes}
2235
+ ${stringify_routes(manifest_data?.routes)}
2161
2236
  ];
2162
2237
  `;
2163
2238
  };
@@ -2173,7 +2248,7 @@ const create_manifest_data_module = (is_build, manifest_data) => {
2173
2248
  * immutable?: Array<{ path: string }>;
2174
2249
  * assets?: Array<{ path: string }>;
2175
2250
  * prerendered?: Array<{ path: string }>;
2176
- * routes?: Array<{ id: string }>;
2251
+ * routes?: Array<{ id: string; page: boolean; endpoint: boolean }>;
2177
2252
  * }} values
2178
2253
  */
2179
2254
  const replace_manifest_placeholder_variables = (chunks, output_dir, values) => {
@@ -1,7 +1,9 @@
1
+ import fs from 'node:fs';
1
2
  import path from 'node:path';
2
3
  import { posixify } from '../../utils/os.js';
3
4
  import { negotiate } from '../../utils/http.js';
4
5
  import { escape_html } from '../../utils/escape.js';
6
+ import { escape_for_regexp } from '../../utils/regex.js';
5
7
  import { stackless } from '../../utils/error.js';
6
8
  import { dedent } from '../../core/sync/utils.js';
7
9
  import { app_server, app_env_private, sveltekit_env_private } from './module_ids.js';
@@ -44,13 +46,6 @@ export function get_config_aliases(config, root) {
44
46
  return alias;
45
47
  }
46
48
 
47
- /**
48
- * @param {string} str
49
- */
50
- function escape_for_regexp(str) {
51
- return str.replace(/[.*+?^${}()|[\]\\]/g, (match) => '\\' + match);
52
- }
53
-
54
49
  /**
55
50
  * Silently respond with 404 for Chrome DevTools workspaces request.
56
51
  * Chrome always requests this at the root, regardless of base path.
@@ -119,6 +114,16 @@ const query_pattern = /\?.*$/s;
119
114
  export function normalize_id(id, aliases, cwd) {
120
115
  id = id.replace(query_pattern, '');
121
116
 
117
+ // check before the cwd is removed — in a user's app these modules live
118
+ // inside `node_modules`, i.e. within the cwd
119
+ if (id === app_server) {
120
+ return '$app/server';
121
+ }
122
+
123
+ if (id === app_env_private || id === sveltekit_env_private) {
124
+ return '$app/env/private';
125
+ }
126
+
122
127
  for (const { alias, path } of aliases) {
123
128
  if (id === path || id.startsWith(path + '/')) {
124
129
  id = id.replace(path, alias);
@@ -130,19 +135,61 @@ export function normalize_id(id, aliases, cwd) {
130
135
  id = path.relative(cwd, id);
131
136
  }
132
137
 
133
- if (id === app_server) {
134
- return '$app/server';
135
- }
138
+ return posixify(id);
139
+ }
136
140
 
137
- if (id === app_env_private || id === sveltekit_env_private) {
138
- return '$app/env/private';
141
+ export const remote_module_pattern = /[/.]remote\.[^/]+$/;
142
+
143
+ /**
144
+ * A cache of which directories can export remote modules
145
+ * @type {Map<string, boolean>}
146
+ */
147
+ const remote_module_cache = new Map();
148
+
149
+ /**
150
+ * Whether `id` is a remote module. Files in node_modules only count if the
151
+ * package they belong to has a peer dependency on `@sveltejs/kit`
152
+ * @param {string} id
153
+ * @returns {boolean}
154
+ */
155
+ export function is_remote_module(id) {
156
+ id = posixify(id);
157
+ if (!remote_module_pattern.test(id)) return false;
158
+ if (!id.includes('node_modules')) return true;
159
+
160
+ return can_export_remote_module(path.dirname(id));
161
+ }
162
+
163
+ /**
164
+ * @param {string} directory
165
+ * @returns {boolean}
166
+ */
167
+ function can_export_remote_module(directory) {
168
+ let cached = remote_module_cache.get(directory);
169
+ if (cached !== undefined) return cached;
170
+
171
+ let pkg;
172
+
173
+ try {
174
+ pkg = JSON.parse(fs.readFileSync(path.join(directory, 'package.json'), 'utf8'));
175
+ } catch {}
176
+
177
+ if (pkg?.peerDependencies?.['@sveltejs/kit']) {
178
+ cached = true;
179
+ } else {
180
+ const parent = path.dirname(directory);
181
+
182
+ cached =
183
+ path.basename(directory) === 'node_modules' || parent === directory
184
+ ? false // base case
185
+ : can_export_remote_module(parent); // recurse
139
186
  }
140
187
 
141
- return posixify(id);
188
+ remote_module_cache.set(directory, cached);
189
+ return cached;
142
190
  }
143
191
 
144
- export const remote_module_pattern = /[/.]remote(\.[^/]+)+$/;
145
- export const server_only_module_pattern = /[/.]server(\.[^/]+)+$/;
192
+ export const server_only_module_pattern = /[/.]server\.[^/]+$/;
146
193
  export const server_only_directory_pattern = /\/server\//;
147
194
 
148
195
  export const strip_virtual_prefix = /** @param {string} id */ (id) => id.replace('\0virtual:', '');
package/src/runner.js CHANGED
@@ -1,10 +1,12 @@
1
1
  /** @import { ViteDevServer } from 'vite' */
2
- import * as vite from 'vite';
3
2
 
4
3
  /**
4
+ * @param {typeof import('vite')} vite the peer resolved vite module
5
5
  * @param {ViteDevServer} server
6
6
  */
7
- export function get_runner(server) {
7
+ export function get_runner(vite, server) {
8
+ // `isRunnableDevEnvironment` does an `instanceof` check and will fail if
9
+ // we're using different instances of Vite
8
10
  if (!vite.isRunnableDevEnvironment(server.environments.ssr)) {
9
11
  throw new Error('The configured Vite SSR environment must be a RunnableDevEnvironment');
10
12
  }
@@ -1,10 +1,9 @@
1
- import * as devalue from 'devalue';
2
- import { BROWSER, DEV } from 'esm-env';
1
+ import { DEV } from 'esm-env';
3
2
  import { noop } from '../../utils/functions.js';
4
3
  import { refreshAll } from './navigation.js';
5
- import { app as client_app, applyAction, handle_error } from '../client/client.js';
6
- import { app as server_app } from '../server/app.js';
4
+ import { applyAction, handle_error } from '../client/client.js';
7
5
  import { notify_version } from '../client/state.svelte.js';
6
+ import { parse } from '#app/internal/transport';
8
7
 
9
8
  export { applyAction };
10
9
 
@@ -38,9 +37,7 @@ export function deserialize(result) {
38
37
  const parsed = JSON.parse(result);
39
38
 
40
39
  if (parsed.data) {
41
- // the decoders should never be initialised at the top-level because `app`
42
- // will not be initialised yet if `output.bundleStrategy` is 'single' or 'inline'
43
- parsed.data = devalue.parse(parsed.data, BROWSER ? client_app.decoders : server_app.decoders);
40
+ parsed.data = parse(parsed.data);
44
41
  }
45
42
 
46
43
  return parsed;