@sveltejs/kit 3.0.0-next.4 → 3.0.0-next.7
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 +23 -18
- package/src/core/adapt/builder.js +29 -43
- package/src/core/adapt/index.js +1 -4
- package/src/core/config/index.js +135 -71
- package/src/core/config/options.js +291 -244
- package/src/core/config/types.d.ts +1 -1
- package/src/core/env.js +120 -5
- package/src/core/generate_manifest/index.js +12 -15
- package/src/core/postbuild/analyse.js +8 -12
- package/src/core/postbuild/crawl.js +22 -6
- package/src/core/postbuild/prerender.js +40 -23
- package/src/core/sync/create_manifest_data/index.js +29 -49
- package/src/core/sync/write_client_manifest.js +14 -14
- package/src/core/sync/write_non_ambient.js +10 -7
- package/src/core/sync/write_root.js +9 -30
- package/src/core/sync/write_server.js +13 -11
- package/src/core/sync/write_tsconfig.js +2 -4
- package/src/core/sync/write_types/index.js +11 -10
- package/src/exports/index.js +34 -12
- package/src/exports/internal/client.js +5 -0
- package/src/exports/internal/env.js +1 -1
- package/src/exports/internal/index.js +1 -90
- package/src/exports/internal/{event.js → server/event.js} +1 -2
- package/src/exports/internal/server/index.js +33 -0
- package/src/exports/internal/shared.js +89 -0
- package/src/exports/node/index.js +58 -7
- package/src/exports/params.js +63 -0
- package/src/exports/public.d.ts +299 -145
- package/src/exports/url.js +84 -0
- package/src/exports/vite/build/build_server.js +6 -1
- package/src/exports/vite/dev/index.js +38 -37
- package/src/exports/vite/index.js +498 -353
- package/src/exports/vite/preview/index.js +16 -8
- package/src/exports/vite/utils.js +7 -11
- package/src/runtime/app/env/types.d.ts +1 -1
- package/src/runtime/app/forms.js +22 -5
- package/src/runtime/app/paths/client.js +4 -10
- package/src/runtime/app/paths/public.d.ts +0 -28
- package/src/runtime/app/paths/server.js +8 -4
- package/src/runtime/app/server/remote/form.js +10 -3
- package/src/runtime/app/server/remote/query.js +9 -18
- package/src/runtime/app/server/remote/requested.js +8 -4
- package/src/runtime/app/server/remote/shared.js +5 -7
- package/src/runtime/app/state/client.js +1 -2
- package/src/runtime/app/stores.js +13 -76
- package/src/runtime/client/client.js +205 -167
- package/src/runtime/client/fetcher.js +3 -2
- package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
- package/src/runtime/client/remote-functions/form.svelte.js +122 -31
- package/src/runtime/client/remote-functions/prerender.svelte.js +17 -4
- package/src/runtime/client/remote-functions/query/index.js +3 -2
- package/src/runtime/client/remote-functions/query/instance.svelte.js +27 -11
- package/src/runtime/client/remote-functions/query-batch.svelte.js +4 -3
- package/src/runtime/client/remote-functions/query-live/instance.svelte.js +42 -15
- package/src/runtime/client/remote-functions/shared.svelte.js +18 -9
- package/src/runtime/client/state.svelte.js +66 -49
- package/src/runtime/client/types.d.ts +10 -2
- package/src/runtime/client/utils.js +0 -96
- package/src/runtime/form-utils.js +99 -18
- package/src/runtime/server/cookie.js +22 -33
- package/src/runtime/server/csrf.js +65 -0
- package/src/runtime/server/data/index.js +7 -7
- package/src/runtime/server/env_module.js +0 -5
- package/src/runtime/server/index.js +2 -2
- package/src/runtime/server/page/actions.js +41 -26
- package/src/runtime/server/page/index.js +2 -1
- package/src/runtime/server/page/load_data.js +1 -1
- package/src/runtime/server/page/render.js +36 -47
- package/src/runtime/server/page/respond_with_error.js +7 -8
- package/src/runtime/server/page/server_routing.js +13 -9
- package/src/runtime/server/remote.js +85 -39
- package/src/runtime/server/respond.js +92 -58
- package/src/runtime/server/utils.js +7 -7
- package/src/runtime/telemetry/otel.js +1 -1
- package/src/types/ambient.d.ts +10 -5
- package/src/types/global-private.d.ts +4 -4
- package/src/types/internal.d.ts +17 -20
- package/src/types/private.d.ts +33 -1
- package/src/types/synthetic/$lib.md +1 -1
- package/src/utils/error.js +12 -4
- package/src/utils/mime.js +9 -0
- package/src/utils/params.js +66 -0
- package/src/utils/routing.js +84 -38
- package/src/utils/shared-iterator.js +5 -0
- package/src/utils/streaming.js +14 -4
- package/src/utils/url.js +20 -2
- package/src/version.js +1 -1
- package/types/index.d.ts +434 -269
- package/types/index.d.ts.map +19 -15
- package/src/exports/internal/server.js +0 -22
- /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { DEV } from 'esm-env';
|
|
2
|
+
// we use the export subpath to conditionally import the client/server `get_origin`
|
|
3
|
+
// so that `node:async_hooks` isn't pulled into the client build
|
|
4
|
+
import { get_origin } from '#internal';
|
|
5
|
+
import { matches_external_allowlist_entry } from '../utils/url.js';
|
|
6
|
+
|
|
7
|
+
// See https://datatracker.ietf.org/doc/html/rfc2606 - no domains under the .invalid TLD can be registered
|
|
8
|
+
const REDIRECT_BASE = 'https://sveltekit-redirect.invalid';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Whether a redirect location is absolute, i.e. not a root-relative or path-relative URL,
|
|
12
|
+
* and not pointing to the same origin as we're currently on (if determineable).
|
|
13
|
+
* @param {string} location
|
|
14
|
+
*/
|
|
15
|
+
export function is_external_location(location) {
|
|
16
|
+
const origin = get_origin();
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
return !matches_external_allowlist_entry(location, origin ?? REDIRECT_BASE);
|
|
20
|
+
} catch {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param {string} location
|
|
27
|
+
*/
|
|
28
|
+
function is_javascript_location(location) {
|
|
29
|
+
try {
|
|
30
|
+
return new URL(location, REDIRECT_BASE).protocol === 'javascript:';
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @param {string} location
|
|
38
|
+
* @param {{ external?: boolean | string[] }} [options]
|
|
39
|
+
*/
|
|
40
|
+
export function validate_redirect_location(location, options) {
|
|
41
|
+
if (!is_external_location(location)) return;
|
|
42
|
+
|
|
43
|
+
const external = options?.external;
|
|
44
|
+
|
|
45
|
+
if (!external) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
DEV
|
|
48
|
+
? `Cannot redirect to external URL ${JSON.stringify(location)}. ` +
|
|
49
|
+
'To redirect to an external URL, pass `{ external: true }` or an allowlist of permitted origins as the third argument to `redirect`'
|
|
50
|
+
: 'Cannot redirect to external URL unless explicitly allowed'
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (external === true) {
|
|
55
|
+
if (is_javascript_location(location)) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
DEV
|
|
58
|
+
? `Cannot redirect to ${JSON.stringify(location)} with \`{ external: true }\`. ` +
|
|
59
|
+
'The `:javascript` protocol must be explicitly listed in the `external` allowlist'
|
|
60
|
+
: 'Cannot redirect to external URL unless explicitly allowed'
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (Array.isArray(external)) {
|
|
68
|
+
if (!external.some((allowed) => matches_external_allowlist_entry(location, allowed))) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
DEV
|
|
71
|
+
? `Cannot redirect to ${JSON.stringify(location)}: URL origin is not included in the \`external\` allowlist`
|
|
72
|
+
: 'Cannot redirect to external URL unless explicitly allowed'
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
throw new Error(
|
|
80
|
+
DEV
|
|
81
|
+
? '`redirect` options.external must be `true` or an array of allowed origins'
|
|
82
|
+
: 'Invalid redirect options.external value'
|
|
83
|
+
);
|
|
84
|
+
}
|
|
@@ -149,7 +149,12 @@ export function build_server_nodes(
|
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
if (node.universal) {
|
|
152
|
-
if (
|
|
152
|
+
if (
|
|
153
|
+
(kit.router.type === 'hash' &&
|
|
154
|
+
node.page_options !== null &&
|
|
155
|
+
node.page_options?.ssr === undefined) ||
|
|
156
|
+
(node.page_options && node.page_options.ssr === false)
|
|
157
|
+
) {
|
|
153
158
|
exports.push(`export const universal = ${s(node.page_options, null, 2)};`);
|
|
154
159
|
} else {
|
|
155
160
|
imports.push(
|
|
@@ -10,12 +10,14 @@ import { isCSSRequest, loadEnv, buildErrorMessage } from 'vite';
|
|
|
10
10
|
import { createReadableStream, getRequest, setResponse } from '../../../exports/node/index.js';
|
|
11
11
|
import { coalesce_to_error } from '../../../utils/error.js';
|
|
12
12
|
import { resolve_entry } from '../../../utils/filesystem.js';
|
|
13
|
+
import { load_and_validate_params } from '../../../utils/params.js';
|
|
13
14
|
import { from_fs, to_fs } from '../../../utils/vite.js';
|
|
14
15
|
import { posixify } from '../../../utils/os.js';
|
|
15
16
|
import { load_error_page } from '../../../core/config/index.js';
|
|
16
17
|
import { SVELTE_KIT_ASSETS } from '../../../constants.js';
|
|
17
18
|
import * as sync from '../../../core/sync/sync.js';
|
|
18
19
|
import { get_mime_lookup, get_runtime_base } from '../../../core/utils.js';
|
|
20
|
+
import '../../../utils/mime.js'; // extend mrmime with additional types (affects sirv too)
|
|
19
21
|
import { compact } from '../../../utils/array.js';
|
|
20
22
|
import { is_chrome_devtools_request, not_found } from '../utils.js';
|
|
21
23
|
import { SCHEME } from '../../../utils/url.js';
|
|
@@ -31,10 +33,9 @@ const vite_css_query_regex = /(?:\?|&)(?:raw|url|inline)(?:&|$)/;
|
|
|
31
33
|
* @param {import('types').ValidatedConfig} svelte_config
|
|
32
34
|
* @param {() => Array<{ hash: string, file: string }>} get_remotes
|
|
33
35
|
* @param {string} root The project root directory
|
|
34
|
-
* @param {import('@sveltejs/kit').Adapter | undefined} adapter
|
|
35
36
|
* @return {Promise<Promise<() => void>>}
|
|
36
37
|
*/
|
|
37
|
-
export async function dev(vite, vite_config, svelte_config, get_remotes, root
|
|
38
|
+
export async function dev(vite, vite_config, svelte_config, get_remotes, root) {
|
|
38
39
|
/** @type {AsyncLocalStorage<{ event: RequestEvent, config: any, prerender: PrerenderOption }>} */
|
|
39
40
|
const async_local_storage = new AsyncLocalStorage();
|
|
40
41
|
|
|
@@ -42,7 +43,12 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
|
|
|
42
43
|
const context = async_local_storage.getStore();
|
|
43
44
|
if (!context || context.prerender === true) return;
|
|
44
45
|
|
|
45
|
-
check_feature(
|
|
46
|
+
check_feature(
|
|
47
|
+
/** @type {string} */ (context.event.route.id),
|
|
48
|
+
context.config,
|
|
49
|
+
label,
|
|
50
|
+
svelte_config.kit.adapter
|
|
51
|
+
);
|
|
46
52
|
};
|
|
47
53
|
|
|
48
54
|
const fetch = globalThis.fetch;
|
|
@@ -79,6 +85,10 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
|
|
|
79
85
|
vite.config.logger.error(msg, { error: err });
|
|
80
86
|
}
|
|
81
87
|
|
|
88
|
+
// TODO this is inadequate — it doesn't reliably show the overlay on every page load,
|
|
89
|
+
// and when it does appear it may immediately vanish. `vite.ws.send` broadcasts
|
|
90
|
+
// to all connected clients, even ones that are unaffected by the error.
|
|
91
|
+
// we need a more considered approach
|
|
82
92
|
vite.ws.send({
|
|
83
93
|
type: 'error',
|
|
84
94
|
err: /** @type {import('vite').ErrorPayload['err']} */ ({
|
|
@@ -106,10 +116,17 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
|
|
|
106
116
|
return { module, module_node, url };
|
|
107
117
|
}
|
|
108
118
|
|
|
109
|
-
function update_manifest() {
|
|
119
|
+
async function update_manifest() {
|
|
110
120
|
try {
|
|
111
121
|
({ manifest_data } = sync.create(svelte_config, root));
|
|
112
122
|
|
|
123
|
+
await load_and_validate_params({
|
|
124
|
+
routes: manifest_data.routes,
|
|
125
|
+
params_path: manifest_data.params,
|
|
126
|
+
root,
|
|
127
|
+
load: (file) => loud_ssr_load_module(file)
|
|
128
|
+
});
|
|
129
|
+
|
|
113
130
|
if (manifest_error) {
|
|
114
131
|
manifest_error = null;
|
|
115
132
|
vite.ws.send({ type: 'full-reload' });
|
|
@@ -288,22 +305,18 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
|
|
|
288
305
|
})
|
|
289
306
|
),
|
|
290
307
|
matchers: async () => {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
matchers[key] = module.match;
|
|
301
|
-
} else {
|
|
302
|
-
throw new Error(`${file} does not export a \`match\` function`);
|
|
303
|
-
}
|
|
308
|
+
if (!manifest_data.params) return {};
|
|
309
|
+
|
|
310
|
+
const url = path.resolve(root, manifest_data.params);
|
|
311
|
+
const module = await vite.ssrLoadModule(url, { fixStacktrace: true });
|
|
312
|
+
|
|
313
|
+
if (!module.params) {
|
|
314
|
+
throw new Error(
|
|
315
|
+
`${manifest_data.params} does not export \`params\` from \`defineParams\``
|
|
316
|
+
);
|
|
304
317
|
}
|
|
305
318
|
|
|
306
|
-
return
|
|
319
|
+
return module.params;
|
|
307
320
|
}
|
|
308
321
|
}
|
|
309
322
|
};
|
|
@@ -320,7 +333,9 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
|
|
|
320
333
|
return error.stack?.replaceAll('\0', ''); // remove null bytes from e.g. virtual module IDs, or the response will fail
|
|
321
334
|
}
|
|
322
335
|
|
|
323
|
-
update_manifest();
|
|
336
|
+
await update_manifest();
|
|
337
|
+
|
|
338
|
+
const params_file = resolve_entry(svelte_config.kit.files.params);
|
|
324
339
|
|
|
325
340
|
/**
|
|
326
341
|
* @param {string} event
|
|
@@ -330,7 +345,7 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
|
|
|
330
345
|
vite.watcher.on(event, (file) => {
|
|
331
346
|
if (
|
|
332
347
|
file.startsWith(svelte_config.kit.files.routes + path.sep) ||
|
|
333
|
-
|
|
348
|
+
(params_file && file === params_file) ||
|
|
334
349
|
svelte_config.kit.moduleExtensions.some((ext) => file.endsWith(`.remote${ext}`)) ||
|
|
335
350
|
// in contrast to server hooks, client hooks are written to the client manifest
|
|
336
351
|
// and therefore need rebuilding when they are added/removed
|
|
@@ -351,9 +366,6 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
|
|
|
351
366
|
}, 100);
|
|
352
367
|
};
|
|
353
368
|
|
|
354
|
-
// flag to skip watchers if server is already restarting
|
|
355
|
-
let restarting = false;
|
|
356
|
-
|
|
357
369
|
// Debounce add/unlink events because in case of folder deletion or moves
|
|
358
370
|
// they fire in rapid succession, causing needless invocations.
|
|
359
371
|
// These watchers only run for routes, param matchers, and client hooks.
|
|
@@ -362,7 +374,7 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
|
|
|
362
374
|
watch('change', (file) => {
|
|
363
375
|
// Don't run for a single file if the whole manifest is about to get updated
|
|
364
376
|
// Unless it's a file where the trailing slash page option might have changed
|
|
365
|
-
if (timeout ||
|
|
377
|
+
if (timeout || !/\+(page|layout|server).*$/.test(file)) return;
|
|
366
378
|
sync.update(svelte_config, manifest_data, file, root);
|
|
367
379
|
});
|
|
368
380
|
|
|
@@ -373,7 +385,7 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
|
|
|
373
385
|
// send the vite client a full-reload event without path being set
|
|
374
386
|
if (appTemplate !== 'index.html') {
|
|
375
387
|
vite.watcher.on('change', (file) => {
|
|
376
|
-
if (file === appTemplate
|
|
388
|
+
if (file === appTemplate) {
|
|
377
389
|
vite.ws.send({ type: 'full-reload' });
|
|
378
390
|
}
|
|
379
391
|
});
|
|
@@ -390,17 +402,6 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
|
|
|
390
402
|
}
|
|
391
403
|
});
|
|
392
404
|
|
|
393
|
-
vite.watcher.on('change', async (file) => {
|
|
394
|
-
// changing the svelte config requires restarting the dev server
|
|
395
|
-
// the config is only read on start and passed on to vite-plugin-svelte
|
|
396
|
-
// which needs up-to-date values to operate correctly
|
|
397
|
-
if (file.match(/[/\\]svelte\.config\.[jt]s$/)) {
|
|
398
|
-
console.log(`svelte config changed, restarting vite dev-server. changed file: ${file}`);
|
|
399
|
-
restarting = true;
|
|
400
|
-
await vite.restart();
|
|
401
|
-
}
|
|
402
|
-
});
|
|
403
|
-
|
|
404
405
|
const assets = svelte_config.kit.paths.assets ? SVELTE_KIT_ASSETS : svelte_config.kit.paths.base;
|
|
405
406
|
const asset_server = sirv(svelte_config.kit.files.assets, {
|
|
406
407
|
dev: true,
|
|
@@ -436,7 +437,7 @@ export async function dev(vite, vite_config, svelte_config, get_remotes, root, a
|
|
|
436
437
|
});
|
|
437
438
|
|
|
438
439
|
const env = loadEnv(vite_config.mode, svelte_config.kit.env.dir, '');
|
|
439
|
-
const emulator = await adapter?.emulate?.();
|
|
440
|
+
const emulator = await svelte_config.kit.adapter?.emulate?.();
|
|
440
441
|
|
|
441
442
|
return () => {
|
|
442
443
|
const serve_static_middleware = vite.middlewares.stack.find(
|