@sveltejs/kit 3.0.0-next.2 → 3.0.0-next.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +62 -36
- package/src/cli.js +15 -12
- package/src/constants.js +6 -1
- package/src/core/adapt/builder.js +66 -72
- package/src/core/adapt/index.js +17 -6
- package/src/core/config/index.js +134 -80
- package/src/core/config/options.js +295 -273
- package/src/core/config/types.d.ts +1 -1
- package/src/core/env.js +146 -16
- package/src/core/generate_manifest/index.js +18 -15
- package/src/core/postbuild/analyse.js +8 -20
- package/src/core/postbuild/crawl.js +22 -6
- package/src/core/postbuild/entities.js +8 -2
- package/src/core/postbuild/fallback.js +4 -2
- package/src/core/postbuild/prerender.js +222 -70
- package/src/core/postbuild/queue.js +2 -1
- package/src/core/sync/create_manifest_data/conflict.js +1 -1
- package/src/core/sync/create_manifest_data/index.js +82 -62
- package/src/core/sync/sync.js +40 -31
- package/src/core/sync/ts.js +1 -1
- package/src/core/sync/utils.js +22 -2
- package/src/core/sync/{write_non_ambient.js → write_app_types.js} +107 -58
- package/src/core/sync/write_client_manifest.js +14 -29
- package/src/core/sync/write_env.js +7 -5
- package/src/core/sync/write_server.js +37 -45
- package/src/core/sync/write_tsconfig/index.js +274 -0
- package/src/core/sync/write_tsconfig/test-app/package.json +7 -0
- package/src/core/sync/write_tsconfig/utils.js +77 -0
- package/src/core/sync/write_tsconfig/validate.js +128 -0
- package/src/core/sync/write_types/index.js +127 -123
- package/src/core/utils.js +30 -5
- package/src/exports/env/index.js +77 -0
- package/src/exports/env/public.d.ts +55 -0
- package/src/exports/hooks/index.js +3 -9
- package/src/exports/hooks/public.d.ts +195 -0
- package/src/exports/hooks/sequence.js +9 -6
- package/src/exports/index.js +52 -29
- package/src/exports/internal/client.js +5 -0
- package/src/exports/internal/env.js +8 -5
- package/src/exports/internal/index.js +1 -90
- package/src/exports/internal/{event.js → server/event.js} +2 -3
- package/src/exports/internal/server/index.js +37 -0
- package/src/exports/internal/server/telemetry.js +95 -0
- package/src/exports/internal/shared.js +90 -0
- package/src/exports/node/index.js +64 -22
- package/src/exports/params/index.js +70 -0
- package/src/exports/params/public.d.ts +63 -0
- package/src/exports/public.d.ts +50 -1733
- package/src/exports/remote/index.js +11 -0
- package/src/exports/remote/public.d.ts +519 -0
- package/src/exports/url.js +86 -0
- package/src/exports/vite/build/build_server.js +54 -65
- package/src/exports/vite/build/remote.js +24 -19
- package/src/exports/vite/build/utils.js +0 -8
- package/src/exports/vite/dev/index.js +218 -146
- package/src/exports/vite/index.js +1590 -858
- package/src/exports/vite/module_ids.js +2 -2
- package/src/exports/vite/preview/index.js +40 -32
- package/src/exports/vite/public.d.ts +588 -0
- package/src/exports/vite/utils.js +84 -46
- package/src/pathname.js +55 -0
- package/src/runner.js +15 -0
- package/src/runtime/app/env/internal.js +4 -4
- package/src/runtime/app/env/types.d.ts +1 -1
- package/src/runtime/app/environment/index.js +3 -3
- package/src/runtime/app/{forms.js → forms/index.js} +73 -42
- package/src/runtime/app/forms/public.d.ts +2 -0
- package/src/runtime/app/forms/types.d.ts +56 -0
- package/src/runtime/app/internal/transport.js +53 -0
- package/src/runtime/app/manifest/index.js +1 -0
- package/src/runtime/app/{navigation.js → navigation/index.js} +2 -1
- package/src/runtime/app/navigation/public.d.ts +237 -0
- package/src/runtime/app/paths/client.js +37 -37
- package/src/runtime/app/paths/index.js +1 -1
- package/src/runtime/app/paths/internal/client.js +34 -2
- package/src/runtime/app/paths/internal/server.js +6 -23
- package/src/runtime/app/paths/internal.d.ts +3 -0
- package/src/runtime/app/paths/public.d.ts +1 -29
- package/src/runtime/app/paths/server.js +36 -17
- package/src/runtime/app/paths/types.d.ts +11 -19
- package/src/runtime/app/server/index.js +2 -2
- package/src/runtime/app/server/public.d.ts +201 -0
- package/src/runtime/app/server/remote/command.js +13 -11
- package/src/runtime/app/server/remote/form.js +61 -39
- package/src/runtime/app/server/remote/prerender.js +45 -45
- package/src/runtime/app/server/remote/query.js +106 -108
- package/src/runtime/app/server/remote/requested.js +27 -19
- package/src/runtime/app/server/remote/shared.js +76 -76
- package/src/runtime/app/service-worker/index.js +24 -0
- package/src/runtime/app/state/client.js +4 -2
- package/src/runtime/app/state/index.js +7 -5
- package/src/runtime/app/state/public.d.ts +72 -0
- package/src/runtime/app/state/server.js +3 -0
- package/src/runtime/app/stores.js +15 -78
- package/src/runtime/client/bundle.js +1 -1
- package/src/runtime/client/client-entry.js +3 -0
- package/src/runtime/client/client.js +1336 -648
- package/src/runtime/client/constants.js +3 -6
- package/src/runtime/client/entry.js +24 -3
- package/src/runtime/client/fetcher.js +25 -25
- package/src/runtime/client/ndjson.js +1 -1
- package/src/runtime/client/parse.js +1 -1
- package/src/runtime/client/payload.js +17 -0
- package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
- package/src/runtime/client/remote-functions/command.svelte.js +37 -61
- package/src/runtime/client/remote-functions/form.svelte.js +267 -178
- package/src/runtime/client/remote-functions/prerender.svelte.js +32 -11
- package/src/runtime/client/remote-functions/query/index.js +10 -17
- package/src/runtime/client/remote-functions/query/instance.svelte.js +64 -18
- package/src/runtime/client/remote-functions/query/proxy.js +5 -5
- package/src/runtime/client/remote-functions/query-batch.svelte.js +61 -70
- package/src/runtime/client/remote-functions/query-live/index.js +1 -1
- package/src/runtime/client/remote-functions/query-live/instance.svelte.js +63 -21
- package/src/runtime/client/remote-functions/query-live/iterator.js +15 -12
- package/src/runtime/client/remote-functions/query-live/proxy.js +2 -12
- package/src/runtime/client/remote-functions/shared.svelte.js +90 -65
- package/src/runtime/client/snapshots.js +147 -0
- package/src/runtime/client/state.svelte.js +94 -55
- package/src/runtime/client/stream.js +3 -2
- package/src/runtime/client/types.d.ts +13 -9
- package/src/runtime/client/utils.js +22 -110
- package/src/runtime/components/root.svelte +56 -0
- package/src/runtime/env/dynamic/private.js +7 -0
- package/src/runtime/env/dynamic/public.js +7 -0
- package/src/runtime/env/static/private.js +6 -0
- package/src/runtime/env/static/public.js +6 -0
- package/src/runtime/form-utils.js +172 -61
- package/src/runtime/pathname.js +20 -32
- package/src/runtime/props.svelte.js +72 -0
- package/src/runtime/server/constants.js +0 -3
- package/src/runtime/server/cookie.js +72 -55
- package/src/runtime/server/csrf.js +65 -0
- package/src/runtime/server/data/index.js +49 -53
- package/src/runtime/server/dev.js +22 -0
- package/src/runtime/server/endpoint.js +6 -7
- package/src/runtime/server/env_module.js +0 -5
- package/src/runtime/server/errors.js +160 -0
- package/src/runtime/server/fetch.js +32 -39
- package/src/runtime/server/index.js +90 -64
- package/src/runtime/server/internal.js +71 -0
- package/src/runtime/server/page/actions.js +85 -64
- package/src/runtime/server/page/crypto.js +2 -2
- package/src/runtime/server/page/csp.js +88 -104
- package/src/runtime/server/page/data_serializer.js +24 -25
- package/src/runtime/server/page/index.js +36 -53
- package/src/runtime/server/page/load_data.js +50 -57
- package/src/runtime/server/page/render.js +173 -239
- package/src/runtime/server/page/respond_with_error.js +17 -31
- package/src/runtime/server/page/serialize_data.js +2 -13
- package/src/runtime/server/page/server_routing.js +85 -26
- package/src/runtime/server/remote-functions.js +640 -0
- package/src/runtime/server/respond.js +190 -131
- package/src/runtime/server/sourcemaps.js +183 -0
- package/src/runtime/server/state.js +53 -0
- package/src/runtime/server/utils.js +13 -155
- package/src/runtime/shared.js +20 -40
- package/src/runtime/utils.js +3 -0
- package/src/types/ambient-private.d.ts +11 -1
- package/src/types/ambient.d.ts +87 -36
- package/src/types/global-private.d.ts +25 -25
- package/src/types/internal.d.ts +163 -157
- package/src/types/private.d.ts +41 -1
- package/src/utils/error.js +28 -4
- package/src/utils/escape.js +9 -25
- package/src/utils/features.js +1 -1
- package/src/utils/filesystem.js +1 -23
- package/src/utils/fork.js +7 -2
- package/src/utils/hash.js +21 -0
- package/src/utils/http.js +8 -7
- package/src/utils/import.js +9 -2
- package/src/utils/imports.js +83 -0
- package/src/utils/mime.js +9 -0
- package/src/utils/page_nodes.js +6 -7
- package/src/utils/params.js +67 -0
- package/src/utils/regex.js +9 -0
- package/src/utils/routing.js +145 -73
- package/src/utils/shared-iterator.js +5 -0
- package/src/utils/streaming.js +14 -4
- package/src/utils/url.js +33 -2
- package/src/version.js +1 -1
- package/types/index.d.ts +2616 -2433
- package/types/index.d.ts.map +120 -106
- package/src/core/sync/write_ambient.js +0 -18
- package/src/core/sync/write_root.js +0 -148
- package/src/core/sync/write_tsconfig.js +0 -250
- package/src/exports/internal/server.js +0 -22
- package/src/exports/node/polyfills.js +0 -30
- package/src/runtime/server/app.js +0 -9
- package/src/runtime/server/remote.js +0 -457
- package/src/runtime/shared-server.js +0 -7
- package/src/runtime/telemetry/otel.js +0 -21
- package/src/runtime/telemetry/record_span.js +0 -65
- package/src/types/synthetic/$lib.md +0 -5
- /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
- /package/src/{runtime/telemetry/noop.js → telemetry.js} +0 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
/** @import { RemoteLiveQuery, RemoteLiveQueryFunction, RemoteQuery, RemoteQueryFunction } from '@sveltejs/kit' */
|
|
1
|
+
/** @import { RemoteLiveQuery, RemoteLiveQueryFunction, RemoteQuery, RemoteQueryFunction } from '@sveltejs/kit/remote' */
|
|
2
|
+
/** @import { RequestEvent } from '$app/server' */
|
|
2
3
|
/** @import { RemoteInternals, MaybePromise, RequestState, RemoteQueryLiveInternals, RemoteQueryBatchInternals, RemoteQueryInternals, RemoteLiveQueryUserFunctionReturnType } from 'types' */
|
|
3
4
|
/** @import { StandardSchemaV1 } from '@standard-schema/spec' */
|
|
4
5
|
import { get_request_store } from '@sveltejs/kit/internal/server';
|
|
5
|
-
import { create_remote_key,
|
|
6
|
+
import { create_remote_key, stringify_remote_arg } from '../../../shared.js';
|
|
6
7
|
import { prerendering } from '$app/env/internal';
|
|
7
8
|
import {
|
|
8
9
|
create_validator,
|
|
@@ -11,10 +12,9 @@ import {
|
|
|
11
12
|
run_remote_function,
|
|
12
13
|
run_remote_generator
|
|
13
14
|
} from './shared.js';
|
|
14
|
-
import { handle_error_and_jsonify } from '../../../server/utils.js';
|
|
15
|
-
import { HttpError, SvelteKitError } from '@sveltejs/kit/internal';
|
|
16
15
|
import { noop } from '../../../../utils/functions.js';
|
|
17
16
|
import { SharedIterator } from '../../../../utils/shared-iterator.js';
|
|
17
|
+
import { handle_error_and_jsonify } from '../../../server/errors.js';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Creates a remote query. When called from the browser, the function will be invoked on the server via a `fetch` call.
|
|
@@ -78,8 +78,14 @@ export function query(validate_or_fn, maybe_fn) {
|
|
|
78
78
|
bind(payload, validated_arg) {
|
|
79
79
|
const { event, state } = get_request_store();
|
|
80
80
|
|
|
81
|
-
return create_query_resource(__, payload, state, () =>
|
|
82
|
-
run_remote_function(
|
|
81
|
+
return create_query_resource(__, payload, event, state, () =>
|
|
82
|
+
run_remote_function(
|
|
83
|
+
event,
|
|
84
|
+
{ ...state, is_in_remote_query: true },
|
|
85
|
+
false,
|
|
86
|
+
() => validated_arg,
|
|
87
|
+
fn
|
|
88
|
+
)
|
|
83
89
|
);
|
|
84
90
|
}
|
|
85
91
|
};
|
|
@@ -93,10 +99,16 @@ export function query(validate_or_fn, maybe_fn) {
|
|
|
93
99
|
}
|
|
94
100
|
|
|
95
101
|
const { event, state } = get_request_store();
|
|
96
|
-
const payload = stringify_remote_arg(arg
|
|
102
|
+
const payload = stringify_remote_arg(arg);
|
|
97
103
|
|
|
98
|
-
return create_query_resource(__, payload, state, () =>
|
|
99
|
-
run_remote_function(
|
|
104
|
+
return create_query_resource(__, payload, event, state, () =>
|
|
105
|
+
run_remote_function(
|
|
106
|
+
event,
|
|
107
|
+
{ ...state, is_in_remote_query: true },
|
|
108
|
+
false,
|
|
109
|
+
() => validate(arg),
|
|
110
|
+
fn
|
|
111
|
+
)
|
|
100
112
|
);
|
|
101
113
|
};
|
|
102
114
|
|
|
@@ -152,7 +164,14 @@ function live(validate_or_fn, maybe_fn) {
|
|
|
152
164
|
* @param {any} get_input
|
|
153
165
|
*/
|
|
154
166
|
const run = (event, state, get_input) =>
|
|
155
|
-
run_remote_generator(
|
|
167
|
+
run_remote_generator(
|
|
168
|
+
event,
|
|
169
|
+
{ ...state, is_in_remote_query: true },
|
|
170
|
+
false,
|
|
171
|
+
get_input,
|
|
172
|
+
fn,
|
|
173
|
+
__.name
|
|
174
|
+
);
|
|
156
175
|
|
|
157
176
|
/** @type {RemoteQueryLiveInternals} */
|
|
158
177
|
const __ = {
|
|
@@ -164,7 +183,7 @@ function live(validate_or_fn, maybe_fn) {
|
|
|
164
183
|
bind(payload, validated_arg) {
|
|
165
184
|
const { event, state } = get_request_store();
|
|
166
185
|
|
|
167
|
-
return create_live_query_resource(__, payload,
|
|
186
|
+
return create_live_query_resource(__, payload, event, state, () =>
|
|
168
187
|
run(event, state, () => validated_arg)
|
|
169
188
|
);
|
|
170
189
|
}
|
|
@@ -179,9 +198,9 @@ function live(validate_or_fn, maybe_fn) {
|
|
|
179
198
|
}
|
|
180
199
|
|
|
181
200
|
const { event, state } = get_request_store();
|
|
182
|
-
const payload = stringify_remote_arg(arg
|
|
201
|
+
const payload = stringify_remote_arg(arg);
|
|
183
202
|
|
|
184
|
-
return create_live_query_resource(__, payload,
|
|
203
|
+
return create_live_query_resource(__, payload, event, state, () =>
|
|
185
204
|
run(event, state, () => validate(arg))
|
|
186
205
|
);
|
|
187
206
|
};
|
|
@@ -273,7 +292,7 @@ function batch(validate_or_fn, maybe_fn) {
|
|
|
273
292
|
try {
|
|
274
293
|
return await run_remote_function(
|
|
275
294
|
event,
|
|
276
|
-
state,
|
|
295
|
+
{ ...state, is_in_remote_query: true },
|
|
277
296
|
false,
|
|
278
297
|
async () => Promise.all(entries.map((entry) => entry.get_validated())),
|
|
279
298
|
async (input) => {
|
|
@@ -316,7 +335,7 @@ function batch(validate_or_fn, maybe_fn) {
|
|
|
316
335
|
|
|
317
336
|
return run_remote_function(
|
|
318
337
|
event,
|
|
319
|
-
state,
|
|
338
|
+
{ ...state, is_in_remote_query: true },
|
|
320
339
|
false,
|
|
321
340
|
async () => Promise.all(args.map(validate)),
|
|
322
341
|
async (/** @type {any[]} */ input) => {
|
|
@@ -326,15 +345,13 @@ function batch(validate_or_fn, maybe_fn) {
|
|
|
326
345
|
input.map(async (arg, i) => {
|
|
327
346
|
try {
|
|
328
347
|
const data = get_result(arg, i);
|
|
329
|
-
return { type: 'result', data
|
|
348
|
+
return { type: 'result', data };
|
|
330
349
|
} catch (error) {
|
|
350
|
+
const transformed = await handle_error_and_jsonify(event, state, options, error);
|
|
351
|
+
|
|
331
352
|
return {
|
|
332
353
|
type: 'error',
|
|
333
|
-
error:
|
|
334
|
-
status:
|
|
335
|
-
error instanceof HttpError || error instanceof SvelteKitError
|
|
336
|
-
? error.status
|
|
337
|
-
: 500
|
|
354
|
+
error: transformed
|
|
338
355
|
};
|
|
339
356
|
}
|
|
340
357
|
})
|
|
@@ -343,9 +360,11 @@ function batch(validate_or_fn, maybe_fn) {
|
|
|
343
360
|
);
|
|
344
361
|
},
|
|
345
362
|
bind(payload, validated_arg) {
|
|
346
|
-
const { state } = get_request_store();
|
|
363
|
+
const { event, state } = get_request_store();
|
|
347
364
|
|
|
348
|
-
return create_query_resource(__, payload,
|
|
365
|
+
return create_query_resource(__, payload, event, state, () =>
|
|
366
|
+
enqueue(payload, () => validated_arg)
|
|
367
|
+
);
|
|
349
368
|
}
|
|
350
369
|
};
|
|
351
370
|
|
|
@@ -357,10 +376,10 @@ function batch(validate_or_fn, maybe_fn) {
|
|
|
357
376
|
);
|
|
358
377
|
}
|
|
359
378
|
|
|
360
|
-
const { state } = get_request_store();
|
|
361
|
-
const payload = stringify_remote_arg(arg
|
|
379
|
+
const { event, state } = get_request_store();
|
|
380
|
+
const payload = stringify_remote_arg(arg);
|
|
362
381
|
|
|
363
|
-
return create_query_resource(__, payload, state, () =>
|
|
382
|
+
return create_query_resource(__, payload, event, state, () =>
|
|
364
383
|
// Collect all the calls to the same query in the same macrotask,
|
|
365
384
|
// then execute them as one backend request.
|
|
366
385
|
enqueue(payload, () => validate(arg))
|
|
@@ -372,14 +391,48 @@ function batch(validate_or_fn, maybe_fn) {
|
|
|
372
391
|
return wrapper;
|
|
373
392
|
}
|
|
374
393
|
|
|
394
|
+
/**
|
|
395
|
+
* Include this value in the returned payload...
|
|
396
|
+
* @param {RequestEvent} event
|
|
397
|
+
* @param {RequestState} state
|
|
398
|
+
* @param {RemoteInternals} internals
|
|
399
|
+
* @param {string} payload
|
|
400
|
+
* @param {() => Promise<any>} fn
|
|
401
|
+
*/
|
|
402
|
+
export function refresh(event, state, internals, payload, fn) {
|
|
403
|
+
if (!internals.id) {
|
|
404
|
+
// unless this is a non-exported (i.e. private) query...
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
if (!event.isRemoteRequest && state.is_in_remote_form_or_command) {
|
|
409
|
+
// ...or this is a no-JS (native) form submission, where the page re-renders
|
|
410
|
+
// anyway so there's no live client cache to apply a single-flight update to.
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const key = create_remote_key(internals.id, payload);
|
|
415
|
+
|
|
416
|
+
// `fn` is stored rather than invoked eagerly. The query is run at the end of
|
|
417
|
+
// the request (in `collect_remote_data`), so that it observes any state
|
|
418
|
+
// mutations that happen after `refresh()` is called. If the developer re-awaits
|
|
419
|
+
// the query before the request finishes, the cache entry created by that await
|
|
420
|
+
// is reused instead of re-running the query.
|
|
421
|
+
(state.remote.explicit ??= new Map()).set(key, {
|
|
422
|
+
internals,
|
|
423
|
+
fn
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
|
|
375
427
|
/**
|
|
376
428
|
* @param {RemoteInternals} __
|
|
377
429
|
* @param {string} payload — the stringified raw argument (i.e. the cache key the client will use)
|
|
430
|
+
* @param {RequestEvent} event
|
|
378
431
|
* @param {RequestState} state
|
|
379
432
|
* @param {() => Promise<any>} fn
|
|
380
433
|
* @returns {RemoteQuery<any>}
|
|
381
434
|
*/
|
|
382
|
-
function create_query_resource(__, payload, state, fn) {
|
|
435
|
+
function create_query_resource(__, payload, event, state, fn) {
|
|
383
436
|
/** @type {Promise<any> | null} */
|
|
384
437
|
let promise = null;
|
|
385
438
|
|
|
@@ -391,7 +444,11 @@ function create_query_resource(__, payload, state, fn) {
|
|
|
391
444
|
// accessing data properties needs to kick off the work
|
|
392
445
|
// so that it gets seeded in the hydration cache
|
|
393
446
|
// and becomes available on the client
|
|
394
|
-
|
|
447
|
+
if (__.id && state.is_in_render) {
|
|
448
|
+
// swallow rejections so they don't crash the server — the error is
|
|
449
|
+
// serialized into the response and surfaced on the client instead
|
|
450
|
+
get_promise().catch(noop);
|
|
451
|
+
}
|
|
395
452
|
};
|
|
396
453
|
|
|
397
454
|
return {
|
|
@@ -420,20 +477,19 @@ function create_query_resource(__, payload, state, fn) {
|
|
|
420
477
|
return false;
|
|
421
478
|
},
|
|
422
479
|
refresh() {
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
const refresh_context = get_refresh_context(__, 'refresh', payload);
|
|
430
|
-
const is_immediate_refresh = !refresh_context.cache[refresh_context.payload];
|
|
431
|
-
const value = is_immediate_refresh ? get_promise() : fn();
|
|
432
|
-
return update_refresh_value(refresh_context, value, is_immediate_refresh);
|
|
480
|
+
promise = null;
|
|
481
|
+
delete get_cache(__, state)[payload];
|
|
482
|
+
|
|
483
|
+
refresh(event, state, __, payload, get_promise);
|
|
484
|
+
|
|
485
|
+
return Promise.resolve();
|
|
433
486
|
},
|
|
434
487
|
/** @param {any} value */
|
|
435
488
|
set(value) {
|
|
436
|
-
|
|
489
|
+
const p = (promise = Promise.resolve(value));
|
|
490
|
+
get_cache(__, state)[payload] = p;
|
|
491
|
+
|
|
492
|
+
refresh(event, state, __, payload, () => p);
|
|
437
493
|
},
|
|
438
494
|
/** @type {Promise<any>['then']} */
|
|
439
495
|
then(onfulfilled, onrejected) {
|
|
@@ -451,12 +507,12 @@ function create_query_resource(__, payload, state, fn) {
|
|
|
451
507
|
/**
|
|
452
508
|
* @param {RemoteQueryLiveInternals} __
|
|
453
509
|
* @param {string} payload — the stringified raw argument (i.e. the cache key the client will use)
|
|
510
|
+
* @param {RequestEvent} event
|
|
454
511
|
* @param {RequestState} state
|
|
455
|
-
* @param {AbortSignal} signal — the request signal; aborts in-flight iteration when the client disconnects
|
|
456
512
|
* @param {() => AsyncGenerator<any, void, void>} get_generator
|
|
457
513
|
* @returns {RemoteLiveQuery<any>}
|
|
458
514
|
*/
|
|
459
|
-
function create_live_query_resource(__, payload,
|
|
515
|
+
function create_live_query_resource(__, payload, event, state, get_generator) {
|
|
460
516
|
/** @type {Promise<any> | null} */
|
|
461
517
|
let promise = null;
|
|
462
518
|
|
|
@@ -472,7 +528,11 @@ function create_live_query_resource(__, payload, state, signal, get_generator) {
|
|
|
472
528
|
};
|
|
473
529
|
|
|
474
530
|
const populate_hydratable = () => {
|
|
475
|
-
|
|
531
|
+
if (__.id && state.is_in_render) {
|
|
532
|
+
// swallow rejections so they don't crash the server — the error is
|
|
533
|
+
// serialized into the response and surfaced on the client instead
|
|
534
|
+
get_promise().catch(noop);
|
|
535
|
+
}
|
|
476
536
|
};
|
|
477
537
|
|
|
478
538
|
return {
|
|
@@ -509,23 +569,13 @@ function create_live_query_resource(__, payload, state, signal, get_generator) {
|
|
|
509
569
|
return false;
|
|
510
570
|
},
|
|
511
571
|
reconnect() {
|
|
512
|
-
|
|
572
|
+
promise = null;
|
|
573
|
+
delete get_cache(__, state)[payload];
|
|
513
574
|
|
|
514
|
-
|
|
515
|
-
throw new Error(
|
|
516
|
-
`Cannot call reconnect on query.live '${__.name}' because it is not executed in the context of a command/form remote function`
|
|
517
|
-
);
|
|
518
|
-
}
|
|
575
|
+
refresh(event, state, __, payload, get_promise);
|
|
519
576
|
|
|
520
|
-
reconnects.set(create_remote_key(__.id, payload), get_promise());
|
|
521
577
|
return Promise.resolve();
|
|
522
578
|
},
|
|
523
|
-
/** @ts-expect-error This method no longer exists */
|
|
524
|
-
run() {
|
|
525
|
-
throw new Error(
|
|
526
|
-
'`.run()` has been removed from live queries. Use `for await (const value of liveQuery())` instead.'
|
|
527
|
-
);
|
|
528
|
-
},
|
|
529
579
|
/** @type {Promise<any>['then']} */
|
|
530
580
|
then(onfulfilled, onrejected) {
|
|
531
581
|
return get_promise().then(onfulfilled, onrejected);
|
|
@@ -535,7 +585,7 @@ function create_live_query_resource(__, payload, state, signal, get_generator) {
|
|
|
535
585
|
const cache = (state.remote.live_iterators ??= new Map());
|
|
536
586
|
let cached = cache.get(key);
|
|
537
587
|
if (!cached) {
|
|
538
|
-
cached = create_shared_live_iterator(signal, get_generator);
|
|
588
|
+
cached = create_shared_live_iterator(event.request.signal, get_generator);
|
|
539
589
|
cache.set(key, cached);
|
|
540
590
|
}
|
|
541
591
|
return cached.subscribe();
|
|
@@ -613,55 +663,3 @@ function create_shared_live_iterator(signal, get_generator) {
|
|
|
613
663
|
// Add batch as a property to the query function
|
|
614
664
|
Object.defineProperty(query, 'batch', { value: batch, enumerable: true });
|
|
615
665
|
Object.defineProperty(query, 'live', { value: live, enumerable: true });
|
|
616
|
-
|
|
617
|
-
/**
|
|
618
|
-
* @param {RemoteInternals} __
|
|
619
|
-
* @param {'set' | 'refresh'} action
|
|
620
|
-
* @param {string} payload — the stringified raw argument (i.e. the cache key the client will use)
|
|
621
|
-
* @returns {{ __: RemoteInternals; state: any; refreshes: Map<string, Promise<any>>; cache: Record<string, { serialize: boolean; data: any }>; refreshes_key: string; payload: string }}
|
|
622
|
-
*/
|
|
623
|
-
function get_refresh_context(__, action, payload) {
|
|
624
|
-
const { state } = get_request_store();
|
|
625
|
-
const { refreshes } = state.remote;
|
|
626
|
-
|
|
627
|
-
if (!refreshes) {
|
|
628
|
-
const name = __.type === 'query_batch' ? `query.batch '${__.name}'` : `query '${__.name}'`;
|
|
629
|
-
throw new Error(
|
|
630
|
-
`Cannot call ${action} on ${name} because it is not executed in the context of a command/form remote function`
|
|
631
|
-
);
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
const cache = get_cache(__, state);
|
|
635
|
-
const refreshes_key = create_remote_key(__.id, payload);
|
|
636
|
-
|
|
637
|
-
return { __, state, refreshes, refreshes_key, cache, payload };
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
/**
|
|
641
|
-
* @param {{ __: RemoteInternals; refreshes: Map<string, Promise<any>>; cache: Record<string, { serialize: boolean; data: any }>; refreshes_key: string; payload: string }} context
|
|
642
|
-
* @param {any} value
|
|
643
|
-
* @param {boolean} [is_immediate_refresh=false]
|
|
644
|
-
* @returns {Promise<void>}
|
|
645
|
-
*/
|
|
646
|
-
function update_refresh_value(
|
|
647
|
-
{ __, refreshes, refreshes_key, cache, payload },
|
|
648
|
-
value,
|
|
649
|
-
is_immediate_refresh = false
|
|
650
|
-
) {
|
|
651
|
-
const promise = Promise.resolve(value);
|
|
652
|
-
|
|
653
|
-
if (!is_immediate_refresh) {
|
|
654
|
-
cache[payload] = { serialize: true, data: promise };
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
if (__.id) {
|
|
658
|
-
refreshes.set(refreshes_key, promise);
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
promise.catch(noop);
|
|
662
|
-
|
|
663
|
-
// we return an immediately-resolving promise so that the `refresh()` signature is consistent,
|
|
664
|
-
// but it doesn't delay anything if awaited inside a command. this way, people aren't
|
|
665
|
-
// penalised if they do `await q1.refresh(); await q2.refresh()`
|
|
666
|
-
return Promise.resolve();
|
|
667
|
-
}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
/** @import { RemoteLiveQuery, RemoteLiveQueryFunction, RemoteQuery, RemoteQueryFunction, RequestedResult, QueryRequestedResult, LiveQueryRequestedResult } from '@sveltejs/kit' */
|
|
1
|
+
/** @import { RemoteLiveQuery, RemoteLiveQueryFunction, RemoteQuery, RemoteQueryFunction, RequestedResult, QueryRequestedResult, LiveQueryRequestedResult } from '@sveltejs/kit/remote' */
|
|
2
2
|
/** @import { MaybePromise, RemoteAnyQueryInternals } from 'types' */
|
|
3
|
+
import { HttpError } from '@sveltejs/kit/internal';
|
|
3
4
|
import { get_request_store } from '@sveltejs/kit/internal/server';
|
|
4
|
-
import {
|
|
5
|
+
import { parse_remote_arg } from '../../../shared.js';
|
|
5
6
|
import { noop } from '../../../../utils/functions.js';
|
|
7
|
+
import { get_cache } from './shared.js';
|
|
8
|
+
import { refresh } from './query.js';
|
|
6
9
|
|
|
7
10
|
/**
|
|
8
|
-
*
|
|
9
|
-
* of `{ arg, query }` entries for the
|
|
11
|
+
* Inside a remote `command` or `form` callback, returns an iterable
|
|
12
|
+
* of `{ arg, query }` entries for the query instances the client asked to refresh, up to
|
|
10
13
|
* the supplied `limit`. Each `query` is a `RemoteQuery` bound to the original
|
|
11
14
|
* client-side cache key, so `refresh()` / `set()` propagate correctly even when
|
|
12
15
|
* the query's schema transforms the input. `arg` is the *validated* argument,
|
|
@@ -15,6 +18,8 @@ import { noop } from '../../../../utils/functions.js';
|
|
|
15
18
|
*
|
|
16
19
|
* Arguments that fail validation or exceed `limit` are recorded as failures in
|
|
17
20
|
* the response to the client.
|
|
21
|
+
* See [Client-requested refreshes](https://svelte.dev/docs/kit/remote-functions#Single-flight-mutations-Client-requested-refreshes)
|
|
22
|
+
* for usage in a remote `command` or `form`.
|
|
18
23
|
*
|
|
19
24
|
* @example
|
|
20
25
|
* ```ts
|
|
@@ -51,14 +56,16 @@ import { noop } from '../../../../utils/functions.js';
|
|
|
51
56
|
* @returns {QueryRequestedResult<Validated, Output>}
|
|
52
57
|
*/
|
|
53
58
|
/**
|
|
54
|
-
*
|
|
55
|
-
* of `{ arg, query }` entries for the
|
|
59
|
+
* Inside a remote `command` or `form` callback, returns an iterable
|
|
60
|
+
* of `{ arg, query }` entries for the live query instances the client asked to reconnect, up to
|
|
56
61
|
* the supplied `limit`. Each `query` is a `RemoteLiveQuery` bound to the original
|
|
57
62
|
* client-side cache key, so `reconnect()` propagates correctly even when
|
|
58
63
|
* the query's schema transforms the input. `arg` is the *validated* argument.
|
|
59
64
|
*
|
|
60
65
|
* Arguments that fail validation or exceed `limit` are recorded as failures in
|
|
61
66
|
* the response to the client.
|
|
67
|
+
* See [Client-requested refreshes](https://svelte.dev/docs/kit/remote-functions#Single-flight-mutations-Client-requested-refreshes)
|
|
68
|
+
* for usage in a remote `command` or `form`.
|
|
62
69
|
*
|
|
63
70
|
* @example
|
|
64
71
|
* ```ts
|
|
@@ -95,7 +102,7 @@ import { noop } from '../../../../utils/functions.js';
|
|
|
95
102
|
* @returns {RequestedResult<Validated, Output>}
|
|
96
103
|
*/
|
|
97
104
|
export function requested(query, limit) {
|
|
98
|
-
const { state } = get_request_store();
|
|
105
|
+
const { event, state } = get_request_store();
|
|
99
106
|
const internals = /** @type {RemoteAnyQueryInternals | undefined} */ (
|
|
100
107
|
/** @type {any} */ (query).__
|
|
101
108
|
);
|
|
@@ -115,15 +122,12 @@ export function requested(query, limit) {
|
|
|
115
122
|
|
|
116
123
|
const requested = state.remote.requested;
|
|
117
124
|
const payloads = requested?.get(__.id) ?? [];
|
|
125
|
+
|
|
118
126
|
// note: don't initialize these maps here -- they will be initialized by the
|
|
119
127
|
// command/form wrapper when we enter them, and if we initialize them here
|
|
120
128
|
// we will enable requested(...) in contexts where it shouldn't be allowed,
|
|
121
129
|
// such as load functions or other server functions
|
|
122
|
-
|
|
123
|
-
const reconnects = state.remote.reconnects;
|
|
124
|
-
const store = __.type === 'query_live' ? reconnects : refreshes;
|
|
125
|
-
|
|
126
|
-
if (!store) {
|
|
130
|
+
if (!state.is_in_remote_form_or_command) {
|
|
127
131
|
throw new Error(
|
|
128
132
|
'requested(...) can only be called in the context of a command/form remote function'
|
|
129
133
|
);
|
|
@@ -131,6 +135,9 @@ export function requested(query, limit) {
|
|
|
131
135
|
const [selected, skipped] = split_limit(payloads, limit);
|
|
132
136
|
|
|
133
137
|
/**
|
|
138
|
+
* Registers the failure exactly like `.set()` registers a value: the error record
|
|
139
|
+
* is serialized to the client (putting the query there into a failed state), and
|
|
140
|
+
* subsequent server-side calls of the query with the same argument reject with it.
|
|
134
141
|
* @param {string} payload
|
|
135
142
|
* @param {unknown} error
|
|
136
143
|
*/
|
|
@@ -138,16 +145,17 @@ export function requested(query, limit) {
|
|
|
138
145
|
const promise = Promise.reject(error);
|
|
139
146
|
promise.catch(noop);
|
|
140
147
|
|
|
141
|
-
|
|
142
|
-
|
|
148
|
+
get_cache(__, state)[payload] = promise;
|
|
149
|
+
refresh(event, state, __, payload, () => promise);
|
|
143
150
|
};
|
|
144
151
|
|
|
145
152
|
for (const payload of skipped) {
|
|
146
153
|
record_failure(
|
|
147
154
|
payload,
|
|
148
|
-
new
|
|
149
|
-
|
|
150
|
-
|
|
155
|
+
new HttpError({
|
|
156
|
+
status: 400,
|
|
157
|
+
message: `Requested refresh was rejected because it exceeded requested(${__.name}, ${limit}) limit`
|
|
158
|
+
})
|
|
151
159
|
);
|
|
152
160
|
}
|
|
153
161
|
|
|
@@ -155,7 +163,7 @@ export function requested(query, limit) {
|
|
|
155
163
|
*[Symbol.iterator]() {
|
|
156
164
|
for (const payload of selected) {
|
|
157
165
|
try {
|
|
158
|
-
const parsed = parse_remote_arg(payload
|
|
166
|
+
const parsed = parse_remote_arg(payload);
|
|
159
167
|
const validated = __.validate(parsed);
|
|
160
168
|
|
|
161
169
|
if (is_thenable(validated)) {
|
|
@@ -175,7 +183,7 @@ export function requested(query, limit) {
|
|
|
175
183
|
async *[Symbol.asyncIterator]() {
|
|
176
184
|
yield* race_all(selected, async (payload) => {
|
|
177
185
|
try {
|
|
178
|
-
const parsed = parse_remote_arg(payload
|
|
186
|
+
const parsed = parse_remote_arg(payload);
|
|
179
187
|
const validated = await __.validate(parsed);
|
|
180
188
|
return { arg: validated, query: __.bind(payload, validated) };
|
|
181
189
|
} catch (error) {
|