@sveltejs/kit 3.0.0-next.14 → 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 (56) hide show
  1. package/package.json +6 -3
  2. package/src/cli.js +6 -3
  3. package/src/core/adapt/builder.js +12 -5
  4. package/src/core/config/index.js +4 -5
  5. package/src/core/env.js +3 -3
  6. package/src/core/postbuild/prerender.js +6 -10
  7. package/src/core/sync/sync.js +3 -2
  8. package/src/core/sync/utils.js +2 -2
  9. package/src/core/sync/write_tsconfig/index.js +71 -53
  10. package/src/core/sync/write_tsconfig/utils.js +0 -61
  11. package/src/core/sync/write_tsconfig/validate.js +128 -0
  12. package/src/core/sync/write_types/index.js +2 -2
  13. package/src/exports/public.d.ts +22 -16
  14. package/src/exports/vite/build/build_server.js +2 -3
  15. package/src/exports/vite/dev/index.js +44 -36
  16. package/src/exports/vite/index.js +46 -5
  17. package/src/exports/vite/utils.js +61 -8
  18. package/src/runner.js +4 -2
  19. package/src/runtime/app/forms.js +4 -7
  20. package/src/runtime/app/internal/transport.js +53 -0
  21. package/src/runtime/app/paths/client.js +2 -2
  22. package/src/runtime/app/paths/internal/client.js +2 -2
  23. package/src/runtime/app/server/remote/prerender.js +6 -10
  24. package/src/runtime/app/server/remote/query.js +3 -3
  25. package/src/runtime/app/server/remote/requested.js +2 -2
  26. package/src/runtime/app/server/remote/shared.js +1 -16
  27. package/src/runtime/client/client.js +29 -25
  28. package/src/runtime/client/parse.js +1 -1
  29. package/src/runtime/client/remote-functions/command.svelte.js +1 -2
  30. package/src/runtime/client/remote-functions/prerender.svelte.js +1 -1
  31. package/src/runtime/client/remote-functions/query/proxy.js +2 -2
  32. package/src/runtime/client/remote-functions/query-live/proxy.js +2 -2
  33. package/src/runtime/pathname.js +7 -1
  34. package/src/runtime/server/data/index.js +5 -8
  35. package/src/runtime/server/dev.js +22 -0
  36. package/src/runtime/server/endpoint.js +3 -4
  37. package/src/runtime/server/fetch.js +22 -24
  38. package/src/runtime/server/index.js +54 -22
  39. package/src/runtime/server/internal.js +12 -5
  40. package/src/runtime/server/page/actions.js +18 -43
  41. package/src/runtime/server/page/data_serializer.js +12 -13
  42. package/src/runtime/server/page/index.js +16 -32
  43. package/src/runtime/server/page/load_data.js +26 -15
  44. package/src/runtime/server/page/render.js +9 -11
  45. package/src/runtime/server/page/respond_with_error.js +8 -20
  46. package/src/runtime/server/remote-functions.js +11 -15
  47. package/src/runtime/server/respond.js +26 -31
  48. package/src/runtime/server/state.js +36 -19
  49. package/src/runtime/server/utils.js +0 -20
  50. package/src/runtime/shared.js +16 -38
  51. package/src/types/internal.d.ts +45 -52
  52. package/src/utils/filesystem.js +1 -23
  53. package/src/version.js +1 -1
  54. package/types/index.d.ts +24 -18
  55. package/types/index.d.ts.map +1 -1
  56. package/src/runtime/server/app.js +0 -9
