@sveltejs/kit 1.0.0-next.52 → 1.0.0-next.520

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 (128) hide show
  1. package/README.md +6 -3
  2. package/package.json +93 -67
  3. package/postinstall.js +47 -0
  4. package/scripts/special-types/$env+dynamic+private.md +10 -0
  5. package/scripts/special-types/$env+dynamic+public.md +8 -0
  6. package/scripts/special-types/$env+static+private.md +19 -0
  7. package/scripts/special-types/$env+static+public.md +7 -0
  8. package/scripts/special-types/$lib.md +5 -0
  9. package/src/cli.js +108 -0
  10. package/src/constants.js +7 -0
  11. package/src/core/adapt/builder.js +215 -0
  12. package/src/core/adapt/index.js +31 -0
  13. package/src/core/config/default-error.html +56 -0
  14. package/src/core/config/index.js +110 -0
  15. package/src/core/config/options.js +504 -0
  16. package/src/core/config/types.d.ts +1 -0
  17. package/src/core/env.js +121 -0
  18. package/src/core/generate_manifest/index.js +94 -0
  19. package/src/core/prerender/crawl.js +198 -0
  20. package/src/core/prerender/entities.js +2252 -0
  21. package/src/core/prerender/prerender.js +458 -0
  22. package/src/core/prerender/queue.js +80 -0
  23. package/src/core/sync/create_manifest_data/conflict.js +0 -0
  24. package/src/core/sync/create_manifest_data/index.js +470 -0
  25. package/src/core/sync/create_manifest_data/sort.js +163 -0
  26. package/src/core/sync/create_manifest_data/types.d.ts +37 -0
  27. package/src/core/sync/sync.js +78 -0
  28. package/src/core/sync/utils.js +33 -0
  29. package/src/core/sync/write_ambient.js +53 -0
  30. package/src/core/sync/write_client_manifest.js +106 -0
  31. package/src/core/sync/write_matchers.js +25 -0
  32. package/src/core/sync/write_root.js +91 -0
  33. package/src/core/sync/write_tsconfig.js +195 -0
  34. package/src/core/sync/write_types/index.js +783 -0
  35. package/src/core/utils.js +70 -0
  36. package/src/exports/hooks/index.js +1 -0
  37. package/src/exports/hooks/sequence.js +44 -0
  38. package/src/exports/index.js +45 -0
  39. package/src/exports/node/index.js +161 -0
  40. package/src/exports/node/polyfills.js +28 -0
  41. package/src/exports/vite/build/build_server.js +378 -0
  42. package/src/exports/vite/build/build_service_worker.js +91 -0
  43. package/src/exports/vite/build/utils.js +181 -0
  44. package/src/exports/vite/dev/index.js +581 -0
  45. package/src/exports/vite/graph_analysis/index.js +277 -0
  46. package/src/exports/vite/graph_analysis/types.d.ts +5 -0
  47. package/src/exports/vite/graph_analysis/utils.js +30 -0
  48. package/src/exports/vite/index.js +603 -0
  49. package/src/exports/vite/preview/index.js +189 -0
  50. package/src/exports/vite/types.d.ts +3 -0
  51. package/src/exports/vite/utils.js +157 -0
  52. package/src/runtime/app/env.js +1 -0
  53. package/src/runtime/app/environment.js +11 -0
  54. package/src/runtime/app/forms.js +123 -0
  55. package/src/runtime/app/navigation.js +23 -0
  56. package/src/runtime/app/paths.js +1 -0
  57. package/src/runtime/app/stores.js +102 -0
  58. package/src/runtime/client/ambient.d.ts +30 -0
  59. package/src/runtime/client/client.js +1595 -0
  60. package/src/runtime/client/fetcher.js +107 -0
  61. package/src/runtime/client/parse.js +60 -0
  62. package/src/runtime/client/singletons.js +21 -0
  63. package/src/runtime/client/start.js +37 -0
  64. package/src/runtime/client/types.d.ts +84 -0
  65. package/src/runtime/client/utils.js +159 -0
  66. package/src/runtime/components/error.svelte +16 -0
  67. package/{assets → src/runtime}/components/layout.svelte +0 -0
  68. package/src/runtime/control.js +98 -0
  69. package/src/runtime/env/dynamic/private.js +1 -0
  70. package/src/runtime/env/dynamic/public.js +1 -0
  71. package/src/runtime/env-private.js +6 -0
  72. package/src/runtime/env-public.js +6 -0
  73. package/src/runtime/env.js +6 -0
  74. package/src/runtime/hash.js +20 -0
  75. package/src/runtime/paths.js +11 -0
  76. package/src/runtime/server/cookie.js +166 -0
  77. package/src/runtime/server/data/index.js +131 -0
  78. package/src/runtime/server/endpoint.js +92 -0
  79. package/src/runtime/server/fetch.js +174 -0
  80. package/src/runtime/server/index.js +355 -0
  81. package/src/runtime/server/page/actions.js +256 -0
  82. package/src/runtime/server/page/crypto.js +239 -0
  83. package/src/runtime/server/page/csp.js +250 -0
  84. package/src/runtime/server/page/index.js +304 -0
  85. package/src/runtime/server/page/load_data.js +215 -0
  86. package/src/runtime/server/page/render.js +346 -0
  87. package/src/runtime/server/page/respond_with_error.js +102 -0
  88. package/src/runtime/server/page/serialize_data.js +87 -0
  89. package/src/runtime/server/page/types.d.ts +35 -0
  90. package/src/runtime/server/utils.js +181 -0
  91. package/src/utils/array.js +9 -0
  92. package/src/utils/error.js +22 -0
  93. package/src/utils/escape.js +46 -0
  94. package/src/utils/filesystem.js +142 -0
  95. package/src/utils/functions.js +16 -0
  96. package/src/utils/http.js +72 -0
  97. package/src/utils/misc.js +1 -0
  98. package/src/utils/promises.js +17 -0
  99. package/src/utils/routing.js +130 -0
  100. package/src/utils/unit_test.js +11 -0
  101. package/src/utils/url.js +144 -0
  102. package/svelte-kit.js +1 -1
  103. package/types/ambient.d.ts +431 -0
  104. package/types/index.d.ts +477 -0
  105. package/types/internal.d.ts +380 -0
  106. package/types/private.d.ts +224 -0
  107. package/CHANGELOG.md +0 -496
  108. package/assets/components/error.svelte +0 -13
  109. package/assets/runtime/app/env.js +0 -5
  110. package/assets/runtime/app/navigation.js +0 -44
  111. package/assets/runtime/app/paths.js +0 -1
  112. package/assets/runtime/app/stores.js +0 -93
  113. package/assets/runtime/chunks/utils.js +0 -22
  114. package/assets/runtime/internal/singletons.js +0 -23
  115. package/assets/runtime/internal/start.js +0 -776
  116. package/assets/runtime/paths.js +0 -12
  117. package/dist/chunks/index.js +0 -3537
  118. package/dist/chunks/index2.js +0 -587
  119. package/dist/chunks/index3.js +0 -246
  120. package/dist/chunks/index4.js +0 -568
  121. package/dist/chunks/index5.js +0 -763
  122. package/dist/chunks/index6.js +0 -323
  123. package/dist/chunks/standard.js +0 -99
  124. package/dist/chunks/utils.js +0 -83
  125. package/dist/cli.js +0 -555
  126. package/dist/ssr.js +0 -2604
  127. package/types.d.ts +0 -73
  128. package/types.internal.d.ts +0 -222
