@sveltejs/kit 3.0.0-next.2 → 3.0.0-next.21

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 (195) hide show
  1. package/package.json +62 -36
  2. package/src/cli.js +15 -12
  3. package/src/constants.js +6 -1
  4. package/src/core/adapt/builder.js +66 -72
  5. package/src/core/adapt/index.js +17 -6
  6. package/src/core/config/index.js +134 -80
  7. package/src/core/config/options.js +295 -273
  8. package/src/core/config/types.d.ts +1 -1
  9. package/src/core/env.js +146 -16
  10. package/src/core/generate_manifest/index.js +18 -15
  11. package/src/core/postbuild/analyse.js +8 -20
  12. package/src/core/postbuild/crawl.js +22 -6
  13. package/src/core/postbuild/entities.js +8 -2
  14. package/src/core/postbuild/fallback.js +4 -2
  15. package/src/core/postbuild/prerender.js +222 -70
  16. package/src/core/postbuild/queue.js +2 -1
  17. package/src/core/sync/create_manifest_data/conflict.js +1 -1
  18. package/src/core/sync/create_manifest_data/index.js +82 -62
  19. package/src/core/sync/sync.js +40 -31
  20. package/src/core/sync/ts.js +1 -1
  21. package/src/core/sync/utils.js +22 -2
  22. package/src/core/sync/{write_non_ambient.js → write_app_types.js} +107 -58
  23. package/src/core/sync/write_client_manifest.js +14 -29
  24. package/src/core/sync/write_env.js +7 -5
  25. package/src/core/sync/write_server.js +37 -45
  26. package/src/core/sync/write_tsconfig/index.js +274 -0
  27. package/src/core/sync/write_tsconfig/test-app/package.json +7 -0
  28. package/src/core/sync/write_tsconfig/utils.js +77 -0
  29. package/src/core/sync/write_tsconfig/validate.js +128 -0
  30. package/src/core/sync/write_types/index.js +127 -123
  31. package/src/core/utils.js +30 -5
  32. package/src/exports/env/index.js +77 -0
  33. package/src/exports/env/public.d.ts +55 -0
  34. package/src/exports/hooks/index.js +3 -9
  35. package/src/exports/hooks/public.d.ts +195 -0
  36. package/src/exports/hooks/sequence.js +9 -6
  37. package/src/exports/index.js +52 -29
  38. package/src/exports/internal/client.js +5 -0
  39. package/src/exports/internal/env.js +8 -5
  40. package/src/exports/internal/index.js +1 -90
  41. package/src/exports/internal/{event.js → server/event.js} +2 -3
  42. package/src/exports/internal/server/index.js +37 -0
  43. package/src/exports/internal/server/telemetry.js +95 -0
  44. package/src/exports/internal/shared.js +90 -0
  45. package/src/exports/node/index.js +64 -22
  46. package/src/exports/params/index.js +70 -0
  47. package/src/exports/params/public.d.ts +63 -0
  48. package/src/exports/public.d.ts +50 -1733
  49. package/src/exports/remote/index.js +11 -0
  50. package/src/exports/remote/public.d.ts +519 -0
  51. package/src/exports/url.js +86 -0
  52. package/src/exports/vite/build/build_server.js +54 -65
  53. package/src/exports/vite/build/remote.js +24 -19
  54. package/src/exports/vite/build/utils.js +0 -8
  55. package/src/exports/vite/dev/index.js +218 -146
  56. package/src/exports/vite/index.js +1590 -858
  57. package/src/exports/vite/module_ids.js +2 -2
  58. package/src/exports/vite/preview/index.js +40 -32
  59. package/src/exports/vite/public.d.ts +588 -0
  60. package/src/exports/vite/utils.js +84 -46
  61. package/src/pathname.js +55 -0
  62. package/src/runner.js +15 -0
  63. package/src/runtime/app/env/internal.js +4 -4
  64. package/src/runtime/app/env/types.d.ts +1 -1
  65. package/src/runtime/app/environment/index.js +3 -3
  66. package/src/runtime/app/{forms.js → forms/index.js} +73 -42
  67. package/src/runtime/app/forms/public.d.ts +2 -0
  68. package/src/runtime/app/forms/types.d.ts +56 -0
  69. package/src/runtime/app/internal/transport.js +53 -0
  70. package/src/runtime/app/manifest/index.js +1 -0
  71. package/src/runtime/app/{navigation.js → navigation/index.js} +2 -1
  72. package/src/runtime/app/navigation/public.d.ts +237 -0
  73. package/src/runtime/app/paths/client.js +37 -37
  74. package/src/runtime/app/paths/index.js +1 -1
  75. package/src/runtime/app/paths/internal/client.js +34 -2
  76. package/src/runtime/app/paths/internal/server.js +6 -23
  77. package/src/runtime/app/paths/internal.d.ts +3 -0
  78. package/src/runtime/app/paths/public.d.ts +1 -29
  79. package/src/runtime/app/paths/server.js +36 -17
  80. package/src/runtime/app/paths/types.d.ts +11 -19
  81. package/src/runtime/app/server/index.js +2 -2
  82. package/src/runtime/app/server/public.d.ts +201 -0
  83. package/src/runtime/app/server/remote/command.js +13 -11
  84. package/src/runtime/app/server/remote/form.js +61 -39
  85. package/src/runtime/app/server/remote/prerender.js +45 -45
  86. package/src/runtime/app/server/remote/query.js +106 -108
  87. package/src/runtime/app/server/remote/requested.js +27 -19
  88. package/src/runtime/app/server/remote/shared.js +76 -76
  89. package/src/runtime/app/service-worker/index.js +24 -0
  90. package/src/runtime/app/state/client.js +4 -2
  91. package/src/runtime/app/state/index.js +7 -5
  92. package/src/runtime/app/state/public.d.ts +72 -0
  93. package/src/runtime/app/state/server.js +3 -0
  94. package/src/runtime/app/stores.js +15 -78
  95. package/src/runtime/client/bundle.js +1 -1
  96. package/src/runtime/client/client-entry.js +3 -0
  97. package/src/runtime/client/client.js +1336 -648
  98. package/src/runtime/client/constants.js +3 -6
  99. package/src/runtime/client/entry.js +24 -3
  100. package/src/runtime/client/fetcher.js +25 -25
  101. package/src/runtime/client/ndjson.js +1 -1
  102. package/src/runtime/client/parse.js +1 -1
  103. package/src/runtime/client/payload.js +17 -0
  104. package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
  105. package/src/runtime/client/remote-functions/command.svelte.js +37 -61
  106. package/src/runtime/client/remote-functions/form.svelte.js +267 -178
  107. package/src/runtime/client/remote-functions/prerender.svelte.js +32 -11
  108. package/src/runtime/client/remote-functions/query/index.js +10 -17
  109. package/src/runtime/client/remote-functions/query/instance.svelte.js +64 -18
  110. package/src/runtime/client/remote-functions/query/proxy.js +5 -5
  111. package/src/runtime/client/remote-functions/query-batch.svelte.js +61 -70
  112. package/src/runtime/client/remote-functions/query-live/index.js +1 -1
  113. package/src/runtime/client/remote-functions/query-live/instance.svelte.js +63 -21
  114. package/src/runtime/client/remote-functions/query-live/iterator.js +15 -12
  115. package/src/runtime/client/remote-functions/query-live/proxy.js +2 -12
  116. package/src/runtime/client/remote-functions/shared.svelte.js +90 -65
  117. package/src/runtime/client/snapshots.js +147 -0
  118. package/src/runtime/client/state.svelte.js +94 -55
  119. package/src/runtime/client/stream.js +3 -2
  120. package/src/runtime/client/types.d.ts +13 -9
  121. package/src/runtime/client/utils.js +22 -110
  122. package/src/runtime/components/root.svelte +56 -0
  123. package/src/runtime/env/dynamic/private.js +7 -0
  124. package/src/runtime/env/dynamic/public.js +7 -0
  125. package/src/runtime/env/static/private.js +6 -0
  126. package/src/runtime/env/static/public.js +6 -0
  127. package/src/runtime/form-utils.js +172 -61
  128. package/src/runtime/pathname.js +20 -32
  129. package/src/runtime/props.svelte.js +72 -0
  130. package/src/runtime/server/constants.js +0 -3
  131. package/src/runtime/server/cookie.js +72 -55
  132. package/src/runtime/server/csrf.js +65 -0
  133. package/src/runtime/server/data/index.js +49 -53
  134. package/src/runtime/server/dev.js +22 -0
  135. package/src/runtime/server/endpoint.js +6 -7
  136. package/src/runtime/server/env_module.js +0 -5
  137. package/src/runtime/server/errors.js +160 -0
  138. package/src/runtime/server/fetch.js +32 -39
  139. package/src/runtime/server/index.js +90 -64
  140. package/src/runtime/server/internal.js +71 -0
  141. package/src/runtime/server/page/actions.js +85 -64
  142. package/src/runtime/server/page/crypto.js +2 -2
  143. package/src/runtime/server/page/csp.js +88 -104
  144. package/src/runtime/server/page/data_serializer.js +24 -25
  145. package/src/runtime/server/page/index.js +36 -53
  146. package/src/runtime/server/page/load_data.js +50 -57
  147. package/src/runtime/server/page/render.js +173 -239
  148. package/src/runtime/server/page/respond_with_error.js +17 -31
  149. package/src/runtime/server/page/serialize_data.js +2 -13
  150. package/src/runtime/server/page/server_routing.js +85 -26
  151. package/src/runtime/server/remote-functions.js +640 -0
  152. package/src/runtime/server/respond.js +190 -131
  153. package/src/runtime/server/sourcemaps.js +183 -0
  154. package/src/runtime/server/state.js +53 -0
  155. package/src/runtime/server/utils.js +13 -155
  156. package/src/runtime/shared.js +20 -40
  157. package/src/runtime/utils.js +3 -0
  158. package/src/types/ambient-private.d.ts +11 -1
  159. package/src/types/ambient.d.ts +87 -36
  160. package/src/types/global-private.d.ts +25 -25
  161. package/src/types/internal.d.ts +163 -157
  162. package/src/types/private.d.ts +41 -1
  163. package/src/utils/error.js +28 -4
  164. package/src/utils/escape.js +9 -25
  165. package/src/utils/features.js +1 -1
  166. package/src/utils/filesystem.js +1 -23
  167. package/src/utils/fork.js +7 -2
  168. package/src/utils/hash.js +21 -0
  169. package/src/utils/http.js +8 -7
  170. package/src/utils/import.js +9 -2
  171. package/src/utils/imports.js +83 -0
  172. package/src/utils/mime.js +9 -0
  173. package/src/utils/page_nodes.js +6 -7
  174. package/src/utils/params.js +67 -0
  175. package/src/utils/regex.js +9 -0
  176. package/src/utils/routing.js +145 -73
  177. package/src/utils/shared-iterator.js +5 -0
  178. package/src/utils/streaming.js +14 -4
  179. package/src/utils/url.js +33 -2
  180. package/src/version.js +1 -1
  181. package/types/index.d.ts +2616 -2433
  182. package/types/index.d.ts.map +120 -106
  183. package/src/core/sync/write_ambient.js +0 -18
  184. package/src/core/sync/write_root.js +0 -148
  185. package/src/core/sync/write_tsconfig.js +0 -250
  186. package/src/exports/internal/server.js +0 -22
  187. package/src/exports/node/polyfills.js +0 -30
  188. package/src/runtime/server/app.js +0 -9
  189. package/src/runtime/server/remote.js +0 -457
  190. package/src/runtime/shared-server.js +0 -7
  191. package/src/runtime/telemetry/otel.js +0 -21
  192. package/src/runtime/telemetry/record_span.js +0 -65
  193. package/src/types/synthetic/$lib.md +0 -5
  194. /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
  195. /package/src/{runtime/telemetry/noop.js → telemetry.js} +0 -0
