@sveltejs/kit 1.0.0-next.43 → 1.0.0-next.430

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 (104) hide show
  1. package/README.md +12 -9
  2. package/package.json +95 -63
  3. package/src/cli.js +112 -0
  4. package/src/core/adapt/builder.js +207 -0
  5. package/src/core/adapt/index.js +19 -0
  6. package/src/core/config/index.js +86 -0
  7. package/src/core/config/options.js +488 -0
  8. package/src/core/config/types.d.ts +1 -0
  9. package/src/core/constants.js +5 -0
  10. package/src/core/env.js +97 -0
  11. package/src/core/generate_manifest/index.js +99 -0
  12. package/src/core/prerender/crawl.js +194 -0
  13. package/src/core/prerender/prerender.js +378 -0
  14. package/src/core/prerender/queue.js +80 -0
  15. package/src/core/sync/create_manifest_data/index.js +506 -0
  16. package/src/core/sync/create_manifest_data/types.d.ts +40 -0
  17. package/src/core/sync/sync.js +59 -0
  18. package/src/core/sync/utils.js +44 -0
  19. package/src/core/sync/write_ambient.js +27 -0
  20. package/src/core/sync/write_client_manifest.js +82 -0
  21. package/src/core/sync/write_matchers.js +25 -0
  22. package/src/core/sync/write_root.js +91 -0
  23. package/src/core/sync/write_tsconfig.js +195 -0
  24. package/src/core/sync/write_types.js +775 -0
  25. package/src/core/utils.js +70 -0
  26. package/src/hooks.js +26 -0
  27. package/src/index/index.js +45 -0
  28. package/src/index/private.js +33 -0
  29. package/src/node/index.js +145 -0
  30. package/src/node/polyfills.js +40 -0
  31. package/src/runtime/app/env.js +11 -0
  32. package/src/runtime/app/navigation.js +22 -0
  33. package/src/runtime/app/paths.js +1 -0
  34. package/src/runtime/app/stores.js +102 -0
  35. package/src/runtime/client/ambient.d.ts +17 -0
  36. package/src/runtime/client/client.js +1289 -0
  37. package/src/runtime/client/fetcher.js +60 -0
  38. package/src/runtime/client/parse.js +36 -0
  39. package/src/runtime/client/singletons.js +21 -0
  40. package/src/runtime/client/start.js +46 -0
  41. package/src/runtime/client/types.d.ts +105 -0
  42. package/src/runtime/client/utils.js +113 -0
  43. package/src/runtime/components/error.svelte +16 -0
  44. package/{assets → src/runtime}/components/layout.svelte +0 -0
  45. package/src/runtime/env/dynamic/private.js +1 -0
  46. package/src/runtime/env/dynamic/public.js +1 -0
  47. package/src/runtime/env-private.js +7 -0
  48. package/src/runtime/env-public.js +7 -0
  49. package/src/runtime/env.js +6 -0
  50. package/src/runtime/hash.js +16 -0
  51. package/src/runtime/paths.js +11 -0
  52. package/src/runtime/server/endpoint.js +58 -0
  53. package/src/runtime/server/index.js +448 -0
  54. package/src/runtime/server/page/cookie.js +25 -0
  55. package/src/runtime/server/page/crypto.js +239 -0
  56. package/src/runtime/server/page/csp.js +249 -0
  57. package/src/runtime/server/page/fetch.js +266 -0
  58. package/src/runtime/server/page/index.js +416 -0
  59. package/src/runtime/server/page/load_data.js +135 -0
  60. package/src/runtime/server/page/render.js +362 -0
  61. package/src/runtime/server/page/respond_with_error.js +94 -0
  62. package/src/runtime/server/page/types.d.ts +44 -0
  63. package/src/runtime/server/utils.js +116 -0
  64. package/src/utils/error.js +22 -0
  65. package/src/utils/escape.js +104 -0
  66. package/src/utils/filesystem.js +108 -0
  67. package/src/utils/http.js +55 -0
  68. package/src/utils/misc.js +1 -0
  69. package/src/utils/routing.js +108 -0
  70. package/src/utils/url.js +97 -0
  71. package/src/vite/build/build_server.js +337 -0
  72. package/src/vite/build/build_service_worker.js +90 -0
  73. package/src/vite/build/utils.js +160 -0
  74. package/src/vite/dev/index.js +551 -0
  75. package/src/vite/index.js +574 -0
  76. package/src/vite/preview/index.js +186 -0
  77. package/src/vite/types.d.ts +3 -0
  78. package/src/vite/utils.js +345 -0
  79. package/svelte-kit.js +1 -1
  80. package/types/ambient.d.ts +357 -0
  81. package/types/index.d.ts +343 -0
  82. package/types/internal.d.ts +308 -0
  83. package/types/private.d.ts +209 -0
  84. package/CHANGELOG.md +0 -431
  85. package/assets/components/error.svelte +0 -13
  86. package/assets/runtime/app/env.js +0 -5
  87. package/assets/runtime/app/navigation.js +0 -41
  88. package/assets/runtime/app/paths.js +0 -1
  89. package/assets/runtime/app/stores.js +0 -93
  90. package/assets/runtime/chunks/utils.js +0 -19
  91. package/assets/runtime/internal/singletons.js +0 -23
  92. package/assets/runtime/internal/start.js +0 -770
  93. package/assets/runtime/paths.js +0 -12
  94. package/dist/.DS_Store +0 -0
  95. package/dist/chunks/index.js +0 -3521
  96. package/dist/chunks/index2.js +0 -587
  97. package/dist/chunks/index3.js +0 -246
  98. package/dist/chunks/index4.js +0 -538
  99. package/dist/chunks/index5.js +0 -761
  100. package/dist/chunks/index6.js +0 -322
  101. package/dist/chunks/standard.js +0 -99
  102. package/dist/chunks/utils.js +0 -83
  103. package/dist/cli.js +0 -546
  104. package/dist/ssr.js +0 -2581
