@sveltejs/kit 3.0.0-next.2 → 3.0.0-next.21
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 +62 -36
- package/src/cli.js +15 -12
- package/src/constants.js +6 -1
- package/src/core/adapt/builder.js +66 -72
- package/src/core/adapt/index.js +17 -6
- package/src/core/config/index.js +134 -80
- package/src/core/config/options.js +295 -273
- package/src/core/config/types.d.ts +1 -1
- package/src/core/env.js +146 -16
- package/src/core/generate_manifest/index.js +18 -15
- package/src/core/postbuild/analyse.js +8 -20
- package/src/core/postbuild/crawl.js +22 -6
- package/src/core/postbuild/entities.js +8 -2
- package/src/core/postbuild/fallback.js +4 -2
- package/src/core/postbuild/prerender.js +222 -70
- package/src/core/postbuild/queue.js +2 -1
- package/src/core/sync/create_manifest_data/conflict.js +1 -1
- package/src/core/sync/create_manifest_data/index.js +82 -62
- package/src/core/sync/sync.js +40 -31
- package/src/core/sync/ts.js +1 -1
- package/src/core/sync/utils.js +22 -2
- package/src/core/sync/{write_non_ambient.js → write_app_types.js} +107 -58
- package/src/core/sync/write_client_manifest.js +14 -29
- package/src/core/sync/write_env.js +7 -5
- package/src/core/sync/write_server.js +37 -45
- package/src/core/sync/write_tsconfig/index.js +274 -0
- package/src/core/sync/write_tsconfig/test-app/package.json +7 -0
- package/src/core/sync/write_tsconfig/utils.js +77 -0
- package/src/core/sync/write_tsconfig/validate.js +128 -0
- package/src/core/sync/write_types/index.js +127 -123
- package/src/core/utils.js +30 -5
- package/src/exports/env/index.js +77 -0
- package/src/exports/env/public.d.ts +55 -0
- package/src/exports/hooks/index.js +3 -9
- package/src/exports/hooks/public.d.ts +195 -0
- package/src/exports/hooks/sequence.js +9 -6
- package/src/exports/index.js +52 -29
- package/src/exports/internal/client.js +5 -0
- package/src/exports/internal/env.js +8 -5
- package/src/exports/internal/index.js +1 -90
- package/src/exports/internal/{event.js → server/event.js} +2 -3
- package/src/exports/internal/server/index.js +37 -0
- package/src/exports/internal/server/telemetry.js +95 -0
- package/src/exports/internal/shared.js +90 -0
- package/src/exports/node/index.js +64 -22
- package/src/exports/params/index.js +70 -0
- package/src/exports/params/public.d.ts +63 -0
- package/src/exports/public.d.ts +50 -1733
- package/src/exports/remote/index.js +11 -0
- package/src/exports/remote/public.d.ts +519 -0
- package/src/exports/url.js +86 -0
- package/src/exports/vite/build/build_server.js +54 -65
- package/src/exports/vite/build/remote.js +24 -19
- package/src/exports/vite/build/utils.js +0 -8
- package/src/exports/vite/dev/index.js +218 -146
- package/src/exports/vite/index.js +1590 -858
- package/src/exports/vite/module_ids.js +2 -2
- package/src/exports/vite/preview/index.js +40 -32
- package/src/exports/vite/public.d.ts +588 -0
- package/src/exports/vite/utils.js +84 -46
- package/src/pathname.js +55 -0
- package/src/runner.js +15 -0
- package/src/runtime/app/env/internal.js +4 -4
- package/src/runtime/app/env/types.d.ts +1 -1
- package/src/runtime/app/environment/index.js +3 -3
- package/src/runtime/app/{forms.js → forms/index.js} +73 -42
- package/src/runtime/app/forms/public.d.ts +2 -0
- package/src/runtime/app/forms/types.d.ts +56 -0
- package/src/runtime/app/internal/transport.js +53 -0
- package/src/runtime/app/manifest/index.js +1 -0
- package/src/runtime/app/{navigation.js → navigation/index.js} +2 -1
- package/src/runtime/app/navigation/public.d.ts +237 -0
- package/src/runtime/app/paths/client.js +37 -37
- package/src/runtime/app/paths/index.js +1 -1
- package/src/runtime/app/paths/internal/client.js +34 -2
- package/src/runtime/app/paths/internal/server.js +6 -23
- package/src/runtime/app/paths/internal.d.ts +3 -0
- package/src/runtime/app/paths/public.d.ts +1 -29
- package/src/runtime/app/paths/server.js +36 -17
- package/src/runtime/app/paths/types.d.ts +11 -19
- package/src/runtime/app/server/index.js +2 -2
- package/src/runtime/app/server/public.d.ts +201 -0
- package/src/runtime/app/server/remote/command.js +13 -11
- package/src/runtime/app/server/remote/form.js +61 -39
- package/src/runtime/app/server/remote/prerender.js +45 -45
- package/src/runtime/app/server/remote/query.js +106 -108
- package/src/runtime/app/server/remote/requested.js +27 -19
- package/src/runtime/app/server/remote/shared.js +76 -76
- package/src/runtime/app/service-worker/index.js +24 -0
- package/src/runtime/app/state/client.js +4 -2
- package/src/runtime/app/state/index.js +7 -5
- package/src/runtime/app/state/public.d.ts +72 -0
- package/src/runtime/app/state/server.js +3 -0
- package/src/runtime/app/stores.js +15 -78
- package/src/runtime/client/bundle.js +1 -1
- package/src/runtime/client/client-entry.js +3 -0
- package/src/runtime/client/client.js +1336 -648
- package/src/runtime/client/constants.js +3 -6
- package/src/runtime/client/entry.js +24 -3
- package/src/runtime/client/fetcher.js +25 -25
- package/src/runtime/client/ndjson.js +1 -1
- package/src/runtime/client/parse.js +1 -1
- package/src/runtime/client/payload.js +17 -0
- package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
- package/src/runtime/client/remote-functions/command.svelte.js +37 -61
- package/src/runtime/client/remote-functions/form.svelte.js +267 -178
- package/src/runtime/client/remote-functions/prerender.svelte.js +32 -11
- package/src/runtime/client/remote-functions/query/index.js +10 -17
- package/src/runtime/client/remote-functions/query/instance.svelte.js +64 -18
- package/src/runtime/client/remote-functions/query/proxy.js +5 -5
- package/src/runtime/client/remote-functions/query-batch.svelte.js +61 -70
- package/src/runtime/client/remote-functions/query-live/index.js +1 -1
- package/src/runtime/client/remote-functions/query-live/instance.svelte.js +63 -21
- package/src/runtime/client/remote-functions/query-live/iterator.js +15 -12
- package/src/runtime/client/remote-functions/query-live/proxy.js +2 -12
- package/src/runtime/client/remote-functions/shared.svelte.js +90 -65
- package/src/runtime/client/snapshots.js +147 -0
- package/src/runtime/client/state.svelte.js +94 -55
- package/src/runtime/client/stream.js +3 -2
- package/src/runtime/client/types.d.ts +13 -9
- package/src/runtime/client/utils.js +22 -110
- package/src/runtime/components/root.svelte +56 -0
- package/src/runtime/env/dynamic/private.js +7 -0
- package/src/runtime/env/dynamic/public.js +7 -0
- package/src/runtime/env/static/private.js +6 -0
- package/src/runtime/env/static/public.js +6 -0
- package/src/runtime/form-utils.js +172 -61
- package/src/runtime/pathname.js +20 -32
- package/src/runtime/props.svelte.js +72 -0
- package/src/runtime/server/constants.js +0 -3
- package/src/runtime/server/cookie.js +72 -55
- package/src/runtime/server/csrf.js +65 -0
- package/src/runtime/server/data/index.js +49 -53
- package/src/runtime/server/dev.js +22 -0
- package/src/runtime/server/endpoint.js +6 -7
- package/src/runtime/server/env_module.js +0 -5
- package/src/runtime/server/errors.js +160 -0
- package/src/runtime/server/fetch.js +32 -39
- package/src/runtime/server/index.js +90 -64
- package/src/runtime/server/internal.js +71 -0
- package/src/runtime/server/page/actions.js +85 -64
- package/src/runtime/server/page/crypto.js +2 -2
- package/src/runtime/server/page/csp.js +88 -104
- package/src/runtime/server/page/data_serializer.js +24 -25
- package/src/runtime/server/page/index.js +36 -53
- package/src/runtime/server/page/load_data.js +50 -57
- package/src/runtime/server/page/render.js +173 -239
- package/src/runtime/server/page/respond_with_error.js +17 -31
- package/src/runtime/server/page/serialize_data.js +2 -13
- package/src/runtime/server/page/server_routing.js +85 -26
- package/src/runtime/server/remote-functions.js +640 -0
- package/src/runtime/server/respond.js +190 -131
- package/src/runtime/server/sourcemaps.js +183 -0
- package/src/runtime/server/state.js +53 -0
- package/src/runtime/server/utils.js +13 -155
- package/src/runtime/shared.js +20 -40
- package/src/runtime/utils.js +3 -0
- package/src/types/ambient-private.d.ts +11 -1
- package/src/types/ambient.d.ts +87 -36
- package/src/types/global-private.d.ts +25 -25
- package/src/types/internal.d.ts +163 -157
- package/src/types/private.d.ts +41 -1
- package/src/utils/error.js +28 -4
- package/src/utils/escape.js +9 -25
- package/src/utils/features.js +1 -1
- package/src/utils/filesystem.js +1 -23
- package/src/utils/fork.js +7 -2
- package/src/utils/hash.js +21 -0
- package/src/utils/http.js +8 -7
- package/src/utils/import.js +9 -2
- package/src/utils/imports.js +83 -0
- package/src/utils/mime.js +9 -0
- package/src/utils/page_nodes.js +6 -7
- package/src/utils/params.js +67 -0
- package/src/utils/regex.js +9 -0
- package/src/utils/routing.js +145 -73
- package/src/utils/shared-iterator.js +5 -0
- package/src/utils/streaming.js +14 -4
- package/src/utils/url.js +33 -2
- package/src/version.js +1 -1
- package/types/index.d.ts +2616 -2433
- package/types/index.d.ts.map +120 -106
- package/src/core/sync/write_ambient.js +0 -18
- package/src/core/sync/write_root.js +0 -148
- package/src/core/sync/write_tsconfig.js +0 -250
- package/src/exports/internal/server.js +0 -22
- package/src/exports/node/polyfills.js +0 -30
- package/src/runtime/server/app.js +0 -9
- package/src/runtime/server/remote.js +0 -457
- package/src/runtime/shared-server.js +0 -7
- package/src/runtime/telemetry/otel.js +0 -21
- package/src/runtime/telemetry/record_span.js +0 -65
- package/src/types/synthetic/$lib.md +0 -5
- /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
- /package/src/{runtime/telemetry/noop.js → telemetry.js} +0 -0
package/src/utils/escape.js
CHANGED
|
@@ -21,24 +21,12 @@ const escape_html_dict = {
|
|
|
21
21
|
'<': '<'
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
// we match it so that we can match unpaired low surrogates in the same pass
|
|
28
|
-
// TODO: use lookbehind assertions once they are widely supported: (?<![\ud800-udbff])[\udc00-\udfff]
|
|
29
|
-
'[\\ud800-\\udbff][\\udc00-\\udfff]|' +
|
|
30
|
-
// unpaired low surrogate (see previous match)
|
|
31
|
-
'[\\udc00-\\udfff]';
|
|
24
|
+
// `\p{Surrogate}` only matches unpaired surrogates with the `u` flag (a pair is one code point)
|
|
25
|
+
/** @param {Record<string, string>} dict */
|
|
26
|
+
const escape_regex = (dict) => new RegExp(`[${Object.keys(dict).join('')}]|\\p{Surrogate}`, 'gu');
|
|
32
27
|
|
|
33
|
-
const escape_html_attr_regex =
|
|
34
|
-
|
|
35
|
-
'g'
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
const escape_html_regex = new RegExp(
|
|
39
|
-
`[${Object.keys(escape_html_dict).join('')}]|` + surrogates,
|
|
40
|
-
'g'
|
|
41
|
-
);
|
|
28
|
+
const escape_html_attr_regex = escape_regex(escape_html_attr_dict);
|
|
29
|
+
const escape_html_regex = escape_regex(escape_html_dict);
|
|
42
30
|
|
|
43
31
|
/**
|
|
44
32
|
* Escapes unpaired surrogates (which are allowed in js strings but invalid in HTML) and
|
|
@@ -51,14 +39,10 @@ const escape_html_regex = new RegExp(
|
|
|
51
39
|
*/
|
|
52
40
|
export function escape_html(str, is_attr) {
|
|
53
41
|
const dict = is_attr ? escape_html_attr_dict : escape_html_dict;
|
|
54
|
-
const escaped_str = str.replace(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return dict[match] ?? `&#${match.charCodeAt(0)};`;
|
|
61
|
-
});
|
|
42
|
+
const escaped_str = str.replace(
|
|
43
|
+
is_attr ? escape_html_attr_regex : escape_html_regex,
|
|
44
|
+
(match) => dict[match] ?? `&#${match.charCodeAt(0)};`
|
|
45
|
+
);
|
|
62
46
|
|
|
63
47
|
return escaped_str;
|
|
64
48
|
}
|
package/src/utils/features.js
CHANGED
package/src/utils/filesystem.js
CHANGED
|
@@ -2,28 +2,6 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { posixify } from './os.js';
|
|
4
4
|
|
|
5
|
-
/** @param {string} dir */
|
|
6
|
-
export function mkdirp(dir) {
|
|
7
|
-
try {
|
|
8
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
9
|
-
} catch (/** @type {any} */ e) {
|
|
10
|
-
if (e.code === 'EEXIST') {
|
|
11
|
-
if (!fs.statSync(dir).isDirectory()) {
|
|
12
|
-
throw new Error(`Cannot create directory ${dir}, a file already exists at this position`, {
|
|
13
|
-
cause: e
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
throw e;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/** @param {string} path */
|
|
23
|
-
export function rimraf(path) {
|
|
24
|
-
fs.rmSync(path, { force: true, recursive: true });
|
|
25
|
-
}
|
|
26
|
-
|
|
27
5
|
/**
|
|
28
6
|
* @param {string} source
|
|
29
7
|
* @param {string} target
|
|
@@ -58,7 +36,7 @@ export function copy(source, target, opts = {}) {
|
|
|
58
36
|
go(path.join(from, file), path.join(to, file));
|
|
59
37
|
});
|
|
60
38
|
} else {
|
|
61
|
-
|
|
39
|
+
fs.mkdirSync(path.dirname(to), { recursive: true });
|
|
62
40
|
|
|
63
41
|
if (opts.replace) {
|
|
64
42
|
const data = fs.readFileSync(from, 'utf-8');
|
package/src/utils/fork.js
CHANGED
|
@@ -38,7 +38,8 @@ export function forked(module, callback) {
|
|
|
38
38
|
const worker = new Worker(fileURLToPath(module), {
|
|
39
39
|
env: {
|
|
40
40
|
...process.env,
|
|
41
|
-
SVELTEKIT_FORK: 'true'
|
|
41
|
+
SVELTEKIT_FORK: 'true',
|
|
42
|
+
FORCE_COLOR: '1'
|
|
42
43
|
}
|
|
43
44
|
});
|
|
44
45
|
|
|
@@ -60,9 +61,13 @@ export function forked(module, callback) {
|
|
|
60
61
|
}
|
|
61
62
|
);
|
|
62
63
|
|
|
64
|
+
worker.once('error', reject);
|
|
65
|
+
|
|
63
66
|
worker.on('exit', (code) => {
|
|
64
67
|
if (code) {
|
|
65
|
-
|
|
68
|
+
const error = new Error(`Failed with code ${code}`);
|
|
69
|
+
error.stack = error.message;
|
|
70
|
+
reject(error);
|
|
66
71
|
}
|
|
67
72
|
});
|
|
68
73
|
});
|
package/src/utils/hash.js
CHANGED
|
@@ -20,3 +20,24 @@ export function hash(...values) {
|
|
|
20
20
|
|
|
21
21
|
return (hash >>> 0).toString(36);
|
|
22
22
|
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Hash of the headers and body a `fetch` was called with. The server-side serializer and the
|
|
26
|
+
* client-side cache lookup must produce identical values for cached responses to be found.
|
|
27
|
+
* @param {HeadersInit | undefined} headers
|
|
28
|
+
* @param {import('types').StrictBody | null | undefined} body
|
|
29
|
+
*/
|
|
30
|
+
export function hash_request(headers, body) {
|
|
31
|
+
/** @type {import('types').StrictBody[]} */
|
|
32
|
+
const values = [];
|
|
33
|
+
|
|
34
|
+
if (headers) {
|
|
35
|
+
values.push([...new Headers(headers)].join(','));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (body) {
|
|
39
|
+
values.push(body);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return hash(...values);
|
|
43
|
+
}
|
package/src/utils/http.js
CHANGED
|
@@ -11,7 +11,7 @@ export function negotiate(accept, types) {
|
|
|
11
11
|
const parts = [];
|
|
12
12
|
|
|
13
13
|
accept.split(',').forEach((str, i) => {
|
|
14
|
-
const match =
|
|
14
|
+
const match = /^[ \t]*([^/ \t]+)\/([^; \t]+)[ \t]*(?:;[ \t]*q=([0-9.]+))?/.exec(str);
|
|
15
15
|
|
|
16
16
|
// no match equals invalid header — ignore
|
|
17
17
|
if (match) {
|
|
@@ -57,12 +57,13 @@ export function negotiate(accept, types) {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
|
-
* Returns `true` if
|
|
61
|
-
*
|
|
60
|
+
* Returns `true` if a `content-type` header value is one of the given types, ignoring
|
|
61
|
+
* parameters such as `charset` and comparing case-insensitively
|
|
62
|
+
* @param {string | null | undefined} header
|
|
62
63
|
* @param {...string} types
|
|
63
64
|
*/
|
|
64
|
-
function
|
|
65
|
-
const type =
|
|
65
|
+
export function matches_content_type(header, ...types) {
|
|
66
|
+
const type = header?.split(';', 1)[0].trim() ?? '';
|
|
66
67
|
return types.includes(type.toLowerCase());
|
|
67
68
|
}
|
|
68
69
|
|
|
@@ -72,8 +73,8 @@ function is_content_type(request, ...types) {
|
|
|
72
73
|
export function is_form_content_type(request) {
|
|
73
74
|
// These content types must be protected against CSRF
|
|
74
75
|
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/enctype
|
|
75
|
-
return
|
|
76
|
-
request,
|
|
76
|
+
return matches_content_type(
|
|
77
|
+
request.headers.get('content-type'),
|
|
77
78
|
'application/x-www-form-urlencoded',
|
|
78
79
|
'multipart/form-data',
|
|
79
80
|
'text/plain',
|
package/src/utils/import.js
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
|
-
* Resolves a peer dependency relative to the current working directory.
|
|
6
|
+
* Resolves a peer dependency relative to the current working directory.
|
|
7
|
+
*
|
|
8
|
+
* Mainly used to resolve the correct Vite package when an app's SvelteKit is a
|
|
9
|
+
* linked local repository.
|
|
10
|
+
*
|
|
11
|
+
* Duplicated with `packages/adapter-auto`
|
|
6
12
|
* @param {string} dependency
|
|
7
13
|
* @param {string} root
|
|
8
14
|
*/
|
|
@@ -46,8 +52,9 @@ function resolve_peer(dependency, root) {
|
|
|
46
52
|
*/
|
|
47
53
|
export async function import_peer(dependency, root) {
|
|
48
54
|
try {
|
|
49
|
-
return await import(/* @vite-ignore */ resolve_peer(dependency, root));
|
|
55
|
+
return await import(/* @vite-ignore */ pathToFileURL(resolve_peer(dependency, root)).href);
|
|
50
56
|
} catch {
|
|
57
|
+
// eslint-disable-next-line kit-node-custom/require-path-to-file-url -- bare package specifier, not a path
|
|
51
58
|
return await import(/* @vite-ignore */ dependency);
|
|
52
59
|
}
|
|
53
60
|
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Reads the `imports` field from the package.json at the given directory.
|
|
6
|
+
* @param {string} cwd
|
|
7
|
+
* @returns {Record<string, string | Record<string, string>> | undefined}
|
|
8
|
+
*/
|
|
9
|
+
export function read_package_imports(cwd) {
|
|
10
|
+
const pkg_path = path.resolve(cwd, 'package.json');
|
|
11
|
+
if (fs.existsSync(pkg_path)) {
|
|
12
|
+
try {
|
|
13
|
+
return JSON.parse(fs.readFileSync(pkg_path, 'utf-8')).imports;
|
|
14
|
+
} catch {
|
|
15
|
+
// malformed package.json — ignore, the user will see other errors
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Normalizes an import value to a string path, handling both string values
|
|
22
|
+
* and conditional export objects (using the `default` key).
|
|
23
|
+
* @param {string | Record<string, string>} value
|
|
24
|
+
* @returns {string | null}
|
|
25
|
+
*/
|
|
26
|
+
export function normalize_import_value(value) {
|
|
27
|
+
if (typeof value === 'string') {
|
|
28
|
+
return value.replace(/^\.\//, '');
|
|
29
|
+
}
|
|
30
|
+
if (value && typeof value === 'object' && typeof value.default === 'string') {
|
|
31
|
+
return value.default.replace(/^\.\//, '');
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Returns the `#`-prefixed import keys from the package.json `imports` field.
|
|
38
|
+
* @param {string} cwd
|
|
39
|
+
* @returns {string[]}
|
|
40
|
+
*/
|
|
41
|
+
export function get_hash_import_keys(cwd) {
|
|
42
|
+
const imports = read_package_imports(cwd);
|
|
43
|
+
if (!imports) return [];
|
|
44
|
+
return Object.keys(imports).filter((key) => key.startsWith('#'));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Computes alias entries for `normalize_id` from the package.json `imports` field.
|
|
49
|
+
* Each entry maps a `#xx` alias to its absolute target path. Entries are sorted
|
|
50
|
+
* by path length descending so that longer/more-specific paths are matched first.
|
|
51
|
+
*
|
|
52
|
+
* @param {string} root
|
|
53
|
+
* @param {(p: string) => string} [normalize] - optional path normalizer (e.g. `vite.normalizePath`)
|
|
54
|
+
* @returns {Array<{ alias: string, path: string }>}
|
|
55
|
+
*/
|
|
56
|
+
export function get_import_aliases(root, normalize) {
|
|
57
|
+
const imports = read_package_imports(root);
|
|
58
|
+
if (!imports) return [];
|
|
59
|
+
|
|
60
|
+
/** @type {Array<{ alias: string, path: string }>} */
|
|
61
|
+
const aliases = [];
|
|
62
|
+
|
|
63
|
+
for (const [key, raw_value] of Object.entries(imports)) {
|
|
64
|
+
if (!key.startsWith('#')) continue;
|
|
65
|
+
|
|
66
|
+
const value = normalize_import_value(raw_value);
|
|
67
|
+
if (!value) continue;
|
|
68
|
+
|
|
69
|
+
// For `#xx/*` imports, the target directory is the value without `/*`
|
|
70
|
+
// For `#xx` imports, the target is the file itself
|
|
71
|
+
const target = value.endsWith('/*') ? value.slice(0, -2) : value;
|
|
72
|
+
if (target.includes('*')) continue; // not sure if this is even allowed in Node, anyway it's too niche/complex to support here
|
|
73
|
+
const abs = path.resolve(root, target);
|
|
74
|
+
const alias = key.endsWith('/*') ? key.slice(0, -2) : key;
|
|
75
|
+
|
|
76
|
+
aliases.push({ alias, path: normalize ? normalize(abs) : abs });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Sort by path length descending so longer/more-specific paths match first
|
|
80
|
+
aliases.sort((a, b) => b.path.length - a.path.length);
|
|
81
|
+
|
|
82
|
+
return aliases;
|
|
83
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { mimes, lookup } from 'mrmime';
|
|
2
|
+
|
|
3
|
+
// `mrmime` does not include `.ico` in its database. The IANA-registered
|
|
4
|
+
// type is `image/vnd.microsoft.icon`, but `image/x-icon` is the
|
|
5
|
+
// semi-official type that is universally supported by browsers and other
|
|
6
|
+
// tools, so we use that.
|
|
7
|
+
mimes['ico'] = 'image/x-icon';
|
|
8
|
+
|
|
9
|
+
export { lookup };
|
package/src/utils/page_nodes.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** @import { UniversalNode, ServerNode } from 'types' */
|
|
1
2
|
import {
|
|
2
3
|
validate_layout_exports,
|
|
3
4
|
validate_layout_server_exports,
|
|
@@ -42,10 +43,10 @@ export class PageNodes {
|
|
|
42
43
|
/**
|
|
43
44
|
* @template {'prerender' | 'ssr' | 'csr' | 'trailingSlash'} Option
|
|
44
45
|
* @param {Option} option
|
|
45
|
-
* @returns {
|
|
46
|
+
* @returns {(UniversalNode | ServerNode)[Option] | undefined}
|
|
46
47
|
*/
|
|
47
48
|
#get_option(option) {
|
|
48
|
-
/** @typedef {(
|
|
49
|
+
/** @typedef {(UniversalNode | ServerNode)[Option]} Value */
|
|
49
50
|
|
|
50
51
|
return this.data.reduce((value, node) => {
|
|
51
52
|
return node?.universal?.[option] ?? node?.server?.[option] ?? value;
|
|
@@ -69,7 +70,7 @@ export class PageNodes {
|
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
get_config() {
|
|
72
|
-
/** @type {any} */
|
|
73
|
+
/** @type {Record<string, any>} */
|
|
73
74
|
let current = {};
|
|
74
75
|
|
|
75
76
|
for (const node of this.data) {
|
|
@@ -77,13 +78,11 @@ export class PageNodes {
|
|
|
77
78
|
|
|
78
79
|
current = {
|
|
79
80
|
...current,
|
|
80
|
-
|
|
81
|
-
...node?.universal?.config
|
|
82
|
-
...node?.server?.config
|
|
81
|
+
...node?.server?.config,
|
|
82
|
+
...node?.universal?.config
|
|
83
83
|
};
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
// TODO 3.0 always return `current`? then we can get rid of `?? {}` in other places
|
|
87
86
|
return Object.keys(current).length ? current : undefined;
|
|
88
87
|
}
|
|
89
88
|
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/** @import { ParamMatcher } from '@sveltejs/kit/params' */
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param {import('types').RouteData[]} routes
|
|
7
|
+
* @returns {Set<string>}
|
|
8
|
+
*/
|
|
9
|
+
export function collect_matcher_names(routes) {
|
|
10
|
+
/** @type {Set<string>} */
|
|
11
|
+
const names = new Set();
|
|
12
|
+
|
|
13
|
+
for (const route of routes) {
|
|
14
|
+
for (const param of route.params) {
|
|
15
|
+
if (param.matcher) names.add(param.matcher);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return names;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {Record<string, unknown>} params
|
|
24
|
+
* @param {Set<string>} names
|
|
25
|
+
* @param {string} [file]
|
|
26
|
+
*/
|
|
27
|
+
export function validate_param_matchers(params, names, file) {
|
|
28
|
+
for (const name of names) {
|
|
29
|
+
if (!Object.hasOwn(params, name)) {
|
|
30
|
+
throw new Error(`No matcher found for parameter '${name}'${file ? ` in ${file}` : ''}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @param {{
|
|
37
|
+
* routes: import('types').RouteData[];
|
|
38
|
+
* params_path: string | null;
|
|
39
|
+
* root: string;
|
|
40
|
+
* load?: (file: string) => Promise<Record<string, unknown>>;
|
|
41
|
+
* }} opts
|
|
42
|
+
* @returns {Promise<Record<string, ParamMatcher> | null>}
|
|
43
|
+
*/
|
|
44
|
+
export async function load_and_validate_params({ routes, params_path, root, load }) {
|
|
45
|
+
const names = collect_matcher_names(routes);
|
|
46
|
+
|
|
47
|
+
if (names.size === 0) return null;
|
|
48
|
+
|
|
49
|
+
if (!params_path) {
|
|
50
|
+
throw new Error(`No matcher found for parameter '${names.values().next().value}'`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const file = path.resolve(root, params_path);
|
|
54
|
+
const module = load ? await load(file) : await import(pathToFileURL(file).href);
|
|
55
|
+
|
|
56
|
+
if (!module.params || typeof module.params !== 'object') {
|
|
57
|
+
throw new Error(`${params_path} does not export \`params\` from \`defineParams\``);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
validate_param_matchers(
|
|
61
|
+
/** @type {Record<string, unknown>} */ (module.params),
|
|
62
|
+
names,
|
|
63
|
+
params_path
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
return /** @type {Record<string, ParamMatcher>} */ (module.params);
|
|
67
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Escapes characters that have special meaning in a regular expression.
|
|
3
|
+
* @param {string} str
|
|
4
|
+
* @returns {string} escaped string
|
|
5
|
+
*/
|
|
6
|
+
export function escape_for_regexp(str) {
|
|
7
|
+
// TODO replace with `RegExp.escape(str)` when we require Node >= 24
|
|
8
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, (match) => '\\' + match);
|
|
9
|
+
}
|