@sveltejs/kit 1.0.0-next.430 → 1.0.0-next.433
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.
- package/package.json +1 -2
- package/src/core/adapt/builder.js +28 -13
- package/src/core/generate_manifest/index.js +12 -33
- package/src/core/prerender/prerender.js +3 -2
- package/src/core/sync/create_manifest_data/index.js +273 -333
- package/src/core/sync/create_manifest_data/types.d.ts +1 -4
- package/src/core/sync/sync.js +3 -3
- package/src/core/sync/utils.js +0 -11
- package/src/core/sync/write_client_manifest.js +27 -13
- package/src/core/sync/write_root.js +1 -1
- package/src/core/sync/write_types.js +156 -384
- package/src/runtime/client/ambient.d.ts +4 -3
- package/src/runtime/client/client.js +208 -132
- package/src/runtime/client/parse.js +10 -5
- package/src/runtime/client/types.d.ts +10 -29
- package/src/runtime/server/endpoint.js +2 -10
- package/src/runtime/server/index.js +87 -44
- package/src/runtime/server/page/fetch.js +1 -1
- package/src/runtime/server/page/index.js +13 -25
- package/src/runtime/server/page/load_data.js +47 -10
- package/src/utils/array.js +9 -0
- package/src/utils/functions.js +16 -0
- package/src/utils/routing.js +30 -1
- package/src/vite/build/build_server.js +23 -12
- package/src/vite/dev/index.js +22 -30
- package/src/vite/index.js +7 -1
- package/src/vite/preview/index.js +1 -1
- package/types/index.d.ts +1 -1
- package/types/internal.d.ts +103 -41
|
@@ -1,28 +1,8 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import MagicString from 'magic-string';
|
|
4
|
-
import { posixify, rimraf } from '../../utils/filesystem.js';
|
|
5
|
-
import {
|
|
6
|
-
import { remove_from_previous, write_if_changed } from './utils.js';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @typedef { import('types').PageNode & {
|
|
10
|
-
* parent?: {
|
|
11
|
-
* key: string;
|
|
12
|
-
* name: string;
|
|
13
|
-
* folder_depth_diff: number;
|
|
14
|
-
* }
|
|
15
|
-
* } } Node
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @typedef {{
|
|
20
|
-
* leaf?: Node;
|
|
21
|
-
* default_layout?: Node;
|
|
22
|
-
* named_layouts: Map<string, Node>;
|
|
23
|
-
* endpoint?: string;
|
|
24
|
-
* }} NodeGroup
|
|
25
|
-
*/
|
|
4
|
+
import { posixify, rimraf, walk } from '../../utils/filesystem.js';
|
|
5
|
+
import { compact } from '../../utils/array.js';
|
|
26
6
|
|
|
27
7
|
/**
|
|
28
8
|
* @typedef {{
|
|
@@ -32,200 +12,133 @@ import { remove_from_previous, write_if_changed } from './utils.js';
|
|
|
32
12
|
* } | null} Proxy
|
|
33
13
|
*/
|
|
34
14
|
|
|
15
|
+
/** @type {import('typescript')} */
|
|
16
|
+
// @ts-ignore
|
|
17
|
+
let ts = undefined;
|
|
18
|
+
try {
|
|
19
|
+
ts = (await import('typescript')).default;
|
|
20
|
+
} catch {}
|
|
21
|
+
|
|
35
22
|
const cwd = process.cwd();
|
|
36
23
|
|
|
37
24
|
const shared_names = new Set(['load']);
|
|
38
25
|
const server_names = new Set(['load', 'POST', 'PUT', 'PATCH', 'DELETE']); // TODO replace with a single `action`
|
|
39
26
|
|
|
40
|
-
let first_run = true;
|
|
41
|
-
|
|
42
27
|
/**
|
|
43
28
|
* Creates types for the whole manifest
|
|
44
|
-
*
|
|
45
29
|
* @param {import('types').ValidatedConfig} config
|
|
46
30
|
* @param {import('types').ManifestData} manifest_data
|
|
47
31
|
*/
|
|
48
|
-
export async function
|
|
49
|
-
|
|
50
|
-
let ts = undefined;
|
|
51
|
-
try {
|
|
52
|
-
ts = (await import('typescript')).default;
|
|
53
|
-
} catch (e) {
|
|
54
|
-
// No TypeScript installed - skip type generation
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
32
|
+
export async function write_all_types(config, manifest_data) {
|
|
33
|
+
if (!ts) return;
|
|
57
34
|
|
|
58
35
|
const types_dir = `${config.kit.outDir}/types`;
|
|
59
36
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const routes_dir = posixify(path.relative('.', config.kit.files.routes));
|
|
66
|
-
const groups = get_groups(manifest_data, routes_dir);
|
|
37
|
+
// empty out files that no longer need to exist
|
|
38
|
+
const routes_dir = path.relative('.', config.kit.files.routes);
|
|
39
|
+
const expected_directories = new Set(
|
|
40
|
+
manifest_data.routes.map((route) => path.join(routes_dir, route.id))
|
|
41
|
+
);
|
|
67
42
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
43
|
+
if (fs.existsSync(types_dir)) {
|
|
44
|
+
for (const file of walk(types_dir)) {
|
|
45
|
+
const dir = path.dirname(file);
|
|
46
|
+
if (!expected_directories.has(dir)) {
|
|
47
|
+
rimraf(file);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
73
50
|
}
|
|
74
51
|
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
rimraf(file);
|
|
80
|
-
}
|
|
81
|
-
return was_removed;
|
|
82
|
-
});
|
|
52
|
+
// For each directory, write $types.d.ts
|
|
53
|
+
for (const route of manifest_data.routes) {
|
|
54
|
+
update_types(config, manifest_data, route);
|
|
55
|
+
}
|
|
83
56
|
}
|
|
84
57
|
|
|
85
58
|
/**
|
|
86
59
|
* Creates types related to the given file. This should only be called
|
|
87
60
|
* if the file in question was edited, not if it was created/deleted/moved.
|
|
88
|
-
*
|
|
89
61
|
* @param {import('types').ValidatedConfig} config
|
|
90
62
|
* @param {import('types').ManifestData} manifest_data
|
|
91
63
|
* @param {string} file
|
|
92
64
|
*/
|
|
93
|
-
export async function
|
|
65
|
+
export async function write_types(config, manifest_data, file) {
|
|
66
|
+
if (!ts) return;
|
|
67
|
+
|
|
94
68
|
if (!path.basename(file).startsWith('+')) {
|
|
95
69
|
// Not a route file
|
|
96
70
|
return;
|
|
97
71
|
}
|
|
98
72
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
try {
|
|
102
|
-
ts = (await import('typescript')).default;
|
|
103
|
-
} catch (e) {
|
|
104
|
-
// No TypeScript installed - skip type generation
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
73
|
+
const filepath = path.relative(config.kit.files.routes, file);
|
|
74
|
+
const id = path.dirname(filepath);
|
|
107
75
|
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
const groups = get_groups(manifest_data, routes_dir);
|
|
76
|
+
const route = manifest_data.routes.find((route) => route.id === id);
|
|
77
|
+
if (!route) return; // this shouldn't ever happen
|
|
111
78
|
|
|
112
|
-
|
|
113
|
-
write_types_for_dir(config, manifest_data, routes_dir, file_dir, groups, ts);
|
|
79
|
+
update_types(config, manifest_data, route);
|
|
114
80
|
}
|
|
115
81
|
|
|
116
82
|
/**
|
|
83
|
+
*
|
|
84
|
+
* @param {import('types').ValidatedConfig} config
|
|
117
85
|
* @param {import('types').ManifestData} manifest_data
|
|
118
|
-
* @param {
|
|
86
|
+
* @param {import('types').RouteData} route
|
|
119
87
|
*/
|
|
120
|
-
function
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
* manifest_data.routes, because that will exclude +layout
|
|
124
|
-
* files that aren't accompanied by a +page
|
|
125
|
-
* @type {Map<string, NodeGroup>}
|
|
126
|
-
*/
|
|
127
|
-
const groups = new Map();
|
|
128
|
-
|
|
129
|
-
/** @param {string} dir */
|
|
130
|
-
function get_group(dir) {
|
|
131
|
-
let group = groups.get(dir);
|
|
132
|
-
if (!group) {
|
|
133
|
-
group = {
|
|
134
|
-
named_layouts: new Map()
|
|
135
|
-
};
|
|
136
|
-
groups.set(dir, group);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return group;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// first, sort nodes (necessary for finding the nearest layout more efficiently)...
|
|
143
|
-
const nodes = [...manifest_data.nodes].sort((n1, n2) => {
|
|
144
|
-
// Sort by path length first...
|
|
145
|
-
const path_length_diff =
|
|
146
|
-
/** @type {string} */ (n1.component ?? n1.shared ?? n1.server).split('/').length -
|
|
147
|
-
/** @type {string} */ (n2.component ?? n2.shared ?? n2.server).split('/').length;
|
|
148
|
-
|
|
149
|
-
return (
|
|
150
|
-
path_length_diff ||
|
|
151
|
-
// ...on ties, sort named layouts first
|
|
152
|
-
(path.basename(n1.component || '').includes('-')
|
|
153
|
-
? -1
|
|
154
|
-
: path.basename(n2.component || '').includes('-')
|
|
155
|
-
? 1
|
|
156
|
-
: 0)
|
|
157
|
-
);
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
// ...then, populate `directories` with +page/+layout files...
|
|
161
|
-
for (let i = 0; i < nodes.length; i += 1) {
|
|
162
|
-
/** @type {Node} */
|
|
163
|
-
const node = { ...nodes[i] }; // shallow copy so we don't mutate the original when setting parent
|
|
164
|
-
|
|
165
|
-
const file_path = /** @type {string} */ (node.component ?? node.shared ?? node.server);
|
|
166
|
-
// skip default layout/error
|
|
167
|
-
if (!file_path.startsWith(routes_dir)) continue;
|
|
168
|
-
|
|
169
|
-
const parts = file_path.split('/');
|
|
170
|
-
|
|
171
|
-
const file = /** @type {string} */ (parts.pop());
|
|
172
|
-
const dir = parts.join('/').slice(routes_dir.length + 1);
|
|
173
|
-
|
|
174
|
-
// error pages don't need types
|
|
175
|
-
if (!file || file.startsWith('+error')) continue;
|
|
176
|
-
|
|
177
|
-
const group = get_group(dir);
|
|
178
|
-
|
|
179
|
-
if (file.startsWith('+page')) {
|
|
180
|
-
group.leaf = node;
|
|
181
|
-
} else {
|
|
182
|
-
const match = /^\+layout(?:-([^@.]+))?/.exec(file);
|
|
88
|
+
function update_types(config, manifest_data, route) {
|
|
89
|
+
const routes_dir = posixify(path.relative('.', config.kit.files.routes));
|
|
90
|
+
const outdir = path.join(config.kit.outDir, 'types', routes_dir, route.id);
|
|
183
91
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if (!match) throw new Error(`Unexpected route file: ${file}`);
|
|
92
|
+
// first, check if the types are out of date
|
|
93
|
+
const input_files = [];
|
|
187
94
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
95
|
+
/** @type {import('types').PageNode | null} */
|
|
96
|
+
let node = route.leaf;
|
|
97
|
+
while (node) {
|
|
98
|
+
if (node.shared) input_files.push(node.shared);
|
|
99
|
+
if (node.server) input_files.push(node.server);
|
|
100
|
+
node = node.parent ?? null;
|
|
101
|
+
}
|
|
194
102
|
|
|
195
|
-
|
|
103
|
+
/** @type {import('types').PageNode | null} */
|
|
104
|
+
node = route.layout;
|
|
105
|
+
while (node) {
|
|
106
|
+
if (node.shared) input_files.push(node.shared);
|
|
107
|
+
if (node.server) input_files.push(node.server);
|
|
108
|
+
node = node.parent ?? null;
|
|
196
109
|
}
|
|
197
110
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if (route.type === 'endpoint') {
|
|
201
|
-
get_group(route.id).endpoint = route.file;
|
|
202
|
-
}
|
|
111
|
+
if (route.endpoint) {
|
|
112
|
+
input_files.push(route.endpoint.file);
|
|
203
113
|
}
|
|
204
114
|
|
|
205
|
-
return
|
|
206
|
-
}
|
|
115
|
+
if (input_files.length === 0) return; // nothing to do
|
|
207
116
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
117
|
+
try {
|
|
118
|
+
fs.mkdirSync(outdir, { recursive: true });
|
|
119
|
+
} catch {}
|
|
120
|
+
|
|
121
|
+
const output_files = compact(
|
|
122
|
+
fs.readdirSync(outdir).map((name) => {
|
|
123
|
+
const stats = fs.statSync(path.join(outdir, name));
|
|
124
|
+
if (stats.isDirectory()) return;
|
|
125
|
+
return {
|
|
126
|
+
name,
|
|
127
|
+
updated: stats.mtimeMs
|
|
128
|
+
};
|
|
129
|
+
})
|
|
130
|
+
);
|
|
222
131
|
|
|
223
|
-
const
|
|
132
|
+
const source_last_updated = Math.max(...input_files.map((file) => fs.statSync(file).mtimeMs));
|
|
133
|
+
const types_last_updated = Math.max(...output_files.map((file) => file?.updated));
|
|
224
134
|
|
|
225
|
-
|
|
135
|
+
// types were generated more recently than the source files, so don't regenerate
|
|
136
|
+
if (types_last_updated > source_last_updated) return;
|
|
226
137
|
|
|
227
|
-
|
|
228
|
-
const
|
|
138
|
+
// track which old files end up being surplus to requirements
|
|
139
|
+
const to_delete = new Set(output_files.map((file) => file.name));
|
|
140
|
+
|
|
141
|
+
const imports = [`import type * as Kit from '@sveltejs/kit';`];
|
|
229
142
|
|
|
230
143
|
/** @type {string[]} */
|
|
231
144
|
const declarations = [];
|
|
@@ -233,10 +146,8 @@ function write_types_for_dir(config, manifest_data, routes_dir, dir, groups, ts)
|
|
|
233
146
|
/** @type {string[]} */
|
|
234
147
|
const exports = [];
|
|
235
148
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
if (route_params.length > 0) {
|
|
239
|
-
const params = route_params.map((param) => `${param}: string`).join('; ');
|
|
149
|
+
if (route.names.length > 0) {
|
|
150
|
+
const params = route.names.map((param) => `${param}: string`).join('; ');
|
|
240
151
|
declarations.push(
|
|
241
152
|
`interface RouteParams extends Partial<Record<string, string>> { ${params} }`
|
|
242
153
|
);
|
|
@@ -244,15 +155,14 @@ function write_types_for_dir(config, manifest_data, routes_dir, dir, groups, ts)
|
|
|
244
155
|
declarations.push(`interface RouteParams extends Partial<Record<string, string>> {}`);
|
|
245
156
|
}
|
|
246
157
|
|
|
247
|
-
if (
|
|
158
|
+
if (route.leaf) {
|
|
248
159
|
const { data, server_data, load, server_load, errors, written_proxies } = process_node(
|
|
249
|
-
|
|
250
|
-
group.leaf,
|
|
160
|
+
route.leaf,
|
|
251
161
|
outdir,
|
|
252
|
-
'RouteParams'
|
|
253
|
-
groups
|
|
162
|
+
'RouteParams'
|
|
254
163
|
);
|
|
255
|
-
|
|
164
|
+
|
|
165
|
+
for (const file of written_proxies) to_delete.delete(file);
|
|
256
166
|
|
|
257
167
|
exports.push(`export type Errors = ${errors};`);
|
|
258
168
|
|
|
@@ -272,20 +182,18 @@ function write_types_for_dir(config, manifest_data, routes_dir, dir, groups, ts)
|
|
|
272
182
|
exports.push('export type PageServerLoadEvent = Parameters<PageServerLoad>[0];');
|
|
273
183
|
}
|
|
274
184
|
|
|
275
|
-
if (
|
|
185
|
+
if (route.leaf.server) {
|
|
276
186
|
exports.push(`export type Action = Kit.Action<RouteParams>`);
|
|
277
187
|
}
|
|
278
188
|
}
|
|
279
189
|
|
|
280
|
-
if (
|
|
281
|
-
// TODO
|
|
282
|
-
// layout, and only include params for child pages that use each layout.
|
|
283
|
-
// but that's more work than i care to do right now
|
|
190
|
+
if (route.layout) {
|
|
191
|
+
// TODO collect children in create_manifest_data, instead of this inefficient O(n^2) algorithm
|
|
284
192
|
const layout_params = new Set();
|
|
285
|
-
manifest_data.routes.forEach((
|
|
286
|
-
if (
|
|
193
|
+
manifest_data.routes.forEach((other) => {
|
|
194
|
+
if (other.page && other.id.startsWith(route.id + '/')) {
|
|
287
195
|
// TODO this is O(n^2), see if we need to speed it up
|
|
288
|
-
for (const name of
|
|
196
|
+
for (const name of other.names) {
|
|
289
197
|
layout_params.add(name);
|
|
290
198
|
}
|
|
291
199
|
}
|
|
@@ -298,95 +206,32 @@ function write_types_for_dir(config, manifest_data, routes_dir, dir, groups, ts)
|
|
|
298
206
|
declarations.push(`interface LayoutParams extends RouteParams {}`);
|
|
299
207
|
}
|
|
300
208
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
'LayoutParams',
|
|
307
|
-
groups
|
|
308
|
-
);
|
|
309
|
-
written_files.push(...written_proxies);
|
|
310
|
-
|
|
311
|
-
exports.push(`export type LayoutData = ${data};`);
|
|
312
|
-
if (load) {
|
|
313
|
-
exports.push(
|
|
314
|
-
`export type LayoutLoad<OutputData extends Record<string, any> | void = Record<string, any> | void> = ${load};`
|
|
315
|
-
);
|
|
316
|
-
exports.push('export type LayoutLoadEvent = Parameters<LayoutLoad>[0];');
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
exports.push(`export type LayoutServerData = ${server_data};`);
|
|
320
|
-
if (server_load) {
|
|
321
|
-
exports.push(
|
|
322
|
-
`export type LayoutServerLoad<OutputData extends Record<string, any> | void = Record<string, any> | void> = ${server_load};`
|
|
323
|
-
);
|
|
324
|
-
exports.push('export type LayoutServerLoadEvent = Parameters<LayoutServerLoad>[0];');
|
|
325
|
-
}
|
|
326
|
-
}
|
|
209
|
+
const { data, server_data, load, server_load, written_proxies } = process_node(
|
|
210
|
+
route.layout,
|
|
211
|
+
outdir,
|
|
212
|
+
'LayoutParams'
|
|
213
|
+
);
|
|
327
214
|
|
|
328
|
-
|
|
329
|
-
/** @type {string[]} */
|
|
330
|
-
const data_exports = [];
|
|
331
|
-
|
|
332
|
-
/** @type {string[]} */
|
|
333
|
-
const server_data_exports = [];
|
|
334
|
-
|
|
335
|
-
/** @type {string[]} */
|
|
336
|
-
const load_exports = [];
|
|
337
|
-
|
|
338
|
-
/** @type {string[]} */
|
|
339
|
-
const load_event_exports = [];
|
|
340
|
-
|
|
341
|
-
/** @type {string[]} */
|
|
342
|
-
const server_load_exports = [];
|
|
343
|
-
|
|
344
|
-
/** @type {string[]} */
|
|
345
|
-
const server_load_event_exports = [];
|
|
346
|
-
|
|
347
|
-
for (const [name, node] of group.named_layouts) {
|
|
348
|
-
const { data, server_data, load, server_load, written_proxies } = process_node(
|
|
349
|
-
ts,
|
|
350
|
-
node,
|
|
351
|
-
outdir,
|
|
352
|
-
'LayoutParams',
|
|
353
|
-
groups
|
|
354
|
-
);
|
|
355
|
-
written_files.push(...written_proxies);
|
|
356
|
-
data_exports.push(`export type ${name} = ${data};`);
|
|
357
|
-
server_data_exports.push(`export type ${name} = ${server_data};`);
|
|
358
|
-
if (load) {
|
|
359
|
-
load_exports.push(
|
|
360
|
-
`export type ${name}<OutputData extends Record<string, any> | void = Record<string, any> | void> = ${load};`
|
|
361
|
-
);
|
|
362
|
-
load_event_exports.push(`export type ${name} = Parameters<LayoutLoad.${name}>[0];`);
|
|
363
|
-
}
|
|
364
|
-
if (server_load) {
|
|
365
|
-
server_load_exports.push(
|
|
366
|
-
`export type ${name}<OutputData extends Record<string, any> | void = Record<string, any> | void> = ${server_load};`
|
|
367
|
-
);
|
|
368
|
-
server_load_event_exports.push(
|
|
369
|
-
`export type ${name} = Parameters<LayoutServerLoad.${name}>[0];`
|
|
370
|
-
);
|
|
371
|
-
}
|
|
372
|
-
}
|
|
215
|
+
for (const file of written_proxies) to_delete.delete(file);
|
|
373
216
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
exports.push(`\nexport namespace LayoutLoadEvent {\n\t${load_event_exports.join('\n\t')}\n}`);
|
|
377
|
-
exports.push(
|
|
378
|
-
`\nexport namespace LayoutServerData {\n\t${server_data_exports.join('\n\t')}\n}`
|
|
379
|
-
);
|
|
217
|
+
exports.push(`export type LayoutData = ${data};`);
|
|
218
|
+
if (load) {
|
|
380
219
|
exports.push(
|
|
381
|
-
|
|
220
|
+
`export type LayoutLoad<OutputData extends Record<string, any> | void = Record<string, any> | void> = ${load};`
|
|
382
221
|
);
|
|
222
|
+
exports.push('export type LayoutLoadEvent = Parameters<LayoutLoad>[0];');
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
exports.push(`export type LayoutServerData = ${server_data};`);
|
|
226
|
+
if (server_load) {
|
|
383
227
|
exports.push(
|
|
384
|
-
|
|
228
|
+
`export type LayoutServerLoad<OutputData extends Record<string, any> | void = Record<string, any> | void> = ${server_load};`
|
|
385
229
|
);
|
|
230
|
+
exports.push('export type LayoutServerLoadEvent = Parameters<LayoutServerLoad>[0];');
|
|
386
231
|
}
|
|
387
232
|
}
|
|
388
233
|
|
|
389
|
-
if (
|
|
234
|
+
if (route.endpoint) {
|
|
390
235
|
exports.push(`export type RequestHandler = Kit.RequestHandler<RouteParams>;`);
|
|
391
236
|
exports.push(`export type RequestEvent = Kit.RequestEvent<RouteParams>;`);
|
|
392
237
|
}
|
|
@@ -395,19 +240,20 @@ function write_types_for_dir(config, manifest_data, routes_dir, dir, groups, ts)
|
|
|
395
240
|
.filter(Boolean)
|
|
396
241
|
.join('\n\n');
|
|
397
242
|
|
|
398
|
-
|
|
243
|
+
fs.writeFileSync(`${outdir}/$types.d.ts`, output);
|
|
244
|
+
to_delete.delete('$types.d.ts');
|
|
399
245
|
|
|
400
|
-
|
|
246
|
+
for (const file of to_delete) {
|
|
247
|
+
fs.unlinkSync(path.join(outdir, file));
|
|
248
|
+
}
|
|
401
249
|
}
|
|
402
250
|
|
|
403
251
|
/**
|
|
404
|
-
* @param {import('
|
|
405
|
-
* @param {Node} node
|
|
252
|
+
* @param {import('types').PageNode} node
|
|
406
253
|
* @param {string} outdir
|
|
407
254
|
* @param {string} params
|
|
408
|
-
* @param {Map<string, NodeGroup>} groups
|
|
409
255
|
*/
|
|
410
|
-
function process_node(
|
|
256
|
+
function process_node(node, outdir, params) {
|
|
411
257
|
let data;
|
|
412
258
|
let load;
|
|
413
259
|
let server_load;
|
|
@@ -420,14 +266,18 @@ function process_node(ts, node, outdir, params, groups) {
|
|
|
420
266
|
|
|
421
267
|
if (node.server) {
|
|
422
268
|
const content = fs.readFileSync(node.server, 'utf8');
|
|
423
|
-
const proxy = tweak_types(
|
|
269
|
+
const proxy = tweak_types(content, server_names);
|
|
424
270
|
const basename = path.basename(node.server);
|
|
425
271
|
if (proxy?.modified) {
|
|
426
|
-
|
|
272
|
+
fs.writeFileSync(`${outdir}/proxy${basename}`, proxy.code);
|
|
273
|
+
written_proxies.push(`proxy${basename}`);
|
|
427
274
|
}
|
|
428
275
|
|
|
429
276
|
server_data = get_data_type(node.server, 'null', proxy);
|
|
430
|
-
server_load = `Kit.ServerLoad<${params}, ${get_parent_type(
|
|
277
|
+
server_load = `Kit.ServerLoad<${params}, ${get_parent_type(
|
|
278
|
+
node,
|
|
279
|
+
'LayoutServerData'
|
|
280
|
+
)}, OutputData>`;
|
|
431
281
|
|
|
432
282
|
if (proxy) {
|
|
433
283
|
const types = [];
|
|
@@ -450,13 +300,14 @@ function process_node(ts, node, outdir, params, groups) {
|
|
|
450
300
|
server_data = 'null';
|
|
451
301
|
}
|
|
452
302
|
|
|
453
|
-
const parent_type = get_parent_type('LayoutData');
|
|
303
|
+
const parent_type = get_parent_type(node, 'LayoutData');
|
|
454
304
|
|
|
455
305
|
if (node.shared) {
|
|
456
306
|
const content = fs.readFileSync(node.shared, 'utf8');
|
|
457
|
-
const proxy = tweak_types(
|
|
307
|
+
const proxy = tweak_types(content, shared_names);
|
|
458
308
|
if (proxy?.modified) {
|
|
459
|
-
|
|
309
|
+
fs.writeFileSync(`${outdir}/proxy${path.basename(node.shared)}`, proxy.code);
|
|
310
|
+
written_proxies.push(`proxy${path.basename(node.shared)}`);
|
|
460
311
|
}
|
|
461
312
|
|
|
462
313
|
const type = get_data_type(node.shared, `${parent_type} & ${server_data}`, proxy);
|
|
@@ -492,39 +343,35 @@ function process_node(ts, node, outdir, params, groups) {
|
|
|
492
343
|
return 'unknown';
|
|
493
344
|
}
|
|
494
345
|
}
|
|
346
|
+
}
|
|
495
347
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
let acc_diff = 0;
|
|
504
|
-
|
|
505
|
-
while (parent) {
|
|
506
|
-
acc_diff += parent.folder_depth_diff;
|
|
507
|
-
let parent_group = /** @type {NodeGroup} */ (groups.get(parent.key));
|
|
508
|
-
// unshift because we need it the other way round for the import string
|
|
509
|
-
parent_imports.unshift(
|
|
510
|
-
(acc_diff === 0 ? '' : `import('` + '../'.repeat(acc_diff) + '$types.js' + `').`) +
|
|
511
|
-
`${type}${parent.name ? `.${parent.name}` : ''}`
|
|
512
|
-
);
|
|
513
|
-
let parent_layout = /** @type {Node} */ (
|
|
514
|
-
parent.name ? parent_group.named_layouts.get(parent.name) : parent_group.default_layout
|
|
515
|
-
);
|
|
516
|
-
parent = parent_layout.parent;
|
|
517
|
-
}
|
|
348
|
+
/**
|
|
349
|
+
* Get the parent type string by recursively looking up the parent layout and accumulate them to one type.
|
|
350
|
+
* @param {import('types').PageNode} node
|
|
351
|
+
* @param {string} type
|
|
352
|
+
*/
|
|
353
|
+
function get_parent_type(node, type) {
|
|
354
|
+
const parent_imports = [];
|
|
518
355
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
356
|
+
let parent = node.parent;
|
|
357
|
+
|
|
358
|
+
while (parent) {
|
|
359
|
+
const d = node.depth - parent.depth;
|
|
360
|
+
// unshift because we need it the other way round for the import string
|
|
361
|
+
parent_imports.unshift(
|
|
362
|
+
`${d === 0 ? '' : `import('${'../'.repeat(d)}${'$types.js'}').`}${type}`
|
|
363
|
+
);
|
|
364
|
+
parent = parent.parent;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
let parent_str = parent_imports[0] || 'Record<never, never>';
|
|
368
|
+
for (let i = 1; i < parent_imports.length; i++) {
|
|
369
|
+
// Omit is necessary because a parent could have a property with the same key which would
|
|
370
|
+
// cause a type conflict. At runtime the child overwrites the parent property in this case,
|
|
371
|
+
// so reflect that in the type definition.
|
|
372
|
+
parent_str = `Omit<${parent_str}, keyof ${parent_imports[i]}> & ${parent_imports[i]}`;
|
|
527
373
|
}
|
|
374
|
+
return parent_str;
|
|
528
375
|
}
|
|
529
376
|
|
|
530
377
|
/**
|
|
@@ -546,12 +393,11 @@ function replace_ext_with_js(file_path) {
|
|
|
546
393
|
}
|
|
547
394
|
|
|
548
395
|
/**
|
|
549
|
-
* @param {import('typescript')} ts
|
|
550
396
|
* @param {string} content
|
|
551
397
|
* @param {Set<string>} names
|
|
552
398
|
* @returns {Proxy}
|
|
553
399
|
*/
|
|
554
|
-
export function tweak_types(
|
|
400
|
+
export function tweak_types(content, names) {
|
|
555
401
|
try {
|
|
556
402
|
let modified = false;
|
|
557
403
|
|
|
@@ -699,77 +545,3 @@ export function tweak_types(ts, content, names) {
|
|
|
699
545
|
return null;
|
|
700
546
|
}
|
|
701
547
|
}
|
|
702
|
-
|
|
703
|
-
/**
|
|
704
|
-
* @param {string} file
|
|
705
|
-
* @param {string} content
|
|
706
|
-
*/
|
|
707
|
-
function write(file, content) {
|
|
708
|
-
write_if_changed(file, content);
|
|
709
|
-
return file;
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
/**
|
|
713
|
-
* Finds the nearest layout for given node.
|
|
714
|
-
* Assumes that nodes is sorted by path length (lowest first).
|
|
715
|
-
*
|
|
716
|
-
* @param {string} routes_dir
|
|
717
|
-
* @param {import('types').PageNode[]} nodes
|
|
718
|
-
* @param {number} start_idx
|
|
719
|
-
*/
|
|
720
|
-
export function find_nearest_layout(routes_dir, nodes, start_idx) {
|
|
721
|
-
const start_file = /** @type {string} */ (
|
|
722
|
-
nodes[start_idx].component || nodes[start_idx].shared || nodes[start_idx].server
|
|
723
|
-
);
|
|
724
|
-
|
|
725
|
-
let name = '';
|
|
726
|
-
const match = /^\+(layout|page)(?:-([^@.]+))?(?:@([^@.]+))?/.exec(path.basename(start_file));
|
|
727
|
-
if (!match) throw new Error(`Unexpected route file: ${start_file}`);
|
|
728
|
-
if (match[3] && match[3] !== 'default') {
|
|
729
|
-
name = match[3]; // a named layout is referenced
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
let common_path = path.dirname(start_file);
|
|
733
|
-
if (match[1] === 'layout' && !match[2] && !name) {
|
|
734
|
-
// We are a default layout, so we skip the current level
|
|
735
|
-
common_path = path.dirname(common_path);
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
for (let i = start_idx - 1; i >= 0; i -= 1) {
|
|
739
|
-
const node = nodes[i];
|
|
740
|
-
const file = /** @type {string} */ (node.component || node.shared || node.server);
|
|
741
|
-
|
|
742
|
-
const current_path = path.dirname(file);
|
|
743
|
-
const common_path_length = common_path.split('/').length;
|
|
744
|
-
const current_path_length = current_path.split('/').length;
|
|
745
|
-
|
|
746
|
-
if (common_path_length < current_path_length) {
|
|
747
|
-
// this is a layout in a different tree
|
|
748
|
-
continue;
|
|
749
|
-
} else if (common_path_length > current_path_length) {
|
|
750
|
-
// we've gone back up a folder level
|
|
751
|
-
common_path = path.dirname(common_path);
|
|
752
|
-
}
|
|
753
|
-
if (common_path !== current_path) {
|
|
754
|
-
// this is a layout in a different tree
|
|
755
|
-
continue;
|
|
756
|
-
}
|
|
757
|
-
if (
|
|
758
|
-
path.basename(file, path.extname(file)).split('@')[0] !==
|
|
759
|
-
'+layout' + (name ? `-${name}` : '')
|
|
760
|
-
) {
|
|
761
|
-
// this is not the layout we are searching for
|
|
762
|
-
continue;
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
// matching parent layout found
|
|
766
|
-
let folder_depth_diff =
|
|
767
|
-
posixify(path.relative(path.dirname(start_file), common_path + '/$types.js')).split('/')
|
|
768
|
-
.length - 1;
|
|
769
|
-
return {
|
|
770
|
-
key: path.dirname(file).slice(routes_dir.length + 1),
|
|
771
|
-
name,
|
|
772
|
-
folder_depth_diff
|
|
773
|
-
};
|
|
774
|
-
}
|
|
775
|
-
}
|