@sveltejs/kit 1.0.0-next.572 → 1.0.0-next.573
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 +2 -2
- package/src/core/prerender/prerender.js +40 -23
- package/src/core/sync/create_manifest_data/index.js +5 -4
- package/src/core/sync/write_types/index.js +1 -1
- package/src/exports/vite/dev/index.js +6 -1
- package/src/runtime/client/client.js +6 -1
- package/src/runtime/server/index.js +32 -3
- package/src/runtime/server/page/actions.js +19 -10
- package/src/runtime/server/page/index.js +1 -3
- package/src/utils/exports.js +54 -0
- package/types/internal.d.ts +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sveltejs/kit",
|
|
3
|
-
"version": "1.0.0-next.
|
|
3
|
+
"version": "1.0.0-next.573",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/sveltejs/kit",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"@types/connect": "^3.4.35",
|
|
29
29
|
"@types/marked": "^4.0.7",
|
|
30
30
|
"@types/mime": "^3.0.1",
|
|
31
|
-
"@types/node": "^16.18.
|
|
31
|
+
"@types/node": "^16.18.6",
|
|
32
32
|
"@types/sade": "^1.7.4",
|
|
33
33
|
"@types/set-cookie-parser": "^2.4.2",
|
|
34
34
|
"marked": "^4.2.3",
|
|
@@ -11,6 +11,11 @@ import { logger } from '../utils.js';
|
|
|
11
11
|
import { load_config } from '../config/index.js';
|
|
12
12
|
import { get_route_segments } from '../../utils/routing.js';
|
|
13
13
|
import { get_option } from '../../runtime/server/utils.js';
|
|
14
|
+
import {
|
|
15
|
+
validate_common_exports,
|
|
16
|
+
validate_page_server_exports,
|
|
17
|
+
validate_server_exports
|
|
18
|
+
} from '../../utils/exports.js';
|
|
14
19
|
|
|
15
20
|
const [, , client_out_dir, manifest_path, results_path, verbose, env] = process.argv;
|
|
16
21
|
|
|
@@ -357,34 +362,46 @@ export async function prerender() {
|
|
|
357
362
|
}
|
|
358
363
|
|
|
359
364
|
for (const route of manifest._.routes) {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
)
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
prerender_map.set(route.id, mod.prerender);
|
|
365
|
+
if (route.endpoint) {
|
|
366
|
+
const mod = await route.endpoint();
|
|
367
|
+
if (mod.prerender !== undefined) {
|
|
368
|
+
validate_server_exports(mod, route.id);
|
|
369
|
+
|
|
370
|
+
if (mod.prerender && (mod.POST || mod.PATCH || mod.PUT || mod.DELETE)) {
|
|
371
|
+
throw new Error(
|
|
372
|
+
`Cannot prerender a +server file with POST, PATCH, PUT, or DELETE (${route.id})`
|
|
373
|
+
);
|
|
371
374
|
}
|
|
375
|
+
|
|
376
|
+
prerender_map.set(route.id, mod.prerender);
|
|
372
377
|
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
if (route.page) {
|
|
381
|
+
const nodes = await Promise.all(
|
|
382
|
+
[...route.page.layouts, route.page.leaf].map((n) => {
|
|
383
|
+
if (n !== undefined) return manifest._.nodes[n]();
|
|
384
|
+
})
|
|
385
|
+
);
|
|
386
|
+
|
|
387
|
+
const layouts = nodes.slice(0, -1);
|
|
388
|
+
const page = nodes.at(-1);
|
|
373
389
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
const prerender = get_option(nodes, 'prerender') ?? false;
|
|
390
|
+
for (const layout of layouts) {
|
|
391
|
+
if (layout) {
|
|
392
|
+
validate_common_exports(layout.server, route.id);
|
|
393
|
+
validate_common_exports(layout.shared, route.id);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
381
396
|
|
|
382
|
-
|
|
397
|
+
if (page) {
|
|
398
|
+
validate_page_server_exports(page.server, route.id);
|
|
399
|
+
validate_common_exports(page.shared, route.id);
|
|
383
400
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
401
|
+
|
|
402
|
+
const prerender = get_option(nodes, 'prerender') ?? false;
|
|
403
|
+
|
|
404
|
+
prerender_map.set(route.id, prerender);
|
|
388
405
|
}
|
|
389
406
|
}
|
|
390
407
|
|
|
@@ -486,10 +486,11 @@ function prevent_conflicts(routes) {
|
|
|
486
486
|
const matcher = split[i];
|
|
487
487
|
const next = split[i + 1];
|
|
488
488
|
|
|
489
|
-
permutations =
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
489
|
+
permutations = permutations.reduce((a, b) => {
|
|
490
|
+
a.push(b + next);
|
|
491
|
+
if (!(matcher === '*' && b.endsWith('//'))) a.push(b + `<${matcher}>${next}`);
|
|
492
|
+
return a;
|
|
493
|
+
}, /** @type {string[]} */ ([]));
|
|
493
494
|
}
|
|
494
495
|
|
|
495
496
|
for (const permutation of permutations) {
|
|
@@ -401,7 +401,7 @@ function process_node(node, outdir, is_page, proxies, all_pages_have_load = true
|
|
|
401
401
|
? `./proxy${replace_ext_with_js(basename)}`
|
|
402
402
|
: path_to_original(outdir, node.server);
|
|
403
403
|
|
|
404
|
-
type = `Expand<Kit.AwaitedActions<typeof import('${from}').actions>> |
|
|
404
|
+
type = `Expand<Kit.AwaitedActions<typeof import('${from}').actions>> | null`;
|
|
405
405
|
}
|
|
406
406
|
}
|
|
407
407
|
exports.push(`export type ActionData = ${type};`);
|
|
@@ -31,6 +31,9 @@ export async function dev(vite, vite_config, svelte_config) {
|
|
|
31
31
|
// @ts-expect-error
|
|
32
32
|
globalThis.__SVELTEKIT_BROWSER__ = false;
|
|
33
33
|
|
|
34
|
+
// @ts-expect-error
|
|
35
|
+
globalThis.__SVELTEKIT_DEV__ = true;
|
|
36
|
+
|
|
34
37
|
sync.init(svelte_config, vite_config.mode);
|
|
35
38
|
|
|
36
39
|
/** @type {import('types').Respond} */
|
|
@@ -102,6 +105,7 @@ export async function dev(vite, vite_config, svelte_config) {
|
|
|
102
105
|
module_nodes.push(module_node);
|
|
103
106
|
|
|
104
107
|
result.shared = module;
|
|
108
|
+
result.shared_id = node.shared;
|
|
105
109
|
}
|
|
106
110
|
|
|
107
111
|
if (node.server) {
|
|
@@ -163,7 +167,8 @@ export async function dev(vite, vite_config, svelte_config) {
|
|
|
163
167
|
const url = path.resolve(cwd, endpoint.file);
|
|
164
168
|
return await vite.ssrLoadModule(url);
|
|
165
169
|
}
|
|
166
|
-
: null
|
|
170
|
+
: null,
|
|
171
|
+
endpoint_id: endpoint?.file
|
|
167
172
|
};
|
|
168
173
|
})
|
|
169
174
|
),
|
|
@@ -30,6 +30,7 @@ import { stores } from './singletons.js';
|
|
|
30
30
|
import { unwrap_promises } from '../../utils/promises.js';
|
|
31
31
|
import * as devalue from 'devalue';
|
|
32
32
|
import { INDEX_KEY, PRELOAD_PRIORITIES, SCROLL_KEY } from './constants.js';
|
|
33
|
+
import { validate_common_exports } from '../../utils/exports.js';
|
|
33
34
|
|
|
34
35
|
const routes = parse(nodes, server_loads, dictionary, matchers);
|
|
35
36
|
|
|
@@ -497,7 +498,7 @@ export function create_client({ target, base }) {
|
|
|
497
498
|
route,
|
|
498
499
|
status,
|
|
499
500
|
url: new URL(url),
|
|
500
|
-
form,
|
|
501
|
+
form: form ?? null,
|
|
501
502
|
// The whole page store is updated, but this way the object reference stays the same
|
|
502
503
|
data: data_changed ? data : page.data
|
|
503
504
|
};
|
|
@@ -558,6 +559,10 @@ export function create_client({ target, base }) {
|
|
|
558
559
|
|
|
559
560
|
const node = await loader();
|
|
560
561
|
|
|
562
|
+
if (__SVELTEKIT_DEV__) {
|
|
563
|
+
validate_common_exports(node.shared);
|
|
564
|
+
}
|
|
565
|
+
|
|
561
566
|
if (node.shared?.load) {
|
|
562
567
|
/** @param {string[]} deps */
|
|
563
568
|
function depends(...deps) {
|
|
@@ -17,6 +17,12 @@ import { redirect_json_response, render_data } from './data/index.js';
|
|
|
17
17
|
import { add_cookies_to_headers, get_cookies } from './cookie.js';
|
|
18
18
|
import { create_fetch } from './fetch.js';
|
|
19
19
|
import { Redirect } from '../control.js';
|
|
20
|
+
import {
|
|
21
|
+
validate_common_exports,
|
|
22
|
+
validate_page_server_exports,
|
|
23
|
+
validate_server_exports
|
|
24
|
+
} from '../../utils/exports.js';
|
|
25
|
+
import { error, json } from '../../exports/index.js';
|
|
20
26
|
|
|
21
27
|
/* global __SVELTEKIT_ADAPTER_NAME__ */
|
|
22
28
|
|
|
@@ -40,9 +46,11 @@ export async function respond(request, options, state) {
|
|
|
40
46
|
is_form_content_type(request);
|
|
41
47
|
|
|
42
48
|
if (forbidden) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
49
|
+
const csrf_error = error(403, `Cross-site ${request.method} form submissions are forbidden`);
|
|
50
|
+
if (request.headers.get('accept') === 'application/json') {
|
|
51
|
+
return json(csrf_error.body, { status: csrf_error.status });
|
|
52
|
+
}
|
|
53
|
+
return new Response(csrf_error.body.message, { status: csrf_error.status });
|
|
46
54
|
}
|
|
47
55
|
}
|
|
48
56
|
|
|
@@ -185,10 +193,31 @@ export async function respond(request, options, state) {
|
|
|
185
193
|
options.manifest._.nodes[route.page.leaf]()
|
|
186
194
|
]);
|
|
187
195
|
|
|
196
|
+
if (__SVELTEKIT_DEV__) {
|
|
197
|
+
const layouts = nodes.slice(0, -1);
|
|
198
|
+
const page = nodes.at(-1);
|
|
199
|
+
|
|
200
|
+
for (const layout of layouts) {
|
|
201
|
+
if (layout) {
|
|
202
|
+
validate_common_exports(layout.server, /** @type {string} */ (layout.server_id));
|
|
203
|
+
validate_common_exports(layout.shared, /** @type {string} */ (layout.shared_id));
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (page) {
|
|
208
|
+
validate_page_server_exports(page.server, /** @type {string} */ (page.server_id));
|
|
209
|
+
validate_common_exports(page.shared, /** @type {string} */ (page.shared_id));
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
188
213
|
trailing_slash = get_option(nodes, 'trailingSlash');
|
|
189
214
|
} else if (route.endpoint) {
|
|
190
215
|
const node = await route.endpoint();
|
|
191
216
|
trailing_slash = node.trailingSlash;
|
|
217
|
+
|
|
218
|
+
if (__SVELTEKIT_DEV__) {
|
|
219
|
+
validate_server_exports(node, /** @type {string} */ (route.endpoint_id));
|
|
220
|
+
}
|
|
192
221
|
}
|
|
193
222
|
|
|
194
223
|
const normalized = normalize_path(url.pathname, trailing_slash ?? 'never');
|
|
@@ -18,22 +18,31 @@ export function is_action_json_request(event) {
|
|
|
18
18
|
/**
|
|
19
19
|
* @param {import('types').RequestEvent} event
|
|
20
20
|
* @param {import('types').SSROptions} options
|
|
21
|
-
* @param {import('types').SSRNode['server']} server
|
|
21
|
+
* @param {import('types').SSRNode['server'] | undefined} server
|
|
22
22
|
*/
|
|
23
23
|
export async function handle_action_json_request(event, options, server) {
|
|
24
|
-
const actions = server
|
|
24
|
+
const actions = server?.actions;
|
|
25
25
|
|
|
26
26
|
if (!actions) {
|
|
27
|
-
|
|
27
|
+
if (server) {
|
|
28
|
+
maybe_throw_migration_error(server);
|
|
29
|
+
}
|
|
28
30
|
// TODO should this be a different error altogether?
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
const no_actions_error = error(405, 'POST method not allowed. No actions exist for this page');
|
|
32
|
+
return action_json(
|
|
33
|
+
{
|
|
34
|
+
type: 'error',
|
|
35
|
+
error: await handle_error_and_jsonify(event, options, no_actions_error)
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
status: no_actions_error.status,
|
|
39
|
+
headers: {
|
|
40
|
+
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/405
|
|
41
|
+
// "The server must generate an Allow header field in a 405 status code response"
|
|
42
|
+
allow: 'GET'
|
|
43
|
+
}
|
|
35
44
|
}
|
|
36
|
-
|
|
45
|
+
);
|
|
37
46
|
}
|
|
38
47
|
|
|
39
48
|
check_named_default_separate(actions);
|
|
@@ -40,9 +40,7 @@ export async function render_page(event, route, page, options, state, resolve_op
|
|
|
40
40
|
|
|
41
41
|
if (is_action_json_request(event)) {
|
|
42
42
|
const node = await options.manifest._.nodes[page.leaf]();
|
|
43
|
-
|
|
44
|
-
return handle_action_json_request(event, options, node.server);
|
|
45
|
-
}
|
|
43
|
+
return handle_action_json_request(event, options, node?.server);
|
|
46
44
|
}
|
|
47
45
|
|
|
48
46
|
try {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {string[]} expected
|
|
3
|
+
*/
|
|
4
|
+
function validator(expected) {
|
|
5
|
+
const set = new Set(expected);
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {any} module
|
|
9
|
+
* @param {string} [route_id]
|
|
10
|
+
*/
|
|
11
|
+
function validate(module, route_id) {
|
|
12
|
+
if (!module) return;
|
|
13
|
+
|
|
14
|
+
for (const key in module) {
|
|
15
|
+
if (key[0] !== '_' && !set.has(key)) {
|
|
16
|
+
const valid = expected.join(', ');
|
|
17
|
+
throw new Error(
|
|
18
|
+
`Invalid export '${key}'${
|
|
19
|
+
route_id ? ` in ${route_id}` : ''
|
|
20
|
+
} (valid exports are ${valid}, or anything with a '_' prefix)`
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return validate;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const validate_common_exports = validator([
|
|
30
|
+
'load',
|
|
31
|
+
'prerender',
|
|
32
|
+
'csr',
|
|
33
|
+
'ssr',
|
|
34
|
+
'trailingSlash'
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
export const validate_page_server_exports = validator([
|
|
38
|
+
'load',
|
|
39
|
+
'prerender',
|
|
40
|
+
'csr',
|
|
41
|
+
'ssr',
|
|
42
|
+
'actions',
|
|
43
|
+
'trailingSlash'
|
|
44
|
+
]);
|
|
45
|
+
|
|
46
|
+
export const validate_server_exports = validator([
|
|
47
|
+
'GET',
|
|
48
|
+
'POST',
|
|
49
|
+
'PATCH',
|
|
50
|
+
'PUT',
|
|
51
|
+
'DELETE',
|
|
52
|
+
'prerender',
|
|
53
|
+
'trailingSlash'
|
|
54
|
+
]);
|
package/types/internal.d.ts
CHANGED
|
@@ -288,6 +288,7 @@ export interface SSRNode {
|
|
|
288
288
|
|
|
289
289
|
// store this in dev so we can print serialization errors
|
|
290
290
|
server_id?: string;
|
|
291
|
+
shared_id?: string;
|
|
291
292
|
}
|
|
292
293
|
|
|
293
294
|
export type SSRNodeLoader = () => Promise<SSRNode>;
|
|
@@ -346,6 +347,7 @@ export interface SSRRoute {
|
|
|
346
347
|
params: RouteParam[];
|
|
347
348
|
page: PageNodeIndexes | null;
|
|
348
349
|
endpoint: (() => Promise<SSREndpoint>) | null;
|
|
350
|
+
endpoint_id?: string;
|
|
349
351
|
}
|
|
350
352
|
|
|
351
353
|
export interface SSRState {
|