@sveltejs/kit 3.0.0-next.10 → 3.0.0-next.12
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/cli.js +8 -8
- package/src/constants.js +3 -1
- package/src/core/adapt/builder.js +3 -6
- package/src/core/config/index.js +6 -1
- package/src/core/config/options.js +54 -104
- package/src/core/env.js +25 -11
- package/src/core/postbuild/fallback.js +2 -1
- package/src/core/postbuild/prerender.js +75 -28
- package/src/core/postbuild/queue.js +2 -1
- package/src/core/sync/sync.js +11 -14
- package/src/core/sync/utils.js +21 -1
- package/src/core/sync/{write_non_ambient.js → write_app_types.js} +23 -21
- package/src/core/sync/write_client_manifest.js +4 -12
- package/src/core/sync/write_env.js +6 -4
- package/src/core/sync/write_server.js +12 -17
- package/src/core/sync/write_tsconfig/index.js +245 -0
- package/src/core/sync/write_tsconfig/utils.js +162 -0
- package/src/core/sync/write_types/index.js +80 -88
- package/src/core/utils.js +28 -3
- package/src/exports/env/index.js +68 -3
- package/src/exports/internal/env.js +6 -3
- package/src/exports/internal/server/index.js +3 -1
- package/src/exports/params.js +9 -4
- package/src/exports/public.d.ts +69 -71
- package/src/exports/vite/dev/index.js +112 -56
- package/src/exports/vite/index.js +483 -258
- package/src/exports/vite/module_ids.js +2 -2
- package/src/exports/vite/preview/index.js +3 -2
- package/src/exports/vite/utils.js +21 -10
- package/src/runner.js +13 -0
- package/src/runtime/app/forms.js +4 -0
- package/src/runtime/app/manifest/index.js +1 -0
- package/src/runtime/app/paths/client.js +30 -30
- package/src/runtime/app/paths/internal/client.js +26 -0
- package/src/runtime/app/paths/server.js +23 -10
- package/src/runtime/app/paths/types.d.ts +11 -19
- package/src/runtime/app/server/index.js +1 -1
- package/src/runtime/app/server/remote/command.js +12 -7
- package/src/runtime/app/server/remote/form.js +29 -26
- package/src/runtime/app/server/remote/prerender.js +9 -2
- package/src/runtime/app/server/remote/query.js +6 -5
- package/src/runtime/app/server/remote/shared.js +48 -30
- package/src/runtime/app/service-worker/index.js +24 -0
- package/src/runtime/app/state/index.js +1 -1
- package/src/runtime/client/client.js +46 -9
- package/src/runtime/client/ndjson.js +1 -1
- package/src/runtime/client/remote-functions/form.svelte.js +43 -51
- package/src/runtime/client/remote-functions/query/index.js +2 -2
- package/src/runtime/client/remote-functions/query-batch.svelte.js +2 -3
- package/src/runtime/client/remote-functions/query-live/iterator.js +5 -2
- package/src/runtime/client/remote-functions/shared.svelte.js +4 -1
- package/src/runtime/client/state.svelte.js +54 -21
- package/src/runtime/client/stream.js +3 -2
- package/src/runtime/form-utils.js +89 -54
- package/src/runtime/server/cookie.js +1 -1
- package/src/runtime/server/data/index.js +32 -29
- package/src/runtime/server/errors.js +135 -0
- package/src/runtime/server/fetch.js +1 -1
- package/src/runtime/server/index.js +20 -10
- package/src/runtime/server/internal.js +25 -0
- package/src/runtime/server/page/actions.js +4 -3
- package/src/runtime/server/page/data_serializer.js +10 -10
- package/src/runtime/server/page/index.js +3 -2
- package/src/runtime/server/page/load_data.js +1 -1
- package/src/runtime/server/page/render.js +22 -35
- package/src/runtime/server/page/respond_with_error.js +6 -5
- package/src/runtime/server/{remote.js → remote-functions.js} +67 -36
- package/src/runtime/server/respond.js +58 -20
- package/src/runtime/server/sourcemaps.js +183 -0
- package/src/runtime/server/utils.js +12 -157
- package/src/types/ambient-private.d.ts +10 -0
- package/src/types/ambient.d.ts +22 -27
- package/src/types/global-private.d.ts +12 -5
- package/src/types/internal.d.ts +19 -9
- package/src/types/private.d.ts +8 -0
- package/src/utils/escape.js +9 -25
- package/src/utils/features.js +1 -1
- package/src/utils/fork.js +7 -2
- package/src/utils/page_nodes.js +3 -5
- package/src/utils/url.js +12 -0
- package/src/version.js +1 -1
- package/types/index.d.ts +152 -120
- package/types/index.d.ts.map +6 -1
- package/src/core/sync/write_ambient.js +0 -18
- package/src/core/sync/write_tsconfig.js +0 -258
- package/src/runtime/shared-server.js +0 -7
- /package/src/core/sync/{write_tsconfig_test → write_tsconfig/test-app}/package.json +0 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { normalize_import_value, read_package_imports } from '../../../utils/imports.js';
|
|
3
|
+
import { posixify } from '../../../utils/os.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Without these, compilation will fail
|
|
7
|
+
* @type {Record<string, any>}
|
|
8
|
+
*/
|
|
9
|
+
export const ESSENTIAL_OPTIONS = {
|
|
10
|
+
// svelte-preprocess cannot figure out whether you have a value or a type, so tell TypeScript
|
|
11
|
+
// to enforce using \`import type\` instead of \`import\` for Types.
|
|
12
|
+
// Also, TypeScript doesn't know about import usages in the template because it only sees the
|
|
13
|
+
// script of a Svelte file. Therefore preserve all value imports.
|
|
14
|
+
verbatimModuleSyntax: true,
|
|
15
|
+
// Vite compiles modules one at a time
|
|
16
|
+
isolatedModules: true
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Options that are strongly recommended, either because not having them is silly or
|
|
21
|
+
* because the align TypeScript's behaviour with Vite's, but which can be overwritten
|
|
22
|
+
* @type {Record<string, any>}
|
|
23
|
+
*/
|
|
24
|
+
export const RECOMMENDED_OPTIONS = {
|
|
25
|
+
allowJs: true,
|
|
26
|
+
checkJs: true,
|
|
27
|
+
forceConsistentCasingInFileNames: true,
|
|
28
|
+
resolveJsonModule: true,
|
|
29
|
+
moduleDetection: 'force',
|
|
30
|
+
moduleResolution: 'bundler',
|
|
31
|
+
allowImportingTsExtensions: true,
|
|
32
|
+
module: 'esnext',
|
|
33
|
+
target: 'esnext',
|
|
34
|
+
skipLibCheck: true,
|
|
35
|
+
esModuleInterop: true,
|
|
36
|
+
noEmit: true // prevent tsconfig error "overwriting input files" - Vite handles the build and ignores this
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Validates that a tsconfig contains `"extends": "<id>"`
|
|
41
|
+
* @param {any} options
|
|
42
|
+
* @param {string} id
|
|
43
|
+
*/
|
|
44
|
+
export function extends_id(options, id) {
|
|
45
|
+
const o = options.extends;
|
|
46
|
+
return Array.isArray(o) ? o.includes(id) : o === id;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Makes paths relative to the output file
|
|
51
|
+
* @param {string} out
|
|
52
|
+
* @param {any} config
|
|
53
|
+
* @param {(input: any) => any} [transform] TODO get rid of this option
|
|
54
|
+
*/
|
|
55
|
+
export function normalize_config(out, config, transform) {
|
|
56
|
+
const dir = path.dirname(out);
|
|
57
|
+
const relative = (/** @type {string} */ file) => posixify(path.relative(dir, file));
|
|
58
|
+
|
|
59
|
+
const paths =
|
|
60
|
+
config.compilerOptions?.paths &&
|
|
61
|
+
Object.fromEntries(
|
|
62
|
+
Object.entries(config.compilerOptions?.paths).map(([k, v]) => [k, v.map(relative)])
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const normalized = {
|
|
66
|
+
...config,
|
|
67
|
+
compilerOptions: {
|
|
68
|
+
...config.compilerOptions,
|
|
69
|
+
paths,
|
|
70
|
+
rootDirs: config.compilerOptions?.rootDirs?.map(relative)
|
|
71
|
+
},
|
|
72
|
+
include: config.include?.map(relative),
|
|
73
|
+
exclude: config.exclude?.map(relative)
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
return transform?.(normalized) ?? normalized;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @param {any} resolved
|
|
81
|
+
* @param {any} options
|
|
82
|
+
*/
|
|
83
|
+
export function validate_resolved_config(resolved, options) {
|
|
84
|
+
const warnings = [];
|
|
85
|
+
|
|
86
|
+
const join = (/** @type {string[]} */ array) =>
|
|
87
|
+
array
|
|
88
|
+
.map((v) => JSON.stringify(v))
|
|
89
|
+
.join(', ')
|
|
90
|
+
.replace(/, ([^,]*)$/, ' and $1');
|
|
91
|
+
|
|
92
|
+
const missing_types = options.types?.filter(
|
|
93
|
+
(/** @type {string} */ type) => !resolved.types?.includes(type)
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
if (missing_types.length > 0) {
|
|
97
|
+
warnings.push(`"types" was overwritten. It must include ${join(missing_types)}`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (options.paths) {
|
|
101
|
+
/** @type {Set<string>} */
|
|
102
|
+
const mismatch = new Set();
|
|
103
|
+
|
|
104
|
+
for (const [k, expected] of Object.entries(options.paths)) {
|
|
105
|
+
const actual = resolved.paths?.[k]?.map((/** @type {string} */ x) =>
|
|
106
|
+
path.resolve(/** @type {string} */ (resolved.pathsBasePath), x)
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
if (JSON.stringify(expected) !== JSON.stringify(actual)) {
|
|
110
|
+
mismatch.add(remove_trailing_slashstar(k));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (mismatch.size > 0) {
|
|
115
|
+
const joined = join([...mismatch]);
|
|
116
|
+
|
|
117
|
+
warnings.push(`"paths" was overwritten. Imports from ${joined} may not typecheck`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
for (const key in ESSENTIAL_OPTIONS) {
|
|
122
|
+
if (resolved[key] !== options[key]) {
|
|
123
|
+
warnings.push(`"${key}" was overwritten. It should be ${JSON.stringify(options[key])}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return warnings;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* @param {string} file
|
|
132
|
+
*/
|
|
133
|
+
export function remove_trailing_slashstar(file) {
|
|
134
|
+
if (file.endsWith('/*')) {
|
|
135
|
+
return file.slice(0, -2);
|
|
136
|
+
} else {
|
|
137
|
+
return file;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* @param {string} root
|
|
143
|
+
*/
|
|
144
|
+
export function get_subpath_imports(root) {
|
|
145
|
+
// Add all `#`-prefixed imports from package.json as path aliases
|
|
146
|
+
const imports = read_package_imports(root);
|
|
147
|
+
|
|
148
|
+
/** @type {Record<string, string>} */
|
|
149
|
+
const alias = {};
|
|
150
|
+
|
|
151
|
+
if (imports) {
|
|
152
|
+
for (const [key, raw_value] of Object.entries(imports)) {
|
|
153
|
+
if (!key.startsWith('#')) continue;
|
|
154
|
+
const value = normalize_import_value(raw_value);
|
|
155
|
+
if (value) {
|
|
156
|
+
alias[key] = value;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return alias;
|
|
162
|
+
}
|
|
@@ -609,7 +609,7 @@ function generate_params_type(params, outdir, config) {
|
|
|
609
609
|
(param) =>
|
|
610
610
|
`${/^\w+$/.test(param.name) ? param.name : `'${param.name}'`}${param.optional ? '?' : ''}: ${
|
|
611
611
|
param.matcher
|
|
612
|
-
? `
|
|
612
|
+
? `Kit.MatcherParam<(typeof import('${params_import}').params)[${JSON.stringify(param.matcher)}]>`
|
|
613
613
|
: 'string'
|
|
614
614
|
}${param.optional ? ' | undefined' : ''}`
|
|
615
615
|
)
|
|
@@ -717,6 +717,62 @@ export function tweak_types(content, is_server) {
|
|
|
717
717
|
return _modified;
|
|
718
718
|
}
|
|
719
719
|
|
|
720
|
+
/**
|
|
721
|
+
* @param {number} name_end position of the identifier the annotation is attached to
|
|
722
|
+
* @param {import('typescript').TypeNode} type_node
|
|
723
|
+
* @returns {string} the removed annotation's text
|
|
724
|
+
*/
|
|
725
|
+
function strip_type_annotation(name_end, type_node) {
|
|
726
|
+
let a = type_node.pos;
|
|
727
|
+
const b = type_node.end;
|
|
728
|
+
while (is_whitespace(content[a])) a += 1;
|
|
729
|
+
|
|
730
|
+
const type = content.slice(a, b);
|
|
731
|
+
code.remove(name_end, type_node.end);
|
|
732
|
+
modified = true;
|
|
733
|
+
return type;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* Types the first parameter of an untyped arrow/function expression.
|
|
738
|
+
* @param {import('typescript').Expression | undefined} rhs
|
|
739
|
+
* @param {string} type
|
|
740
|
+
* @returns {boolean} `false` if there was nothing to annotate
|
|
741
|
+
*/
|
|
742
|
+
function annotate_first_param(rhs, type) {
|
|
743
|
+
if (
|
|
744
|
+
!rhs ||
|
|
745
|
+
!(ts.isArrowFunction(rhs) || ts.isFunctionExpression(rhs)) ||
|
|
746
|
+
!rhs.parameters.length
|
|
747
|
+
) {
|
|
748
|
+
return false;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
const arg = rhs.parameters[0];
|
|
752
|
+
const add_parens = content[arg.pos - 1] !== '(';
|
|
753
|
+
|
|
754
|
+
if (add_parens) code.prependRight(arg.pos, '(');
|
|
755
|
+
|
|
756
|
+
if (arg.type) return false;
|
|
757
|
+
|
|
758
|
+
code.appendLeft(arg.name.end, `: ${type}` + (add_parens ? ')' : ''));
|
|
759
|
+
return true;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
/**
|
|
763
|
+
* @param {import('typescript').Expression | undefined} initializer
|
|
764
|
+
* @param {(prop: import('typescript').PropertyAssignment) => void} callback
|
|
765
|
+
*/
|
|
766
|
+
function for_each_action(initializer, callback) {
|
|
767
|
+
if (initializer && ts.isObjectLiteralExpression(initializer)) {
|
|
768
|
+
for (const prop of initializer.properties) {
|
|
769
|
+
if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name)) {
|
|
770
|
+
callback(prop);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
|
|
720
776
|
ast.forEachChild((node) => {
|
|
721
777
|
if (ts.isFunctionDeclaration(node) && node.name?.text && node.name?.text === 'load') {
|
|
722
778
|
// remove JSDoc comment above `export function load ...`
|
|
@@ -742,42 +798,13 @@ export function tweak_types(content, is_server) {
|
|
|
742
798
|
// edge case — remove JSDoc comment above individual export
|
|
743
799
|
replace_jsdoc_type_tags(declaration, declaration.initializer);
|
|
744
800
|
|
|
745
|
-
// remove type from `export const load: Load ...`
|
|
746
801
|
if (declaration.type) {
|
|
747
|
-
|
|
748
|
-
const b = declaration.type.end;
|
|
749
|
-
while (is_whitespace(content[a])) a += 1;
|
|
750
|
-
|
|
751
|
-
const type = content.slice(a, b);
|
|
752
|
-
code.remove(declaration.name.end, declaration.type.end);
|
|
802
|
+
const type = strip_type_annotation(declaration.name.end, declaration.type);
|
|
753
803
|
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
if (
|
|
757
|
-
rhs &&
|
|
758
|
-
(ts.isArrowFunction(rhs) || ts.isFunctionExpression(rhs)) &&
|
|
759
|
-
rhs.parameters.length
|
|
760
|
-
) {
|
|
761
|
-
const arg = rhs.parameters[0];
|
|
762
|
-
const add_parens = content[arg.pos - 1] !== '(';
|
|
763
|
-
|
|
764
|
-
if (add_parens) code.prependRight(arg.pos, '(');
|
|
765
|
-
|
|
766
|
-
if (arg && !arg.type) {
|
|
767
|
-
code.appendLeft(
|
|
768
|
-
arg.name.end,
|
|
769
|
-
`: Parameters<${type}>[0]` + (add_parens ? ')' : '')
|
|
770
|
-
);
|
|
771
|
-
} else {
|
|
772
|
-
// prevent "type X is imported but not used" (isn't silenced by @ts-nocheck) when svelte-check runs
|
|
773
|
-
code.append(`;null as any as ${type};`);
|
|
774
|
-
}
|
|
775
|
-
} else {
|
|
804
|
+
if (!annotate_first_param(declaration.initializer, `Parameters<${type}>[0]`)) {
|
|
776
805
|
// prevent "type X is imported but not used" (isn't silenced by @ts-nocheck) when svelte-check runs
|
|
777
806
|
code.append(`;null as any as ${type};`);
|
|
778
807
|
}
|
|
779
|
-
|
|
780
|
-
modified = true;
|
|
781
808
|
}
|
|
782
809
|
} else if (
|
|
783
810
|
is_server &&
|
|
@@ -789,69 +816,34 @@ export function tweak_types(content, is_server) {
|
|
|
789
816
|
const removed = replace_jsdoc_type_tags(node, declaration.initializer);
|
|
790
817
|
// ... and move type to each individual action
|
|
791
818
|
if (removed) {
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
rhs.pos,
|
|
809
|
-
`/** @param {import('./$types').RequestEvent} ${name} */ `
|
|
810
|
-
);
|
|
811
|
-
}
|
|
812
|
-
}
|
|
819
|
+
for_each_action(declaration.initializer, (prop) => {
|
|
820
|
+
const rhs = prop.initializer;
|
|
821
|
+
const replaced = replace_jsdoc_type_tags(prop, rhs);
|
|
822
|
+
if (
|
|
823
|
+
!replaced &&
|
|
824
|
+
rhs &&
|
|
825
|
+
(ts.isArrowFunction(rhs) || ts.isFunctionExpression(rhs)) &&
|
|
826
|
+
rhs.parameters?.[0]
|
|
827
|
+
) {
|
|
828
|
+
const name = ts.isIdentifier(rhs.parameters[0].name)
|
|
829
|
+
? rhs.parameters[0].name.text
|
|
830
|
+
: 'event';
|
|
831
|
+
code.prependRight(
|
|
832
|
+
rhs.pos,
|
|
833
|
+
`/** @param {import('./$types').RequestEvent} ${name} */ `
|
|
834
|
+
);
|
|
813
835
|
}
|
|
814
|
-
}
|
|
836
|
+
});
|
|
815
837
|
}
|
|
816
838
|
|
|
817
|
-
// remove type from `export const actions: Actions ...`
|
|
818
839
|
if (declaration.type) {
|
|
819
|
-
|
|
820
|
-
const b = declaration.type.end;
|
|
821
|
-
while (is_whitespace(content[a])) a += 1;
|
|
822
|
-
|
|
823
|
-
const type = content.slice(a, b);
|
|
824
|
-
code.remove(declaration.name.end, declaration.type.end);
|
|
840
|
+
const type = strip_type_annotation(declaration.name.end, declaration.type);
|
|
825
841
|
code.append(`;null as any as ${type};`);
|
|
826
|
-
modified = true;
|
|
827
842
|
|
|
828
843
|
// ... and move type to each individual action
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name)) {
|
|
833
|
-
const rhs = prop.initializer;
|
|
834
|
-
|
|
835
|
-
if (
|
|
836
|
-
rhs &&
|
|
837
|
-
(ts.isArrowFunction(rhs) || ts.isFunctionExpression(rhs)) &&
|
|
838
|
-
rhs.parameters.length
|
|
839
|
-
) {
|
|
840
|
-
const arg = rhs.parameters[0];
|
|
841
|
-
const add_parens = content[arg.pos - 1] !== '(';
|
|
842
|
-
|
|
843
|
-
if (add_parens) code.prependRight(arg.pos, '(');
|
|
844
|
-
|
|
845
|
-
if (arg && !arg.type) {
|
|
846
|
-
code.appendLeft(
|
|
847
|
-
arg.name.end,
|
|
848
|
-
": import('./$types').RequestEvent" + (add_parens ? ')' : '')
|
|
849
|
-
);
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
}
|
|
844
|
+
for_each_action(declaration.initializer, (prop) => {
|
|
845
|
+
annotate_first_param(prop.initializer, "import('./$types').RequestEvent");
|
|
846
|
+
});
|
|
855
847
|
}
|
|
856
848
|
}
|
|
857
849
|
}
|
package/src/core/utils.js
CHANGED
|
@@ -30,18 +30,43 @@ export function get_runtime_base(root) {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/** @param {{ verbose: boolean }} opts */
|
|
33
|
-
export function logger({ verbose }) {
|
|
33
|
+
export function logger({ verbose } = { verbose: true }) {
|
|
34
34
|
/** @type {import('types').Logger} */
|
|
35
|
-
const log = (msg) => console.log(msg
|
|
35
|
+
const log = (msg) => console.log(msg);
|
|
36
36
|
|
|
37
37
|
/** @param {string} msg */
|
|
38
|
-
const err = (msg) => console.error(msg
|
|
38
|
+
const err = (msg) => console.error(msg);
|
|
39
39
|
|
|
40
40
|
log.success = (msg) => log(styleText('green', `✔ ${msg}`));
|
|
41
41
|
log.error = (msg) => err(styleText(['bold', 'red'], msg));
|
|
42
42
|
log.warn = (msg) => log(styleText(['bold', 'yellow'], msg));
|
|
43
43
|
log.minor = verbose ? (msg) => log(styleText('grey', msg)) : noop;
|
|
44
44
|
log.info = verbose ? log : noop;
|
|
45
|
+
log.err = err;
|
|
46
|
+
|
|
47
|
+
log.prettyError = (error, caller) => {
|
|
48
|
+
/** @type {unknown} */
|
|
49
|
+
let e = error;
|
|
50
|
+
|
|
51
|
+
while (e instanceof Error) {
|
|
52
|
+
let stack = e.stack;
|
|
53
|
+
if (stack) {
|
|
54
|
+
if (caller) {
|
|
55
|
+
const i = stack.indexOf(caller);
|
|
56
|
+
// Cut the stack trace off at the point when our internal one starts
|
|
57
|
+
stack = stack.slice(0, stack.lastIndexOf('\n', i));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
err(stack);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
e = e.cause;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (e) {
|
|
67
|
+
err(String(e));
|
|
68
|
+
}
|
|
69
|
+
};
|
|
45
70
|
|
|
46
71
|
return log;
|
|
47
72
|
}
|
package/src/exports/env/index.js
CHANGED
|
@@ -1,12 +1,77 @@
|
|
|
1
|
-
/** @import {
|
|
1
|
+
/** @import { StandardSchemaV1 } from '@standard-schema/spec' */
|
|
2
|
+
/** @import { DefinedEnvVars, EnvVarConfig } from '@sveltejs/kit' */
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Utility for defining [environment variables](https://svelte.dev/docs/kit/environment-variables),
|
|
5
6
|
* which are made available via `$app/env/public` and `$app/env/private`.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```js
|
|
10
|
+
* import { defineEnvVars } from '@sveltejs/kit/env';
|
|
11
|
+
* import * as v from 'valibot';
|
|
12
|
+
*
|
|
13
|
+
* export const variables = defineEnvVars({
|
|
14
|
+
* API_URL: {
|
|
15
|
+
* schema: v.pipe(v.string(), v.url())
|
|
16
|
+
* },
|
|
17
|
+
* PORT: {
|
|
18
|
+
* schema: (value) => {
|
|
19
|
+
* if (value === undefined) return 3000;
|
|
20
|
+
* const port = Number(value);
|
|
21
|
+
* if (!Number.isInteger(port)) throw new Error('PORT must be an integer');
|
|
22
|
+
* return port;
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
6
28
|
* @template {Record<string, EnvVarConfig<any>>} T
|
|
7
29
|
* @param {T} variables
|
|
8
|
-
* @returns {T}
|
|
30
|
+
* @returns {DefinedEnvVars<T>}
|
|
9
31
|
*/
|
|
10
32
|
export function defineEnvVars(variables) {
|
|
11
|
-
|
|
33
|
+
/** @type {Record<string, EnvVarConfig<any>>} */
|
|
34
|
+
const normalized = {};
|
|
35
|
+
|
|
36
|
+
for (const [name, config] of Object.entries(variables)) {
|
|
37
|
+
// standard schemas can be callable (e.g. ArkType), so a function is only a validator if it isn't one
|
|
38
|
+
normalized[name] =
|
|
39
|
+
typeof config.schema === 'function' && !('~standard' in config.schema)
|
|
40
|
+
? { ...config, schema: normalize_env_schema(config.schema) }
|
|
41
|
+
: config;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return /** @type {DefinedEnvVars<T>} */ (normalized);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @param {(value: string | undefined) => any} fn
|
|
49
|
+
* @returns {StandardSchemaV1<string | undefined, any>}
|
|
50
|
+
*/
|
|
51
|
+
function normalize_env_schema(fn) {
|
|
52
|
+
return /** @type {StandardSchemaV1<string | undefined, any>} */ (
|
|
53
|
+
/** @type {unknown} */ ({
|
|
54
|
+
'~standard': {
|
|
55
|
+
validate(/** @type {unknown} */ value) {
|
|
56
|
+
let result;
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
result = fn(/** @type {string | undefined} */ (value));
|
|
60
|
+
} catch (error) {
|
|
61
|
+
return {
|
|
62
|
+
issues: [
|
|
63
|
+
{
|
|
64
|
+
message: error instanceof Error ? error.message || 'Invalid value' : String(error)
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (result instanceof Promise) return result; // will be rejected upstream
|
|
71
|
+
|
|
72
|
+
return { value: result };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
);
|
|
12
77
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { stackless } from '../../utils/error.js';
|
|
5
5
|
|
|
6
6
|
const MISSING = {
|
|
7
|
-
message: `Value is missing. If it is optional, add a
|
|
7
|
+
message: `Value is missing. If it is optional, add a validator declaring it as such.`
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
const BAD_VALIDATOR = {
|
|
@@ -24,10 +24,13 @@ const ASYNC_VALIDATOR = {
|
|
|
24
24
|
*/
|
|
25
25
|
export function validate(variables, value, name, issues) {
|
|
26
26
|
const config = variables[name] ?? {};
|
|
27
|
-
|
|
27
|
+
// `defineEnvVars` normalizes function validators to standard schemas
|
|
28
|
+
const validator = /** @type {StandardSchemaV1<string | undefined, any> | undefined} */ (
|
|
29
|
+
config.schema
|
|
30
|
+
);
|
|
28
31
|
|
|
29
32
|
if (!validator) {
|
|
30
|
-
if (
|
|
33
|
+
if (value === undefined) issues[name] = [MISSING];
|
|
31
34
|
return value;
|
|
32
35
|
}
|
|
33
36
|
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
import { try_get_request_store } from './event.js';
|
|
3
3
|
|
|
4
4
|
export function get_origin() {
|
|
5
|
-
|
|
5
|
+
// `request.url` rather than `event.url`, which throws inside queries
|
|
6
|
+
const request = try_get_request_store()?.event.request;
|
|
7
|
+
return request && new URL(request.url).origin;
|
|
6
8
|
}
|
|
7
9
|
|
|
8
10
|
/**
|
package/src/exports/params.js
CHANGED
|
@@ -35,6 +35,15 @@ export function defineParams(definitions) {
|
|
|
35
35
|
* @returns {import('@sveltejs/kit').ParamMatcher}
|
|
36
36
|
*/
|
|
37
37
|
export function normalize_param_definition(definition) {
|
|
38
|
+
// standard schemas can be callable (e.g. ArkType), so this must be checked before the function case
|
|
39
|
+
if (
|
|
40
|
+
definition &&
|
|
41
|
+
(typeof definition === 'object' || typeof definition === 'function') &&
|
|
42
|
+
'~standard' in definition
|
|
43
|
+
) {
|
|
44
|
+
return definition;
|
|
45
|
+
}
|
|
46
|
+
|
|
38
47
|
if (typeof definition === 'function') {
|
|
39
48
|
return /** @type {import('@sveltejs/kit').ParamMatcher} */ (
|
|
40
49
|
/** @type {unknown} */ ({
|
|
@@ -55,9 +64,5 @@ export function normalize_param_definition(definition) {
|
|
|
55
64
|
);
|
|
56
65
|
}
|
|
57
66
|
|
|
58
|
-
if (definition && typeof definition === 'object' && '~standard' in definition) {
|
|
59
|
-
return definition;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
67
|
throw new Error('Invalid param definition');
|
|
63
68
|
}
|