@@ -0,0 +1,506 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import mime from 'mime';
4
+ import { runtime_directory } from '../../utils.js';
5
+ import { posixify } from '../../../utils/filesystem.js';
6
+ import { parse_route_id } from '../../../utils/routing.js';
7
+
8
+ const DEFAULT = 'default';
9
+
10
+ /**
11
+ * @param {{
12
+ * config: import('types').ValidatedConfig;
13
+ * fallback?: string;
14
+ * cwd?: string;
15
+ * }} opts
16
+ * @returns {import('types').ManifestData}
17
+ */
18
+ export default function create_manifest_data({
19
+ config,
20
+ fallback = `${runtime_directory}/components`,
21
+ cwd = process.cwd()
22
+ }) {
23
+ /** @type {Map<string, import('types').RouteData>} */
24
+ const route_map = new Map();
25
+
26
+ /** @type {Map<string, import('./types').Part[][]>} */
27
+ const segment_map = new Map();
28
+
29
+ /** @type {import('./types').RouteTree} */
30
+ const tree = new Map();
31
+
32
+ const default_layout = {
33
+ component: posixify(path.relative(cwd, `${fallback}/layout.svelte`))
34
+ };
35
+
36
+ // set default root layout/error
37
+ tree.set('', {
38
+ error: {
39
+ component: posixify(path.relative(cwd, `${fallback}/error.svelte`))
40
+ },
41
+ layouts: { [DEFAULT]: default_layout }
42
+ });
43
+
44
+ /** @param {string} id */
45
+ function tree_node(id) {
46
+ if (!tree.has(id)) {
47
+ tree.set(id, {
48
+ error: undefined,
49
+ layouts: {}
50
+ });
51
+ }
52
+
53
+ return /** @type {import('./types').RouteTreeNode} */ (tree.get(id));
54
+ }
55
+
56
+ const routes_base = posixify(path.relative(cwd, config.kit.files.routes));
57
+ const valid_extensions = [...config.extensions, ...config.kit.moduleExtensions];
58
+
59
+ if (fs.existsSync(config.kit.files.routes)) {
60
+ list_files(config.kit.files.routes).forEach((filepath) => {
61
+ const extension = valid_extensions.find((ext) => filepath.endsWith(ext));
62
+ if (!extension) return;
63
+
64
+ const project_relative = `${routes_base}/${filepath}`;
65
+ const segments = filepath.split('/');
66
+ const file = /** @type {string} */ (segments.pop());
67
+
68
+ if (file[0] !== '+') return; // not a route file
69
+
70
+ const item = analyze(project_relative, file, config.extensions, config.kit.moduleExtensions);
71
+ const id = segments.join('/');
72
+
73
+ if (/\]\[/.test(id)) {
74
+ throw new Error(`Invalid route ${project_relative} — parameters must be separated`);
75
+ }
76
+
77
+ if (count_occurrences('[', id) !== count_occurrences(']', id)) {
78
+ throw new Error(`Invalid route ${project_relative} — brackets are unbalanced`);
79
+ }
80
+
81
+ // error/layout files should be added to the tree, but don't result
82
+ // in a route being created, so deal with them first. note: we are
83
+ // relying on the fact that the +error and +layout files precede
84
+ // +page files alphabetically, and will therefore be processes
85
+ // before we reach the page
86
+ if (item.kind === 'component' && item.is_error) {
87
+ tree_node(id).error = {
88
+ component: project_relative
89
+ };
90
+
91
+ return;
92
+ }
93
+
94
+ if (item.is_layout) {
95
+ if (item.declares_layout === DEFAULT) {
96
+ throw new Error(`${project_relative} cannot use reserved "${DEFAULT}" name`);
97
+ }
98
+
99
+ const layout_id = item.declares_layout || DEFAULT;
100
+
101
+ const group = tree_node(id);
102
+
103
+ const defined = group.layouts[layout_id] || (group.layouts[layout_id] = {});
104
+
105
+ if (defined[item.kind] && layout_id !== DEFAULT) {
106
+ // edge case
107
+ throw new Error(
108
+ `Duplicate layout ${project_relative} already defined at ${defined[item.kind]}`
109
+ );
110
+ }
111
+
112
+ defined[item.kind] = project_relative;
113
+
114
+ return;
115
+ }
116
+
117
+ const type = item.kind === 'server' && !item.is_layout && !item.is_page ? 'endpoint' : 'page';
118
+
119
+ if (type === 'endpoint' && route_map.has(id)) {
120
+ // note that we are relying on +server being lexically ordered after
121
+ // all other route files — if we added +view or something this is
122
+ // potentially brittle, since the server might be added before
123
+ // another route file. a problem for another day
124
+ throw new Error(
125
+ `${file} cannot share a directory with other route files (${project_relative})`
126
+ );
127
+ }
128
+
129
+ if (!route_map.has(id)) {
130
+ const pattern = parse_route_id(id).pattern;
131
+
132
+ segment_map.set(
133
+ id,
134
+ segments.filter(Boolean).map((segment) => {
135
+ /** @type {import('./types').Part[]} */
136
+ const parts = [];
137
+ segment.split(/\[(.+?)\]/).map((content, i) => {
138
+ const dynamic = !!(i % 2);
139
+
140
+ if (!content) return;
141
+
142
+ parts.push({
143
+ content,
144
+ dynamic,
145
+ rest: dynamic && content.startsWith('...'),
146
+ type: (dynamic && content.split('=')[1]) || null
147
+ });
148
+ });
149
+ return parts;
150
+ })
151
+ );
152
+
153
+ if (type === 'endpoint') {
154
+ route_map.set(id, {
155
+ type,
156
+ id,
157
+ pattern,
158
+ file: project_relative
159
+ });
160
+ } else {
161
+ route_map.set(id, {
162
+ type,
163
+ id,
164
+ pattern,
165
+ errors: [],
166
+ layouts: [],
167
+ leaf: {}
168
+ });
169
+ }
170
+ }
171
+
172
+ if (item.is_page) {
173
+ const route = /** @type {import('types').PageData} */ (route_map.get(id));
174
+
175
+ // This ensures that layouts and errors are set for pages that have no Svelte file
176
+ // and only redirect or throw an error, but are set to the Svelte file definition if it exists.
177
+ // This ensures the proper error page is used and rendered in the proper layout.
178
+ if (item.kind === 'component' || route.layouts.length === 0) {
179
+ const { layouts, errors } = trace(
180
+ tree,
181
+ id,
182
+ item.kind === 'component' ? item.uses_layout : undefined,
183
+ project_relative
184
+ );
185
+ route.layouts = layouts;
186
+ route.errors = errors;
187
+ }
188
+
189
+ if (item.kind === 'component') {
190
+ route.leaf.component = project_relative;
191
+ } else if (item.kind === 'server') {
192
+ route.leaf.server = project_relative;
193
+ } else {
194
+ route.leaf.shared = project_relative;
195
+ }
196
+ }
197
+ });
198
+
199
+ // TODO remove for 1.0
200
+ if (route_map.size === 0) {
201
+ throw new Error(
202
+ 'The filesystem router API has changed, see https://github.com/sveltejs/kit/discussions/5774 for details'
203
+ );
204
+ }
205
+ }
206
+
207
+ /** @type {import('types').PageNode[]} */
208
+ const nodes = [];
209
+
210
+ tree.forEach(({ layouts, error }) => {
211
+ // we do [default, error, ...other_layouts] so that components[0] and [1]
212
+ // are the root layout/error. kinda janky, there's probably a nicer way
213
+ if (layouts[DEFAULT]) {
214
+ nodes.push(layouts[DEFAULT]);
215
+ }
216
+
217
+ if (error) {
218
+ nodes.push(error);
219
+ }
220
+
221
+ for (const id in layouts) {
222
+ if (id !== DEFAULT) {
223
+ nodes.push(layouts[id]);
224
+ }
225
+ }
226
+ });
227
+
228
+ route_map.forEach((route) => {
229
+ if (route.type === 'page') {
230
+ nodes.push(route.leaf);
231
+ }
232
+ });
233
+
234
+ const routes = Array.from(route_map.values()).sort((a, b) => compare(a, b, segment_map));
235
+
236
+ /** @type {import('types').Asset[]} */
237
+ const assets = fs.existsSync(config.kit.files.assets)
238
+ ? list_files(config.kit.files.assets).map((file) => ({
239
+ file,
240
+ size: fs.statSync(`${config.kit.files.assets}/${file}`).size,
241
+ type: mime.getType(file)
242
+ }))
243
+ : [];
244
+
245
+ const params_base = path.relative(cwd, config.kit.files.params);
246
+
247
+ /** @type {Record<string, string>} */
248
+ const matchers = {};
249
+ if (fs.existsSync(config.kit.files.params)) {
250
+ for (const file of fs.readdirSync(config.kit.files.params)) {
251
+ const ext = path.extname(file);
252
+ if (!config.kit.moduleExtensions.includes(ext)) continue;
253
+ const type = file.slice(0, -ext.length);
254
+
255
+ if (/^\w+$/.test(type)) {
256
+ const matcher_file = path.join(params_base, file);
257
+
258
+ // Disallow same matcher with different extensions
259
+ if (matchers[type]) {
260
+ throw new Error(`Duplicate matchers: ${matcher_file} and ${matchers[type]}`);
261
+ } else {
262
+ matchers[type] = matcher_file;
263
+ }
264
+ } else {
265
+ throw new Error(
266
+ `Matcher names can only have underscores and alphanumeric characters — "${file}" is invalid`
267
+ );
268
+ }
269
+ }
270
+ }
271
+
272
+ return {
273
+ assets,
274
+ nodes,
275
+ routes,
276
+ matchers
277
+ };
278
+ }
279
+
280
+ /**
281
+ * @param {string} project_relative
282
+ * @param {string} file
283
+ * @param {string[]} component_extensions
284
+ * @param {string[]} module_extensions
285
+ * @returns {import('./types').RouteFile}
286
+ */
287
+ function analyze(project_relative, file, component_extensions, module_extensions) {
288
+ const component_extension = component_extensions.find((ext) => file.endsWith(ext));
289
+ if (component_extension) {
290
+ const name = file.slice(0, -component_extension.length);
291
+ const pattern =
292
+ /^\+(?:(page(?:@([a-zA-Z0-9_-]+))?)|(layout(?:-([a-zA-Z0-9_-]+))?(?:@([a-zA-Z0-9_-]+))?)|(error))$/;
293
+ const match = pattern.exec(name);
294
+ if (!match) {
295
+ throw new Error(`Files prefixed with + are reserved (saw ${project_relative})`);
296
+ }
297
+
298
+ return {
299
+ kind: 'component',
300
+ is_page: !!match[1],
301
+ is_layout: !!match[3],
302
+ is_error: !!match[6],
303
+ uses_layout: match[2] || match[5],
304
+ declares_layout: match[4]
305
+ };
306
+ }
307
+
308
+ const module_extension = module_extensions.find((ext) => file.endsWith(ext));
309
+ if (module_extension) {
310
+ const name = file.slice(0, -module_extension.length);
311
+ const pattern =
312
+ /^\+(?:(server)|(page(?:@([a-zA-Z0-9_-]+))?(\.server)?)|(layout(?:-([a-zA-Z0-9_-]+))?(?:@([a-zA-Z0-9_-]+))?(\.server)?))$/;
313
+ const match = pattern.exec(name);
314
+ if (!match) {
315
+ throw new Error(`Files prefixed with + are reserved (saw ${project_relative})`);
316
+ } else if (match[3] || match[7]) {
317
+ throw new Error(
318
+ // prettier-ignore
319
+ `Only Svelte files can reference named layouts. Remove '@${match[3] || match[7]}' from ${file} (at ${project_relative})`
320
+ );
321
+ }
322
+
323
+ const kind = !!(match[1] || match[4] || match[8]) ? 'server' : 'shared';
324
+
325
+ return {
326
+ kind,
327
+ is_page: !!match[2],
328
+ is_layout: !!match[5],
329
+ declares_layout: match[6]
330
+ };
331
+ }
332
+
333
+ throw new Error(`Files and directories prefixed with + are reserved (saw ${project_relative})`);
334
+ }
335
+
336
+ /**
337
+ * @param {import('./types').RouteTree} tree
338
+ * @param {string} id
339
+ * @param {string} layout_id
340
+ * @param {string} project_relative
341
+ */
342
+ function trace(tree, id, layout_id = DEFAULT, project_relative) {
343
+ /** @type {Array<import('types').PageNode | undefined>} */
344
+ const layouts = [];
345
+
346
+ /** @type {Array<import('types').PageNode | undefined>} */
347
+ const errors = [];
348
+
349
+ const parts = id.split('/').filter(Boolean);
350
+
351
+ // walk up the tree, find which +layout and +error components
352
+ // apply to this page
353
+ while (true) {
354
+ const node = tree.get(parts.join('/'));
355
+ const layout = node?.layouts[layout_id];
356
+
357
+ if (layout && layouts.indexOf(layout) > -1) {
358
+ // TODO this needs to be fixed for #5748
359
+ throw new Error(
360
+ `Recursive layout detected: ${layout.component} -> ${layouts
361
+ .map((l) => l?.component)
362
+ .join(' -> ')}`
363
+ );
364
+ }
365
+
366
+ // any segment that has neither a +layout nor an +error can be discarded.
367
+ // in other words these...
368
+ // layouts: [a, , b, c]
369
+ // errors: [d, , e, ]
370
+ //
371
+ // ...can be compacted to these:
372
+ // layouts: [a, b, c]
373
+ // errors: [d, e, ]
374
+ if (node?.error || layout) {
375
+ errors.unshift(node?.error);
376
+ layouts.unshift(layout);
377
+ }
378
+
379
+ const parent_layout_id = layout?.component?.split('/').at(-1)?.split('@')[1]?.split('.')[0];
380
+
381
+ if (parent_layout_id) {
382
+ layout_id = parent_layout_id;
383
+ } else {
384
+ if (layout) layout_id = DEFAULT;
385
+ if (parts.length === 0) break;
386
+ parts.pop();
387
+ }
388
+ }
389
+
390
+ if (layout_id !== DEFAULT) {
391
+ throw new Error(`${project_relative} references missing layout "${layout_id}"`);
392
+ }
393
+
394
+ // trim empty space off the end of the errors array
395
+ let i = errors.length;
396
+ while (i--) if (errors[i]) break;
397
+ errors.length = i + 1;
398
+
399
+ return { layouts, errors };
400
+ }
401
+
402
+ /**
403
+ * @param {import('types').RouteData} a
404
+ * @param {import('types').RouteData} b
405
+ * @param {Map<string, import('./types').Part[][]>} segment_map
406
+ */
407
+ function compare(a, b, segment_map) {
408
+ const a_segments = /** @type {import('./types').Part[][]} */ (segment_map.get(a.id));
409
+ const b_segments = /** @type {import('./types').Part[][]} */ (segment_map.get(b.id));
410
+
411
+ const max_segments = Math.max(a_segments.length, b_segments.length);
412
+ for (let i = 0; i < max_segments; i += 1) {
413
+ const sa = a_segments[i];
414
+ const sb = b_segments[i];
415
+
416
+ // /x < /x/y, but /[...x]/y < /[...x]
417
+ if (!sa) return a.id.includes('[...') ? +1 : -1;
418
+ if (!sb) return b.id.includes('[...') ? -1 : +1;
419
+
420
+ const max_parts = Math.max(sa.length, sb.length);
421
+ for (let i = 0; i < max_parts; i += 1) {
422
+ const pa = sa[i];
423
+ const pb = sb[i];
424
+
425
+ // xy < x[y], but [x].json < [x]
426
+ if (pa === undefined) return pb.dynamic ? -1 : +1;
427
+ if (pb === undefined) return pa.dynamic ? +1 : -1;
428
+
429
+ // x < [x]
430
+ if (pa.dynamic !== pb.dynamic) {
431
+ return pa.dynamic ? +1 : -1;
432
+ }
433
+
434
+ if (pa.dynamic) {
435
+ // [x] < [...x]
436
+ if (pa.rest !== pb.rest) {
437
+ return pa.rest ? +1 : -1;
438
+ }
439
+
440
+ // [x=type] < [x]
441
+ if (!!pa.type !== !!pb.type) {
442
+ return pa.type ? -1 : +1;
443
+ }
444
+ }
445
+ }
446
+ }
447
+
448
+ const a_is_endpoint = a.type === 'endpoint';
449
+ const b_is_endpoint = b.type === 'endpoint';
450
+
451
+ if (a_is_endpoint !== b_is_endpoint) {
452
+ return a_is_endpoint ? -1 : +1;
453
+ }
454
+
455
+ return a < b ? -1 : 1;
456
+ }
457
+
458
+ /**
459
+ * @param {string} needle
460
+ * @param {string} haystack
461
+ */
462
+ function count_occurrences(needle, haystack) {
463
+ let count = 0;
464
+ for (let i = 0; i < haystack.length; i += 1) {
465
+ if (haystack[i] === needle) count += 1;
466
+ }
467
+ return count;
468
+ }
469
+
470
+ /**
471
+ * @param {string} dir
472
+ * @param {string} [path]
473
+ * @param {string[]} [files]
474
+ */
475
+ function list_files(dir, path = '', files = []) {
476
+ fs.readdirSync(dir)
477
+ .sort((a, b) => {
478
+ // sort each directory in (+layout, +error, everything else) order
479
+ // so that we can trace layouts/errors immediately
480
+
481
+ if (a.startsWith('+layout') || a.startsWith('+error')) {
482
+ if (!b.startsWith('+layout') && !b.startsWith('+error')) return -1;
483
+ } else if (b.startsWith('+layout') || b.startsWith('+error')) {
484
+ return 1;
485
+ } else if (a.startsWith('__')) {
486
+ if (!b.startsWith('__')) return -1;
487
+ } else if (b.startsWith('__')) {
488
+ return 1;
489
+ }
490
+
491
+ return a < b ? -1 : 1;
492
+ })
493
+ .forEach((file) => {
494
+ const full = `${dir}/${file}`;
495
+ const stats = fs.statSync(full);
496
+ const joined = path ? `${path}/${file}` : file;
497
+
498
+ if (stats.isDirectory()) {
499
+ list_files(full, joined, files);
500
+ } else {
501
+ files.push(joined);
502
+ }
503
+ });
504
+
505
+ return files;
506
+ }
@@ -0,0 +1,40 @@
1
+ import { PageNode } from 'types';
2
+
3
+ interface Part {
4
+ content: string;
5
+ dynamic: boolean;
6
+ rest: boolean;
7
+ type: string | null;
8
+ }
9
+
10
+ interface RouteTreeNode {
11
+ error: PageNode | undefined;
12
+ layouts: Record<string, PageNode>;
13
+ }
14
+
15
+ export type RouteTree = Map<string, RouteTreeNode>;
16
+
17
+ interface RouteComponent {
18
+ kind: 'component';
19
+ is_page: boolean;
20
+ is_layout: boolean;
21
+ is_error: boolean;
22
+ uses_layout: string | undefined;
23
+ declares_layout: string | undefined;
24
+ }
25
+
26
+ interface RouteSharedModule {
27
+ kind: 'shared';
28
+ is_page: boolean;
29
+ is_layout: boolean;
30
+ declares_layout: string | undefined;
31
+ }
32
+
33
+ interface RouteServerModule {
34
+ kind: 'server';
35
+ is_page: boolean;
36
+ is_layout: boolean;
37
+ declares_layout: string | undefined;
38
+ }
39
+
40
+ export type RouteFile = RouteComponent | RouteSharedModule | RouteServerModule;
@@ -0,0 +1,59 @@
1
+ import path from 'path';
2
+ import create_manifest_data from './create_manifest_data/index.js';
3
+ import { write_client_manifest } from './write_client_manifest.js';
4
+ import { write_matchers } from './write_matchers.js';
5
+ import { write_root } from './write_root.js';
6
+ import { write_tsconfig } from './write_tsconfig.js';
7
+ import { write_type, write_types } from './write_types.js';
8
+ import { write_ambient } from './write_ambient.js';
9
+
10
+ /**
11
+ * Initialize SvelteKit's generated files.
12
+ * @param {import('types').ValidatedConfig} config
13
+ * @param {string} mode
14
+ */
15
+ export function init(config, mode) {
16
+ write_tsconfig(config.kit);
17
+ write_ambient(config.kit, mode);
18
+ }
19
+
20
+ /**
21
+ * Update SvelteKit's generated files
22
+ * @param {import('types').ValidatedConfig} config
23
+ */
24
+ export async function create(config) {
25
+ const manifest_data = create_manifest_data({ config });
26
+
27
+ const output = path.join(config.kit.outDir, 'generated');
28
+
29
+ write_client_manifest(manifest_data, output);
30
+ write_root(manifest_data, output);
31
+ write_matchers(manifest_data, output);
32
+ await write_types(config, manifest_data);
33
+
34
+ return { manifest_data };
35
+ }
36
+
37
+ /**
38
+ * Update SvelteKit's generated files in response to a single file content update.
39
+ * Do not call this when the file in question was created/deleted.
40
+ *
41
+ * @param {import('types').ValidatedConfig} config
42
+ * @param {import('types').ManifestData} manifest_data
43
+ * @param {string} file
44
+ */
45
+ export async function update(config, manifest_data, file) {
46
+ await write_type(config, manifest_data, file);
47
+
48
+ return { manifest_data };
49
+ }
50
+
51
+ /**
52
+ * Run sync.init and sync.update in series, returning the result from sync.update.
53
+ * @param {import('types').ValidatedConfig} config
54
+ * @param {string} mode The Vite mode
55
+ */
56
+ export async function all(config, mode) {
57
+ init(config, mode);
58
+ return await create(config);
59
+ }
@@ -0,0 +1,44 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { mkdirp } from '../../utils/filesystem.js';
4
+
5
+ /** @type {Map<string, string>} */
6
+ const previous_contents = new Map();
7
+
8
+ /**
9
+ * @param {string} file
10
+ * @param {string} code
11
+ */
12
+ export function write_if_changed(file, code) {
13
+ if (code !== previous_contents.get(file)) {
14
+ write(file, code);
15
+ }
16
+ }
17
+
18
+ /**
19
+ * @param {string} file
20
+ * @param {string} code
21
+ */
22
+ export function write(file, code) {
23
+ previous_contents.set(file, code);
24
+ mkdirp(path.dirname(file));
25
+ fs.writeFileSync(file, code);
26
+ }
27
+
28
+ /**
29
+ * @param {(file: string) => boolean} should_remove
30
+ */
31
+ export function remove_from_previous(should_remove) {
32
+ for (const key of previous_contents.keys()) {
33
+ if (should_remove(key)) {
34
+ previous_contents.delete(key);
35
+ }
36
+ }
37
+ }
38
+
39
+ /** @param {string} str */
40
+ export function trim(str) {
41
+ const indentation = /** @type {RegExpExecArray} */ (/\n?(\s*)/.exec(str))[1];
42
+ const pattern = new RegExp(`^${indentation}`, 'gm');
43
+ return str.replace(pattern, '').trim();
44
+ }
@@ -0,0 +1,27 @@
1
+ import path from 'path';
2
+ import { get_env } from '../../vite/utils.js';
3
+ import { GENERATED_COMMENT } from '../constants.js';
4
+ import { create_types } from '../env.js';
5
+ import { write_if_changed } from './utils.js';
6
+
7
+ const types_reference = '/// <reference types="@sveltejs/kit" />\n\n';
8
+
9
+ /**
10
+ * Writes ambient declarations including types reference to @sveltejs/kit,
11
+ * and the existing environment variables in process.env to
12
+ * $env/static/private and $env/static/public
13
+ * @param {import('types').ValidatedKitConfig} config
14
+ * @param {string} mode The Vite mode
15
+ */
16
+ export function write_ambient(config, mode) {
17
+ const env = get_env(config.env, mode);
18
+
19
+ write_if_changed(
20
+ path.join(config.outDir, 'ambient.d.ts'),
21
+ GENERATED_COMMENT +
22
+ types_reference +
23
+ create_types('$env/static/public', env.public) +
24
+ '\n\n' +
25
+ create_types('$env/static/private', env.private)
26
+ );
27
+ }