@sveltejs/kit 1.0.0-next.98 → 1.0.0

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