@sveltejs/kit 1.0.0-next.503 → 1.0.0-next.505
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 -1
- package/src/core/sync/write_types/index.js +98 -21
- package/src/runtime/app/forms.js +6 -0
- package/types/index.d.ts +29 -1
package/package.json
CHANGED
|
@@ -6,10 +6,18 @@ import { compact } from '../../../utils/array.js';
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* @typedef {{
|
|
9
|
+
* file_name: string;
|
|
9
10
|
* modified: boolean;
|
|
10
11
|
* code: string;
|
|
11
12
|
* exports: any[];
|
|
12
13
|
* } | null} Proxy
|
|
14
|
+
*
|
|
15
|
+
* @typedef {{
|
|
16
|
+
* server: Proxy,
|
|
17
|
+
* shared: Proxy
|
|
18
|
+
* }} Proxies
|
|
19
|
+
*
|
|
20
|
+
* @typedef {Map<import('types').PageNode, {route: import('types').RouteData, proxies: Proxies}>} RoutesMap
|
|
13
21
|
*/
|
|
14
22
|
|
|
15
23
|
/** @type {import('typescript')} */
|
|
@@ -153,11 +161,11 @@ export async function write_types(config, manifest_data, file) {
|
|
|
153
161
|
* @param {import('types').ManifestData} manifest_data
|
|
154
162
|
*/
|
|
155
163
|
function create_routes_map(manifest_data) {
|
|
156
|
-
/** @type {
|
|
164
|
+
/** @type {RoutesMap} */
|
|
157
165
|
const map = new Map();
|
|
158
166
|
for (const route of manifest_data.routes) {
|
|
159
167
|
if (route.leaf) {
|
|
160
|
-
map.set(route.leaf, route);
|
|
168
|
+
map.set(route.leaf, { route, proxies: { server: null, shared: null } });
|
|
161
169
|
}
|
|
162
170
|
}
|
|
163
171
|
return map;
|
|
@@ -166,7 +174,7 @@ function create_routes_map(manifest_data) {
|
|
|
166
174
|
/**
|
|
167
175
|
* Update types for a specific route
|
|
168
176
|
* @param {import('types').ValidatedConfig} config
|
|
169
|
-
* @param {
|
|
177
|
+
* @param {RoutesMap} routes
|
|
170
178
|
* @param {import('types').RouteData} route
|
|
171
179
|
* @param {Set<string>} [to_delete]
|
|
172
180
|
*/
|
|
@@ -208,12 +216,30 @@ function update_types(config, routes, route, to_delete = new Set()) {
|
|
|
208
216
|
}
|
|
209
217
|
|
|
210
218
|
if (route.leaf) {
|
|
211
|
-
|
|
219
|
+
let route_info = routes.get(route.leaf);
|
|
220
|
+
if (!route_info) {
|
|
221
|
+
// This should be defined, but belts and braces
|
|
222
|
+
route_info = { route, proxies: { server: null, shared: null } };
|
|
223
|
+
routes.set(route.leaf, route_info);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const {
|
|
227
|
+
declarations: d,
|
|
228
|
+
exports: e,
|
|
229
|
+
proxies
|
|
230
|
+
} = process_node(route.leaf, outdir, true, route_info.proxies);
|
|
212
231
|
|
|
213
232
|
exports.push(...e);
|
|
214
233
|
declarations.push(...d);
|
|
215
234
|
|
|
216
|
-
|
|
235
|
+
if (proxies.server) {
|
|
236
|
+
route_info.proxies.server = proxies.server;
|
|
237
|
+
if (proxies.server?.modified) to_delete.delete(proxies.server.file_name);
|
|
238
|
+
}
|
|
239
|
+
if (proxies.shared) {
|
|
240
|
+
route_info.proxies.shared = proxies.shared;
|
|
241
|
+
if (proxies.shared?.modified) to_delete.delete(proxies.shared.file_name);
|
|
242
|
+
}
|
|
217
243
|
|
|
218
244
|
if (route.leaf.server) {
|
|
219
245
|
exports.push(`export type Action = Kit.Action<RouteParams>`);
|
|
@@ -227,9 +253,20 @@ function update_types(config, routes, route, to_delete = new Set()) {
|
|
|
227
253
|
route.layout.child_pages?.forEach((page) => {
|
|
228
254
|
const leaf = routes.get(page);
|
|
229
255
|
if (leaf) {
|
|
230
|
-
for (const name of leaf.names) {
|
|
256
|
+
for (const name of leaf.route.names) {
|
|
231
257
|
layout_params.add(name);
|
|
232
258
|
}
|
|
259
|
+
|
|
260
|
+
ensureProxies(page, leaf.proxies);
|
|
261
|
+
|
|
262
|
+
if (
|
|
263
|
+
// Be defensive - if a proxy doesn't exist (because it couldn't be created), assume a load function exists.
|
|
264
|
+
// If we didn't and it's a false negative, the user could wrongfully get a type error on layouts.
|
|
265
|
+
(leaf.proxies.server && !leaf.proxies.server.exports.includes('load')) ||
|
|
266
|
+
(leaf.proxies.shared && !leaf.proxies.shared.exports.includes('load'))
|
|
267
|
+
) {
|
|
268
|
+
all_pages_have_load = false;
|
|
269
|
+
}
|
|
233
270
|
}
|
|
234
271
|
if (!page.server && !page.shared) {
|
|
235
272
|
all_pages_have_load = false;
|
|
@@ -245,20 +282,27 @@ function update_types(config, routes, route, to_delete = new Set()) {
|
|
|
245
282
|
const {
|
|
246
283
|
exports: e,
|
|
247
284
|
declarations: d,
|
|
248
|
-
|
|
249
|
-
} = process_node(
|
|
285
|
+
proxies
|
|
286
|
+
} = process_node(
|
|
287
|
+
route.layout,
|
|
288
|
+
outdir,
|
|
289
|
+
false,
|
|
290
|
+
{ server: null, shared: null },
|
|
291
|
+
all_pages_have_load
|
|
292
|
+
);
|
|
250
293
|
|
|
251
294
|
exports.push(...e);
|
|
252
295
|
declarations.push(...d);
|
|
253
296
|
|
|
254
|
-
|
|
297
|
+
if (proxies.server?.modified) to_delete.delete(proxies.server.file_name);
|
|
298
|
+
if (proxies.shared?.modified) to_delete.delete(proxies.shared.file_name);
|
|
255
299
|
}
|
|
256
300
|
|
|
257
301
|
if (route.endpoint) {
|
|
258
302
|
exports.push(`export type RequestHandler = Kit.RequestHandler<RouteParams>;`);
|
|
259
303
|
}
|
|
260
304
|
|
|
261
|
-
if (route.leaf?.server || route.endpoint) {
|
|
305
|
+
if (route.leaf?.server || route.layout?.server || route.endpoint) {
|
|
262
306
|
exports.push(`export type RequestEvent = Kit.RequestEvent<RouteParams>;`);
|
|
263
307
|
}
|
|
264
308
|
|
|
@@ -278,14 +322,13 @@ function update_types(config, routes, route, to_delete = new Set()) {
|
|
|
278
322
|
* @param {import('types').PageNode} node
|
|
279
323
|
* @param {string} outdir
|
|
280
324
|
* @param {boolean} is_page
|
|
325
|
+
* @param {Proxies} proxies
|
|
281
326
|
* @param {boolean} [all_pages_have_load]
|
|
282
327
|
*/
|
|
283
|
-
function process_node(node, outdir, is_page, all_pages_have_load = true) {
|
|
328
|
+
function process_node(node, outdir, is_page, proxies, all_pages_have_load = true) {
|
|
284
329
|
const params = `${is_page ? 'Route' : 'Layout'}Params`;
|
|
285
330
|
const prefix = is_page ? 'Page' : 'Layout';
|
|
286
331
|
|
|
287
|
-
/** @type {string[]} */
|
|
288
|
-
let written_proxies = [];
|
|
289
332
|
/** @type {string[]} */
|
|
290
333
|
const declarations = [];
|
|
291
334
|
/** @type {string[]} */
|
|
@@ -296,13 +339,13 @@ function process_node(node, outdir, is_page, all_pages_have_load = true) {
|
|
|
296
339
|
/** @type {string} */
|
|
297
340
|
let data;
|
|
298
341
|
|
|
342
|
+
ensureProxies(node, proxies);
|
|
343
|
+
|
|
299
344
|
if (node.server) {
|
|
300
|
-
const content = fs.readFileSync(node.server, 'utf8');
|
|
301
|
-
const proxy = tweak_types(content, true);
|
|
302
345
|
const basename = path.basename(node.server);
|
|
346
|
+
const proxy = proxies.server;
|
|
303
347
|
if (proxy?.modified) {
|
|
304
348
|
fs.writeFileSync(`${outdir}/proxy${basename}`, proxy.code);
|
|
305
|
-
written_proxies.push(`proxy${basename}`);
|
|
306
349
|
}
|
|
307
350
|
|
|
308
351
|
server_data = get_data_type(node.server, 'null', proxy, true);
|
|
@@ -346,11 +389,9 @@ function process_node(node, outdir, is_page, all_pages_have_load = true) {
|
|
|
346
389
|
declarations.push(`type ${parent_type} = ${get_parent_type(node, 'LayoutData')};`);
|
|
347
390
|
|
|
348
391
|
if (node.shared) {
|
|
349
|
-
const
|
|
350
|
-
const proxy = tweak_types(content, false);
|
|
392
|
+
const proxy = proxies.shared;
|
|
351
393
|
if (proxy?.modified) {
|
|
352
394
|
fs.writeFileSync(`${outdir}/proxy${path.basename(node.shared)}`, proxy.code);
|
|
353
|
-
written_proxies.push(`proxy${path.basename(node.shared)}`);
|
|
354
395
|
}
|
|
355
396
|
|
|
356
397
|
const type = get_data_type(
|
|
@@ -378,7 +419,7 @@ function process_node(node, outdir, is_page, all_pages_have_load = true) {
|
|
|
378
419
|
|
|
379
420
|
exports.push(`export type ${prefix}Data = ${data};`);
|
|
380
421
|
|
|
381
|
-
return { declarations, exports,
|
|
422
|
+
return { declarations, exports, proxies };
|
|
382
423
|
|
|
383
424
|
/**
|
|
384
425
|
* @param {string} file_path
|
|
@@ -405,6 +446,42 @@ function process_node(node, outdir, is_page, all_pages_have_load = true) {
|
|
|
405
446
|
}
|
|
406
447
|
}
|
|
407
448
|
|
|
449
|
+
/**
|
|
450
|
+
* This function populates the proxies object, if necessary and not already done.
|
|
451
|
+
* Proxies are used to tweak the code of a file before it's typechecked.
|
|
452
|
+
* They are needed in two places - when generating the types for a page or layout.
|
|
453
|
+
* To not do the same work twice, we generate the proxies once and pass them around.
|
|
454
|
+
*
|
|
455
|
+
* @param {import('types').PageNode} node
|
|
456
|
+
* @param {Proxies} proxies
|
|
457
|
+
*/
|
|
458
|
+
function ensureProxies(node, proxies) {
|
|
459
|
+
if (node.server && !proxies.server) {
|
|
460
|
+
proxies.server = createProxy(node.server, true);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
if (node.shared && !proxies.shared) {
|
|
464
|
+
proxies.shared = createProxy(node.shared, false);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* @param {string} file_path
|
|
470
|
+
* @param {boolean} is_server
|
|
471
|
+
* @returns {Proxy}
|
|
472
|
+
*/
|
|
473
|
+
function createProxy(file_path, is_server) {
|
|
474
|
+
const proxy = tweak_types(fs.readFileSync(file_path, 'utf8'), is_server);
|
|
475
|
+
if (proxy) {
|
|
476
|
+
return {
|
|
477
|
+
...proxy,
|
|
478
|
+
file_name: `proxy${path.basename(file_path)}`
|
|
479
|
+
};
|
|
480
|
+
} else {
|
|
481
|
+
return null;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
408
485
|
/**
|
|
409
486
|
* Get the parent type string by recursively looking up the parent layout and accumulate them to one type.
|
|
410
487
|
* @param {import('types').PageNode} node
|
|
@@ -457,7 +534,7 @@ function replace_ext_with_js(file_path) {
|
|
|
457
534
|
/**
|
|
458
535
|
* @param {string} content
|
|
459
536
|
* @param {boolean} is_server
|
|
460
|
-
* @returns {Proxy}
|
|
537
|
+
* @returns {Omit<NonNullable<Proxy>, 'file_name'> | null}
|
|
461
538
|
*/
|
|
462
539
|
export function tweak_types(content, is_server) {
|
|
463
540
|
const names = new Set(is_server ? ['load', 'actions'] : ['load']);
|
package/src/runtime/app/forms.js
CHANGED
|
@@ -51,6 +51,12 @@ export function enhance(form, submit = () => {}) {
|
|
|
51
51
|
);
|
|
52
52
|
|
|
53
53
|
const data = new FormData(form);
|
|
54
|
+
|
|
55
|
+
const submitter_name = event.submitter?.getAttribute('name');
|
|
56
|
+
if (submitter_name) {
|
|
57
|
+
data.append(submitter_name, event.submitter?.getAttribute('value') ?? '');
|
|
58
|
+
}
|
|
59
|
+
|
|
54
60
|
const controller = new AbortController();
|
|
55
61
|
|
|
56
62
|
let cancelled = false;
|
package/types/index.d.ts
CHANGED
|
@@ -59,7 +59,11 @@ export interface ValidationError<T extends Record<string, unknown> | undefined =
|
|
|
59
59
|
data: T;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
type UnpackValidationError<T> = T extends ValidationError<infer X>
|
|
62
|
+
type UnpackValidationError<T> = T extends ValidationError<infer X>
|
|
63
|
+
? X
|
|
64
|
+
: T extends void
|
|
65
|
+
? undefined // needs to be undefined, because void will corrupt union type
|
|
66
|
+
: T;
|
|
63
67
|
|
|
64
68
|
export interface Builder {
|
|
65
69
|
log: Logger;
|
|
@@ -295,13 +299,37 @@ export interface Navigation {
|
|
|
295
299
|
delta?: number;
|
|
296
300
|
}
|
|
297
301
|
|
|
302
|
+
/**
|
|
303
|
+
* The shape of the `$page` store
|
|
304
|
+
*/
|
|
298
305
|
export interface Page<Params extends Record<string, string> = Record<string, string>> {
|
|
306
|
+
/**
|
|
307
|
+
* The URL of the current page
|
|
308
|
+
*/
|
|
299
309
|
url: URL;
|
|
310
|
+
/**
|
|
311
|
+
* The parameters of the current page - e.g. for a route like `/blog/[slug]`, the `slug` parameter
|
|
312
|
+
*/
|
|
300
313
|
params: Params;
|
|
314
|
+
/**
|
|
315
|
+
* The route ID of the current page - e.g. for `src/routes/blog/[slug]`, it would be `blog/[slug]`
|
|
316
|
+
*/
|
|
301
317
|
routeId: string | null;
|
|
318
|
+
/**
|
|
319
|
+
* Http status code of the current page
|
|
320
|
+
*/
|
|
302
321
|
status: number;
|
|
322
|
+
/**
|
|
323
|
+
* The error object of the current page, if any. Filled from the `handleError` hooks.
|
|
324
|
+
*/
|
|
303
325
|
error: App.Error | null;
|
|
326
|
+
/**
|
|
327
|
+
* The merged result of all data from all `load` functions on the current page. You can type a common denominator through `App.PageData`.
|
|
328
|
+
*/
|
|
304
329
|
data: App.PageData & Record<string, any>;
|
|
330
|
+
/**
|
|
331
|
+
* Filled only after a form submission. See [form actions](https://kit.svelte.dev/docs/form-actions) for more info.
|
|
332
|
+
*/
|
|
305
333
|
form: any;
|
|
306
334
|
}
|
|
307
335
|
|