@sveltejs/kit 1.0.0-next.291 → 1.0.0-next.292

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.
@@ -1,348 +1,13 @@
1
- import fs__default from 'fs';
2
1
  import path__default from 'path';
2
+ import fs__default from 'fs';
3
+ import { g as get_runtime_path, $ } from '../cli.js';
4
+ import { p as posixify, c as copy, m as mkdirp } from './filesystem.js';
5
+ import { fileURLToPath } from 'url';
3
6
  import { s } from './misc.js';
4
- import { m as mkdirp, g as get_runtime_path, p as posixify, $ } from '../cli.js';
5
-
6
- /**
7
- * Takes zero or more objects and returns a new object that has all the values
8
- * deeply merged together. None of the original objects will be mutated at any
9
- * level, and the returned object will have no references to the original
10
- * objects at any depth. If there's a conflict the last one wins, except for
11
- * arrays which will be combined.
12
- * @param {...Object} objects
13
- * @returns {[Record<string, any>, string[]]} a 2-tuple with the merged object,
14
- * and a list of merge conflicts if there were any, in dotted notation
15
- */
16
- function deep_merge(...objects) {
17
- const result = {};
18
- /** @type {string[]} */
19
- const conflicts = [];
20
- objects.forEach((o) => merge_into(result, o, conflicts));
21
- return [result, conflicts];
22
- }
23
-
24
- /**
25
- * normalize kit.vite.resolve.alias as an array
26
- * @param {import('vite').AliasOptions} o
27
- * @returns {import('vite').Alias[]}
28
- */
29
- function normalize_alias(o) {
30
- if (Array.isArray(o)) return o;
31
- return Object.entries(o).map(([find, replacement]) => ({ find, replacement }));
32
- }
33
-
34
- /**
35
- * Merges b into a, recursively, mutating a.
36
- * @param {Record<string, any>} a
37
- * @param {Record<string, any>} b
38
- * @param {string[]} conflicts array to accumulate conflicts in
39
- * @param {string[]} path array of property names representing the current
40
- * location in the tree
41
- */
42
- function merge_into(a, b, conflicts = [], path = []) {
43
- /**
44
- * Checks for "plain old Javascript object", typically made as an object
45
- * literal. Excludes Arrays and built-in types like Buffer.
46
- * @param {any} x
47
- */
48
- const is_plain_object = (x) => typeof x === 'object' && x.constructor === Object;
49
-
50
- for (const prop in b) {
51
- // normalize alias objects to array
52
- if (prop === 'alias' && path[path.length - 1] === 'resolve') {
53
- if (a[prop]) a[prop] = normalize_alias(a[prop]);
54
- if (b[prop]) b[prop] = normalize_alias(b[prop]);
55
- }
56
-
57
- if (is_plain_object(b[prop])) {
58
- if (!is_plain_object(a[prop])) {
59
- if (a[prop] !== undefined) {
60
- conflicts.push([...path, prop].join('.'));
61
- }
62
- a[prop] = {};
63
- }
64
- merge_into(a[prop], b[prop], conflicts, [...path, prop]);
65
- } else if (Array.isArray(b[prop])) {
66
- if (!Array.isArray(a[prop])) {
67
- if (a[prop] !== undefined) {
68
- conflicts.push([...path, prop].join('.'));
69
- }
70
- a[prop] = [];
71
- }
72
- a[prop].push(...b[prop]);
73
- } else {
74
- // Since we're inside a for/in loop which loops over enumerable
75
- // properties only, we want parity here and to check if 'a' has
76
- // enumerable-only property 'prop'. Using 'hasOwnProperty' to
77
- // exclude inherited properties is close enough. It is possible
78
- // that someone uses Object.defineProperty to create a direct,
79
- // non-enumerable property but let's not worry about that.
80
- if (Object.prototype.hasOwnProperty.call(a, prop)) {
81
- conflicts.push([...path, prop].join('.'));
82
- }
83
- a[prop] = b[prop];
84
- }
85
- }
86
- }
87
-
88
- /** @type {Map<string, string>} */
89
- const previous_contents = new Map();
90
-
91
- /**
92
- * @param {string} file
93
- * @param {string} code
94
- */
95
- function write_if_changed(file, code) {
96
- if (code !== previous_contents.get(file)) {
97
- previous_contents.set(file, code);
98
- mkdirp(path__default.dirname(file));
99
- fs__default.writeFileSync(file, code);
100
- }
101
- }
102
-
103
- /** @typedef {import('types').ManifestData} ManifestData */
104
-
105
- /**
106
- * @param {{
107
- * config: import('types').ValidatedConfig;
108
- * manifest_data: ManifestData;
109
- * cwd: string;
110
- * }} options
111
- */
112
- function create_app({ config, manifest_data, cwd = process.cwd() }) {
113
- const output = path__default.join(config.kit.outDir, 'generated');
114
- const base = path__default.relative(cwd, output);
115
-
116
- write_if_changed(`${output}/manifest.js`, generate_client_manifest(manifest_data, base));
117
- write_if_changed(`${output}/root.svelte`, generate_app(manifest_data));
118
-
119
- create_types(config, manifest_data);
120
- }
121
-
122
- /**
123
- * @param {string} str
124
- */
125
- function trim(str) {
126
- return str.replace(/^\t\t/gm, '').trim();
127
- }
128
-
129
- /**
130
- * @param {ManifestData} manifest_data
131
- * @param {string} base
132
- */
133
- function generate_client_manifest(manifest_data, base) {
134
- /** @type {Record<string, number>} */
135
- const component_indexes = {};
136
-
137
- /** @param {string} c */
138
- const get_path = (c) => path__default.relative(base, c);
139
-
140
- const components = `[
141
- ${manifest_data.components
142
- .map((component, i) => {
143
- component_indexes[component] = i;
144
-
145
- return `() => import(${s(get_path(component))})`;
146
- })
147
- .join(',\n\t\t\t\t')}
148
- ]`.replace(/^\t/gm, '');
149
-
150
- /** @param {string[]} parts */
151
- const get_indices = (parts) =>
152
- `[${parts.map((part) => (part ? `c[${component_indexes[part]}]` : '')).join(', ')}]`;
153
-
154
- const routes = `[
155
- ${manifest_data.routes
156
- .map((route) => {
157
- if (route.type === 'page') {
158
- const params =
159
- route.params.length > 0 &&
160
- '(m) => ({ ' +
161
- route.params
162
- .map((param, i) => {
163
- return param.startsWith('...')
164
- ? `${param.slice(3)}: d(m[${i + 1}] || '')`
165
- : `${param}: d(m[${i + 1}])`;
166
- })
167
- .join(', ') +
168
- '})';
169
-
170
- const tuple = [route.pattern, get_indices(route.a), get_indices(route.b)];
171
-
172
- // optional items
173
- if (params || route.shadow) tuple.push(params || 'null');
174
- if (route.shadow) tuple.push('1');
175
-
176
- return `// ${route.a[route.a.length - 1]}\n\t\t[${tuple.join(', ')}]`;
177
- }
178
- })
179
- .filter(Boolean)
180
- .join(',\n\n\t\t')}
181
- ]`.replace(/^\t/gm, '');
182
-
183
- return trim(`
184
- const c = ${components};
185
-
186
- const d = decodeURIComponent;
187
-
188
- export const routes = ${routes};
189
-
190
- // we import the root layout/error components eagerly, so that
191
- // connectivity errors after initialisation don't nuke the app
192
- export const fallback = [c[0](), c[1]()];
193
- `);
194
- }
195
-
196
- /**
197
- * @param {ManifestData} manifest_data
198
- */
199
- function generate_app(manifest_data) {
200
- // TODO remove default layout altogether
201
-
202
- const max_depth = Math.max(
203
- ...manifest_data.routes.map((route) =>
204
- route.type === 'page' ? route.a.filter(Boolean).length : 0
205
- ),
206
- 1
207
- );
208
-
209
- const levels = [];
210
- for (let i = 0; i <= max_depth; i += 1) {
211
- levels.push(i);
212
- }
213
-
214
- let l = max_depth;
215
-
216
- let pyramid = `<svelte:component this={components[${l}]} {...(props_${l} || {})}/>`;
217
-
218
- while (l--) {
219
- pyramid = `
220
- {#if components[${l + 1}]}
221
- <svelte:component this={components[${l}]} {...(props_${l} || {})}>
222
- ${pyramid.replace(/\n/g, '\n\t\t\t\t\t')}
223
- </svelte:component>
224
- {:else}
225
- <svelte:component this={components[${l}]} {...(props_${l} || {})} />
226
- {/if}
227
- `
228
- .replace(/^\t\t\t/gm, '')
229
- .trim();
230
- }
231
-
232
- return trim(`
233
- <!-- This file is generated by @sveltejs/kit — do not edit it! -->
234
- <script>
235
- import { setContext, afterUpdate, onMount } from 'svelte';
236
-
237
- // stores
238
- export let stores;
239
- export let page;
240
-
241
- export let components;
242
- ${levels.map((l) => `export let props_${l} = null;`).join('\n\t\t\t')}
243
-
244
- setContext('__svelte__', stores);
245
-
246
- $: stores.page.set(page);
247
- afterUpdate(stores.page.notify);
248
-
249
- let mounted = false;
250
- let navigated = false;
251
- let title = null;
252
-
253
- onMount(() => {
254
- const unsubscribe = stores.page.subscribe(() => {
255
- if (mounted) {
256
- navigated = true;
257
- title = document.title || 'untitled page';
258
- }
259
- });
260
-
261
- mounted = true;
262
- return unsubscribe;
263
- });
264
- </script>
265
-
266
- ${pyramid.replace(/\n/g, '\n\t\t')}
267
-
268
- {#if mounted}
269
- <div id="svelte-announcer" aria-live="assertive" aria-atomic="true" style="position: absolute; left: 0; top: 0; clip: rect(0 0 0 0); clip-path: inset(50%); overflow: hidden; white-space: nowrap; width: 1px; height: 1px">
270
- {#if navigated}
271
- {title}
272
- {/if}
273
- </div>
274
- {/if}
275
- `);
276
- }
277
-
278
- /**
279
- * @param {import('types').ValidatedConfig} config
280
- * @param {ManifestData} manifest_data
281
- */
282
- function create_types(config, manifest_data) {
283
- /** @type {Map<string, { params: string[], type: 'page' | 'endpoint' | 'both' }>} */
284
- const shadow_types = new Map();
285
-
286
- /** @param {string} key */
287
- function extract_params(key) {
288
- /** @type {string[]} */
289
- const params = [];
290
-
291
- const pattern = /\[([^\]]+)\]/g;
292
- let match;
293
-
294
- while ((match = pattern.exec(key))) {
295
- params.push(match[1]);
296
- }
297
-
298
- return params;
299
- }
300
-
301
- manifest_data.routes.forEach((route) => {
302
- if (route.type === 'endpoint') {
303
- const key = route.file.slice(0, -path__default.extname(route.file).length);
304
- shadow_types.set(key, { params: extract_params(key), type: 'endpoint' });
305
- } else if (route.shadow) {
306
- const key = route.shadow.slice(0, -path__default.extname(route.shadow).length);
307
- shadow_types.set(key, { params: extract_params(key), type: 'both' });
308
- }
309
- });
310
-
311
- manifest_data.components.forEach((component) => {
312
- if (component.startsWith('.')) return; // exclude fallback components
313
-
314
- const ext = /** @type {string} */ (config.extensions.find((ext) => component.endsWith(ext)));
315
- const key = component.slice(0, -ext.length);
316
-
317
- if (!shadow_types.has(key)) {
318
- shadow_types.set(key, { params: extract_params(key), type: 'page' });
319
- }
320
- });
321
-
322
- shadow_types.forEach(({ params, type }, key) => {
323
- const arg = `{ ${params.map((param) => `${param}: string`).join('; ')} }`;
324
-
325
- const imports = [
326
- type !== 'page' && 'RequestHandler as GenericRequestHandler',
327
- type !== 'endpoint' && 'Load as GenericLoad'
328
- ]
329
- .filter(Boolean)
330
- .join(', ');
331
-
332
- const file = `${config.kit.outDir}/types/${key || 'index'}.d.ts`;
333
- const content = [
334
- '// this file is auto-generated',
335
- `import type { ${imports} } from '@sveltejs/kit';`,
336
- type !== 'page' && `export type RequestHandler = GenericRequestHandler<${arg}>;`,
337
- type !== 'endpoint' &&
338
- `export type Load<Props = Record<string, any>> = GenericLoad<${arg}, Props>;`
339
- ]
340
- .filter(Boolean)
341
- .join('\n');
342
-
343
- write_if_changed(file, content);
344
- });
345
- }
7
+ import 'sade';
8
+ import 'child_process';
9
+ import 'net';
10
+ import 'os';
346
11
 
347
12
  /**
348
13
  * @param typeMap [Object] Map of MIME type -> Array[extensions]
@@ -517,7 +182,12 @@ function create_manifest_data({
517
182
  const file = posixify(path__default.relative(cwd, resolved));
518
183
  const is_dir = fs__default.statSync(resolved).isDirectory();
519
184
 
520
- const ext = config.extensions.find((ext) => basename.endsWith(ext)) || path__default.extname(basename);
185
+ const ext = is_dir
186
+ ? ''
187
+ : config.extensions.find((ext) => basename.endsWith(ext)) ||
188
+ config.kit.endpointExtensions.find((ext) => basename.endsWith(ext));
189
+
190
+ if (ext === undefined) return;
521
191
 
522
192
  const name = ext ? basename.slice(0, -ext.length) : basename;
523
193
 
@@ -704,20 +374,19 @@ function create_manifest_data({
704
374
 
705
375
  walk(config.kit.files.routes, [], [], [], [layout], [error]);
706
376
 
707
- // merge matching page/endpoint pairs into shadowed pages
377
+ const lookup = new Map();
378
+ for (const route of routes) {
379
+ if (route.type === 'page') {
380
+ lookup.set(route.key, route);
381
+ }
382
+ }
383
+
708
384
  let i = routes.length;
709
385
  while (i--) {
710
386
  const route = routes[i];
711
- const prev = routes[i - 1];
712
-
713
- if (prev && prev.key === route.key) {
714
- if (prev.type !== 'endpoint' || route.type !== 'page') {
715
- const relative = path__default.relative(cwd, path__default.resolve(config.kit.files.routes, prev.key));
716
- throw new Error(`Duplicate route files: ${relative}`);
717
- }
718
-
719
- route.shadow = prev.file;
720
- routes.splice(--i, 1);
387
+ if (route.type === 'endpoint' && lookup.has(route.key)) {
388
+ lookup.get(route.key).shadow = route.file;
389
+ routes.splice(i, 1);
721
390
  }
722
391
  }
723
392
 
@@ -905,18 +574,215 @@ function list_files({ config, dir, path, files = [] }) {
905
574
  return files;
906
575
  }
907
576
 
577
+ const __filename = fileURLToPath(import.meta.url);
578
+ const __dirname = path__default.dirname(__filename);
579
+
580
+ /** @param {string} dest */
581
+ function copy_assets(dest) {
582
+ let prefix = '..';
583
+ do {
584
+ // we jump through these hoops so that this function
585
+ // works whether or not it's been bundled
586
+ const resolved = path__default.resolve(__dirname, `${prefix}/assets`);
587
+
588
+ if (fs__default.existsSync(resolved)) {
589
+ copy(resolved, dest);
590
+ return;
591
+ }
592
+
593
+ prefix = `../${prefix}`;
594
+ } while (true); // eslint-disable-line
595
+ }
596
+
597
+ /** @type {Map<string, string>} */
598
+ const previous_contents = new Map();
599
+
600
+ /**
601
+ * @param {string} file
602
+ * @param {string} code
603
+ */
604
+ function write_if_changed(file, code) {
605
+ if (code !== previous_contents.get(file)) {
606
+ previous_contents.set(file, code);
607
+ mkdirp(path__default.dirname(file));
608
+ fs__default.writeFileSync(file, code);
609
+ }
610
+ }
611
+
612
+ /** @param {string} str */
613
+ function trim(str) {
614
+ const indentation = /** @type {RegExpExecArray} */ (/\n?(\s*)/.exec(str))[1];
615
+ const pattern = new RegExp(`^${indentation}`, 'gm');
616
+ return str.replace(pattern, '').trim();
617
+ }
618
+
619
+ /**
620
+ * @param {import('types').ManifestData} manifest_data
621
+ * @param {string} base
622
+ * @param {string} output
623
+ */
624
+ function write_manifest(manifest_data, base, output) {
625
+ /** @type {Record<string, number>} */
626
+ const component_indexes = {};
627
+
628
+ /** @param {string} c */
629
+ const get_path = (c) => path__default.relative(base, c);
630
+
631
+ const components = `[
632
+ ${manifest_data.components
633
+ .map((component, i) => {
634
+ component_indexes[component] = i;
635
+
636
+ return `() => import(${s(get_path(component))})`;
637
+ })
638
+ .join(',\n\t\t\t\t\t')}
639
+ ]`.replace(/^\t/gm, '');
640
+
641
+ /** @param {string[]} parts */
642
+ const get_indices = (parts) =>
643
+ `[${parts.map((part) => (part ? `c[${component_indexes[part]}]` : '')).join(', ')}]`;
644
+
645
+ const routes = `[
646
+ ${manifest_data.routes
647
+ .map((route) => {
648
+ if (route.type === 'page') {
649
+ const params =
650
+ route.params.length > 0 &&
651
+ '(m) => ({ ' +
652
+ route.params
653
+ .map((param, i) => {
654
+ return param.startsWith('...')
655
+ ? `${param.slice(3)}: d(m[${i + 1}] || '')`
656
+ : `${param}: d(m[${i + 1}])`;
657
+ })
658
+ .join(', ') +
659
+ '})';
660
+
661
+ const tuple = [route.pattern, get_indices(route.a), get_indices(route.b)];
662
+
663
+ // optional items
664
+ if (params || route.shadow) tuple.push(params || 'null');
665
+ if (route.shadow) tuple.push(`'${route.key}'`);
666
+
667
+ return `// ${route.a[route.a.length - 1]}\n\t\t[${tuple.join(', ')}]`;
668
+ }
669
+ })
670
+ .filter(Boolean)
671
+ .join(',\n\n\t\t')}
672
+ ]`.replace(/^\t/gm, '');
673
+
674
+ write_if_changed(
675
+ `${output}/manifest.js`,
676
+ trim(`
677
+ const c = ${components};
678
+
679
+ const d = decodeURIComponent;
680
+
681
+ export const routes = ${routes};
682
+
683
+ // we import the root layout/error components eagerly, so that
684
+ // connectivity errors after initialisation don't nuke the app
685
+ export const fallback = [c[0](), c[1]()];
686
+ `)
687
+ );
688
+ }
689
+
690
+ /**
691
+ * @param {import('types').ManifestData} manifest_data
692
+ * @param {string} output
693
+ */
694
+ function write_root(manifest_data, output) {
695
+ // TODO remove default layout altogether
696
+
697
+ const max_depth = Math.max(
698
+ ...manifest_data.routes.map((route) =>
699
+ route.type === 'page' ? route.a.filter(Boolean).length : 0
700
+ ),
701
+ 1
702
+ );
703
+
704
+ const levels = [];
705
+ for (let i = 0; i <= max_depth; i += 1) {
706
+ levels.push(i);
707
+ }
708
+
709
+ let l = max_depth;
710
+
711
+ let pyramid = `<svelte:component this={components[${l}]} {...(props_${l} || {})}/>`;
712
+
713
+ while (l--) {
714
+ pyramid = `
715
+ {#if components[${l + 1}]}
716
+ <svelte:component this={components[${l}]} {...(props_${l} || {})}>
717
+ ${pyramid.replace(/\n/g, '\n\t\t\t\t\t')}
718
+ </svelte:component>
719
+ {:else}
720
+ <svelte:component this={components[${l}]} {...(props_${l} || {})} />
721
+ {/if}
722
+ `
723
+ .replace(/^\t\t\t/gm, '')
724
+ .trim();
725
+ }
726
+
727
+ write_if_changed(
728
+ `${output}/root.svelte`,
729
+ trim(`
730
+ <!-- This file is generated by @sveltejs/kit — do not edit it! -->
731
+ <script>
732
+ import { setContext, afterUpdate, onMount } from 'svelte';
733
+
734
+ // stores
735
+ export let stores;
736
+ export let page;
737
+
738
+ export let components;
739
+ ${levels.map((l) => `export let props_${l} = null;`).join('\n\t\t\t\t')}
740
+
741
+ setContext('__svelte__', stores);
742
+
743
+ $: stores.page.set(page);
744
+ afterUpdate(stores.page.notify);
745
+
746
+ let mounted = false;
747
+ let navigated = false;
748
+ let title = null;
749
+
750
+ onMount(() => {
751
+ const unsubscribe = stores.page.subscribe(() => {
752
+ if (mounted) {
753
+ navigated = true;
754
+ title = document.title || 'untitled page';
755
+ }
756
+ });
757
+
758
+ mounted = true;
759
+ return unsubscribe;
760
+ });
761
+ </script>
762
+
763
+ ${pyramid.replace(/\n/g, '\n\t\t\t')}
764
+
765
+ {#if mounted}
766
+ <div id="svelte-announcer" aria-live="assertive" aria-atomic="true" style="position: absolute; left: 0; top: 0; clip: rect(0 0 0 0); clip-path: inset(50%); overflow: hidden; white-space: nowrap; width: 1px; height: 1px">
767
+ {#if navigated}
768
+ {title}
769
+ {/if}
770
+ </div>
771
+ {/if}
772
+ `)
773
+ );
774
+ }
775
+
908
776
  /** @param {string} file */
909
777
  const exists = (file) => fs__default.existsSync(file) && file;
910
778
 
911
779
  /** @param {import('types').ValidatedConfig} config */
912
- function generate_tsconfig(config) {
780
+ function write_tsconfig(config) {
913
781
  const out = path__default.join(config.kit.outDir, 'tsconfig.json');
914
782
  const user_file = exists('tsconfig.json') || exists('jsconfig.json');
915
783
 
916
784
  if (user_file) validate(config, out, user_file);
917
785
 
918
- mkdirp(config.kit.outDir);
919
-
920
786
  /** @param {string} file */
921
787
  const project_relative = (file) => posixify(path__default.relative('.', file));
922
788
 
@@ -936,7 +802,7 @@ function generate_tsconfig(config) {
936
802
  include.push(config_relative(`${dir}/**/*.svelte`));
937
803
  });
938
804
 
939
- fs__default.writeFileSync(
805
+ write_if_changed(
940
806
  out,
941
807
  JSON.stringify(
942
808
  {
@@ -1029,4 +895,105 @@ function validate(config, out, user_file) {
1029
895
  }
1030
896
  }
1031
897
 
1032
- export { create_app as a, create_manifest_data as c, deep_merge as d, generate_tsconfig as g };
898
+ /**
899
+ * @param {import('types').ValidatedConfig} config
900
+ * @param {import('types').ManifestData} manifest_data
901
+ */
902
+ function write_types(config, manifest_data) {
903
+ /** @type {Map<string, { params: string[], type: 'page' | 'endpoint' | 'both' }>} */
904
+ const shadow_types = new Map();
905
+
906
+ /** @param {string} key */
907
+ function extract_params(key) {
908
+ /** @type {string[]} */
909
+ const params = [];
910
+
911
+ const pattern = /\[([^\]]+)\]/g;
912
+ let match;
913
+
914
+ while ((match = pattern.exec(key))) {
915
+ params.push(match[1]);
916
+ }
917
+
918
+ return params;
919
+ }
920
+
921
+ manifest_data.routes.forEach((route) => {
922
+ const file = route.type === 'endpoint' ? route.file : route.shadow;
923
+
924
+ if (file) {
925
+ const ext = /** @type {string} */ (
926
+ config.kit.endpointExtensions.find((ext) => file.endsWith(ext))
927
+ );
928
+ const key = file.slice(0, -ext.length);
929
+ shadow_types.set(key, {
930
+ params: extract_params(key),
931
+ type: route.type === 'endpoint' ? 'endpoint' : 'both'
932
+ });
933
+ }
934
+ });
935
+
936
+ manifest_data.components.forEach((component) => {
937
+ if (component.startsWith('.')) return; // exclude fallback components
938
+
939
+ const ext = /** @type {string} */ (config.extensions.find((ext) => component.endsWith(ext)));
940
+ const key = component.slice(0, -ext.length);
941
+
942
+ if (!shadow_types.has(key)) {
943
+ shadow_types.set(key, { params: extract_params(key), type: 'page' });
944
+ }
945
+ });
946
+
947
+ shadow_types.forEach(({ params, type }, key) => {
948
+ const arg =
949
+ params.length > 0 ? `{ ${params.map((param) => `${param}: string`).join('; ')} }` : '{}';
950
+
951
+ const imports = [
952
+ type !== 'page' && 'RequestHandler as GenericRequestHandler',
953
+ type !== 'endpoint' && 'Load as GenericLoad'
954
+ ]
955
+ .filter(Boolean)
956
+ .join(', ');
957
+
958
+ const file = `${config.kit.outDir}/types/${key || 'index'}.d.ts`;
959
+ const content = [
960
+ '// this file is auto-generated',
961
+ `import type { ${imports} } from '@sveltejs/kit';`,
962
+ type !== 'page' && `export type RequestHandler = GenericRequestHandler<${arg}>;`,
963
+ type !== 'endpoint' &&
964
+ `export type Load<Props = Record<string, any>> = GenericLoad<${arg}, Props>;`
965
+ ]
966
+ .filter(Boolean)
967
+ .join('\n');
968
+
969
+ write_if_changed(file, content);
970
+ });
971
+ }
972
+
973
+ /** @param {import('types').ValidatedConfig} config */
974
+ function init(config) {
975
+ copy_assets(path__default.join(config.kit.outDir, 'runtime'));
976
+ write_tsconfig(config);
977
+ }
978
+
979
+ /** @param {import('types').ValidatedConfig} config */
980
+ function update(config) {
981
+ const manifest_data = create_manifest_data({ config });
982
+
983
+ const output = path__default.join(config.kit.outDir, 'generated');
984
+ const base = path__default.relative('.', output);
985
+
986
+ write_manifest(manifest_data, base, output);
987
+ write_root(manifest_data, output);
988
+ write_types(config, manifest_data);
989
+
990
+ return { manifest_data };
991
+ }
992
+
993
+ /** @param {import('types').ValidatedConfig} config */
994
+ function all(config) {
995
+ init(config);
996
+ return update(config);
997
+ }
998
+
999
+ export { all, init, update };