@@ -1,40 +1,54 @@
1
- /** @import { RequestEvent } from '@sveltejs/kit' */
2
- /** @import { PrerenderOption, UniversalNode } from 'types' */
1
+ /** @import { SSRManifest } from '@sveltejs/kit' */
2
+ /** @import { RequestEvent } from '$app/server' */
3
+ /** @import { EnvironmentModuleNode, ErrorPayload, ResolvedConfig, ViteDevServer } from 'vite' */
4
+ /** @import { ManifestData, PrerenderOption, RemoteChunk, ServerModule, SSRNode, UniversalNode, ValidatedConfig } from 'types' */
5
+ import process from 'node:process';
3
6
  import fs from 'node:fs';
4
7
  import path from 'node:path';
5
8
  import { URL } from 'node:url';
6
9
  import { AsyncLocalStorage } from 'node:async_hooks';
7
10
  import { styleText } from 'node:util';
8
11
  import sirv from 'sirv';
9
- import { isCSSRequest, loadEnv, buildErrorMessage } from 'vite';
10
12
  import { createReadableStream, getRequest, setResponse } from '../../../exports/node/index.js';
11
13
  import { coalesce_to_error } from '../../../utils/error.js';
12
14
  import { resolve_entry } from '../../../utils/filesystem.js';
