@sveltejs/kit 2.47.1 → 2.47.3
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/postbuild/analyse.js +2 -1
- package/src/exports/public.d.ts +31 -4
- package/src/exports/vite/index.js +22 -6
- package/src/exports/vite/static_analysis/index.js +23 -4
- package/src/runtime/app/server/remote/form.js +12 -10
- package/src/runtime/client/client.js +61 -56
- package/src/runtime/client/remote-functions/form.svelte.js +44 -112
- package/src/runtime/{form-utils.svelte.js → form-utils.js} +72 -60
- package/src/runtime/server/page/render.js +1 -2
- package/src/types/global-private.d.ts +10 -0
- package/src/types/internal.d.ts +2 -0
- package/src/utils/streaming.js +11 -35
- package/src/version.js +1 -1
- package/types/index.d.ts +33 -5
- package/types/index.d.ts.map +2 -1
package/package.json
CHANGED
package/src/exports/public.d.ts
CHANGED
|
@@ -1914,10 +1914,28 @@ type RemoteFormFieldContainer<Value> = RemoteFormFieldMethods<Value> & {
|
|
|
1914
1914
|
allIssues(): RemoteFormIssue[] | undefined;
|
|
1915
1915
|
};
|
|
1916
1916
|
|
|
1917
|
+
type UnknownField<Value> = RemoteFormFieldMethods<Value> & {
|
|
1918
|
+
/** Validation issues belonging to this or any of the fields that belong to it, if any */
|
|
1919
|
+
allIssues(): RemoteFormIssue[] | undefined;
|
|
1920
|
+
/**
|
|
1921
|
+
* Returns an object that can be spread onto an input element with the correct type attribute,
|
|
1922
|
+
* aria-invalid attribute if the field is invalid, and appropriate value/checked property getters/setters.
|
|
1923
|
+
* @example
|
|
1924
|
+
* ```svelte
|
|
1925
|
+
* <input {...myForm.fields.myString.as('text')} />
|
|
1926
|
+
* <input {...myForm.fields.myNumber.as('number')} />
|
|
1927
|
+
* <input {...myForm.fields.myBoolean.as('checkbox')} />
|
|
1928
|
+
* ```
|
|
1929
|
+
*/
|
|
1930
|
+
as<T extends RemoteFormFieldType<Value>>(...args: AsArgs<T, Value>): InputElementProps<T>;
|
|
1931
|
+
} & {
|
|
1932
|
+
[key: string | number]: UnknownField<any>;
|
|
1933
|
+
};
|
|
1934
|
+
|
|
1917
1935
|
/**
|
|
1918
1936
|
* Recursive type to build form fields structure with proxy access
|
|
1919
1937
|
*/
|
|
1920
|
-
type RemoteFormFields<T> =
|
|
1938
|
+
export type RemoteFormFields<T> =
|
|
1921
1939
|
WillRecurseIndefinitely<T> extends true
|
|
1922
1940
|
? RecursiveFormFields
|
|
1923
1941
|
: NonNullable<T> extends string | number | boolean | File
|
|
@@ -1925,11 +1943,17 @@ type RemoteFormFields<T> =
|
|
|
1925
1943
|
: T extends string[] | File[]
|
|
1926
1944
|
? RemoteFormField<T> & { [K in number]: RemoteFormField<T[number]> }
|
|
1927
1945
|
: T extends Array<infer U>
|
|
1928
|
-
? RemoteFormFieldContainer<T> & {
|
|
1929
|
-
|
|
1946
|
+
? RemoteFormFieldContainer<T> & {
|
|
1947
|
+
[K in number]: RemoteFormFields<U>;
|
|
1948
|
+
}
|
|
1949
|
+
: RemoteFormFieldContainer<T> & {
|
|
1950
|
+
[K in keyof T]-?: RemoteFormFields<T[K]>;
|
|
1951
|
+
};
|
|
1930
1952
|
|
|
1931
1953
|
// By breaking this out into its own type, we avoid the TS recursion depth limit
|
|
1932
|
-
type RecursiveFormFields =
|
|
1954
|
+
type RecursiveFormFields = RemoteFormFieldContainer<any> & {
|
|
1955
|
+
[key: string | number]: UnknownField<any>;
|
|
1956
|
+
};
|
|
1933
1957
|
|
|
1934
1958
|
type MaybeArray<T> = T | T[];
|
|
1935
1959
|
|
|
@@ -2021,7 +2045,10 @@ export type RemoteForm<Input extends RemoteFormInput | void, Output> = {
|
|
|
2021
2045
|
preflight(schema: StandardSchemaV1<Input, any>): RemoteForm<Input, Output>;
|
|
2022
2046
|
/** Validate the form contents programmatically */
|
|
2023
2047
|
validate(options?: {
|
|
2048
|
+
/** Set this to `true` to also show validation issues of fields that haven't been touched yet. */
|
|
2024
2049
|
includeUntouched?: boolean;
|
|
2050
|
+
/** Set this to `true` to only run the `preflight` validation. */
|
|
2051
|
+
preflightOnly?: boolean;
|
|
2025
2052
|
/** Perform validation as if the form was submitted by the given button. */
|
|
2026
2053
|
submitter?: HTMLButtonElement | HTMLInputElement;
|
|
2027
2054
|
}): Promise<void>;
|
|
@@ -172,8 +172,8 @@ let secondary_build_started = false;
|
|
|
172
172
|
/** @type {import('types').ManifestData} */
|
|
173
173
|
let manifest_data;
|
|
174
174
|
|
|
175
|
-
/** @type {import('types').ServerMetadata
|
|
176
|
-
let
|
|
175
|
+
/** @type {import('types').ServerMetadata | undefined} only set at build time once analysis is finished */
|
|
176
|
+
let build_metadata = undefined;
|
|
177
177
|
|
|
178
178
|
/**
|
|
179
179
|
* Returns the SvelteKit Vite plugin. Vite executes Rollup hooks as well as some of its own.
|
|
@@ -369,12 +369,28 @@ async function kit({ svelte_config }) {
|
|
|
369
369
|
|
|
370
370
|
if (!secondary_build_started) {
|
|
371
371
|
manifest_data = sync.all(svelte_config, config_env.mode).manifest_data;
|
|
372
|
+
// During the initial server build we don't know yet
|
|
373
|
+
new_config.define.__SVELTEKIT_HAS_SERVER_LOAD__ = 'true';
|
|
374
|
+
new_config.define.__SVELTEKIT_HAS_UNIVERSAL_LOAD__ = 'true';
|
|
375
|
+
} else {
|
|
376
|
+
const nodes = Object.values(
|
|
377
|
+
/** @type {import('types').ServerMetadata} */ (build_metadata).nodes
|
|
378
|
+
);
|
|
379
|
+
|
|
380
|
+
// Through the finished analysis we can now check if any node has server or universal load functions
|
|
381
|
+
const has_server_load = nodes.some((node) => node.has_server_load);
|
|
382
|
+
const has_universal_load = nodes.some((node) => node.has_universal_load);
|
|
383
|
+
|
|
384
|
+
new_config.define.__SVELTEKIT_HAS_SERVER_LOAD__ = s(has_server_load);
|
|
385
|
+
new_config.define.__SVELTEKIT_HAS_UNIVERSAL_LOAD__ = s(has_universal_load);
|
|
372
386
|
}
|
|
373
387
|
} else {
|
|
374
388
|
new_config.define = {
|
|
375
389
|
...define,
|
|
376
390
|
__SVELTEKIT_APP_VERSION_POLL_INTERVAL__: '0',
|
|
377
|
-
__SVELTEKIT_PAYLOAD__: 'globalThis.__sveltekit_dev'
|
|
391
|
+
__SVELTEKIT_PAYLOAD__: 'globalThis.__sveltekit_dev',
|
|
392
|
+
__SVELTEKIT_HAS_SERVER_LOAD__: 'true',
|
|
393
|
+
__SVELTEKIT_HAS_UNIVERSAL_LOAD__: 'true'
|
|
378
394
|
};
|
|
379
395
|
|
|
380
396
|
// @ts-ignore this prevents a reference error if `client.js` is imported on the server
|
|
@@ -733,8 +749,8 @@ async function kit({ svelte_config }) {
|
|
|
733
749
|
|
|
734
750
|
// in prod, we already built and analysed the server code before
|
|
735
751
|
// building the client code, so `remote_exports` is populated
|
|
736
|
-
else if (
|
|
737
|
-
const exports =
|
|
752
|
+
else if (build_metadata?.remotes) {
|
|
753
|
+
const exports = build_metadata?.remotes.get(remote.hash);
|
|
738
754
|
if (!exports) throw new Error('Expected to find metadata for remote file ' + id);
|
|
739
755
|
|
|
740
756
|
for (const [name, value] of exports) {
|
|
@@ -1038,7 +1054,7 @@ async function kit({ svelte_config }) {
|
|
|
1038
1054
|
remotes
|
|
1039
1055
|
});
|
|
1040
1056
|
|
|
1041
|
-
|
|
1057
|
+
build_metadata = metadata;
|
|
1042
1058
|
|
|
1043
1059
|
log.info('Building app');
|
|
1044
1060
|
|
|
@@ -4,7 +4,7 @@ import { read } from '../../../utils/filesystem.js';
|
|
|
4
4
|
|
|
5
5
|
const inheritable_page_options = new Set(['ssr', 'prerender', 'csr', 'trailingSlash', 'config']);
|
|
6
6
|
|
|
7
|
-
const valid_page_options = new Set([...inheritable_page_options, 'entries']);
|
|
7
|
+
const valid_page_options = new Set([...inheritable_page_options, 'entries', 'load']);
|
|
8
8
|
|
|
9
9
|
const skip_parsing_regex = new RegExp(
|
|
10
10
|
`${Array.from(valid_page_options).join('|')}|(?:export[\\s\\n]+\\*[\\s\\n]+from)`
|
|
@@ -14,7 +14,8 @@ const parser = Parser.extend(tsPlugin());
|
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Collects page options from a +page.js/+layout.js file, ignoring reassignments
|
|
17
|
-
* and using the declared value
|
|
17
|
+
* and using the declared value (except for load functions, for which the value is `true`).
|
|
18
|
+
* Returns `null` if any export is too difficult to analyse.
|
|
18
19
|
* @param {string} filename The name of the file to report when an error occurs
|
|
19
20
|
* @param {string} input
|
|
20
21
|
* @returns {Record<string, any> | null}
|
|
@@ -116,6 +117,13 @@ export function statically_analyse_page_options(filename, input) {
|
|
|
116
117
|
continue;
|
|
117
118
|
}
|
|
118
119
|
|
|
120
|
+
// Special case: We only want to know that 'load' is exported (in a way that doesn't cause truthy checks in other places to trigger)
|
|
121
|
+
if (variable_declarator.id.name === 'load') {
|
|
122
|
+
page_options.set('load', null);
|
|
123
|
+
export_specifiers.delete('load');
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
|
|
119
127
|
// references a declaration we can't easily evaluate statically
|
|
120
128
|
return null;
|
|
121
129
|
}
|
|
@@ -138,7 +146,12 @@ export function statically_analyse_page_options(filename, input) {
|
|
|
138
146
|
// class and function declarations
|
|
139
147
|
if (statement.declaration.type !== 'VariableDeclaration') {
|
|
140
148
|
if (valid_page_options.has(statement.declaration.id.name)) {
|
|
141
|
-
|
|
149
|
+
// Special case: We only want to know that 'load' is exported (in a way that doesn't cause truthy checks in other places to trigger)
|
|
150
|
+
if (statement.declaration.id.name === 'load') {
|
|
151
|
+
page_options.set('load', null);
|
|
152
|
+
} else {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
142
155
|
}
|
|
143
156
|
continue;
|
|
144
157
|
}
|
|
@@ -157,6 +170,12 @@ export function statically_analyse_page_options(filename, input) {
|
|
|
157
170
|
continue;
|
|
158
171
|
}
|
|
159
172
|
|
|
173
|
+
// Special case: We only want to know that 'load' is exported (in a way that doesn't cause truthy checks in other places to trigger)
|
|
174
|
+
if (declaration.id.name === 'load') {
|
|
175
|
+
page_options.set('load', null);
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
|
|
160
179
|
// references a declaration we can't easily evaluate statically
|
|
161
180
|
return null;
|
|
162
181
|
}
|
|
@@ -187,7 +206,7 @@ export function get_name(node) {
|
|
|
187
206
|
*/
|
|
188
207
|
export function create_node_analyser({ resolve, static_exports = new Map() }) {
|
|
189
208
|
/**
|
|
190
|
-
* Computes the final page options for a node (if possible). Otherwise, returns `null`.
|
|
209
|
+
* Computes the final page options (may include load function as `load: null`; special case) for a node (if possible). Otherwise, returns `null`.
|
|
191
210
|
* @param {import('types').PageNode} node
|
|
192
211
|
* @returns {Promise<Record<string, any> | null>}
|
|
193
212
|
*/
|
|
@@ -5,12 +5,13 @@ import { get_request_store } from '@sveltejs/kit/internal/server';
|
|
|
5
5
|
import { DEV } from 'esm-env';
|
|
6
6
|
import {
|
|
7
7
|
convert_formdata,
|
|
8
|
-
flatten_issues,
|
|
9
8
|
create_field_proxy,
|
|
10
9
|
set_nested_value,
|
|
11
10
|
throw_on_old_property_access,
|
|
12
|
-
deep_set
|
|
13
|
-
|
|
11
|
+
deep_set,
|
|
12
|
+
normalize_issue,
|
|
13
|
+
flatten_issues
|
|
14
|
+
} from '../../../form-utils.js';
|
|
14
15
|
import { get_cache, run_remote_function } from './shared.js';
|
|
15
16
|
|
|
16
17
|
/**
|
|
@@ -46,7 +47,7 @@ import { get_cache, run_remote_function } from './shared.js';
|
|
|
46
47
|
* @template Output
|
|
47
48
|
* @overload
|
|
48
49
|
* @param {Schema} validate
|
|
49
|
-
* @param {(data: StandardSchemaV1.InferOutput<Schema>, invalid: import('@sveltejs/kit').Invalid<StandardSchemaV1.
|
|
50
|
+
* @param {(data: StandardSchemaV1.InferOutput<Schema>, invalid: import('@sveltejs/kit').Invalid<StandardSchemaV1.InferInput<Schema>>) => MaybePromise<Output>} fn
|
|
50
51
|
* @returns {RemoteForm<StandardSchemaV1.InferInput<Schema>, Output>}
|
|
51
52
|
* @since 2.27
|
|
52
53
|
*/
|
|
@@ -142,7 +143,7 @@ export function form(validate_or_fn, maybe_fn) {
|
|
|
142
143
|
}
|
|
143
144
|
}
|
|
144
145
|
|
|
145
|
-
/** @type {{ submission: true, input?: Record<string, any>, issues?:
|
|
146
|
+
/** @type {{ submission: true, input?: Record<string, any>, issues?: InternalRemoteFormIssue[], result: Output }} */
|
|
146
147
|
const output = {};
|
|
147
148
|
|
|
148
149
|
// make it possible to differentiate between user submission and programmatic `field.set(...)` updates
|
|
@@ -209,10 +210,11 @@ export function form(validate_or_fn, maybe_fn) {
|
|
|
209
210
|
Object.defineProperty(instance, 'fields', {
|
|
210
211
|
get() {
|
|
211
212
|
const data = get_cache(__)?.[''];
|
|
213
|
+
const issues = flatten_issues(data?.issues ?? []);
|
|
214
|
+
|
|
212
215
|
return create_field_proxy(
|
|
213
216
|
{},
|
|
214
217
|
() => data?.input ?? {},
|
|
215
|
-
() => {},
|
|
216
218
|
(path, value) => {
|
|
217
219
|
if (data?.submission) {
|
|
218
220
|
// don't override a submission
|
|
@@ -224,7 +226,7 @@ export function form(validate_or_fn, maybe_fn) {
|
|
|
224
226
|
|
|
225
227
|
(get_cache(__)[''] ??= {}).input = input;
|
|
226
228
|
},
|
|
227
|
-
() =>
|
|
229
|
+
() => issues
|
|
228
230
|
);
|
|
229
231
|
}
|
|
230
232
|
});
|
|
@@ -293,13 +295,13 @@ export function form(validate_or_fn, maybe_fn) {
|
|
|
293
295
|
}
|
|
294
296
|
|
|
295
297
|
/**
|
|
296
|
-
* @param {{ issues?:
|
|
298
|
+
* @param {{ issues?: InternalRemoteFormIssue[], input?: Record<string, any>, result: any }} output
|
|
297
299
|
* @param {readonly StandardSchemaV1.Issue[]} issues
|
|
298
300
|
* @param {boolean} is_remote_request
|
|
299
301
|
* @param {FormData} form_data
|
|
300
302
|
*/
|
|
301
303
|
function handle_issues(output, issues, is_remote_request, form_data) {
|
|
302
|
-
output.issues =
|
|
304
|
+
output.issues = issues.map((issue) => normalize_issue(issue, true));
|
|
303
305
|
|
|
304
306
|
// if it was a progressively-enhanced submission, we don't need
|
|
305
307
|
// to return the input — it's already there
|
|
@@ -315,7 +317,7 @@ function handle_issues(output, issues, is_remote_request, form_data) {
|
|
|
315
317
|
|
|
316
318
|
if (is_array) key = key.slice(0, -2);
|
|
317
319
|
|
|
318
|
-
|
|
320
|
+
set_nested_value(
|
|
319
321
|
/** @type {Record<string, any>} */ (output.input),
|
|
320
322
|
key,
|
|
321
323
|
is_array ? values : values[0]
|
|
@@ -732,7 +732,7 @@ async function load_node({ loader, parent, url, params, route, server_data_node
|
|
|
732
732
|
}
|
|
733
733
|
}
|
|
734
734
|
|
|
735
|
-
if (node.universal?.load) {
|
|
735
|
+
if (__SVELTEKIT_HAS_UNIVERSAL_LOAD__ && node.universal?.load) {
|
|
736
736
|
/** @param {string[]} deps */
|
|
737
737
|
function depends(...deps) {
|
|
738
738
|
for (const dep of deps) {
|
|
@@ -1004,49 +1004,52 @@ async function load_route({ id, invalidating, url, params, route, preload }) {
|
|
|
1004
1004
|
const search_params_changed = diff_search_params(current.url, url);
|
|
1005
1005
|
|
|
1006
1006
|
let parent_invalid = false;
|
|
1007
|
-
const invalid_server_nodes = loaders.map((loader, i) => {
|
|
1008
|
-
const previous = current.branch[i];
|
|
1009
1007
|
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1008
|
+
if (__SVELTEKIT_HAS_SERVER_LOAD__) {
|
|
1009
|
+
const invalid_server_nodes = loaders.map((loader, i) => {
|
|
1010
|
+
const previous = current.branch[i];
|
|
1011
|
+
|
|
1012
|
+
const invalid =
|
|
1013
|
+
!!loader?.[0] &&
|
|
1014
|
+
(previous?.loader !== loader[1] ||
|
|
1015
|
+
has_changed(
|
|
1016
|
+
parent_invalid,
|
|
1017
|
+
route_changed,
|
|
1018
|
+
url_changed,
|
|
1019
|
+
search_params_changed,
|
|
1020
|
+
previous.server?.uses,
|
|
1021
|
+
params
|
|
1022
|
+
));
|
|
1023
|
+
|
|
1024
|
+
if (invalid) {
|
|
1025
|
+
// For the next one
|
|
1026
|
+
parent_invalid = true;
|
|
1027
|
+
}
|
|
1026
1028
|
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
+
return invalid;
|
|
1030
|
+
});
|
|
1029
1031
|
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1032
|
+
if (invalid_server_nodes.some(Boolean)) {
|
|
1033
|
+
try {
|
|
1034
|
+
server_data = await load_data(url, invalid_server_nodes);
|
|
1035
|
+
} catch (error) {
|
|
1036
|
+
const handled_error = await handle_error(error, { url, params, route: { id } });
|
|
1035
1037
|
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1038
|
+
if (preload_tokens.has(preload)) {
|
|
1039
|
+
return preload_error({ error: handled_error, url, params, route });
|
|
1040
|
+
}
|
|
1039
1041
|
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1042
|
+
return load_root_error_page({
|
|
1043
|
+
status: get_status(error),
|
|
1044
|
+
error: handled_error,
|
|
1045
|
+
url,
|
|
1046
|
+
route
|
|
1047
|
+
});
|
|
1048
|
+
}
|
|
1047
1049
|
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
+
if (server_data.type === 'redirect') {
|
|
1051
|
+
return server_data;
|
|
1052
|
+
}
|
|
1050
1053
|
}
|
|
1051
1054
|
}
|
|
1052
1055
|
|
|
@@ -1232,27 +1235,29 @@ async function load_root_error_page({ status, error, url, route }) {
|
|
|
1232
1235
|
/** @type {import('types').ServerDataNode | null} */
|
|
1233
1236
|
let server_data_node = null;
|
|
1234
1237
|
|
|
1235
|
-
|
|
1238
|
+
if (__SVELTEKIT_HAS_SERVER_LOAD__) {
|
|
1239
|
+
const default_layout_has_server_load = app.server_loads[0] === 0;
|
|
1236
1240
|
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1241
|
+
if (default_layout_has_server_load) {
|
|
1242
|
+
// TODO post-https://github.com/sveltejs/kit/discussions/6124 we can use
|
|
1243
|
+
// existing root layout data
|
|
1244
|
+
try {
|
|
1245
|
+
const server_data = await load_data(url, [true]);
|
|
1242
1246
|
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1247
|
+
if (
|
|
1248
|
+
server_data.type !== 'data' ||
|
|
1249
|
+
(server_data.nodes[0] && server_data.nodes[0].type !== 'data')
|
|
1250
|
+
) {
|
|
1251
|
+
throw 0;
|
|
1252
|
+
}
|
|
1249
1253
|
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1254
|
+
server_data_node = server_data.nodes[0] ?? null;
|
|
1255
|
+
} catch {
|
|
1256
|
+
// at this point we have no choice but to fall back to the server, if it wouldn't
|
|
1257
|
+
// bring us right back here, turning this into an endless loop
|
|
1258
|
+
if (url.origin !== origin || url.pathname !== location.pathname || hydrated) {
|
|
1259
|
+
await native_navigation(url);
|
|
1260
|
+
}
|
|
1256
1261
|
}
|
|
1257
1262
|
}
|
|
1258
1263
|
}
|
|
@@ -17,28 +17,29 @@ import {
|
|
|
17
17
|
deep_set,
|
|
18
18
|
set_nested_value,
|
|
19
19
|
throw_on_old_property_access,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
} from '../../form-utils.
|
|
20
|
+
build_path_string,
|
|
21
|
+
normalize_issue
|
|
22
|
+
} from '../../form-utils.js';
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
* Merge client issues into server issues
|
|
26
|
-
*
|
|
27
|
-
* @param {
|
|
28
|
-
* @
|
|
25
|
+
* Merge client issues into server issues. Server issues are persisted unless
|
|
26
|
+
* a client-issue exists for the same path, in which case the client-issue overrides it.
|
|
27
|
+
* @param {FormData} form_data
|
|
28
|
+
* @param {InternalRemoteFormIssue[]} current_issues
|
|
29
|
+
* @param {InternalRemoteFormIssue[]} client_issues
|
|
30
|
+
* @returns {InternalRemoteFormIssue[]}
|
|
29
31
|
*/
|
|
30
|
-
function merge_with_server_issues(current_issues, client_issues) {
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
32
|
+
function merge_with_server_issues(form_data, current_issues, client_issues) {
|
|
33
|
+
const merged = [
|
|
34
|
+
...current_issues.filter(
|
|
35
|
+
(issue) => issue.server && !client_issues.some((i) => i.name === issue.name)
|
|
36
|
+
),
|
|
37
|
+
...client_issues
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
const keys = Array.from(form_data.keys());
|
|
40
41
|
|
|
41
|
-
return
|
|
42
|
+
return merged.sort((a, b) => keys.indexOf(a.name) - keys.indexOf(b.name));
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
/**
|
|
@@ -58,27 +59,14 @@ export function form(id) {
|
|
|
58
59
|
const action = '?/remote=' + encodeURIComponent(action_id);
|
|
59
60
|
|
|
60
61
|
/**
|
|
61
|
-
* By making this $state.raw() and creating a new object each time we update it,
|
|
62
|
-
* all consumers along the update chain are properly invalidated.
|
|
63
62
|
* @type {Record<string, string | string[] | File | File[]>}
|
|
64
63
|
*/
|
|
65
|
-
let input = $state
|
|
64
|
+
let input = $state({});
|
|
66
65
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
* This allows us to update individual fields granularly
|
|
70
|
-
* @type {Record<string, number>}
|
|
71
|
-
*/
|
|
72
|
-
const versions = $state({});
|
|
66
|
+
/** @type {InternalRemoteFormIssue[]} */
|
|
67
|
+
let raw_issues = $state.raw([]);
|
|
73
68
|
|
|
74
|
-
|
|
75
|
-
* This ensures that `{field.value()}` is updated even if the version hasn't been initialized
|
|
76
|
-
* @type {Set<string>}
|
|
77
|
-
*/
|
|
78
|
-
const version_reads = new Set();
|
|
79
|
-
|
|
80
|
-
/** @type {Record<string, InternalRemoteFormIssue[]>} */
|
|
81
|
-
let issues = $state.raw({});
|
|
69
|
+
const issues = $derived(flatten_issues(raw_issues));
|
|
82
70
|
|
|
83
71
|
/** @type {any} */
|
|
84
72
|
let result = $state.raw(remote_responses[action_id]);
|
|
@@ -97,16 +85,6 @@ export function form(id) {
|
|
|
97
85
|
|
|
98
86
|
let submitted = false;
|
|
99
87
|
|
|
100
|
-
function update_all_versions() {
|
|
101
|
-
for (const path of version_reads) {
|
|
102
|
-
versions[path] ??= 0;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
for (const key of Object.keys(versions)) {
|
|
106
|
-
versions[key] += 1;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
88
|
/**
|
|
111
89
|
* @param {FormData} form_data
|
|
112
90
|
* @returns {Record<string, any>}
|
|
@@ -132,8 +110,11 @@ export function form(id) {
|
|
|
132
110
|
const validated = await preflight_schema?.['~standard'].validate(data);
|
|
133
111
|
|
|
134
112
|
if (validated?.issues) {
|
|
135
|
-
|
|
136
|
-
|
|
113
|
+
raw_issues = merge_with_server_issues(
|
|
114
|
+
form_data,
|
|
115
|
+
raw_issues,
|
|
116
|
+
validated.issues.map((issue) => normalize_issue(issue, false))
|
|
117
|
+
);
|
|
137
118
|
return;
|
|
138
119
|
}
|
|
139
120
|
|
|
@@ -223,20 +204,11 @@ export function form(id) {
|
|
|
223
204
|
const form_result = /** @type { RemoteFunctionResponse} */ (await response.json());
|
|
224
205
|
|
|
225
206
|
if (form_result.type === 'result') {
|
|
226
|
-
({ issues =
|
|
227
|
-
|
|
228
|
-
// Mark server issues with server: true
|
|
229
|
-
for (const issue_list of Object.values(issues)) {
|
|
230
|
-
for (const issue of issue_list) {
|
|
231
|
-
issue.server = true;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
207
|
+
({ issues: raw_issues = [], result } = devalue.parse(form_result.result, app.decoders));
|
|
234
208
|
|
|
235
209
|
if (issues.$) {
|
|
236
210
|
release_overrides(updates);
|
|
237
211
|
} else {
|
|
238
|
-
update_all_versions();
|
|
239
|
-
|
|
240
212
|
if (form_result.refreshes) {
|
|
241
213
|
refresh_queries(form_result.refreshes, updates);
|
|
242
214
|
} else {
|
|
@@ -386,7 +358,7 @@ export function form(id) {
|
|
|
386
358
|
}
|
|
387
359
|
}
|
|
388
360
|
|
|
389
|
-
|
|
361
|
+
set_nested_value(input, name, value);
|
|
390
362
|
} else if (is_file) {
|
|
391
363
|
if (DEV && element.multiple) {
|
|
392
364
|
throw new Error(
|
|
@@ -397,7 +369,7 @@ export function form(id) {
|
|
|
397
369
|
const file = /** @type {HTMLInputElement & { files: FileList }} */ (element).files[0];
|
|
398
370
|
|
|
399
371
|
if (file) {
|
|
400
|
-
|
|
372
|
+
set_nested_value(input, name, file);
|
|
401
373
|
} else {
|
|
402
374
|
// Remove the property by setting to undefined and clean up
|
|
403
375
|
const path_parts = name.split(/\.|\[|\]/).filter(Boolean);
|
|
@@ -409,7 +381,7 @@ export function form(id) {
|
|
|
409
381
|
delete current[path_parts[path_parts.length - 1]];
|
|
410
382
|
}
|
|
411
383
|
} else {
|
|
412
|
-
|
|
384
|
+
set_nested_value(
|
|
413
385
|
input,
|
|
414
386
|
name,
|
|
415
387
|
element.type === 'checkbox' && !element.checked ? null : element.value
|
|
@@ -418,17 +390,7 @@ export function form(id) {
|
|
|
418
390
|
|
|
419
391
|
name = name.replace(/^[nb]:/, '');
|
|
420
392
|
|
|
421
|
-
|
|
422
|
-
versions[name] += 1;
|
|
423
|
-
|
|
424
|
-
const path = split_path(name);
|
|
425
|
-
|
|
426
|
-
while (path.pop() !== undefined) {
|
|
427
|
-
const name = build_path_string(path);
|
|
428
|
-
|
|
429
|
-
versions[name] ??= 0;
|
|
430
|
-
versions[name] += 1;
|
|
431
|
-
}
|
|
393
|
+
touched[name] = true;
|
|
432
394
|
});
|
|
433
395
|
|
|
434
396
|
form.addEventListener('reset', async () => {
|
|
@@ -437,7 +399,6 @@ export function form(id) {
|
|
|
437
399
|
await tick();
|
|
438
400
|
|
|
439
401
|
input = convert_formdata(new FormData(form));
|
|
440
|
-
update_all_versions();
|
|
441
402
|
});
|
|
442
403
|
|
|
443
404
|
return () => {
|
|
@@ -530,28 +491,14 @@ export function form(id) {
|
|
|
530
491
|
create_field_proxy(
|
|
531
492
|
{},
|
|
532
493
|
() => input,
|
|
533
|
-
(path) => {
|
|
534
|
-
version_reads.add(path);
|
|
535
|
-
versions[path];
|
|
536
|
-
},
|
|
537
494
|
(path, value) => {
|
|
538
495
|
if (path.length === 0) {
|
|
539
496
|
input = value;
|
|
540
|
-
update_all_versions();
|
|
541
497
|
} else {
|
|
542
|
-
|
|
498
|
+
deep_set(input, path.map(String), value);
|
|
543
499
|
|
|
544
500
|
const key = build_path_string(path);
|
|
545
|
-
versions[key] ??= 0;
|
|
546
|
-
versions[key] += 1;
|
|
547
501
|
touched[key] = true;
|
|
548
|
-
|
|
549
|
-
const parent_path = path.slice();
|
|
550
|
-
while (parent_path.pop() !== undefined) {
|
|
551
|
-
const parent_key = build_path_string(parent_path);
|
|
552
|
-
versions[parent_key] ??= 0;
|
|
553
|
-
versions[parent_key] += 1;
|
|
554
|
-
}
|
|
555
502
|
}
|
|
556
503
|
},
|
|
557
504
|
() => issues
|
|
@@ -572,7 +519,7 @@ export function form(id) {
|
|
|
572
519
|
},
|
|
573
520
|
validate: {
|
|
574
521
|
/** @type {RemoteForm<any, any>['validate']} */
|
|
575
|
-
value: async ({ includeUntouched = false, submitter } = {}) => {
|
|
522
|
+
value: async ({ includeUntouched = false, preflightOnly = false, submitter } = {}) => {
|
|
576
523
|
if (!element) return;
|
|
577
524
|
|
|
578
525
|
const id = ++validate_id;
|
|
@@ -582,7 +529,7 @@ export function form(id) {
|
|
|
582
529
|
|
|
583
530
|
const form_data = new FormData(element, submitter);
|
|
584
531
|
|
|
585
|
-
/** @type {
|
|
532
|
+
/** @type {InternalRemoteFormIssue[]} */
|
|
586
533
|
let array = [];
|
|
587
534
|
|
|
588
535
|
const validated = await preflight_schema?.['~standard'].validate(convert(form_data));
|
|
@@ -592,8 +539,8 @@ export function form(id) {
|
|
|
592
539
|
}
|
|
593
540
|
|
|
594
541
|
if (validated?.issues) {
|
|
595
|
-
array = validated.issues;
|
|
596
|
-
} else {
|
|
542
|
+
array = validated.issues.map((issue) => normalize_issue(issue, false));
|
|
543
|
+
} else if (!preflightOnly) {
|
|
597
544
|
form_data.set('sveltekit:validate_only', 'true');
|
|
598
545
|
|
|
599
546
|
const response = await fetch(`${base}/${app_dir}/remote/${action_id}`, {
|
|
@@ -608,36 +555,21 @@ export function form(id) {
|
|
|
608
555
|
}
|
|
609
556
|
|
|
610
557
|
if (result.type === 'result') {
|
|
611
|
-
array = /** @type {
|
|
558
|
+
array = /** @type {InternalRemoteFormIssue[]} */ (
|
|
612
559
|
devalue.parse(result.result, app.decoders)
|
|
613
560
|
);
|
|
614
561
|
}
|
|
615
562
|
}
|
|
616
563
|
|
|
617
564
|
if (!includeUntouched && !submitted) {
|
|
618
|
-
array = array.filter((issue) =>
|
|
619
|
-
if (issue.path !== undefined) {
|
|
620
|
-
let path = '';
|
|
621
|
-
|
|
622
|
-
for (const segment of issue.path) {
|
|
623
|
-
const key = typeof segment === 'object' ? segment.key : segment;
|
|
624
|
-
|
|
625
|
-
if (typeof key === 'number') {
|
|
626
|
-
path += `[${key}]`;
|
|
627
|
-
} else if (typeof key === 'string') {
|
|
628
|
-
path += path === '' ? key : '.' + key;
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
return touched[path];
|
|
633
|
-
}
|
|
634
|
-
});
|
|
565
|
+
array = array.filter((issue) => touched[issue.name]);
|
|
635
566
|
}
|
|
636
567
|
|
|
637
|
-
const is_server_validation = !validated?.issues;
|
|
638
|
-
const new_issues = flatten_issues(array, is_server_validation);
|
|
568
|
+
const is_server_validation = !validated?.issues && !preflightOnly;
|
|
639
569
|
|
|
640
|
-
|
|
570
|
+
raw_issues = is_server_validation
|
|
571
|
+
? array
|
|
572
|
+
: merge_with_server_issues(form_data, raw_issues, array);
|
|
641
573
|
}
|
|
642
574
|
},
|
|
643
575
|
enhance: {
|
|
@@ -3,12 +3,9 @@
|
|
|
3
3
|
/** @import { StandardSchemaV1 } from '@standard-schema/spec' */
|
|
4
4
|
|
|
5
5
|
import { DEV } from 'esm-env';
|
|
6
|
-
import * as svelte from 'svelte';
|
|
7
|
-
// Svelte 4 and under don't have `untrack` - you'll not be able to use remote functions with Svelte 4 but this will still be loaded
|
|
8
|
-
const untrack = svelte.untrack ?? ((value) => value());
|
|
9
6
|
|
|
10
7
|
/**
|
|
11
|
-
* Sets a value in a nested object using a path string,
|
|
8
|
+
* Sets a value in a nested object using a path string, mutating the original object
|
|
12
9
|
* @param {Record<string, any>} object
|
|
13
10
|
* @param {string} path_string
|
|
14
11
|
* @param {any} value
|
|
@@ -22,7 +19,7 @@ export function set_nested_value(object, path_string, value) {
|
|
|
22
19
|
value = value === 'on';
|
|
23
20
|
}
|
|
24
21
|
|
|
25
|
-
|
|
22
|
+
deep_set(object, split_path(path_string), value);
|
|
26
23
|
}
|
|
27
24
|
|
|
28
25
|
/**
|
|
@@ -31,7 +28,7 @@ export function set_nested_value(object, path_string, value) {
|
|
|
31
28
|
*/
|
|
32
29
|
export function convert_formdata(data) {
|
|
33
30
|
/** @type {Record<string, any>} */
|
|
34
|
-
|
|
31
|
+
const result = {};
|
|
35
32
|
|
|
36
33
|
for (let key of data.keys()) {
|
|
37
34
|
if (key.startsWith('sveltekit:')) {
|
|
@@ -61,7 +58,7 @@ export function convert_formdata(data) {
|
|
|
61
58
|
values = values.map((v) => v === 'on');
|
|
62
59
|
}
|
|
63
60
|
|
|
64
|
-
|
|
61
|
+
set_nested_value(result, key, is_array ? values : values[0]);
|
|
65
62
|
}
|
|
66
63
|
|
|
67
64
|
return result;
|
|
@@ -81,18 +78,32 @@ export function split_path(path) {
|
|
|
81
78
|
}
|
|
82
79
|
|
|
83
80
|
/**
|
|
84
|
-
*
|
|
85
|
-
*
|
|
81
|
+
* Check if a property key is dangerous and could lead to prototype pollution
|
|
82
|
+
* @param {string} key
|
|
83
|
+
*/
|
|
84
|
+
function check_prototype_pollution(key) {
|
|
85
|
+
if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
|
|
86
|
+
throw new Error(
|
|
87
|
+
`Invalid key "${key}"` +
|
|
88
|
+
(DEV ? ': This key is not allowed to prevent prototype pollution.' : '')
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Sets a value in a nested object using an array of keys, mutating the original object.
|
|
86
95
|
* @param {Record<string, any>} object
|
|
87
96
|
* @param {string[]} keys
|
|
88
97
|
* @param {any} value
|
|
89
98
|
*/
|
|
90
99
|
export function deep_set(object, keys, value) {
|
|
91
|
-
|
|
92
|
-
let current = result;
|
|
100
|
+
let current = object;
|
|
93
101
|
|
|
94
102
|
for (let i = 0; i < keys.length - 1; i += 1) {
|
|
95
103
|
const key = keys[i];
|
|
104
|
+
|
|
105
|
+
check_prototype_pollution(key);
|
|
106
|
+
|
|
96
107
|
const is_array = /^\d+$/.test(keys[i + 1]);
|
|
97
108
|
const exists = key in current;
|
|
98
109
|
const inner = current[key];
|
|
@@ -101,54 +112,71 @@ export function deep_set(object, keys, value) {
|
|
|
101
112
|
throw new Error(`Invalid array key ${keys[i + 1]}`);
|
|
102
113
|
}
|
|
103
114
|
|
|
104
|
-
|
|
105
|
-
?
|
|
106
|
-
|
|
107
|
-
: []
|
|
108
|
-
: // guard against prototype pollution
|
|
109
|
-
Object.assign(Object.create(null), inner);
|
|
115
|
+
if (!exists) {
|
|
116
|
+
current[key] = is_array ? [] : {};
|
|
117
|
+
}
|
|
110
118
|
|
|
111
119
|
current = current[key];
|
|
112
120
|
}
|
|
113
121
|
|
|
114
|
-
|
|
115
|
-
|
|
122
|
+
const final_key = keys[keys.length - 1];
|
|
123
|
+
check_prototype_pollution(final_key);
|
|
124
|
+
current[final_key] = value;
|
|
116
125
|
}
|
|
117
126
|
|
|
118
127
|
/**
|
|
119
|
-
* @param {
|
|
120
|
-
* @param {boolean}
|
|
128
|
+
* @param {StandardSchemaV1.Issue} issue
|
|
129
|
+
* @param {boolean} server Whether this issue came from server validation
|
|
121
130
|
*/
|
|
122
|
-
export function
|
|
131
|
+
export function normalize_issue(issue, server = false) {
|
|
132
|
+
/** @type {InternalRemoteFormIssue} */
|
|
133
|
+
const normalized = { name: '', path: [], message: issue.message, server };
|
|
134
|
+
|
|
135
|
+
if (issue.path !== undefined) {
|
|
136
|
+
let name = '';
|
|
137
|
+
|
|
138
|
+
for (const segment of issue.path) {
|
|
139
|
+
const key = /** @type {string | number} */ (
|
|
140
|
+
typeof segment === 'object' ? segment.key : segment
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
normalized.path.push(key);
|
|
144
|
+
|
|
145
|
+
if (typeof key === 'number') {
|
|
146
|
+
name += `[${key}]`;
|
|
147
|
+
} else if (typeof key === 'string') {
|
|
148
|
+
name += name === '' ? key : '.' + key;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
normalized.name = name;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return normalized;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* @param {InternalRemoteFormIssue[]} issues
|
|
160
|
+
*/
|
|
161
|
+
export function flatten_issues(issues) {
|
|
123
162
|
/** @type {Record<string, InternalRemoteFormIssue[]>} */
|
|
124
163
|
const result = {};
|
|
125
164
|
|
|
126
165
|
for (const issue of issues) {
|
|
127
|
-
|
|
128
|
-
const normalized = { name: '', path: [], message: issue.message, server };
|
|
129
|
-
|
|
130
|
-
(result.$ ??= []).push(normalized);
|
|
166
|
+
(result.$ ??= []).push(issue);
|
|
131
167
|
|
|
132
168
|
let name = '';
|
|
133
169
|
|
|
134
170
|
if (issue.path !== undefined) {
|
|
135
|
-
for (const
|
|
136
|
-
const key = /** @type {string | number} */ (
|
|
137
|
-
typeof segment === 'object' ? segment.key : segment
|
|
138
|
-
);
|
|
139
|
-
|
|
140
|
-
normalized.path.push(key);
|
|
141
|
-
|
|
171
|
+
for (const key of issue.path) {
|
|
142
172
|
if (typeof key === 'number') {
|
|
143
173
|
name += `[${key}]`;
|
|
144
174
|
} else if (typeof key === 'string') {
|
|
145
175
|
name += name === '' ? key : '.' + key;
|
|
146
176
|
}
|
|
147
177
|
|
|
148
|
-
(result[name] ??= []).push(
|
|
178
|
+
(result[name] ??= []).push(issue);
|
|
149
179
|
}
|
|
150
|
-
|
|
151
|
-
normalized.name = name;
|
|
152
180
|
}
|
|
153
181
|
}
|
|
154
182
|
|
|
@@ -177,18 +205,14 @@ export function deep_get(object, path) {
|
|
|
177
205
|
* Creates a proxy-based field accessor for form data
|
|
178
206
|
* @param {any} target - Function or empty POJO
|
|
179
207
|
* @param {() => Record<string, any>} get_input - Function to get current input data
|
|
180
|
-
* @param {(path: string) => void} depend - Function to make an effect depend on a specific field
|
|
181
208
|
* @param {(path: (string | number)[], value: any) => void} set_input - Function to set input data
|
|
182
209
|
* @param {() => Record<string, InternalRemoteFormIssue[]>} get_issues - Function to get current issues
|
|
183
210
|
* @param {(string | number)[]} path - Current access path
|
|
184
211
|
* @returns {any} Proxy object with name(), value(), and issues() methods
|
|
185
212
|
*/
|
|
186
|
-
export function create_field_proxy(target, get_input,
|
|
187
|
-
const path_string = build_path_string(path);
|
|
188
|
-
|
|
213
|
+
export function create_field_proxy(target, get_input, set_input, get_issues, path = []) {
|
|
189
214
|
const get_value = () => {
|
|
190
|
-
|
|
191
|
-
return untrack(() => deep_get(get_input(), path));
|
|
215
|
+
return deep_get(get_input(), path);
|
|
192
216
|
};
|
|
193
217
|
|
|
194
218
|
return new Proxy(target, {
|
|
@@ -197,7 +221,7 @@ export function create_field_proxy(target, get_input, depend, set_input, get_iss
|
|
|
197
221
|
|
|
198
222
|
// Handle array access like jobs[0]
|
|
199
223
|
if (/^\d+$/.test(prop)) {
|
|
200
|
-
return create_field_proxy({}, get_input,
|
|
224
|
+
return create_field_proxy({}, get_input, set_input, get_issues, [
|
|
201
225
|
...path,
|
|
202
226
|
parseInt(prop, 10)
|
|
203
227
|
]);
|
|
@@ -210,17 +234,11 @@ export function create_field_proxy(target, get_input, depend, set_input, get_iss
|
|
|
210
234
|
set_input(path, newValue);
|
|
211
235
|
return newValue;
|
|
212
236
|
};
|
|
213
|
-
return create_field_proxy(set_func, get_input,
|
|
214
|
-
...path,
|
|
215
|
-
prop
|
|
216
|
-
]);
|
|
237
|
+
return create_field_proxy(set_func, get_input, set_input, get_issues, [...path, prop]);
|
|
217
238
|
}
|
|
218
239
|
|
|
219
240
|
if (prop === 'value') {
|
|
220
|
-
return create_field_proxy(get_value, get_input,
|
|
221
|
-
...path,
|
|
222
|
-
prop
|
|
223
|
-
]);
|
|
241
|
+
return create_field_proxy(get_value, get_input, set_input, get_issues, [...path, prop]);
|
|
224
242
|
}
|
|
225
243
|
|
|
226
244
|
if (prop === 'issues' || prop === 'allIssues') {
|
|
@@ -240,10 +258,7 @@ export function create_field_proxy(target, get_input, depend, set_input, get_iss
|
|
|
240
258
|
}));
|
|
241
259
|
};
|
|
242
260
|
|
|
243
|
-
return create_field_proxy(issues_func, get_input,
|
|
244
|
-
...path,
|
|
245
|
-
prop
|
|
246
|
-
]);
|
|
261
|
+
return create_field_proxy(issues_func, get_input, set_input, get_issues, [...path, prop]);
|
|
247
262
|
}
|
|
248
263
|
|
|
249
264
|
if (prop === 'as') {
|
|
@@ -392,14 +407,11 @@ export function create_field_proxy(target, get_input, depend, set_input, get_iss
|
|
|
392
407
|
});
|
|
393
408
|
};
|
|
394
409
|
|
|
395
|
-
return create_field_proxy(as_func, get_input,
|
|
396
|
-
...path,
|
|
397
|
-
'as'
|
|
398
|
-
]);
|
|
410
|
+
return create_field_proxy(as_func, get_input, set_input, get_issues, [...path, 'as']);
|
|
399
411
|
}
|
|
400
412
|
|
|
401
413
|
// Handle property access (nested fields)
|
|
402
|
-
return create_field_proxy({}, get_input,
|
|
414
|
+
return create_field_proxy({}, get_input, set_input, get_issues, [...path, prop]);
|
|
403
415
|
}
|
|
404
416
|
});
|
|
405
417
|
}
|
|
@@ -227,7 +227,6 @@ export async function render_response({
|
|
|
227
227
|
paths.reset();
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
-
// eslint-disable-next-line
|
|
231
230
|
const { head, html, css } = options.async ? await rendered : rendered;
|
|
232
231
|
|
|
233
232
|
return { head, html, css };
|
|
@@ -654,7 +653,7 @@ export async function render_response({
|
|
|
654
653
|
async start(controller) {
|
|
655
654
|
controller.enqueue(text_encoder.encode(transformed + '\n'));
|
|
656
655
|
for await (const chunk of chunks) {
|
|
657
|
-
controller.enqueue(text_encoder.encode(chunk));
|
|
656
|
+
if (chunk.length) controller.enqueue(text_encoder.encode(chunk));
|
|
658
657
|
}
|
|
659
658
|
controller.close();
|
|
660
659
|
},
|
|
@@ -13,6 +13,16 @@ declare global {
|
|
|
13
13
|
const __SVELTEKIT_EXPERIMENTAL__REMOTE_FUNCTIONS__: boolean;
|
|
14
14
|
/** True if `config.kit.router.resolution === 'client'` */
|
|
15
15
|
const __SVELTEKIT_CLIENT_ROUTING__: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* True if any node in the manifest has a server load function.
|
|
18
|
+
* Used for treeshaking server load code from client bundles when no server loads exist.
|
|
19
|
+
*/
|
|
20
|
+
const __SVELTEKIT_HAS_SERVER_LOAD__: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* True if any node in the manifest has a universal load function.
|
|
23
|
+
* Used for treeshaking universal load code from client bundles when no universal loads exist.
|
|
24
|
+
*/
|
|
25
|
+
const __SVELTEKIT_HAS_UNIVERSAL_LOAD__: boolean;
|
|
16
26
|
/** The `__sveltekit_abc123` object in the init `<script>` */
|
|
17
27
|
const __SVELTEKIT_PAYLOAD__: {
|
|
18
28
|
/** The basepath, usually relative to the current page */
|
package/src/types/internal.d.ts
CHANGED
|
@@ -370,6 +370,7 @@ export interface ServerMetadata {
|
|
|
370
370
|
nodes: Array<{
|
|
371
371
|
/** Also `true` when using `trailingSlash`, because we need to do a server request in that case to get its value. */
|
|
372
372
|
has_server_load: boolean;
|
|
373
|
+
has_universal_load: boolean;
|
|
373
374
|
}>;
|
|
374
375
|
routes: Map<string, ServerMetadataRoute>;
|
|
375
376
|
/** For each hashed remote file, a map of export name -> { type, dynamic }, where `dynamic` is `false` for non-dynamic prerender functions */
|
|
@@ -395,6 +396,7 @@ export interface SSRComponent {
|
|
|
395
396
|
export type SSRComponentLoader = () => Promise<SSRComponent>;
|
|
396
397
|
|
|
397
398
|
export interface UniversalNode {
|
|
399
|
+
/** Is `null` in case static analysis succeeds but the node is ssr=false */
|
|
398
400
|
load?: Load;
|
|
399
401
|
prerender?: PrerenderOption;
|
|
400
402
|
ssr?: boolean;
|
package/src/utils/streaming.js
CHANGED
|
@@ -1,18 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* @returns {import('types').Deferred & { promise: Promise<any> }}}
|
|
3
|
-
*/
|
|
4
|
-
function defer() {
|
|
5
|
-
let fulfil;
|
|
6
|
-
let reject;
|
|
7
|
-
|
|
8
|
-
const promise = new Promise((f, r) => {
|
|
9
|
-
fulfil = f;
|
|
10
|
-
reject = r;
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
// @ts-expect-error
|
|
14
|
-
return { promise, fulfil, reject };
|
|
15
|
-
}
|
|
1
|
+
import { with_resolvers } from './promise.js';
|
|
16
2
|
|
|
17
3
|
/**
|
|
18
4
|
* Create an async iterator and a function to push values into it
|
|
@@ -23,9 +9,11 @@ function defer() {
|
|
|
23
9
|
* }}
|
|
24
10
|
*/
|
|
25
11
|
export function create_async_iterator() {
|
|
26
|
-
let
|
|
12
|
+
let resolved = -1;
|
|
13
|
+
let returned = -1;
|
|
27
14
|
|
|
28
|
-
|
|
15
|
+
/** @type {import('./promise.js').PromiseWithResolvers<T>[]} */
|
|
16
|
+
const deferred = [];
|
|
29
17
|
|
|
30
18
|
return {
|
|
31
19
|
iterate: (transform = (x) => x) => {
|
|
@@ -33,32 +21,20 @@ export function create_async_iterator() {
|
|
|
33
21
|
[Symbol.asyncIterator]() {
|
|
34
22
|
return {
|
|
35
23
|
next: async () => {
|
|
36
|
-
const next =
|
|
24
|
+
const next = deferred[++returned];
|
|
25
|
+
if (!next) return { value: null, done: true };
|
|
37
26
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return { value: transform(next.value), done: false };
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return next;
|
|
27
|
+
const value = await next.promise;
|
|
28
|
+
return { value: transform(value), done: false };
|
|
44
29
|
}
|
|
45
30
|
};
|
|
46
31
|
}
|
|
47
32
|
};
|
|
48
33
|
},
|
|
49
34
|
add: (promise) => {
|
|
50
|
-
|
|
51
|
-
|
|
35
|
+
deferred.push(with_resolvers());
|
|
52
36
|
void promise.then((value) => {
|
|
53
|
-
deferred[
|
|
54
|
-
value,
|
|
55
|
-
done: false
|
|
56
|
-
});
|
|
57
|
-
deferred.push(defer());
|
|
58
|
-
|
|
59
|
-
if (--count === 0) {
|
|
60
|
-
deferred[deferred.length - 1].fulfil({ done: true });
|
|
61
|
-
}
|
|
37
|
+
deferred[++resolved].resolve(value);
|
|
62
38
|
});
|
|
63
39
|
}
|
|
64
40
|
};
|
package/src/version.js
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -1890,10 +1890,28 @@ declare module '@sveltejs/kit' {
|
|
|
1890
1890
|
allIssues(): RemoteFormIssue[] | undefined;
|
|
1891
1891
|
};
|
|
1892
1892
|
|
|
1893
|
+
type UnknownField<Value> = RemoteFormFieldMethods<Value> & {
|
|
1894
|
+
/** Validation issues belonging to this or any of the fields that belong to it, if any */
|
|
1895
|
+
allIssues(): RemoteFormIssue[] | undefined;
|
|
1896
|
+
/**
|
|
1897
|
+
* Returns an object that can be spread onto an input element with the correct type attribute,
|
|
1898
|
+
* aria-invalid attribute if the field is invalid, and appropriate value/checked property getters/setters.
|
|
1899
|
+
* @example
|
|
1900
|
+
* ```svelte
|
|
1901
|
+
* <input {...myForm.fields.myString.as('text')} />
|
|
1902
|
+
* <input {...myForm.fields.myNumber.as('number')} />
|
|
1903
|
+
* <input {...myForm.fields.myBoolean.as('checkbox')} />
|
|
1904
|
+
* ```
|
|
1905
|
+
*/
|
|
1906
|
+
as<T extends RemoteFormFieldType<Value>>(...args: AsArgs<T, Value>): InputElementProps<T>;
|
|
1907
|
+
} & {
|
|
1908
|
+
[key: string | number]: UnknownField<any>;
|
|
1909
|
+
};
|
|
1910
|
+
|
|
1893
1911
|
/**
|
|
1894
1912
|
* Recursive type to build form fields structure with proxy access
|
|
1895
1913
|
*/
|
|
1896
|
-
type RemoteFormFields<T> =
|
|
1914
|
+
export type RemoteFormFields<T> =
|
|
1897
1915
|
WillRecurseIndefinitely<T> extends true
|
|
1898
1916
|
? RecursiveFormFields
|
|
1899
1917
|
: NonNullable<T> extends string | number | boolean | File
|
|
@@ -1901,11 +1919,17 @@ declare module '@sveltejs/kit' {
|
|
|
1901
1919
|
: T extends string[] | File[]
|
|
1902
1920
|
? RemoteFormField<T> & { [K in number]: RemoteFormField<T[number]> }
|
|
1903
1921
|
: T extends Array<infer U>
|
|
1904
|
-
? RemoteFormFieldContainer<T> & {
|
|
1905
|
-
|
|
1922
|
+
? RemoteFormFieldContainer<T> & {
|
|
1923
|
+
[K in number]: RemoteFormFields<U>;
|
|
1924
|
+
}
|
|
1925
|
+
: RemoteFormFieldContainer<T> & {
|
|
1926
|
+
[K in keyof T]-?: RemoteFormFields<T[K]>;
|
|
1927
|
+
};
|
|
1906
1928
|
|
|
1907
1929
|
// By breaking this out into its own type, we avoid the TS recursion depth limit
|
|
1908
|
-
type RecursiveFormFields =
|
|
1930
|
+
type RecursiveFormFields = RemoteFormFieldContainer<any> & {
|
|
1931
|
+
[key: string | number]: UnknownField<any>;
|
|
1932
|
+
};
|
|
1909
1933
|
|
|
1910
1934
|
type MaybeArray<T> = T | T[];
|
|
1911
1935
|
|
|
@@ -1997,7 +2021,10 @@ declare module '@sveltejs/kit' {
|
|
|
1997
2021
|
preflight(schema: StandardSchemaV1<Input, any>): RemoteForm<Input, Output>;
|
|
1998
2022
|
/** Validate the form contents programmatically */
|
|
1999
2023
|
validate(options?: {
|
|
2024
|
+
/** Set this to `true` to also show validation issues of fields that haven't been touched yet. */
|
|
2000
2025
|
includeUntouched?: boolean;
|
|
2026
|
+
/** Set this to `true` to only run the `preflight` validation. */
|
|
2027
|
+
preflightOnly?: boolean;
|
|
2001
2028
|
/** Perform validation as if the form was submitted by the given button. */
|
|
2002
2029
|
submitter?: HTMLButtonElement | HTMLInputElement;
|
|
2003
2030
|
}): Promise<void>;
|
|
@@ -2488,6 +2515,7 @@ declare module '@sveltejs/kit' {
|
|
|
2488
2515
|
type SSRComponentLoader = () => Promise<SSRComponent>;
|
|
2489
2516
|
|
|
2490
2517
|
interface UniversalNode {
|
|
2518
|
+
/** Is `null` in case static analysis succeeds but the node is ssr=false */
|
|
2491
2519
|
load?: Load;
|
|
2492
2520
|
prerender?: PrerenderOption;
|
|
2493
2521
|
ssr?: boolean;
|
|
@@ -3158,7 +3186,7 @@ declare module '$app/server' {
|
|
|
3158
3186
|
*
|
|
3159
3187
|
* @since 2.27
|
|
3160
3188
|
*/
|
|
3161
|
-
export function form<Schema extends StandardSchemaV1<RemoteFormInput, Record<string, any>>, Output>(validate: Schema, fn: (data: StandardSchemaV1.InferOutput<Schema>, invalid: import("@sveltejs/kit").Invalid<StandardSchemaV1.
|
|
3189
|
+
export function form<Schema extends StandardSchemaV1<RemoteFormInput, Record<string, any>>, Output>(validate: Schema, fn: (data: StandardSchemaV1.InferOutput<Schema>, invalid: import("@sveltejs/kit").Invalid<StandardSchemaV1.InferInput<Schema>>) => MaybePromise<Output>): RemoteForm<StandardSchemaV1.InferInput<Schema>, Output>;
|
|
3162
3190
|
/**
|
|
3163
3191
|
* Creates a remote prerender function. When called from the browser, the function will be invoked on the server via a `fetch` call.
|
|
3164
3192
|
*
|
package/types/index.d.ts.map
CHANGED
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
"AsArgs",
|
|
67
67
|
"RemoteFormField",
|
|
68
68
|
"RemoteFormFieldContainer",
|
|
69
|
+
"UnknownField",
|
|
69
70
|
"RemoteFormFields",
|
|
70
71
|
"RecursiveFormFields",
|
|
71
72
|
"MaybeArray",
|
|
@@ -211,6 +212,6 @@
|
|
|
211
212
|
null,
|
|
212
213
|
null
|
|
213
214
|
],
|
|
214
|
-
"mappings": "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
|
|
215
|
+
"mappings": "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",
|
|
215
216
|
"ignoreList": []
|
|
216
217
|
}
|