@@ -0,0 +1,581 @@
1
+ import fs from 'fs';
2
+ import colors from 'kleur';
3
+ import path from 'path';
4
+ import sirv from 'sirv';
5
+ import { URL } from 'url';
6
+ import { getRequest, setResponse } from '../../../exports/node/index.js';
7
+ import { installPolyfills } from '../../../exports/node/polyfills.js';
8
+ import { coalesce_to_error } from '../../../utils/error.js';
9
+ import { posixify, resolve_entry } from '../../../utils/filesystem.js';
10
+ import { load_error_page, load_template } from '../../../core/config/index.js';
11
+ import { SVELTE_KIT_ASSETS } from '../../../constants.js';
12
+ import * as sync from '../../../core/sync/sync.js';
13
+ import { get_mime_lookup, runtime_base, runtime_prefix } from '../../../core/utils.js';
14
+ import { prevent_illegal_vite_imports } from '../graph_analysis/index.js';
15
+ import { compact } from '../../../utils/array.js';
16
+ import { normalizePath } from 'vite';
17
+
18
+ // Vite doesn't expose this so we just copy the list for now
19
+ // https://github.com/vitejs/vite/blob/3edd1af56e980aef56641a5a51cf2932bb580d41/packages/vite/src/node/plugins/css.ts#L96
20
+ const style_pattern = /\.(css|less|sass|scss|styl|stylus|pcss|postcss)$/;
21
+
22
+ const cwd = process.cwd();
23
+
24
+ /**
25
+ * @param {import('vite').ViteDevServer} vite
26
+ * @param {import('vite').ResolvedConfig} vite_config
27
+ * @param {import('types').ValidatedConfig} svelte_config
28
+ * @return {Promise<Promise<() => void>>}
29
+ */
30
+ export async function dev(vite, vite_config, svelte_config) {
31
+ installPolyfills();
32
+
33
+ // @ts-expect-error
34
+ globalThis.__SVELTEKIT_BROWSER__ = false;
35
+
36
+ sync.init(svelte_config, vite_config.mode);
37
+
38
+ /** @type {import('types').Respond} */
39
+ const respond = (await import(`${runtime_prefix}/server/index.js`)).respond;
40
+
41
+ /** @type {import('types').ManifestData} */
42
+ let manifest_data;
43
+ /** @type {import('types').SSRManifest} */
44
+ let manifest;
45
+
46
+ const extensions = [...svelte_config.extensions, ...svelte_config.kit.moduleExtensions];
47
+
48
+ /** @param {string} id */
49
+ async function resolve(id) {
50
+ const url = id.startsWith('..') ? `/@fs${path.posix.resolve(id)}` : `/${id}`;
51
+
52
+ const module = await vite.ssrLoadModule(url);
53
+
54
+ const module_node = await vite.moduleGraph.getModuleByUrl(url);
55
+ if (!module_node) throw new Error(`Could not find node for ${url}`);
56
+
57
+ return { module, module_node, url };
58
+ }
59
+
60
+ async function update_manifest() {
61
+ ({ manifest_data } = await sync.create(svelte_config));
62
+
63
+ manifest = {
64
+ appDir: svelte_config.kit.appDir,
65
+ appPath: svelte_config.kit.appDir,
66
+ assets: new Set(manifest_data.assets.map((asset) => asset.file)),
67
+ mimeTypes: get_mime_lookup(manifest_data),
68
+ _: {
69
+ entry: {
70
+ file: `/@fs${runtime_prefix}/client/start.js`,
71
+ imports: [],
72
+ stylesheets: []
73
+ },
74
+ nodes: manifest_data.nodes.map((node, index) => {
75
+ return async () => {
76
+ /** @type {import('types').SSRNode} */
77
+ const result = {};
78
+
79
+ /** @type {import('vite').ModuleNode[]} */
80
+ const module_nodes = [];
81
+
82
+ result.index = index;
83
+
84
+ // these are unused in dev, it's easier to include them
85
+ result.imports = [];
86
+ result.stylesheets = [];
87
+
88
+ if (node.component) {
89
+ result.component = async () => {
90
+ const { module_node, module, url } = await resolve(
91
+ /** @type {string} */ (node.component)
92
+ );
93
+
94
+ module_nodes.push(module_node);
95
+ result.file = url.endsWith('.svelte') ? url : url + '?import'; // TODO what is this for?
96
+
97
+ prevent_illegal_vite_imports(
98
+ module_node,
99
+ normalizePath(svelte_config.kit.files.lib),
100
+ extensions
101
+ );
102
+
103
+ return module.default;
104
+ };
105
+ }
106
+
107
+ if (node.shared) {
108
+ const { module, module_node } = await resolve(node.shared);
109
+
110
+ module_nodes.push(module_node);
111
+
112
+ result.shared = module;
113
+
114
+ prevent_illegal_vite_imports(
115
+ module_node,
116
+ normalizePath(svelte_config.kit.files.lib),
117
+ extensions
118
+ );
119
+ }
120
+
121
+ if (node.server) {
122
+ const { module } = await resolve(node.server);
123
+ result.server = module;
124
+ result.server_id = node.server;
125
+ }
126
+
127
+ // in dev we inline all styles to avoid FOUC. this gets populated lazily so that
128
+ // components/stylesheets loaded via import() during `load` are included
129
+ result.inline_styles = async () => {
130
+ const deps = new Set();
131
+
132
+ for (const module_node of module_nodes) {
133
+ await find_deps(vite, module_node, deps);
134
+ }
135
+
136
+ /** @type {Record<string, string>} */
137
+ const styles = {};
138
+
139
+ for (const dep of deps) {
140
+ const parsed = new URL(dep.url, 'http://localhost/');
141
+ const query = parsed.searchParams;
142
+
143
+ if (
144
+ style_pattern.test(dep.file) ||
145
+ (query.has('svelte') && query.get('type') === 'style')
146
+ ) {
147
+ try {
148
+ const mod = await vite.ssrLoadModule(dep.url);
149
+ styles[dep.url] = mod.default;
150
+ } catch {
151
+ // this can happen with dynamically imported modules, I think
152
+ // because the Vite module graph doesn't distinguish between
153
+ // static and dynamic imports? TODO investigate, submit fix
154
+ }
155
+ }
156
+ }
157
+
158
+ return styles;
159
+ };
160
+
161
+ return result;
162
+ };
163
+ }),
164
+ routes: compact(
165
+ manifest_data.routes.map((route) => {
166
+ if (!route.page && !route.endpoint) return null;
167
+
168
+ const endpoint = route.endpoint;
169
+
170
+ return {
171
+ id: route.id,
172
+ pattern: route.pattern,
173
+ names: route.names,
174
+ types: route.types,
175
+ page: route.page,
176
+ endpoint: endpoint
177
+ ? async () => {
178
+ const url = path.resolve(cwd, endpoint.file);
179
+ return await vite.ssrLoadModule(url);
180
+ }
181
+ : null
182
+ };
183
+ })
184
+ ),
185
+ matchers: async () => {
186
+ /** @type {Record<string, import('types').ParamMatcher>} */
187
+ const matchers = {};
188
+
189
+ for (const key in manifest_data.matchers) {
190
+ const file = manifest_data.matchers[key];
191
+ const url = path.resolve(cwd, file);
192
+ const module = await vite.ssrLoadModule(url);
193
+
194
+ if (module.match) {
195
+ matchers[key] = module.match;
196
+ } else {
197
+ throw new Error(`${file} does not export a \`match\` function`);
198
+ }
199
+ }
200
+
201
+ return matchers;
202
+ }
203
+ }
204
+ };
205
+ }
206
+
207
+ /** @param {Error} error */
208
+ function fix_stack_trace(error) {
209
+ return error.stack ? vite.ssrRewriteStacktrace(error.stack) : error.stack;
210
+ }
211
+
212
+ await update_manifest();
213
+
214
+ /**
215
+ * @param {string} event
216
+ * @param {(file: string) => void} cb
217
+ */
218
+ const watch = (event, cb) => {
219
+ vite.watcher.on(event, (file) => {
220
+ if (file.startsWith(svelte_config.kit.files.routes + path.sep)) {
221
+ cb(file);
222
+ }
223
+ });
224
+ };
225
+ /** @type {NodeJS.Timeout | null } */
226
+ let timeout = null;
227
+ /** @param {() => void} to_run */
228
+ const debounce = (to_run) => {
229
+ timeout && clearTimeout(timeout);
230
+ timeout = setTimeout(() => {
231
+ timeout = null;
232
+ to_run();
233
+ }, 100);
234
+ };
235
+
236
+ // Debounce add/unlink events because in case of folder deletion or moves
237
+ // they fire in rapid succession, causing needless invocations.
238
+ watch('add', () => debounce(update_manifest));
239
+ watch('unlink', () => debounce(update_manifest));
240
+ watch('change', (file) => {
241
+ // Don't run for a single file if the whole manifest is about to get updated
242
+ if (timeout) return;
243
+
244
+ sync.update(svelte_config, manifest_data, file);
245
+ });
246
+
247
+ const assets = svelte_config.kit.paths.assets ? SVELTE_KIT_ASSETS : svelte_config.kit.paths.base;
248
+ const asset_server = sirv(svelte_config.kit.files.assets, {
249
+ dev: true,
250
+ etag: true,
251
+ maxAge: 0,
252
+ extensions: []
253
+ });
254
+
255
+ vite.middlewares.use(async (req, res, next) => {
256
+ try {
257
+ const base = `${vite.config.server.https ? 'https' : 'http'}://${
258
+ req.headers[':authority'] || req.headers.host
259
+ }`;
260
+
261
+ const decoded = decodeURI(new URL(base + req.url).pathname);
262
+
263
+ if (decoded.startsWith(assets)) {
264
+ const pathname = decoded.slice(assets.length);
265
+ const file = svelte_config.kit.files.assets + pathname;
266
+
267
+ if (fs.existsSync(file) && !fs.statSync(file).isDirectory()) {
268
+ if (has_correct_case(file, svelte_config.kit.files.assets)) {
269
+ req.url = encodeURI(pathname); // don't need query/hash
270
+ asset_server(req, res);
271
+ return;
272
+ }
273
+ }
274
+ }
275
+
276
+ next();
277
+ } catch (e) {
278
+ const error = coalesce_to_error(e);
279
+ res.statusCode = 500;
280
+ res.end(fix_stack_trace(error));
281
+ }
282
+ });
283
+
284
+ return () => {
285
+ const serve_static_middleware = vite.middlewares.stack.find(
286
+ (middleware) =>
287
+ /** @type {function} */ (middleware.handle).name === 'viteServeStaticMiddleware'
288
+ );
289
+
290
+ remove_static_middlewares(vite.middlewares);
291
+
292
+ vite.middlewares.use(async (req, res) => {
293
+ try {
294
+ const base = `${vite.config.server.https ? 'https' : 'http'}://${
295
+ req.headers[':authority'] || req.headers.host
296
+ }`;
297
+
298
+ const decoded = decodeURI(new URL(base + req.url).pathname);
299
+ const file = posixify(path.resolve(decoded.slice(1)));
300
+ const is_file = fs.existsSync(file) && !fs.statSync(file).isDirectory();
301
+ const allowed =
302
+ !vite_config.server.fs.strict ||
303
+ vite_config.server.fs.allow.some((dir) => file.startsWith(dir));
304
+
305
+ if (is_file && allowed) {
306
+ // @ts-expect-error
307
+ serve_static_middleware.handle(req, res);
308
+ return;
309
+ }
310
+
311
+ if (!decoded.startsWith(svelte_config.kit.paths.base)) {
312
+ return not_found(
313
+ res,
314
+ `Not found (did you mean ${svelte_config.kit.paths.base + req.url}?)`
315
+ );
316
+ }
317
+
318
+ const hooks_file = svelte_config.kit.files.hooks.server;
319
+ /** @type {Partial<import('types').ServerHooks>} */
320
+ const user_hooks = resolve_entry(hooks_file)
321
+ ? await vite.ssrLoadModule(`/${hooks_file}`)
322
+ : {};
323
+
324
+ // TODO remove for 1.0
325
+ if (!resolve_entry(hooks_file)) {
326
+ const old_file = resolve_entry(path.join(process.cwd(), 'src', 'hooks'));
327
+ if (old_file && fs.existsSync(old_file)) {
328
+ throw new Error(
329
+ `Rename your server hook file from ${posixify(
330
+ path.relative(process.cwd(), old_file)
331
+ )} to ${posixify(
332
+ path.relative(process.cwd(), svelte_config.kit.files.hooks.server)
333
+ )}${path.extname(
334
+ old_file
335
+ )} (because there's also client hooks now). See the PR for more information: https://github.com/sveltejs/kit/pull/6586`
336
+ );
337
+ }
338
+ }
339
+
340
+ const handle = user_hooks.handle || (({ event, resolve }) => resolve(event));
341
+
342
+ // TODO remove for 1.0
343
+ // @ts-expect-error
344
+ if (user_hooks.externalFetch) {
345
+ throw new Error(
346
+ 'externalFetch has been removed — use handleFetch instead. See https://github.com/sveltejs/kit/pull/6565 for details'
347
+ );
348
+ }
349
+
350
+ /** @type {import('types').ServerHooks} */
351
+ const hooks = {
352
+ handle,
353
+ handleError:
354
+ user_hooks.handleError ||
355
+ (({ error: e }) => {
356
+ const error = /** @type {Error & { frame?: string }} */ (e);
357
+ console.error(colors.bold().red(error.message ?? error)); // Could be anything
358
+ if (error.frame) {
359
+ console.error(colors.gray(error.frame));
360
+ }
361
+ if (error.stack) {
362
+ console.error(colors.gray(error.stack));
363
+ }
364
+ }),
365
+ handleFetch: user_hooks.handleFetch || (({ request, fetch }) => fetch(request))
366
+ };
367
+
368
+ if (/** @type {any} */ (hooks).getContext) {
369
+ // TODO remove this for 1.0
370
+ throw new Error(
371
+ 'The getContext hook has been removed. See https://kit.svelte.dev/docs/hooks'
372
+ );
373
+ }
374
+
375
+ if (/** @type {any} */ (hooks).serverFetch) {
376
+ // TODO remove this for 1.0
377
+ throw new Error('The serverFetch hook has been renamed to externalFetch.');
378
+ }
379
+
380
+ // TODO the / prefix will probably fail if outDir is outside the cwd (which
381
+ // could be the case in a monorepo setup), but without it these modules
382
+ // can get loaded twice via different URLs, which causes failures. Might
383
+ // require changes to Vite to fix
384
+ const { default: root } = await vite.ssrLoadModule(
385
+ `/${posixify(path.relative(cwd, `${svelte_config.kit.outDir}/generated/root.svelte`))}`
386
+ );
387
+
388
+ const paths = await vite.ssrLoadModule(`${runtime_base}/paths.js`);
389
+
390
+ paths.set_paths({
391
+ base: svelte_config.kit.paths.base,
392
+ assets
393
+ });
394
+
395
+ let request;
396
+
397
+ try {
398
+ request = await getRequest({
399
+ base,
400
+ request: req
401
+ });
402
+ } catch (/** @type {any} */ err) {
403
+ res.statusCode = err.status || 400;
404
+ return res.end('Invalid request body');
405
+ }
406
+
407
+ const template = load_template(cwd, svelte_config);
408
+ const error_page = load_error_page(svelte_config);
409
+
410
+ const rendered = await respond(
411
+ request,
412
+ {
413
+ csp: svelte_config.kit.csp,
414
+ csrf: {
415
+ check_origin: svelte_config.kit.csrf.checkOrigin
416
+ },
417
+ dev: true,
418
+ handle_error: (error, event) => {
419
+ return (
420
+ hooks.handleError({
421
+ error: new Proxy(error, {
422
+ get: (target, property) => {
423
+ if (property === 'stack') {
424
+ return fix_stack_trace(error);
425
+ }
426
+
427
+ return Reflect.get(target, property, target);
428
+ }
429
+ }),
430
+ event,
431
+
432
+ // TODO remove for 1.0
433
+ // @ts-expect-error
434
+ get request() {
435
+ throw new Error(
436
+ 'request in handleError has been replaced with event. See https://github.com/sveltejs/kit/pull/3384 for details'
437
+ );
438
+ }
439
+ }) ?? { message: event.routeId != null ? 'Internal Error' : 'Not Found' }
440
+ );
441
+ },
442
+ hooks,
443
+ manifest,
444
+ paths: {
445
+ base: svelte_config.kit.paths.base,
446
+ assets
447
+ },
448
+ public_env: {},
449
+ read: (file) => fs.readFileSync(path.join(svelte_config.kit.files.assets, file)),
450
+ root,
451
+ app_template: ({ head, body, assets, nonce }) => {
452
+ return (
453
+ template
454
+ .replace(/%sveltekit\.assets%/g, assets)
455
+ .replace(/%sveltekit\.nonce%/g, nonce)
456
+ // head and body must be replaced last, in case someone tries to sneak in %sveltekit.assets% etc
457
+ .replace('%sveltekit.head%', () => head)
458
+ .replace('%sveltekit.body%', () => body)
459
+ );
460
+ },
461
+ app_template_contains_nonce: template.includes('%sveltekit.nonce%'),
462
+ error_template: ({ status, message }) => {
463
+ return error_page
464
+ .replace(/%sveltekit\.status%/g, String(status))
465
+ .replace(/%sveltekit\.error\.message%/g, message);
466
+ },
467
+ service_worker: false,
468
+ trailing_slash: svelte_config.kit.trailingSlash
469
+ },
470
+ {
471
+ getClientAddress: () => {
472
+ const { remoteAddress } = req.socket;
473
+ if (remoteAddress) return remoteAddress;
474
+ throw new Error('Could not determine clientAddress');
475
+ }
476
+ }
477
+ );
478
+
479
+ if (rendered.status === 404) {
480
+ // @ts-expect-error
481
+ serve_static_middleware.handle(req, res, () => {
482
+ setResponse(res, rendered);
483
+ });
484
+ } else {
485
+ setResponse(res, rendered);
486
+ }
487
+ } catch (e) {
488
+ const error = coalesce_to_error(e);
489
+ res.statusCode = 500;
490
+ res.end(fix_stack_trace(error));
491
+ }
492
+ });
493
+ };
494
+ }
495
+
496
+ /** @param {import('http').ServerResponse} res */
497
+ function not_found(res, message = 'Not found') {
498
+ res.statusCode = 404;
499
+ res.end(message);
500
+ }
501
+
502
+ /**
503
+ * @param {import('connect').Server} server
504
+ */
505
+ function remove_static_middlewares(server) {
506
+ // We don't use viteServePublicMiddleware because of the following issues:
507
+ // https://github.com/vitejs/vite/issues/9260
508
+ // https://github.com/vitejs/vite/issues/9236
509
+ // https://github.com/vitejs/vite/issues/9234
510
+ const static_middlewares = ['viteServePublicMiddleware', 'viteServeStaticMiddleware'];
511
+ for (let i = server.stack.length - 1; i > 0; i--) {
512
+ // @ts-expect-error using internals
513
+ if (static_middlewares.includes(server.stack[i].handle.name)) {
514
+ server.stack.splice(i, 1);
515
+ }
516
+ }
517
+ }
518
+
519
+ /**
520
+ * @param {import('vite').ViteDevServer} vite
521
+ * @param {import('vite').ModuleNode} node
522
+ * @param {Set<import('vite').ModuleNode>} deps
523
+ */
524
+ async function find_deps(vite, node, deps) {
525
+ // since `ssrTransformResult.deps` contains URLs instead of `ModuleNode`s, this process is asynchronous.
526
+ // instead of using `await`, we resolve all branches in parallel.
527
+ /** @type {Promise<void>[]} */
528
+ const branches = [];
529
+
530
+ /** @param {import('vite').ModuleNode} node */
531
+ async function add(node) {
532
+ if (!deps.has(node)) {
533
+ deps.add(node);
534
+ await find_deps(vite, node, deps);
535
+ }
536
+ }
537
+
538
+ /** @param {string} url */
539
+ async function add_by_url(url) {
540
+ const node = await vite.moduleGraph.getModuleByUrl(url);
541
+
542
+ if (node) {
543
+ await add(node);
544
+ }
545
+ }
546
+
547
+ if (node.ssrTransformResult) {
548
+ if (node.ssrTransformResult.deps) {
549
+ node.ssrTransformResult.deps.forEach((url) => branches.push(add_by_url(url)));
550
+ }
551
+
552
+ if (node.ssrTransformResult.dynamicDeps) {
553
+ node.ssrTransformResult.dynamicDeps.forEach((url) => branches.push(add_by_url(url)));
554
+ }
555
+ } else {
556
+ node.importedModules.forEach((node) => branches.push(add(node)));
557
+ }
558
+
559
+ await Promise.all(branches);
560
+ }
561
+
562
+ /**
563
+ * Determine if a file is being requested with the correct case,
564
+ * to ensure consistent behaviour between dev and prod and across
565
+ * operating systems. Note that we can't use realpath here,
566
+ * because we don't want to follow symlinks
567
+ * @param {string} file
568
+ * @param {string} assets
569
+ * @returns {boolean}
570
+ */
571
+ function has_correct_case(file, assets) {
572
+ if (file === assets) return true;
573
+
574
+ const parent = path.dirname(file);
575
+
576
+ if (fs.readdirSync(parent).includes(path.basename(file))) {
577
+ return has_correct_case(parent, assets);
578
+ }
579
+
580
+ return false;
581
+ }