15
+ import { load_and_validate_params } from '../../../utils/params.js';
13
16
  import { from_fs, to_fs } from '../../../utils/vite.js';
14
17
  import { posixify } from '../../../utils/os.js';
15
18
  import { load_error_page } from '../../../core/config/index.js';
16
- import { SVELTE_KIT_ASSETS } from '../../../constants.js';
19
+ import { SRC_ROOT, SVELTE_KIT_ASSETS } from '../../../constants.js';
17
20
  import * as sync from '../../../core/sync/sync.js';
18
21
  import { get_mime_lookup, get_runtime_base } from '../../../core/utils.js';
22
+ import '../../../utils/mime.js'; // extend mrmime with additional types (affects sirv too)
19
23
  import { compact } from '../../../utils/array.js';
20
- import { is_chrome_devtools_request, not_found } from '../utils.js';
24
+ import { is_chrome_devtools_request, is_remote_module, not_found } from '../utils.js';
21
25
  import { SCHEME } from '../../../utils/url.js';
22
26
  import { check_feature } from '../../../utils/features.js';
23
27
  import { escape_html } from '../../../utils/escape.js';
28
+ import { get_runner } from '../../../runner.js';
24
29
 
25
30
  // vite-specifc queries that we should skip handling for css urls
26
31
  const vite_css_query_regex = /(?:\?|&)(?:raw|url|inline)(?:&|$)/;
27
32
 
28
33
  /**
29
- * @param {import('vite').ViteDevServer} vite
30
- * @param {import('vite').ResolvedConfig} vite_config
31
- * @param {import('types').ValidatedConfig} svelte_config
32
- * @param {() => Array<{ hash: string, file: string }>} get_remotes
34
+ * @param {typeof import('vite')} vite the peer resolved vite module
35
+ * @param {ViteDevServer} vite_dev_server
36
+ * @param {ResolvedConfig} vite_config
37
+ * @param {ValidatedConfig} svelte_config
38
+ * @param {() => RemoteChunk[]} get_remotes
33
39
  * @param {string} root The project root directory
34
- * @param {import('@sveltejs/kit').Adapter | undefined} adapter
40
+ * @param {(manifest_data: ManifestData) => void} set_manifest_data
35
41
  * @return {Promise<Promise<() => void>>}
36
42
  */
