@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,10 +1,12 @@
|
|
|
1
|
-
/** @import { RemotePrerenderFunction } from '@sveltejs/kit' */
|
|
2
|
-
import { app_dir, base } from '
|
|
1
|
+
/** @import { RemotePrerenderFunction } from '@sveltejs/kit/remote' */
|
|
2
|
+
import { app_dir, base } from '#app/paths';
|
|
3
3
|
import { version } from '$app/env';
|
|
4
4
|
import * as devalue from 'devalue';
|
|
5
|
-
import { app, prerender_responses } from '../client.js';
|
|
6
|
-
import { get_remote_request_headers, remote_request } from './shared.svelte.js';
|
|
5
|
+
import { app, _goto, handle_error, prerender_responses } from '../client.js';
|
|
6
|
+
import { get_remote_request_headers, remote_request, unwrap_node } from './shared.svelte.js';
|
|
7
7
|
import { create_remote_key, stringify_remote_arg } from '../../shared.js';
|
|
8
|
+
import { noop } from '../../../utils/functions.js';
|
|
9
|
+
import { HandledHttpError } from '@sveltejs/kit/internal';
|
|
8
10
|
|
|
9
11
|
// Initialize Cache API for prerender functions
|
|
10
12
|
const CACHE_NAME = __SVELTEKIT_DEV__ ? `sveltekit:${Date.now()}` : `sveltekit:${version}`;
|
|
@@ -55,7 +57,7 @@ function put(url, encoded) {
|
|
|
55
57
|
*/
|
|
56
58
|
export function prerender(id) {
|
|
57
59
|
return (arg) => {
|
|
58
|
-
const payload = stringify_remote_arg(arg
|
|
60
|
+
const payload = stringify_remote_arg(arg);
|
|
59
61
|
const cache_key = create_remote_key(id, payload);
|
|
60
62
|
|
|
61
63
|
let resource = prerender_resources.get(cache_key)?.deref();
|
|
@@ -67,7 +69,7 @@ export function prerender(id) {
|
|
|
67
69
|
const url = `${base}/${app_dir}/remote/${id}${payload ? `/${payload}` : ''}`;
|
|
68
70
|
|
|
69
71
|
if (Object.hasOwn(prerender_responses, cache_key)) {
|
|
70
|
-
const data = prerender_responses[cache_key];
|
|
72
|
+
const data = unwrap_node(prerender_responses[cache_key]);
|
|
71
73
|
|
|
72
74
|
if (prerender_cache) {
|
|
73
75
|
void put(url, devalue.stringify(data, app.encoders));
|
|
@@ -77,6 +79,7 @@ export function prerender(id) {
|
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
// Do this here, after await Svelte' reactivity context is gone.
|
|
82
|
+
// TODO we really don't want to be sending these specific headers here?
|
|
80
83
|
const headers = get_remote_request_headers();
|
|
81
84
|
|
|
82
85
|
// Check the Cache API first
|
|
@@ -93,14 +96,22 @@ export function prerender(id) {
|
|
|
93
96
|
}
|
|
94
97
|
}
|
|
95
98
|
|
|
96
|
-
const
|
|
99
|
+
const result = await remote_request(url, { headers });
|
|
100
|
+
|
|
101
|
+
if (result.redirect) {
|
|
102
|
+
// Use internal version to allow redirects to external URLs
|
|
103
|
+
void _goto(result.redirect);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const data = result._;
|
|
97
108
|
|
|
98
109
|
// For successful prerender requests, save to cache
|
|
99
110
|
if (prerender_cache) {
|
|
100
|
-
void put(url,
|
|
111
|
+
void put(url, devalue.stringify(data, app.encoders));
|
|
101
112
|
}
|
|
102
113
|
|
|
103
|
-
return
|
|
114
|
+
return data;
|
|
104
115
|
});
|
|
105
116
|
|
|
106
117
|
prerender_resources.set(cache_key, new WeakRef(resource));
|
|
@@ -138,6 +149,7 @@ class Prerender {
|
|
|
138
149
|
/** @type {T | undefined} */
|
|
139
150
|
#current = $state.raw();
|
|
140
151
|
|
|
152
|
+
/** @type {App.Error | undefined} */
|
|
141
153
|
#error = $state.raw(undefined);
|
|
142
154
|
|
|
143
155
|
/**
|
|
@@ -152,12 +164,21 @@ class Prerender {
|
|
|
152
164
|
this.#error = undefined;
|
|
153
165
|
return value;
|
|
154
166
|
},
|
|
155
|
-
(
|
|
167
|
+
async (e) => {
|
|
168
|
+
const error = await handle_error(e, {
|
|
169
|
+
params: {},
|
|
170
|
+
route: { id: null },
|
|
171
|
+
url: new URL(location.href)
|
|
172
|
+
});
|
|
156
173
|
this.#loading = false;
|
|
157
174
|
this.#error = error;
|
|
158
|
-
throw error;
|
|
175
|
+
throw new HandledHttpError(error);
|
|
159
176
|
}
|
|
160
177
|
);
|
|
178
|
+
|
|
179
|
+
// rejections are surfaced via `.error` for reactive consumers — make sure the
|
|
180
|
+
// stored promise (consumed without `await`) never becomes an unhandled rejection
|
|
181
|
+
this.#promise.catch(noop);
|
|
161
182
|
}
|
|
162
183
|
|
|
163
184
|
/**
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
/** @import { RemoteQueryFunction } from '@sveltejs/kit' */
|
|
2
|
-
import { app_dir, base } from '
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import * as devalue from 'devalue';
|
|
1
|
+
/** @import { RemoteQueryFunction } from '@sveltejs/kit/remote' */
|
|
2
|
+
import { app_dir, base } from '#app/paths';
|
|
3
|
+
import { _goto, query_map } from '../../client.js';
|
|
4
|
+
import { QUERY_FUNCTION_ID, remote_request } from '../shared.svelte.js';
|
|
6
5
|
import { DEV } from 'esm-env';
|
|
7
|
-
import { hydratable } from 'svelte';
|
|
8
6
|
import { QueryProxy } from './proxy.js';
|
|
9
7
|
|
|
10
8
|
/**
|
|
@@ -25,20 +23,15 @@ export function query(id) {
|
|
|
25
23
|
|
|
26
24
|
/** @type {RemoteQueryFunction<any, any>} */
|
|
27
25
|
const wrapper = (arg) => {
|
|
28
|
-
return new QueryProxy(id, arg, async (
|
|
29
|
-
if (Object.hasOwn(query_responses, key)) {
|
|
30
|
-
const value = query_responses[key];
|
|
31
|
-
delete query_responses[key];
|
|
32
|
-
return value;
|
|
33
|
-
}
|
|
34
|
-
|
|
26
|
+
return new QueryProxy(id, arg, async (payload) => {
|
|
35
27
|
const url = `${base}/${app_dir}/remote/${id}${payload ? `?payload=${payload}` : ''}`;
|
|
36
28
|
|
|
37
|
-
const
|
|
38
|
-
remote_request(url, get_remote_request_headers())
|
|
39
|
-
);
|
|
29
|
+
const result = await remote_request(url);
|
|
40
30
|
|
|
41
|
-
|
|
31
|
+
if (result.redirect) {
|
|
32
|
+
// Use internal version to allow redirects to external URLs
|
|
33
|
+
await _goto(result.redirect);
|
|
34
|
+
}
|
|
42
35
|
});
|
|
43
36
|
};
|
|
44
37
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
/** @import { HttpError } from '@sveltejs/kit' */
|
|
2
|
+
import { query_responses, handle_error } from '../../client.js';
|
|
3
|
+
import { HandledHttpError } from '@sveltejs/kit/internal';
|
|
2
4
|
import { QUERY_OVERRIDE_KEY } from '../shared.svelte.js';
|
|
3
5
|
import { noop } from '../../../../utils/functions.js';
|
|
4
6
|
import { tick, untrack } from 'svelte';
|
|
@@ -36,7 +38,7 @@ export class Query {
|
|
|
36
38
|
return this.#overrides.reduce((v, r) => r(v), /** @type {T} */ (this.#raw));
|
|
37
39
|
});
|
|
38
40
|
|
|
39
|
-
/** @type {
|
|
41
|
+
/** @type {App.Error | undefined} */
|
|
40
42
|
#error = $state.raw(undefined);
|
|
41
43
|
|
|
42
44
|
/** @type {Promise<T>['then']} */
|
|
@@ -63,6 +65,17 @@ export class Query {
|
|
|
63
65
|
constructor(key, fn) {
|
|
64
66
|
this.#key = key;
|
|
65
67
|
this.#fn = fn;
|
|
68
|
+
|
|
69
|
+
if (Object.hasOwn(query_responses, key)) {
|
|
70
|
+
const node = query_responses[key];
|
|
71
|
+
delete query_responses[key];
|
|
72
|
+
|
|
73
|
+
if (node.e) {
|
|
74
|
+
this.fail(new HandledHttpError(node.e));
|
|
75
|
+
} else {
|
|
76
|
+
this.set(/** @type {T} */ (node.v));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
66
79
|
}
|
|
67
80
|
|
|
68
81
|
#get_promise() {
|
|
@@ -70,12 +83,14 @@ export class Query {
|
|
|
70
83
|
return /** @type {Promise<T>} */ (this.#promise);
|
|
71
84
|
}
|
|
72
85
|
|
|
73
|
-
|
|
86
|
+
start() {
|
|
74
87
|
// there is a really weird bug with untrack and writes and initializations
|
|
75
88
|
// every time you see this comment, try removing the `tick.then` here and see
|
|
76
89
|
// if all the tests still pass with the latest svelte version
|
|
77
90
|
// if they do, congrats, you can remove tick.then
|
|
78
|
-
void tick()
|
|
91
|
+
void tick()
|
|
92
|
+
.then(() => this.#get_promise())
|
|
93
|
+
.catch(noop);
|
|
79
94
|
}
|
|
80
95
|
|
|
81
96
|
#clear_pending() {
|
|
@@ -88,6 +103,11 @@ export class Query {
|
|
|
88
103
|
|
|
89
104
|
const { promise, resolve, reject } = Promise.withResolvers();
|
|
90
105
|
|
|
106
|
+
// the rejection is surfaced via `.error` / the `then` getter for awaiting
|
|
107
|
+
// consumers — a purely reactive consumer (`.current`) attaches no handler,
|
|
108
|
+
// so make sure the stored promise can never become an unhandled rejection
|
|
109
|
+
promise.catch(noop);
|
|
110
|
+
|
|
91
111
|
this.#latest.push(resolve);
|
|
92
112
|
|
|
93
113
|
Promise.resolve(this.#fn())
|
|
@@ -107,22 +127,33 @@ export class Query {
|
|
|
107
127
|
|
|
108
128
|
resolve(undefined);
|
|
109
129
|
})
|
|
110
|
-
.catch((e) => {
|
|
130
|
+
.catch(async (e) => {
|
|
111
131
|
// TODO: Our behavior here could be better:
|
|
112
132
|
// - We should not reject on redirects, but should hook into the router
|
|
113
133
|
// to ensure the query is properly refreshed before the navigation completes
|
|
114
134
|
// - Instead of failing on transport-level errors, we should probably do what
|
|
115
135
|
// LiveQuery does and preserve the last known good value and retry the connection
|
|
136
|
+
if (this.#latest.indexOf(resolve) === -1) return;
|
|
137
|
+
|
|
138
|
+
const error = await handle_error(e, {
|
|
139
|
+
params: {},
|
|
140
|
+
route: { id: null },
|
|
141
|
+
url: new URL(location.href)
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Re-check after the async `handle_error` gap: a later request may have
|
|
145
|
+
// resolved/rejected while we were awaiting and superseded this one, so
|
|
146
|
+
// recompute the index and bail out if this request is no longer current
|
|
116
147
|
const idx = this.#latest.indexOf(resolve);
|
|
117
148
|
if (idx === -1) return;
|
|
118
149
|
|
|
119
150
|
untrack(() => {
|
|
120
151
|
this.#latest.splice(0, idx).forEach((r) => r(undefined));
|
|
121
|
-
this.#error =
|
|
152
|
+
this.#error = error;
|
|
122
153
|
this.#loading = false;
|
|
123
154
|
});
|
|
124
155
|
|
|
125
|
-
reject(
|
|
156
|
+
reject(new HandledHttpError(error));
|
|
126
157
|
});
|
|
127
158
|
|
|
128
159
|
return promise;
|
|
@@ -131,12 +162,12 @@ export class Query {
|
|
|
131
162
|
get then() {
|
|
132
163
|
// TODO this should be unnecessary but due to the bug described
|
|
133
164
|
// in #start, we need to do this in some circumstances
|
|
134
|
-
this
|
|
165
|
+
this.start();
|
|
135
166
|
return this.#then;
|
|
136
167
|
}
|
|
137
168
|
|
|
138
169
|
get catch() {
|
|
139
|
-
this
|
|
170
|
+
this.start();
|
|
140
171
|
this.#then;
|
|
141
172
|
return (/** @type {any} */ reject) => {
|
|
142
173
|
return this.#then(undefined, reject);
|
|
@@ -144,7 +175,7 @@ export class Query {
|
|
|
144
175
|
}
|
|
145
176
|
|
|
146
177
|
get finally() {
|
|
147
|
-
this
|
|
178
|
+
this.start();
|
|
148
179
|
this.#then;
|
|
149
180
|
return (/** @type {any} */ fn) => {
|
|
150
181
|
return this.#then(
|
|
@@ -161,12 +192,12 @@ export class Query {
|
|
|
161
192
|
}
|
|
162
193
|
|
|
163
194
|
get current() {
|
|
164
|
-
this
|
|
195
|
+
this.start();
|
|
165
196
|
return this.#current;
|
|
166
197
|
}
|
|
167
198
|
|
|
168
199
|
get error() {
|
|
169
|
-
this
|
|
200
|
+
this.start();
|
|
170
201
|
return this.#error;
|
|
171
202
|
}
|
|
172
203
|
|
|
@@ -174,7 +205,7 @@ export class Query {
|
|
|
174
205
|
* Returns true if the resource is loading or reloading.
|
|
175
206
|
*/
|
|
176
207
|
get loading() {
|
|
177
|
-
this
|
|
208
|
+
this.start();
|
|
178
209
|
return this.#loading;
|
|
179
210
|
}
|
|
180
211
|
|
|
@@ -182,7 +213,7 @@ export class Query {
|
|
|
182
213
|
* Returns true once the resource has been loaded for the first time.
|
|
183
214
|
*/
|
|
184
215
|
get ready() {
|
|
185
|
-
this
|
|
216
|
+
this.start();
|
|
186
217
|
return this.#ready;
|
|
187
218
|
}
|
|
188
219
|
|
|
@@ -198,6 +229,10 @@ export class Query {
|
|
|
198
229
|
* @param {T} value
|
|
199
230
|
*/
|
|
200
231
|
set(value) {
|
|
232
|
+
// normally consumed in the constructor, but make sure a leftover
|
|
233
|
+
// SSR record can never shadow the newly-set value
|
|
234
|
+
delete query_responses[this.#key];
|
|
235
|
+
|
|
201
236
|
this.#clear_pending();
|
|
202
237
|
this.#ready = true;
|
|
203
238
|
this.#loading = false;
|
|
@@ -206,13 +241,15 @@ export class Query {
|
|
|
206
241
|
this.#promise = Promise.resolve();
|
|
207
242
|
}
|
|
208
243
|
|
|
209
|
-
/**
|
|
210
|
-
* @param {unknown} error
|
|
211
|
-
*/
|
|
244
|
+
/** @param {HttpError} error */
|
|
212
245
|
fail(error) {
|
|
246
|
+
// normally consumed in the constructor, but make sure a leftover
|
|
247
|
+
// SSR record can never shadow the newly-set error
|
|
248
|
+
delete query_responses[this.#key];
|
|
249
|
+
|
|
213
250
|
this.#clear_pending();
|
|
214
251
|
this.#loading = false;
|
|
215
|
-
this.#error = error;
|
|
252
|
+
this.#error = error.body;
|
|
216
253
|
|
|
217
254
|
const promise = Promise.reject(error);
|
|
218
255
|
|
|
@@ -242,6 +279,15 @@ export class Query {
|
|
|
242
279
|
return release;
|
|
243
280
|
}
|
|
244
281
|
|
|
282
|
+
/**
|
|
283
|
+
* Reset ahead of a navigation that invalidates all, to force newly
|
|
284
|
+
* rendered queries to get fresh data
|
|
285
|
+
*/
|
|
286
|
+
reset() {
|
|
287
|
+
this.#promise = null;
|
|
288
|
+
delete query_responses[this.#key];
|
|
289
|
+
}
|
|
290
|
+
|
|
245
291
|
get [Symbol.toStringTag]() {
|
|
246
292
|
return 'Query';
|
|
247
293
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { query_map } from '../../client.js';
|
|
2
2
|
import {
|
|
3
3
|
pin_in_effect,
|
|
4
4
|
pin_while_resolving,
|
|
@@ -25,11 +25,11 @@ export class QueryProxy {
|
|
|
25
25
|
/**
|
|
26
26
|
* @param {string} id
|
|
27
27
|
* @param {any} arg
|
|
28
|
-
* @param {(
|
|
28
|
+
* @param {(payload: string) => Promise<T>} fn
|
|
29
29
|
*/
|
|
30
30
|
constructor(id, arg, fn) {
|
|
31
31
|
this.#id = id;
|
|
32
|
-
this.#payload = stringify_remote_arg(arg
|
|
32
|
+
this.#payload = stringify_remote_arg(arg);
|
|
33
33
|
this.#key = create_remote_key(id, this.#payload);
|
|
34
34
|
Object.defineProperty(this, QUERY_RESOURCE_KEY, { value: this.#key });
|
|
35
35
|
this.#fn = fn;
|
|
@@ -41,7 +41,7 @@ export class QueryProxy {
|
|
|
41
41
|
this.#payload,
|
|
42
42
|
// IMPORTANT: This cannot close over `this` or it becomes impossible to
|
|
43
43
|
// garbage collect the QueryProxy and thus impossible to evict cache entries.
|
|
44
|
-
() => new Query(key, () => fn(
|
|
44
|
+
() => new Query(key, () => fn(payload))
|
|
45
45
|
);
|
|
46
46
|
|
|
47
47
|
cache.ref(this, entry, this.#id, this.#payload);
|
|
@@ -98,7 +98,7 @@ export class QueryProxy {
|
|
|
98
98
|
this.#payload,
|
|
99
99
|
// IMPORTANT: This cannot close over `this` or it becomes impossible to
|
|
100
100
|
// garbage collect the QueryProxy and thus impossible to evict cache entries.
|
|
101
|
-
() => new Query(key_ref, () => fn_ref(
|
|
101
|
+
() => new Query(key_ref, () => fn_ref(payload_ref))
|
|
102
102
|
);
|
|
103
103
|
|
|
104
104
|
const deref = cache.manual_ref(entry, this.#id, this.#payload);
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
/** @import { RemoteQueryFunction } from '@sveltejs/kit' */
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { get_remote_request_headers, QUERY_FUNCTION_ID } from './shared.svelte.js';
|
|
1
|
+
/** @import { RemoteQueryFunction } from '@sveltejs/kit/remote' */
|
|
2
|
+
import { app_dir, base } from '#app/paths';
|
|
3
|
+
import { _goto } from '../client.js';
|
|
4
|
+
import { QUERY_FUNCTION_ID, remote_request } from './shared.svelte.js';
|
|
6
5
|
import { QueryProxy } from './query/proxy.js';
|
|
7
|
-
import
|
|
8
|
-
import { HttpError, Redirect } from '@sveltejs/kit/internal';
|
|
9
|
-
import { hydratable } from 'svelte';
|
|
6
|
+
import { HandledHttpError } from '@sveltejs/kit/internal';
|
|
10
7
|
|
|
11
8
|
/**
|
|
12
9
|
* @param {string} id
|
|
@@ -18,84 +15,78 @@ export function query_batch(id) {
|
|
|
18
15
|
|
|
19
16
|
/** @type {RemoteQueryFunction<any, any>} */
|
|
20
17
|
const wrapper = (arg) => {
|
|
21
|
-
return new QueryProxy(id, arg, async (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
batching.set(payload, entry);
|
|
18
|
+
return new QueryProxy(id, arg, async (payload) => {
|
|
19
|
+
return await new Promise((resolve, reject) => {
|
|
20
|
+
// create_remote_function caches identical calls, but in case a refresh to the same query is called multiple times this function
|
|
21
|
+
// is invoked multiple times with the same payload, so we need to deduplicate here
|
|
22
|
+
const entry = batching.get(payload) ?? [];
|
|
23
|
+
entry.push({ resolve, reject });
|
|
24
|
+
batching.set(payload, entry);
|
|
29
25
|
|
|
30
|
-
|
|
26
|
+
if (batching.size > 1) return;
|
|
31
27
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
};
|
|
28
|
+
// Do this here, after await Svelte' reactivity context is gone.
|
|
29
|
+
// TODO is it possible to have batches of the same key
|
|
30
|
+
// but in different forks/async contexts and in the same macrotask?
|
|
31
|
+
// If so this would potentially be buggy
|
|
32
|
+
const headers = {
|
|
33
|
+
'Content-Type': 'application/json'
|
|
34
|
+
};
|
|
40
35
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
36
|
+
// Wait for the next macrotask - don't use microtask as Svelte runtime uses these to collect changes and flush them,
|
|
37
|
+
// and flushes could reveal more queries that should be batched.
|
|
38
|
+
setTimeout(async () => {
|
|
39
|
+
const batched = batching;
|
|
40
|
+
batching = new Map();
|
|
46
41
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
42
|
+
try {
|
|
43
|
+
const response = await remote_request(`${base}/${app_dir}/remote/${id}`, {
|
|
44
|
+
method: 'POST',
|
|
45
|
+
body: JSON.stringify({
|
|
46
|
+
payloads: Array.from(batched.keys())
|
|
47
|
+
}),
|
|
48
|
+
headers
|
|
49
|
+
});
|
|
55
50
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
51
|
+
if (response.redirect) {
|
|
52
|
+
// Use internal version to allow redirects to external URLs
|
|
53
|
+
await _goto(response.redirect);
|
|
59
54
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
55
|
+
// settle all batched promises (with `undefined`, like a redirect
|
|
56
|
+
// from a non-batched query) so that callers don't hang forever
|
|
57
|
+
for (const resolvers of batched.values()) {
|
|
58
|
+
for (const { resolve } of resolvers) {
|
|
59
|
+
resolve(undefined);
|
|
60
|
+
}
|
|
63
61
|
}
|
|
64
62
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
throw new Redirect(307, result.location);
|
|
68
|
-
}
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
69
65
|
|
|
70
|
-
|
|
66
|
+
const results = response._;
|
|
67
|
+
let i = 0;
|
|
71
68
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
let i = 0;
|
|
69
|
+
for (const resolvers of batched.values()) {
|
|
70
|
+
const result = results[i];
|
|
75
71
|
|
|
76
|
-
for (const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
resolve(results[i].data);
|
|
82
|
-
}
|
|
72
|
+
for (const { resolve, reject } of resolvers) {
|
|
73
|
+
if (result.type === 'error') {
|
|
74
|
+
reject(new HandledHttpError(result.error));
|
|
75
|
+
} else {
|
|
76
|
+
resolve(result.data);
|
|
83
77
|
}
|
|
84
|
-
i++;
|
|
85
78
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
79
|
+
i++;
|
|
80
|
+
}
|
|
81
|
+
} catch (e) {
|
|
82
|
+
for (const resolvers of batched.values()) {
|
|
83
|
+
for (const { reject } of resolvers) {
|
|
84
|
+
reject(e);
|
|
92
85
|
}
|
|
93
86
|
}
|
|
94
|
-
}
|
|
95
|
-
});
|
|
87
|
+
}
|
|
88
|
+
}, 0);
|
|
96
89
|
});
|
|
97
|
-
|
|
98
|
-
return devalue.parse(serialized, app.decoders);
|
|
99
90
|
});
|
|
100
91
|
};
|
|
101
92
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @import { RemoteLiveQuery, RemoteLiveQueryFunction } from '@sveltejs/kit' */
|
|
1
|
+
/** @import { RemoteLiveQuery, RemoteLiveQueryFunction } from '@sveltejs/kit/remote' */
|
|
2
2
|
import { live_query_map } from '../../client.js';
|
|
3
3
|
import { QUERY_FUNCTION_ID } from '../shared.svelte.js';
|
|
4
4
|
import { DEV } from 'esm-env';
|