@sveltejs/kit 2.60.1 → 2.61.1
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 +8 -9
- package/src/core/postbuild/analyse.js +1 -3
- package/src/core/sync/create_manifest_data/conflict.js +72 -0
- package/src/core/sync/create_manifest_data/index.js +1 -65
- package/src/core/sync/write_non_ambient.js +2 -2
- package/src/core/sync/write_types/index.js +1 -1
- package/src/exports/public.d.ts +23 -30
- package/src/exports/vite/build/build_server.js +36 -13
- package/src/exports/vite/dev/index.js +4 -2
- package/src/exports/vite/index.js +18 -16
- package/src/runtime/app/server/index.js +1 -2
- package/src/runtime/app/server/remote/form.js +10 -0
- package/src/runtime/app/server/remote/query.js +100 -36
- package/src/runtime/client/client.js +13 -8
- package/src/runtime/client/remote-functions/cache.svelte.js +157 -0
- package/src/runtime/client/remote-functions/form.svelte.js +235 -196
- package/src/runtime/client/remote-functions/index.js +2 -2
- package/src/runtime/client/remote-functions/prerender.svelte.js +1 -2
- package/src/runtime/client/remote-functions/query/cache.js +4 -0
- package/src/runtime/client/remote-functions/query/index.js +48 -0
- package/src/runtime/client/remote-functions/query/instance.svelte.js +249 -0
- package/src/runtime/client/remote-functions/query/proxy.js +156 -0
- package/src/runtime/client/remote-functions/query-batch.svelte.js +1 -1
- package/src/runtime/client/remote-functions/query-live/cache.js +4 -0
- package/src/runtime/client/remote-functions/query-live/index.js +31 -0
- package/src/runtime/client/remote-functions/{query-live.svelte.js → query-live/instance.svelte.js} +61 -310
- package/src/runtime/client/remote-functions/query-live/iterator.js +91 -0
- package/src/runtime/client/remote-functions/query-live/proxy.js +144 -0
- package/src/runtime/client/remote-functions/shared.svelte.js +53 -6
- package/src/runtime/client/utils.js +1 -1
- package/src/runtime/form-utils.js +7 -16
- package/src/runtime/server/index.js +2 -3
- package/src/runtime/server/page/actions.js +2 -9
- package/src/runtime/server/page/csp.js +3 -4
- package/src/runtime/server/page/render.js +13 -14
- package/src/runtime/server/respond.js +60 -36
- package/src/runtime/server/utils.js +23 -3
- package/src/types/global-private.d.ts +5 -0
- package/src/types/internal.d.ts +29 -6
- package/src/utils/routing.js +3 -1
- package/src/utils/shared-iterator.js +213 -0
- package/src/version.js +1 -1
- package/types/index.d.ts +27 -31
- package/types/index.d.ts.map +1 -1
- package/src/runtime/client/remote-functions/query.svelte.js +0 -512
|
@@ -79,6 +79,15 @@ export function form(id) {
|
|
|
79
79
|
/** @type {StandardSchemaV1 | undefined} */
|
|
80
80
|
let preflight_schema = undefined;
|
|
81
81
|
|
|
82
|
+
/**
|
|
83
|
+
* @param {Omit<RemoteForm<T, U>, 'enhance' | 'element'> & { readonly element: HTMLFormElement }} instance
|
|
84
|
+
*/
|
|
85
|
+
let enhance_callback = async (instance) => {
|
|
86
|
+
if (await instance.submit()) {
|
|
87
|
+
instance.element.reset();
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
82
91
|
/** @type {HTMLFormElement | null} */
|
|
83
92
|
let element = null;
|
|
84
93
|
|
|
@@ -132,86 +141,11 @@ export function form(id) {
|
|
|
132
141
|
}
|
|
133
142
|
|
|
134
143
|
/**
|
|
135
|
-
* @param {HTMLFormElement} form
|
|
136
144
|
* @param {FormData} form_data
|
|
137
|
-
* @param {
|
|
138
|
-
*/
|
|
139
|
-
async function handle_submit(form, form_data, callback) {
|
|
140
|
-
const data = convert(form_data);
|
|
141
|
-
|
|
142
|
-
submitted = true;
|
|
143
|
-
|
|
144
|
-
// Increment pending count immediately so that `pending` reflects
|
|
145
|
-
// the in-progress state during async preflight validation
|
|
146
|
-
pending_count++;
|
|
147
|
-
|
|
148
|
-
const validated = await preflight_schema?.['~standard'].validate(data);
|
|
149
|
-
|
|
150
|
-
if (validated?.issues) {
|
|
151
|
-
raw_issues = merge_with_server_issues(
|
|
152
|
-
form_data,
|
|
153
|
-
raw_issues,
|
|
154
|
-
validated.issues.map((issue) => normalize_issue(issue, false))
|
|
155
|
-
);
|
|
156
|
-
|
|
157
|
-
if (DEV) {
|
|
158
|
-
warn_on_missing_issue_reads();
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
pending_count--;
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// Preflight passed - clear stale client-side preflight issues
|
|
166
|
-
if (preflight_schema) {
|
|
167
|
-
raw_issues = raw_issues.filter((issue) => issue.server);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// TODO 3.0 remove this warning
|
|
171
|
-
if (DEV) {
|
|
172
|
-
const error = () => {
|
|
173
|
-
throw new Error(
|
|
174
|
-
'Remote form functions no longer get passed a FormData object. The payload is now a POJO. See https://kit.svelte.dev/docs/remote-functions#form for details.'
|
|
175
|
-
);
|
|
176
|
-
};
|
|
177
|
-
for (const key of [
|
|
178
|
-
'append',
|
|
179
|
-
'delete',
|
|
180
|
-
'entries',
|
|
181
|
-
'forEach',
|
|
182
|
-
'get',
|
|
183
|
-
'getAll',
|
|
184
|
-
'has',
|
|
185
|
-
'keys',
|
|
186
|
-
'set',
|
|
187
|
-
'values'
|
|
188
|
-
]) {
|
|
189
|
-
if (!(key in data)) {
|
|
190
|
-
Object.defineProperty(data, key, { get: error });
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
try {
|
|
196
|
-
await callback({
|
|
197
|
-
form,
|
|
198
|
-
data,
|
|
199
|
-
submit: () => submit(form_data)
|
|
200
|
-
});
|
|
201
|
-
} catch (e) {
|
|
202
|
-
const error = e instanceof HttpError ? e.body : { message: /** @type {any} */ (e).message };
|
|
203
|
-
const status = e instanceof HttpError ? e.status : 500;
|
|
204
|
-
void set_nearest_error_page(error, status);
|
|
205
|
-
} finally {
|
|
206
|
-
pending_count--;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* @param {FormData} data
|
|
145
|
+
* @param {boolean} should_preflight
|
|
212
146
|
* @returns {Promise<boolean> & { updates: (...args: any[]) => Promise<boolean> }}
|
|
213
147
|
*/
|
|
214
|
-
function submit(
|
|
148
|
+
function submit(form_data, should_preflight) {
|
|
215
149
|
// Store a reference to the current instance and increment the usage count for the duration
|
|
216
150
|
// of the request. This ensures that the instance is not deleted in case of an optimistic update
|
|
217
151
|
// (e.g. when deleting an item in a list) that fails and wants to surface an error to the user afterwards.
|
|
@@ -239,7 +173,12 @@ export function form(id) {
|
|
|
239
173
|
throw updates_error;
|
|
240
174
|
}
|
|
241
175
|
|
|
242
|
-
|
|
176
|
+
if (should_preflight) {
|
|
177
|
+
const valid = await preflight(form_data);
|
|
178
|
+
if (!valid) return false;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const { blob } = serialize_binary_form(convert(form_data), {
|
|
243
182
|
remote_refreshes: Array.from(refreshes ?? [])
|
|
244
183
|
});
|
|
245
184
|
|
|
@@ -351,16 +290,99 @@ export function form(id) {
|
|
|
351
290
|
return promise;
|
|
352
291
|
}
|
|
353
292
|
|
|
293
|
+
/**
|
|
294
|
+
* @param {HTMLFormElement} form
|
|
295
|
+
* @param {FormData} form_data
|
|
296
|
+
* @returns {Omit<RemoteForm<T, U>, 'enhance' | 'element'> & { readonly element: HTMLFormElement }}
|
|
297
|
+
*/
|
|
298
|
+
function create_enhance_callback_instance(form, form_data) {
|
|
299
|
+
const { enhance: _enhance, ...descriptors } = Object.getOwnPropertyDescriptors(instance);
|
|
300
|
+
void _enhance;
|
|
301
|
+
|
|
302
|
+
return /** @type {Omit<RemoteForm<T, U>, 'enhance' | 'element'> & { readonly element: HTMLFormElement }} */ (
|
|
303
|
+
Object.defineProperties(
|
|
304
|
+
{},
|
|
305
|
+
{
|
|
306
|
+
...descriptors,
|
|
307
|
+
data: {
|
|
308
|
+
get() {
|
|
309
|
+
// TODO 3.0 remove
|
|
310
|
+
throw new Error(
|
|
311
|
+
`The \`data\` property has been removed from the \`enhance\` callback argument. Use \`instance.fields.value()\` instead.`
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
},
|
|
315
|
+
form: {
|
|
316
|
+
get() {
|
|
317
|
+
// TODO 3.0 remove
|
|
318
|
+
throw new Error(
|
|
319
|
+
`The \`form\` property has been removed from the \`enhance\` callback argument. To get the current \`<form>\` element, use \`instance.element\` instead.`
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
},
|
|
323
|
+
element: {
|
|
324
|
+
value: form
|
|
325
|
+
},
|
|
326
|
+
submit: {
|
|
327
|
+
value: () => submit(form_data, false)
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
)
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* @param {FormData} form_data
|
|
336
|
+
*/
|
|
337
|
+
async function preflight(form_data) {
|
|
338
|
+
const data = convert(form_data);
|
|
339
|
+
const validated = await preflight_schema?.['~standard'].validate(data);
|
|
340
|
+
|
|
341
|
+
if (validated?.issues) {
|
|
342
|
+
raw_issues = merge_with_server_issues(
|
|
343
|
+
form_data,
|
|
344
|
+
raw_issues,
|
|
345
|
+
validated.issues.map((issue) => normalize_issue(issue, false))
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
if (DEV) {
|
|
349
|
+
warn_on_missing_issue_reads();
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Preflight passed - clear stale client-side preflight issues
|
|
356
|
+
if (preflight_schema) {
|
|
357
|
+
raw_issues = raw_issues.filter((issue) => issue.server);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
return true;
|
|
361
|
+
}
|
|
362
|
+
|
|
354
363
|
/** @type {RemoteForm<T, U>} */
|
|
355
364
|
const instance = {};
|
|
356
365
|
|
|
357
366
|
instance.method = 'POST';
|
|
358
367
|
instance.action = action;
|
|
359
368
|
|
|
360
|
-
/** @
|
|
361
|
-
|
|
369
|
+
instance[createAttachmentKey()] = (/** @type {HTMLFormElement} */ form) => {
|
|
370
|
+
if (element) {
|
|
371
|
+
let message = `A form object can only be attached to a single \`<form>\` element`;
|
|
372
|
+
if (DEV && !key) {
|
|
373
|
+
const name = id.split('/').pop();
|
|
374
|
+
message += `. To create multiple instances, use \`${name}.for(key)\``;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
throw new Error(message);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
element = form;
|
|
381
|
+
|
|
382
|
+
touched = {};
|
|
383
|
+
|
|
362
384
|
/** @param {SubmitEvent} event */
|
|
363
|
-
|
|
385
|
+
const handle_submit = async (event) => {
|
|
364
386
|
const form = /** @type {HTMLFormElement} */ (event.target);
|
|
365
387
|
const method = event.submitter?.hasAttribute('formmethod')
|
|
366
388
|
? /** @type {HTMLButtonElement | HTMLInputElement} */ (event.submitter).formMethod
|
|
@@ -395,142 +417,129 @@ export function form(id) {
|
|
|
395
417
|
validate_form_data(form_data, clone(form).enctype);
|
|
396
418
|
}
|
|
397
419
|
|
|
398
|
-
|
|
399
|
-
};
|
|
400
|
-
};
|
|
401
|
-
|
|
402
|
-
/** @param {(event: SubmitEvent) => void} onsubmit */
|
|
403
|
-
function create_attachment(onsubmit) {
|
|
404
|
-
return (/** @type {HTMLFormElement} */ form) => {
|
|
405
|
-
if (element) {
|
|
406
|
-
let message = `A form object can only be attached to a single \`<form>\` element`;
|
|
407
|
-
if (DEV && !key) {
|
|
408
|
-
const name = id.split('/').pop();
|
|
409
|
-
message += `. To create multiple instances, use \`${name}.for(key)\``;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
throw new Error(message);
|
|
413
|
-
}
|
|
420
|
+
submitted = true;
|
|
414
421
|
|
|
415
|
-
|
|
422
|
+
try {
|
|
423
|
+
// Increment pending count immediately so that `pending` reflects
|
|
424
|
+
// the in-progress state during async preflight validation
|
|
425
|
+
pending_count++;
|
|
416
426
|
|
|
417
|
-
|
|
427
|
+
const valid = await preflight(form_data);
|
|
428
|
+
if (!valid) return;
|
|
418
429
|
|
|
419
|
-
|
|
430
|
+
await enhance_callback(create_enhance_callback_instance(form, form_data));
|
|
431
|
+
} catch (e) {
|
|
432
|
+
const error =
|
|
433
|
+
e instanceof HttpError ? e.body : { message: /** @type {any} */ (e).message };
|
|
434
|
+
const status = e instanceof HttpError ? e.status : 500;
|
|
435
|
+
void set_nearest_error_page(error, status);
|
|
436
|
+
} finally {
|
|
437
|
+
pending_count--;
|
|
438
|
+
}
|
|
439
|
+
};
|
|
420
440
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
441
|
+
/** @param {Event} e */
|
|
442
|
+
const handle_input = (e) => {
|
|
443
|
+
// strictly speaking it can be an HTMLTextAreaElement or HTMLSelectElement
|
|
444
|
+
// but that makes the types unnecessarily awkward
|
|
445
|
+
const element = /** @type {HTMLInputElement} */ (e.target);
|
|
426
446
|
|
|
427
|
-
|
|
428
|
-
|
|
447
|
+
let name = element.name;
|
|
448
|
+
if (!name) return;
|
|
429
449
|
|
|
430
|
-
|
|
431
|
-
|
|
450
|
+
const is_array = name.endsWith('[]');
|
|
451
|
+
if (is_array) name = name.slice(0, -2);
|
|
432
452
|
|
|
433
|
-
|
|
453
|
+
const is_file = element.type === 'file';
|
|
434
454
|
|
|
435
|
-
|
|
455
|
+
touched[name] = true;
|
|
436
456
|
|
|
437
|
-
|
|
438
|
-
|
|
457
|
+
if (is_array) {
|
|
458
|
+
let value;
|
|
439
459
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
460
|
+
if (element.tagName === 'SELECT') {
|
|
461
|
+
value = Array.from(
|
|
462
|
+
element.querySelectorAll('option:checked'),
|
|
463
|
+
(e) => /** @type {HTMLOptionElement} */ (e).value
|
|
464
|
+
);
|
|
465
|
+
} else {
|
|
466
|
+
const elements = /** @type {HTMLInputElement[]} */ (
|
|
467
|
+
Array.from(form.querySelectorAll(`[name="${name}[]"]`))
|
|
468
|
+
);
|
|
449
469
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
}
|
|
470
|
+
if (DEV) {
|
|
471
|
+
for (const e of elements) {
|
|
472
|
+
if ((e.type === 'file') !== is_file) {
|
|
473
|
+
throw new Error(
|
|
474
|
+
`Cannot mix and match file and non-file inputs under the same name ("${element.name}")`
|
|
475
|
+
);
|
|
457
476
|
}
|
|
458
477
|
}
|
|
459
|
-
|
|
460
|
-
value = is_file
|
|
461
|
-
? elements.map((input) => Array.from(input.files ?? [])).flat()
|
|
462
|
-
: elements.map((element) => element.value);
|
|
463
|
-
if (element.type === 'checkbox') {
|
|
464
|
-
value = /** @type {string[]} */ (value.filter((_, i) => elements[i].checked));
|
|
465
|
-
}
|
|
466
478
|
}
|
|
467
479
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
);
|
|
480
|
+
value = is_file
|
|
481
|
+
? elements.map((input) => Array.from(input.files ?? [])).flat()
|
|
482
|
+
: elements.map((element) => element.value);
|
|
483
|
+
if (element.type === 'checkbox') {
|
|
484
|
+
value = /** @type {string[]} */ (value.filter((_, i) => elements[i].checked));
|
|
474
485
|
}
|
|
486
|
+
}
|
|
475
487
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
// Remove the property by setting to undefined and clean up
|
|
482
|
-
const path_parts = name.split(/\.|\[|\]/).filter(Boolean);
|
|
483
|
-
let current = /** @type {any} */ (input);
|
|
484
|
-
for (let i = 0; i < path_parts.length - 1; i++) {
|
|
485
|
-
if (current[path_parts[i]] == null) return;
|
|
486
|
-
current = current[path_parts[i]];
|
|
487
|
-
}
|
|
488
|
-
delete current[path_parts[path_parts.length - 1]];
|
|
489
|
-
}
|
|
490
|
-
} else {
|
|
491
|
-
set_nested_value(
|
|
492
|
-
input,
|
|
493
|
-
name,
|
|
494
|
-
element.type === 'checkbox' && !element.checked ? null : element.value
|
|
488
|
+
set_nested_value(input, name, value);
|
|
489
|
+
} else if (is_file) {
|
|
490
|
+
if (DEV && element.multiple) {
|
|
491
|
+
throw new Error(
|
|
492
|
+
`Can only use the \`multiple\` attribute when \`name\` includes a \`[]\` suffix — consider changing "${name}" to "${name}[]"`
|
|
495
493
|
);
|
|
496
494
|
}
|
|
497
495
|
|
|
498
|
-
|
|
496
|
+
const file = /** @type {HTMLInputElement & { files: FileList }} */ (element).files[0];
|
|
499
497
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
498
|
+
if (file) {
|
|
499
|
+
set_nested_value(input, name, file);
|
|
500
|
+
} else {
|
|
501
|
+
// Remove the property by setting to undefined and clean up
|
|
502
|
+
const path_parts = name.split(/\.|\[|\]/).filter(Boolean);
|
|
503
|
+
let current = /** @type {any} */ (input);
|
|
504
|
+
for (let i = 0; i < path_parts.length - 1; i++) {
|
|
505
|
+
if (current[path_parts[i]] == null) return;
|
|
506
|
+
current = current[path_parts[i]];
|
|
507
|
+
}
|
|
508
|
+
delete current[path_parts[path_parts.length - 1]];
|
|
509
|
+
}
|
|
510
|
+
} else {
|
|
511
|
+
set_nested_value(
|
|
512
|
+
input,
|
|
513
|
+
name,
|
|
514
|
+
element.type === 'checkbox' && !element.checked ? null : element.value
|
|
515
|
+
);
|
|
516
|
+
}
|
|
504
517
|
|
|
505
|
-
|
|
506
|
-
// need to wait a moment, because the `reset` event occurs before
|
|
507
|
-
// the inputs are actually updated (so that it can be cancelled)
|
|
508
|
-
await tick();
|
|
518
|
+
name = name.replace(/^[nb]:/, '');
|
|
509
519
|
|
|
510
|
-
|
|
511
|
-
|
|
520
|
+
touched[name] = true;
|
|
521
|
+
};
|
|
512
522
|
|
|
513
|
-
|
|
523
|
+
const handle_reset = async () => {
|
|
524
|
+
// need to wait a moment, because the `reset` event occurs before
|
|
525
|
+
// the inputs are actually updated (so that it can be cancelled)
|
|
526
|
+
await tick();
|
|
514
527
|
|
|
515
|
-
|
|
516
|
-
form.removeEventListener('submit', onsubmit);
|
|
517
|
-
form.removeEventListener('input', handle_input);
|
|
518
|
-
form.removeEventListener('reset', handle_reset);
|
|
519
|
-
element = null;
|
|
520
|
-
preflight_schema = undefined;
|
|
521
|
-
};
|
|
528
|
+
input = convert_formdata(new FormData(form));
|
|
522
529
|
};
|
|
523
|
-
}
|
|
524
530
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
531
|
+
form.addEventListener('submit', handle_submit);
|
|
532
|
+
form.addEventListener('input', handle_input);
|
|
533
|
+
form.addEventListener('reset', handle_reset);
|
|
534
|
+
|
|
535
|
+
return () => {
|
|
536
|
+
form.removeEventListener('submit', handle_submit);
|
|
537
|
+
form.removeEventListener('input', handle_input);
|
|
538
|
+
form.removeEventListener('reset', handle_reset);
|
|
539
|
+
element = null;
|
|
540
|
+
preflight_schema = undefined;
|
|
541
|
+
};
|
|
542
|
+
};
|
|
534
543
|
|
|
535
544
|
let validate_id = 0;
|
|
536
545
|
|
|
@@ -549,6 +558,37 @@ export function form(id) {
|
|
|
549
558
|
}
|
|
550
559
|
|
|
551
560
|
Object.defineProperties(instance, {
|
|
561
|
+
element: {
|
|
562
|
+
get: () => element
|
|
563
|
+
},
|
|
564
|
+
submit: {
|
|
565
|
+
value: () => {
|
|
566
|
+
if (!element) {
|
|
567
|
+
throw new Error('Cannot call submit() before the form is attached');
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
const default_submitter = /** @type {HTMLElement | undefined} */ (
|
|
571
|
+
element.querySelector('button:not([type]), [type="submit"]')
|
|
572
|
+
);
|
|
573
|
+
|
|
574
|
+
const form_data = new FormData(element, default_submitter);
|
|
575
|
+
|
|
576
|
+
if (DEV) {
|
|
577
|
+
validate_form_data(form_data, clone(element).enctype);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
submitted = true;
|
|
581
|
+
pending_count++;
|
|
582
|
+
|
|
583
|
+
const submission = submit(form_data, true);
|
|
584
|
+
|
|
585
|
+
void submission.finally(() => {
|
|
586
|
+
pending_count--;
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
return submission;
|
|
590
|
+
}
|
|
591
|
+
},
|
|
552
592
|
fields: {
|
|
553
593
|
get: () =>
|
|
554
594
|
create_field_proxy(
|
|
@@ -659,13 +699,12 @@ export function form(id) {
|
|
|
659
699
|
}
|
|
660
700
|
},
|
|
661
701
|
enhance: {
|
|
662
|
-
/**
|
|
702
|
+
/**
|
|
703
|
+
* @param {(instance: Omit<RemoteForm<T, U>, 'enhance' | 'element'> & { readonly element: HTMLFormElement }) => any} callback
|
|
704
|
+
*/
|
|
663
705
|
value: (callback) => {
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
action,
|
|
667
|
-
[createAttachmentKey()]: create_attachment(form_onsubmit(callback))
|
|
668
|
-
};
|
|
706
|
+
enhance_callback = callback;
|
|
707
|
+
return instance;
|
|
669
708
|
}
|
|
670
709
|
}
|
|
671
710
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { command } from './command.svelte.js';
|
|
2
2
|
export { form } from './form.svelte.js';
|
|
3
3
|
export { prerender } from './prerender.svelte.js';
|
|
4
|
-
export { query } from './query.
|
|
4
|
+
export { query } from './query/index.js';
|
|
5
5
|
export { query_batch } from './query-batch.svelte.js';
|
|
6
|
-
export { query_live } from './query-live.
|
|
6
|
+
export { query_live } from './query-live/index.js';
|
|
@@ -2,13 +2,12 @@
|
|
|
2
2
|
import { app_dir, base } from '$app/paths/internal/client';
|
|
3
3
|
import { version } from '__sveltekit/environment';
|
|
4
4
|
import * as devalue from 'devalue';
|
|
5
|
-
import { DEV } from 'esm-env';
|
|
6
5
|
import { app, prerender_responses } from '../client.js';
|
|
7
6
|
import { get_remote_request_headers, remote_request } from './shared.svelte.js';
|
|
8
7
|
import { create_remote_key, stringify_remote_arg } from '../../shared.js';
|
|
9
8
|
|
|
10
9
|
// Initialize Cache API for prerender functions
|
|
11
|
-
const CACHE_NAME =
|
|
10
|
+
const CACHE_NAME = __SVELTEKIT_DEV__ ? `sveltekit:${Date.now()}` : `sveltekit:${version}`;
|
|
12
11
|
/** @type {Cache | undefined} */
|
|
13
12
|
let prerender_cache;
|
|
14
13
|
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** @import { RemoteQueryFunction } from '@sveltejs/kit' */
|
|
2
|
+
import { app_dir, base } from '$app/paths/internal/client';
|
|
3
|
+
import { app, query_map, query_responses } from '../../client.js';
|
|
4
|
+
import { get_remote_request_headers, QUERY_FUNCTION_ID, remote_request } from '../shared.svelte.js';
|
|
5
|
+
import * as devalue from 'devalue';
|
|
6
|
+
import { DEV } from 'esm-env';
|
|
7
|
+
import { unfriendly_hydratable } from '../../../shared.js';
|
|
8
|
+
import { QueryProxy } from './proxy.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {string} id
|
|
12
|
+
* @returns {RemoteQueryFunction<any, any>}
|
|
13
|
+
*/
|
|
14
|
+
export function query(id) {
|
|
15
|
+
if (DEV) {
|
|
16
|
+
// If this reruns as part of HMR, refresh all live entries.
|
|
17
|
+
const entries = query_map.get(id);
|
|
18
|
+
|
|
19
|
+
if (entries) {
|
|
20
|
+
for (const { resource } of entries.values()) {
|
|
21
|
+
void resource.refresh();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** @type {RemoteQueryFunction<any, any>} */
|
|
27
|
+
const wrapper = (arg) => {
|
|
28
|
+
return new QueryProxy(id, arg, async (key, payload) => {
|
|
29
|
+
if (Object.hasOwn(query_responses, key)) {
|
|
30
|
+
const value = query_responses[key];
|
|
31
|
+
delete query_responses[key];
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const url = `${base}/${app_dir}/remote/${id}${payload ? `?payload=${payload}` : ''}`;
|
|
36
|
+
|
|
37
|
+
const serialized = await unfriendly_hydratable(key, () =>
|
|
38
|
+
remote_request(url, get_remote_request_headers())
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
return devalue.parse(serialized, app.decoders);
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
Object.defineProperty(wrapper, QUERY_FUNCTION_ID, { value: id });
|
|
46
|
+
|
|
47
|
+
return wrapper;
|
|
48
|
+
}
|