37
- export async function dev(vite, vite_config, svelte_config, get_remotes, root, adapter) {
43
+ export async function dev(
44
+ vite,
45
+ vite_dev_server,
46
+ vite_config,
47
+ svelte_config,
48
+ get_remotes,
49
+ root,
50
+ set_manifest_data
51
+ ) {
38
52
  /** @type {AsyncLocalStorage<{ event: RequestEvent, config: any, prerender: PrerenderOption }>} */
39
53
  const async_local_storage = new AsyncLocalStorage();
40
54
 
@@ -42,7 +56,12 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
42
56
  const context = async_local_storage.getStore();
43
57
  if (!context || context.prerender === true) return;
44
58
 
45
- check_feature(/** @type {string} */ (context.event.route.id), context.config, label, adapter);
59
+ check_feature(
60
+ /** @type {string} */ (context.event.route.id),
61
+ context.config,
62
+ label,
63
+ svelte_config.adapter
64
+ );
46
65
  };
47
66
 
48
67
  const fetch = globalThis.fetch;
@@ -58,30 +77,39 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
58
77
 
59
78
  sync.init(svelte_config, root);
60
79
 
61
- /** @type {import('types').ManifestData} */
80
+ /** @type {ManifestData} */
62
81
  let manifest_data;
63
- /** @type {import('@sveltejs/kit').SSRManifest} */
82
+ /** @type {SSRManifest} */
64
83
  let manifest;
65
84
 
66
85
  /** @type {Error | null} */
67
86
  let manifest_error = null;
68
87
 
69
- /** @param {string} url */
88
+ const runner = get_runner(vite, vite_dev_server);
89
+
90
+ /**
91
+ * @param {string} url
92
+ * @returns {Promise<Record<string, any>>}
93
+ */
70
94
  async function loud_ssr_load_module(url) {
71
95
  try {
72
- return await vite.ssrLoadModule(url, { fixStacktrace: true });
96
+ return await runner.import(url);
73
97
  } catch (/** @type {any} */ err) {
74
- const msg = buildErrorMessage(err, [
98
+ const msg = vite.buildErrorMessage(err, [
75
99
  styleText('red', `Internal server error: ${err.message}`)
76
100
  ]);
77
101
 
78
- if (!vite.config.logger.hasErrorLogged(err)) {
79
- vite.config.logger.error(msg, { error: err });
102
+ if (!vite_dev_server.config.logger.hasErrorLogged(err)) {
103
+ vite_dev_server.config.logger.error(msg, { error: err });
80
104
  }
81
105
 
82
- vite.ws.send({
106
+ // TODO this is inadequate — it doesn't reliably show the overlay on every page load,
107
+ // and when it does appear it may immediately vanish. `vite.hot.send` broadcasts
108
+ // to all connected clients, even ones that are unaffected by the error.
109
+ // we need a more considered approach
110
+ vite_dev_server.hot.send({
83
111
  type: 'error',
84
- err: /** @type {import('vite').ErrorPayload['err']} */ ({
112
+ err: /** @type {ErrorPayload['err']} */ ({
85
113
  ...err,
86
114
  // these properties are non-enumerable and will
87
115
  // not be serialized unless we explicitly include them
@@ -100,25 +128,33 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
100
128
 
101
129
  const module = await loud_ssr_load_module(url);
102
130
 
103
- const module_node = await vite.moduleGraph.getModuleByUrl(url);
131
+ const module_node = await vite_dev_server.environments.ssr.moduleGraph.getModuleByUrl(url);
104
132
  if (!module_node) throw new Error(`Could not find node for ${url}`);
105
133
 
106
134
  return { module, module_node, url };
107
135
  }
108
136
 
109
- function update_manifest() {
137
+ async function update_manifest() {
110
138
  try {
111
139
  ({ manifest_data } = sync.create(svelte_config, root));
140
+ set_manifest_data(manifest_data);
141
+
142
+ await load_and_validate_params({
143
+ routes: manifest_data.routes,
144
+ params_path: manifest_data.params,
145
+ root,
146
+ load: (file) => loud_ssr_load_module(file)
147
+ });
112
148
 
113
149
  if (manifest_error) {
114
150
  manifest_error = null;
115
- vite.ws.send({ type: 'full-reload' });
151
+ vite_dev_server.hot.send({ type: 'full-reload' });
116
152
  }
117
153
  } catch (error) {
118
154
  manifest_error = /** @type {Error} */ (error);
119
155
 
120
156
  console.error(styleText(['bold', 'red'], manifest_error.message));
121
- vite.ws.send({
157
+ vite_dev_server.hot.send({
122
158
  type: 'error',
123
159
  err: {
124
160
  message: manifest_error.message ?? 'Invalid routes',
@@ -130,29 +166,29 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
130
166
  }
131
167
 
132
168
  manifest = {
133
- appDir: svelte_config.kit.appDir,
134
- appPath: svelte_config.kit.appDir,
169
+ appDir: svelte_config.appDir,
170
+ appPath: svelte_config.appDir,
135
171
  assets: new Set(manifest_data.assets.map((asset) => asset.file)),
136
172
  mimeTypes: get_mime_lookup(manifest_data),
137
173
  _: {
138
174
  client: {
139
175
  start: `${get_runtime_base(root)}/client/entry.js`,
140
- app: `${to_fs(svelte_config.kit.outDir)}/generated/client/app.js`,
176
+ app: `${to_fs(svelte_config.outDir)}/generated/client/app.js`,
141
177
  imports: [],
142
178
  stylesheets: [],
143
179
  fonts: [],
144
180
  uses_env_dynamic_public: true,
145
181
  nodes:
146
- svelte_config.kit.router.resolution === 'client'
182
+ svelte_config.router.resolution === 'client'
147
183
  ? undefined
148
184
  : manifest_data.nodes.map((node, i) => {
149
185
  if (node.component || node.universal) {
150
- return `${svelte_config.kit.paths.base}${to_fs(svelte_config.kit.outDir)}/generated/client/nodes/${i}.js`;
186
+ return `${svelte_config.paths.base}${to_fs(svelte_config.outDir)}/generated/client/nodes/${i}.js`;
151
187
  }
152
188
  }),
153
189
  // `css` is not necessary in dev, as the JS file from `nodes` will reference the CSS file
154
190
  routes:
155
- svelte_config.kit.router.resolution === 'client'
191
+ svelte_config.router.resolution === 'client'
156
192
  ? undefined
157
193
  : compact(
158
194
  manifest_data.routes.map((route) => {
@@ -180,8 +216,7 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
180
216
  ),
181
217
  nodes: manifest_data.nodes.map((node, index) => {
182
218
  return async () => {
183
- /** @type {import('types').SSRNode} */
184
- const result = {};
219
+ const result = /** @type {SSRNode} */ ({});
185
220
  result.index = index;
186
221
  result.universal_id = node.universal;
187
222
  result.server_id = node.server;
@@ -191,7 +226,7 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
191
226
  result.stylesheets = [];
192
227
  result.fonts = [];
193
228
 
194
- /** @type {import('vite').ModuleNode[]} */
229
+ /** @type {EnvironmentModuleNode[]} */
195
230
  const module_nodes = [];
196
231
 
197
232
  if (node.component) {
@@ -225,23 +260,23 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
225
260
  // in dev we inline all styles to avoid FOUC. this gets populated lazily so that
226
261
  // components/stylesheets loaded via import() during `load` are included
227
262
  result.inline_styles = async () => {
228
- /** @type {Set<import('vite').ModuleNode | import('vite').EnvironmentModuleNode>} */
263
+ /** @type {Set<EnvironmentModuleNode>} */
229
264
  const deps = new Set();
230
265
 
231
266
  for (const module_node of module_nodes) {
232
- await find_deps(vite, module_node, deps);
267
+ await find_deps(vite_dev_server, module_node, deps);
233
268
  }
234
269
 
235
270
  /** @type {Record<string, string>} */
236
271
  const styles = {};
237
272
 
238
273
  for (const dep of deps) {
239
- if (isCSSRequest(dep.url) && !vite_css_query_regex.test(dep.url)) {
274
+ if (vite.isCSSRequest(dep.url) && !vite_css_query_regex.test(dep.url)) {
240
275
  const inlineCssUrl = dep.url.includes('?')
241
276
  ? dep.url.replace('?', '?inline&')
242
277
  : dep.url + '?inline';
243
278
  try {
244
- const mod = await vite.ssrLoadModule(inlineCssUrl);
279
+ const mod = await runner.import(inlineCssUrl);
245
280
  styles[dep.url] = mod.default;
246
281
  } catch {
247
282
  // this can happen with dynamically imported modules, I think
@@ -262,7 +297,7 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
262
297
  return Object.fromEntries(
263
298
  get_remotes().map((remote) => [
264
299
  remote.hash,
265
- () => vite.ssrLoadModule(remote.file).then((module) => ({ default: module }))
300
+ () => runner.import(remote.file).then((module) => ({ default: module }))
266
301
  ])
267
302
  );
268
303
  },
@@ -288,22 +323,18 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
288
323
  })
289
324
  ),
290
325
  matchers: async () => {
291
- /** @type {Record<string, import('@sveltejs/kit').ParamMatcher>} */
292
- const matchers = {};
293
-
294
- for (const key in manifest_data.matchers) {
295
- const file = manifest_data.matchers[key];
296
- const url = path.resolve(root, file);
297
- const module = await vite.ssrLoadModule(url, { fixStacktrace: true });
298
-
299
- if (module.match) {
300
- matchers[key] = module.match;
301
- } else {
302
- throw new Error(`${file} does not export a \`match\` function`);
303
- }
326
+ if (!manifest_data.params) return {};
327
+
328
+ const url = path.resolve(root, manifest_data.params);
329
+ const module = await runner.import(url);
330
+
331
+ if (!module.params) {
332
+ throw new Error(
333
+ `${manifest_data.params} does not export \`params\` from \`defineParams\``
334
+ );
304
335
  }
305
336
 
306
- return matchers;
337
+ return module.params;
307
338
  }
308
339
  }
309
340
  };
@@ -311,30 +342,62 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
311
342
 
312
343
  /** @param {Error} error */
313
344
  function fix_stack_trace(error) {
314
- try {
315
- vite.ssrFixStacktrace(error);
316
- } catch {
317
- // ssrFixStacktrace can fail on StackBlitz web containers and we don't know why
318
- // by ignoring it the line numbers are wrong, but at least we can show the error
345
+ if (!error.stack) {
346
+ return;
319
347
  }
320
- return error.stack?.replaceAll('\0', ''); // remove null bytes from e.g. virtual module IDs, or the response will fail
348
+
349
+ let prelude = '';
350
+ let start = -1;
351
+ let end = 0;
352
+
353
+ const lines = error.stack
354
+ .replaceAll('\0', '') // remove null bytes from e.g. virtual module IDs, or the response will fail
355
+ .split('\n')
356
+ .map((line, i) => {
357
+ const match = /^ {4}at (?:[^(]+ \((.+)\)|(.+))$/.exec(line);
358
+ if (!match) {
359
+ prelude += line + '\n';
360
+ end = i + 1;
361
+ return line;
362
+ }
363
+
364
+ const loc = match[1] ?? match[2];
365
+ const file = loc.replace(/:\d+:\d+$/, '');
366
+
367
+ if (fs.existsSync(file)) {
368
+ if (!file.includes('node_modules') && !file.includes(SRC_ROOT)) {
369
+ if (start === -1) start = i;
370
+ end = i + 1;
371
+ }
372
+
373
+ return line.replace(file, path.relative(process.cwd(), file));
374
+ }
375
+
376
+ return line;
377
+ })
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);
381
+
382
+ return (error.stack = prelude + lines.join('\n'));
321
383
  }
322
384
 
323
- update_manifest();
385
+ const params_file = resolve_entry(svelte_config.files.params);
324
386
 
325
387
  /**
326
388
  * @param {string} event
327
389
  * @param {(file: string) => void} cb
328
390
  */
329
391
  const watch = (event, cb) => {
330
- vite.watcher.on(event, (file) => {
392
+ vite_dev_server.watcher.on(event, (file) => {
331
393
  if (
332
- file.startsWith(svelte_config.kit.files.routes + path.sep) ||
333
- file.startsWith(svelte_config.kit.files.params + path.sep) ||
334
- svelte_config.kit.moduleExtensions.some((ext) => file.endsWith(`.remote${ext}`)) ||
394
+ file.startsWith(svelte_config.files.routes + path.sep) ||
395
+ file.startsWith(svelte_config.files.assets + path.sep) ||
396
+ (params_file && file === params_file) ||
397
+ is_remote_module(file) ||
335
398
  // in contrast to server hooks, client hooks are written to the client manifest
336
399
  // and therefore need rebuilding when they are added/removed
337
- file.startsWith(svelte_config.kit.files.hooks.client)
400
+ file.startsWith(svelte_config.files.hooks.client)
338
401
  ) {
339
402
  cb(file);
340
403
  }
@@ -351,35 +414,37 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
351
414
  }, 100);
352
415
  };
353
416
 
354
- // flag to skip watchers if server is already restarting
355
- let restarting = false;
356
-
357
417
  // Debounce add/unlink events because in case of folder deletion or moves
358
418
  // they fire in rapid succession, causing needless invocations.
359
419
  // These watchers only run for routes, param matchers, and client hooks.
360
420
  watch('add', () => debounce(update_manifest));
361
421
  watch('unlink', () => debounce(update_manifest));
362
422
  watch('change', (file) => {
423
+ // `manifest_data` is populated lazily on the first request (see `update_manifest`
424
+ // call in the middleware below), so it may still be undefined if a file changes
425
+ // before the dev server has served a request. In that case there's nothing to
426
+ // update — the manifest will be created from scratch on the first request.
427
+ if (!manifest_data) return;
363
428
  // Don't run for a single file if the whole manifest is about to get updated
364
429
  // Unless it's a file where the trailing slash page option might have changed
365
- if (timeout || restarting || !/\+(page|layout|server).*$/.test(file)) return;
366
- sync.update(svelte_config, manifest_data, file, root);
430
+ if (timeout || !/\+(page|layout|server).*$/.test(file)) return;
431
+ if (!sync.update(svelte_config, manifest_data, file, root)) debounce(update_manifest);
367
432
  });
368
433
 
369
- const { appTemplate, errorTemplate, serviceWorker, hooks } = svelte_config.kit.files;
434
+ const { appTemplate, errorTemplate, serviceWorker, hooks } = svelte_config.files;
370
435
 
371
436
  // vite client only executes a full reload if the triggering html file path is index.html
372
437
  // kit defaults to src/app.html, so unless user changed that to index.html
373
438
  // send the vite client a full-reload event without path being set
374
439
  if (appTemplate !== 'index.html') {
375
- vite.watcher.on('change', (file) => {
376
- if (file === appTemplate && !restarting) {
377
- vite.ws.send({ type: 'full-reload' });
440
+ vite_dev_server.watcher.on('change', (file) => {
441
+ if (file === appTemplate) {
442
+ vite_dev_server.hot.send({ type: 'full-reload' });
378
443
  }
379
444
  });
380
445
  }
381
446
 
382
- vite.watcher.on('all', (_, file) => {
447
+ vite_dev_server.watcher.on('all', (_, file) => {
383
448
  if (
384
449
  file === appTemplate ||
385
450
  file === errorTemplate ||
@@ -390,30 +455,16 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
390
455
  }
391
456
  });
392
457
 
393
- vite.watcher.on('change', async (file) => {
394
- // changing the svelte config requires restarting the dev server
395
- // the config is only read on start and passed on to vite-plugin-svelte
396
- // which needs up-to-date values to operate correctly
397
- if (file.match(/[/\\]svelte\.config\.[jt]s$/)) {
398
- console.log(`svelte config changed, restarting vite dev-server. changed file: ${file}`);
399
- restarting = true;
400
- await vite.restart();
401
- }
402
- });
403
-
404
- const assets = svelte_config.kit.paths.assets ? SVELTE_KIT_ASSETS : svelte_config.kit.paths.base;
405
- const asset_server = sirv(svelte_config.kit.files.assets, {
458
+ const assets = svelte_config.paths.assets ? SVELTE_KIT_ASSETS : svelte_config.paths.base;
459
+ const asset_server = sirv(svelte_config.files.assets, {
406
460
  dev: true,
407
461
  etag: true,
408
462
  maxAge: 0,
409
- extensions: [],
410
- setHeaders: (res) => {
411
- res.setHeader('access-control-allow-origin', '*');
412
- }
463
+ extensions: []
413
464
  });
414
465
 
415
- vite.middlewares.use((req, res, next) => {
416
- 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'}://${
417
468
  req.headers[':authority'] || req.headers.host
418
469
  }`;
419
470
 
@@ -421,10 +472,10 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
421
472
 
422
473
  if (decoded.startsWith(assets)) {
423
474
  const pathname = decoded.slice(assets.length);
424
- const file = svelte_config.kit.files.assets + pathname;
475
+ const file = svelte_config.files.assets + pathname;
425
476
 
426
477
  if (fs.existsSync(file) && !fs.statSync(file).isDirectory()) {
427
- if (has_correct_case(file, svelte_config.kit.files.assets)) {
478
+ if (has_correct_case(file, svelte_config.files.assets)) {
428
479
  req.url = encodeURI(pathname); // don't need query/hash
429
480
  asset_server(req, res);
430
481
  return;
@@ -435,31 +486,39 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
435
486
  next();
436
487
  });
437
488
 
438
- const env = loadEnv(vite_config.mode, svelte_config.kit.env.dir, '');
439
- const emulator = await adapter?.emulate?.();
489
+ const env = vite.loadEnv(vite_config.mode, svelte_config.env.dir, '');
490
+ const emulator = await svelte_config.adapter?.emulate?.();
491
+
492
+ /** @type {Promise<void> | undefined} */
493
+ let init_manifest;
440
494
 
441
495
  return () => {
442
- const serve_static_middleware = vite.middlewares.stack.find(
496
+ const serve_static_middleware = vite_dev_server.middlewares.stack.find(
443
497
  (middleware) =>
444
498
  /** @type {Function} */ (middleware.handle).name === 'viteServeStaticMiddleware'
445
499
  );
446
500
 
447
501
  // Vite will give a 403 on URLs like /test, /static, and /package.json preventing us from
448
502
  // serving routes with those names. See https://github.com/vitejs/vite/issues/7363
449
- remove_static_middlewares(vite.middlewares);
503
+ remove_static_middlewares(vite_dev_server.middlewares);
504
+
505
+ vite_dev_server.middlewares.use(async (req, res) => {
506
+ // Vite throws a Cannot read properties of undefined (reading 'wrapDynamicImport')
507
+ // if you try to run ssr.runner.import before the server has started so
508
+ // we do it inside here to avoid that
509
+ await (init_manifest ??= update_manifest());
450
510
 
451
- vite.middlewares.use(async (req, res) => {
452
511
  // Vite's base middleware strips out the base path. Restore it
453
512
  const original_url = req.url;
454
513
  req.url = req.originalUrl;
455
514
  try {
456
- const base = `${vite.config.server.https ? 'https' : 'http'}://${
515
+ const base = `${vite_dev_server.config.server.https ? 'https' : 'http'}://${
457
516
  req.headers[':authority'] || req.headers.host
458
517
  }`;
459
518
 
460
519
  const decoded = decodeURI(new URL(base + req.url).pathname);
461
520
  const file = posixify(
462
- path.resolve(root, decoded.slice(svelte_config.kit.paths.base.length + 1))
521
+ path.resolve(root, decoded.slice(svelte_config.paths.base.length + 1))
463
522
  );
464
523
  const is_file = fs.existsSync(file) && !fs.statSync(file).isDirectory();
465
524
  const allowed =
@@ -477,18 +536,18 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
477
536
  return;
478
537
  }
479
538
 
480
- if (!decoded.startsWith(svelte_config.kit.paths.base)) {
481
- return not_found(req, res, svelte_config.kit.paths.base);
539
+ if (!decoded.startsWith(svelte_config.paths.base)) {
540
+ return not_found(req, res, svelte_config.paths.base);
482
541
  }
483
542
 
484
- if (decoded === svelte_config.kit.paths.base + '/service-worker.js') {
485
- const resolved = resolve_entry(svelte_config.kit.files.serviceWorker);
543
+ if (decoded === svelte_config.paths.base + '/service-worker.js') {
544
+ const resolved = resolve_entry(svelte_config.files.serviceWorker);
486
545
 
487
546
  if (resolved) {
488
547
  res.writeHead(200, {
489
548
  'content-type': 'application/javascript'
490
549
  });
491
- res.end(`import '${svelte_config.kit.paths.base}${to_fs(resolved)}';`);
550
+ res.end(`import '${svelte_config.paths.base}${to_fs(resolved)}';`);
492
551
  } else {
493
552
  res.writeHead(404);
494
553
  res.end('not found');
@@ -497,27 +556,33 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
497
556
  return;
498
557
  }
499
558
 
559
+ // resolve the instrumentation file per request so that changes to it
560
+ // are picked up on new requests
500
561
  const resolved_instrumentation = resolve_entry(
501
- path.join(svelte_config.kit.files.src, 'instrumentation.server')
562
+ path.join(svelte_config.files.src, 'instrumentation.server')
502
563
  );
503
564
 
504
565
  if (resolved_instrumentation) {
505
- await vite.ssrLoadModule(resolved_instrumentation);
566
+ if (svelte_config.adapter && !svelte_config.adapter.supports?.instrumentation?.()) {
567
+ throw new Error(
568
+ `${resolved_instrumentation} is unsupported in ${svelte_config.adapter.name}.`
569
+ );
570
+ }
571
+
572
+ await runner.import(resolved_instrumentation);
506
573
  }
507
574
 
508
575
  // we have to import `Server` before calling `set_assets`
509
- const { Server } = /** @type {import('types').ServerModule} */ (
510
- await vite.ssrLoadModule(`${get_runtime_base(root)}/server/index.js`, {
511
- fixStacktrace: true
512
- })
576
+ const { Server } = /** @type {ServerModule} */ (
577
+ await runner.import(`${get_runtime_base(root)}/server/index.js`)
513
578
  );
514
579
 
515
- const { set_fix_stack_trace } = await vite.ssrLoadModule(
516
- `${get_runtime_base(root)}/shared-server.js`
580
+ const { set_fix_stack_trace, log_response } = await runner.import(
581
+ `${get_runtime_base(root)}/server/internal.js`
517
582
  );
518
583
  set_fix_stack_trace(fix_stack_trace);
519
584
 
520
- const { set_assets } = await vite.ssrLoadModule('$app/paths/internal/server');
585
+ const { set_assets } = await runner.import('$app/paths/internal/server');
521
586
  set_assets(assets);
522
587
 
523
588
  const server = new Server(manifest);
@@ -527,7 +592,7 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
527
592
  read: (file) => createReadableStream(from_fs(file))
528
593
  });
529
594
 
530
- const request = await getRequest({
595
+ const request = getRequest({
531
596
  base,
532
597
  request: req
533
598
  });
@@ -565,7 +630,7 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
565
630
  return fs.readFileSync(from_fs(file));
566
631
  }
567
632
 
568
- return fs.readFileSync(path.join(svelte_config.kit.files.assets, file));
633
+ return fs.readFileSync(path.join(svelte_config.files.assets, file));
569
634
  },
570
635
  before_handle: async (event, config, prerender, handle) => {
571
636
  // we need to use .run because .enterWith() is not supported in Cloudflare Workers
@@ -578,15 +643,19 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
578
643
  if (rendered.status === 404) {
579
644
  // @ts-expect-error
580
645
  serve_static_middleware.handle(req, res, () => {
581
- void setResponse(res, rendered);
646
+ log_response(rendered.status, request);
647
+ setResponse(res, rendered);
582
648
  });
583
649
  } else {
584
- void setResponse(res, rendered);
650
+ log_response(rendered.status, request);
651
+ setResponse(res, rendered);
585
652
  }
586
653
  } catch (e) {
587
654
  const error = coalesce_to_error(e);
588
655
  res.statusCode = 500;
589
- res.end(fix_stack_trace(error) || error.message); // handle `stackless` errors
656
+ fix_stack_trace(error);
657
+ console.error(styleText(['bold', 'red'], String(error)));
658
+ res.end(error.stack || error.message); // handle `stackless` errors
590
659
  }
591
660
  });
592
661
  };
@@ -606,17 +675,17 @@ function remove_static_middlewares(server) {
606
675
  }
607
676
 
608
677
  /**
609
- * @param {import('vite').ViteDevServer} vite
610
- * @param {import('vite').ModuleNode | import('vite').EnvironmentModuleNode} node
611
- * @param {Set<import('vite').ModuleNode | import('vite').EnvironmentModuleNode>} deps
678
+ * @param {ViteDevServer} vite
679
+ * @param {EnvironmentModuleNode} node
680
+ * @param {Set<EnvironmentModuleNode>} deps
612
681
  */
613
682
  async function find_deps(vite, node, deps) {
614
- // since `ssrTransformResult.deps` contains URLs instead of `ModuleNode`s, this process is asynchronous.
683
+ // since `transformResult.deps` contains URLs instead of `ModuleNode`s, this process is asynchronous.
615
684
  // instead of using `await`, we resolve all branches in parallel.
616
685
  /** @type {Promise<void>[]} */
617
686
  const branches = [];
618
687
 
619
- /** @param {import('vite').ModuleNode | import('vite').EnvironmentModuleNode} node */
688
+ /** @param {EnvironmentModuleNode} node */
620
689
  async function add(node) {
621
690
  if (!deps.has(node)) {
622
691
  deps.add(node);
@@ -626,23 +695,20 @@ async function find_deps(vite, node, deps) {
626
695
 
627
696
  /** @param {string} url */
628
697
  async function add_by_url(url) {
629
- const node = await get_server_module_by_url(vite, url);
698
+ const node = await vite.environments.ssr.moduleGraph.getModuleByUrl(url);
630
699
 
631
700
  if (node) {
632
701
  await add(node);
633
702
  }
634
703
  }
635
704
 
636
- const transform_result =
637
- /** @type {import('vite').ModuleNode} */ (node).ssrTransformResult || node.transformResult;
638
-
639
- if (transform_result) {
640
- if (transform_result.deps) {
641
- transform_result.deps.forEach((url) => branches.push(add_by_url(url)));
705
+ if (node.transformResult) {
706
+ if (node.transformResult.deps) {
707
+ node.transformResult.deps.forEach((url) => branches.push(add_by_url(url)));
642
708
  }
643
709
 
644
- if (transform_result.dynamicDeps) {
645
- transform_result.dynamicDeps.forEach((url) => branches.push(add_by_url(url)));
710
+ if (node.transformResult.dynamicDeps) {
711
+ node.transformResult.dynamicDeps.forEach((url) => branches.push(add_by_url(url)));
646
712
  }
647
713
  } else {
648
714
  node.importedModules.forEach((node) => branches.push(add(node)));
@@ -651,16 +717,6 @@ async function find_deps(vite, node, deps) {
651
717
  await Promise.all(branches);
652
718
  }
653
719
 
654
- /**
655
- * @param {import('vite').ViteDevServer} vite
656
- * @param {string} url
657
- */
658
- function get_server_module_by_url(vite, url) {
659
- return vite.environments
660
- ? vite.environments.ssr.moduleGraph.getModuleByUrl(url)
661
- : vite.moduleGraph.getModuleByUrl(url, true);
662
- }
663
-
664
720
  /**
665
721
  * Determine if a file is being requested with the correct case,
666
722
  * to ensure consistent behaviour between dev and prod and across
@@ -681,3 +737,19 @@ function has_correct_case(file, assets) {
681
737
 
682
738
  return false;
683
739
  }
740
+
741
+ /**
742
+ * Invalidates a module in all environments.
743
+ * @param {ViteDevServer} server
744
+ * @param {string} id
745
+ * @returns {void}
746
+ */
747
+ export function invalidate_module(server, id) {
748
+ for (const environment in server.environments) {
749
+ const module = server.environments[environment].moduleGraph.getModuleById(id);
750
+ if (module) {
751
+ server.environments[environment].moduleGraph.invalidateModule(module);
752
+ void server.environments[environment].reloadModule(module);
753
+ }
754
+ }
755
+ }