@@ -121,9 +121,15 @@ type UnpackValidationError<T> =
121
121
  export interface Builder {
122
122
  /** Print messages to the console. `log.info` and `log.minor` are silent unless Vite's `logLevel` is `info`. */
123
123
  log: Logger;
124
- /** Remove `dir` and all its contents. */
124
+ /**
125
+ * Remove `dir` and all its contents.
126
+ * @deprecated Use `fs.rmSync(dir, { force: true, recursive: true })` instead
127
+ */
125
128
  rimraf: (dir: string) => void;
126
- /** Create `dir` and any required parent directories. */
129
+ /**
130
+ * Create `dir` and any required parent directories.
131
+ * @deprecated Use `fs.mkdirSync(dir, { recursive: true })` instead
132
+ */
127
133
  mkdirp: (dir: string) => void;
128
134
 
129
135
  /** The fully resolved SvelteKit config. */
@@ -1614,7 +1620,7 @@ export interface RequestEvent<
1614
1620
  /**
1615
1621
  * Get or set cookies related to the current request
1616
1622
  */
1617
- cookies: Cookies;
1623
+ readonly cookies: Cookies;
1618
1624
  /**
1619
1625
  * `fetch` is equivalent to the [native `fetch` web API](https://developer.mozilla.org/en-US/docs/Web/API/fetch), with a few additional features:
1620
1626
  *
@@ -1626,15 +1632,15 @@ export interface RequestEvent<
1626
1632
  *
1627
1633
  * You can learn more about making credentialed requests with cookies [here](https://svelte.dev/docs/kit/load#Cookies).
1628
1634
  */
1629
- fetch: typeof fetch;
1635
+ readonly fetch: typeof fetch;
1630
1636
  /**
1631
1637
  * The client's IP address, set by the adapter.
1632
1638
  */
1633
- getClientAddress: () => string;
1639
+ readonly getClientAddress: () => string;
1634
1640
  /**
1635
1641
  * Contains custom data that was added to the request within the [`server handle hook`](https://svelte.dev/docs/kit/hooks#handle).
1636
1642
  */
1637
- locals: App.Locals;
1643
+ readonly locals: App.Locals;
1638
1644
  /**
1639
1645
  * The parameters of the current route - e.g. for a route like `/blog/[slug]`, a `{ slug: string }` object.
1640
1646
  *
@@ -1643,19 +1649,19 @@ export interface RequestEvent<
1643
1649
  * the remote function was called from, _not_ the URL of the endpoint SvelteKit creates for the remote function. Never use it
1644
1650
  * to determine whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.
1645
1651
  */
1646
- params: Params;
1652
+ readonly params: Params;
1647
1653
  /**
1648
1654
  * Additional data made available through the adapter.
1649
1655
  */
1650
- platform: Readonly<App.Platform> | undefined;
1656
+ readonly platform: Readonly<App.Platform> | undefined;
1651
1657
  /**
1652
1658
  * The original request object.
1653
1659
  */
1654
- request: Request;
1660
+ readonly request: Request;
1655
1661
  /**
1656
1662
  * Info about the current route.
1657
1663
  */
1658
- route: {
1664
+ readonly route: {
1659
1665
  /**
1660
1666
  * The ID of the current route - e.g. for `src/routes/blog/[slug]`, it would be `/blog/[slug]`. It is `null` when no route is matched.
1661
1667
  *
@@ -1688,7 +1694,7 @@ export interface RequestEvent<
1688
1694
  *
1689
1695
  * You cannot add a `set-cookie` header with `setHeaders` — use the [`cookies`](https://svelte.dev/docs/kit/@sveltejs-kit#Cookies) API instead.
1690
1696
  */
1691
- setHeaders: (headers: Record<string, string>) => void;
1697
+ readonly setHeaders: (headers: Record<string, string>) => void;
1692
1698
  /**
1693
1699
  * The requested URL.
1694
1700
  *
@@ -1697,22 +1703,22 @@ export interface RequestEvent<
1697
1703
  * the remote function was called from, _not_ the URL of the endpoint SvelteKit creates for the remote function. Never use it
1698
1704
  * to determine whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.
1699
1705
  */
1700
- url: URL;
1706
+ readonly url: URL;
1701
1707
  /**
1702
1708
  * `true` if the request comes from the client asking for `+page/layout.server.js` data. The `url` property will be stripped of the internal information
1703
1709
  * related to the data request in this case. Use this property instead if the distinction is important to you.
1704
1710
  */
1705
- isDataRequest: boolean;
1711
+ readonly isDataRequest: boolean;
1706
1712
  /**
1707
1713
  * `true` for `+server.js` calls coming from SvelteKit without the overhead of actually making an HTTP request. This happens when you make same-origin `fetch` requests on the server.
1708
1714
  */
1709
- isSubRequest: boolean;
1715
+ readonly isSubRequest: boolean;
1710
1716
 
1711
1717
  /**
1712
1718
  * Access to spans for tracing. If tracing is not enabled, these spans will do nothing.
1713
1719
  * @since 2.31.0
1714
1720
  */
1715
- tracing: {
1721
+ readonly tracing: {
1716
1722
  /** Whether tracing is enabled. */
1717
1723
  enabled: boolean;
1718
1724
  /** The root span for the request. This span is named `sveltekit.handle.root`. */
@@ -1725,7 +1731,7 @@ export interface RequestEvent<
1725
1731
  * `true` if the request comes from the client via a remote function. The `url` property will be stripped of the internal information
1726
1732
  * related to the data request in this case. Use this property instead if the distinction is important to you.
1727
1733
  */
1728
- isRemoteRequest: boolean;
1734
+ readonly isRemoteRequest: boolean;
1729
1735
  }
1730
1736
 
1731
1737
  /**
@@ -1,7 +1,6 @@
1
1
  /** @import { AssetDependencies, ManifestData, SSRNode, ValidatedKitConfig } from 'types' */
2
2
  /** @import { Manifest, Rolldown } from 'vite' */
3
3
  import fs from 'node:fs';
4
- import { mkdirp } from '../../../utils/filesystem.js';
5
4
  import {
6
5
  create_function_as_string,
7
6
  filter_fonts,
@@ -36,8 +35,8 @@ export function build_server_nodes(
36
35
  chunks,
37
36
  root
38
37
  ) {
39
- mkdirp(`${out}/server/nodes`);
40
- mkdirp(`${out}/server/stylesheets`);
38
+ fs.mkdirSync(`${out}/server/nodes`, { recursive: true });
39
+ fs.mkdirSync(`${out}/server/stylesheets`, { recursive: true });
41
40
 
42
41
  /**
43
42
  * Stylesheet names and their contents which are below the inline threshold
@@ -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
 
@@ -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,
@@ -106,6 +107,21 @@ const enforced_config = {
106
107
 
107
108
  const options_regex = /(export\s+const\s+(prerender|csr|ssr|trailingSlash))\s*=/s;
108
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
+
109
125
  /** @type {Set<string>} */
110
126
  const warned = new Set();
111
127
 
@@ -316,6 +332,26 @@ function kit({ svelte_config }) {
316
332
  api: {
317
333
  options: svelte_config
318
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
+ },
319
355
 
320
356
  /**
321
357
  * Build the SvelteKit-provided Vite config to be merged with the user's vite.config.js file.
@@ -472,6 +508,7 @@ function kit({ svelte_config }) {
472
508
  async handler(id, importer) {
473
509
  const resolved = await this.resolve(id, importer, { skipSelf: true });
474
510
  if (!resolved) return { id, external: true };
511
+ if (!is_remote_module(resolved.id)) return;
475
512
  // a servable /@fs url; 'absolute' stops rolldown relativizing it in the deps bundle
476
513
  return { id: to_fs(resolved.id), external: 'absolute' };
477
514
  }
@@ -582,7 +619,7 @@ function kit({ svelte_config }) {
582
619
 
583
620
  async configResolved(config) {
584
621
  explicit_env_entry = resolve_explicit_env_entry(kit);
585
- 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);
586
623
  },
587
624
 
588
625
  configureServer(server) {
@@ -596,6 +633,7 @@ function kit({ svelte_config }) {
596
633
  if (file === explicit_env_entry || file === resolved) {
597
634
  explicit_env_entry = resolved;
598
635
  explicit_env_config = await sync.env(
636
+ vite,
599
637
  kit,
600
638
  explicit_env_entry,
601
639
  vite_config.root,
@@ -894,6 +932,8 @@ function kit({ svelte_config }) {
894
932
  id: remote_module_pattern
895
933
  },
896
934
  async handler(code, id) {
935
+ if (!is_remote_module(id)) return;
936
+
897
937
  const file = posixify(path.relative(root, id));
898
938
  const remote = {
899
939
  hash: hash(file),
@@ -956,7 +996,7 @@ function kit({ svelte_config }) {
956
996
  // being called again with `opts.ssr === true` if the module isn't
957
997
  // already loaded) so we can determine what it exports
958
998
  if (dev_server) {
959
- const module = await get_runner(dev_server).import(id);
999
+ const module = await get_runner(vite, dev_server).import(id);
960
1000
 
961
1001
  for (const [name, value] of Object.entries(module)) {
962
1002
  const type = value?.__?.type;
@@ -1503,6 +1543,7 @@ function kit({ svelte_config }) {
1503
1543
  */
1504
1544
  async configureServer(server) {
1505
1545
  return await dev(
1546
+ vite,
1506
1547
  server,
1507
1548
  vite_config,
1508
1549
  svelte_config,
@@ -1555,9 +1596,9 @@ function kit({ svelte_config }) {
1555
1596
  async buildApp(builder) {
1556
1597
  // clears the output directories
1557
1598
  if (!builder.config.build.watch) {
1558
- rimraf(out);
1599
+ fs.rmSync(out, { force: true, recursive: true });
1559
1600
  }
1560
- mkdirp(out);
1601
+ fs.mkdirSync(out, { recursive: true });
1561
1602
 
1562
1603
  await load_and_validate_params({
1563
1604
  routes: manifest_data.routes,
@@ -1,3 +1,4 @@
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';
@@ -113,6 +114,16 @@ const query_pattern = /\?.*$/s;
113
114
  export function normalize_id(id, aliases, cwd) {
114
115
  id = id.replace(query_pattern, '');
115
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
+
116
127
  for (const { alias, path } of aliases) {
117
128
  if (id === path || id.startsWith(path + '/')) {
118
129
  id = id.replace(path, alias);
@@ -124,19 +135,61 @@ export function normalize_id(id, aliases, cwd) {
124
135
  id = path.relative(cwd, id);
125
136
  }
126
137
 
127
- if (id === app_server) {
128
- return '$app/server';
129
- }
138
+ return posixify(id);
139
+ }
130
140
 
131
- if (id === app_env_private || id === sveltekit_env_private) {
132
- 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
133
186
  }
134
187
 
135
- return posixify(id);
188
+ remote_module_cache.set(directory, cached);
189
+ return cached;
136
190
  }
137
191
 
138
- export const remote_module_pattern = /[/.]remote(\.[^/]+)+$/;
139
- export const server_only_module_pattern = /[/.]server(\.[^/]+)+$/;
192
+ export const server_only_module_pattern = /[/.]server\.[^/]+$/;
140
193
  export const server_only_directory_pattern = /\/server\//;
141
194
 
142
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;