@sveltejs/kit 2.54.0 → 2.56.0
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 +3 -4
- package/src/core/postbuild/analyse.js +3 -3
- package/src/core/postbuild/prerender.js +9 -6
- package/src/core/sync/write_non_ambient.js +143 -37
- package/src/core/sync/write_tsconfig.js +3 -1
- package/src/core/sync/write_types/index.js +1 -5
- package/src/exports/internal/remote-functions.js +2 -2
- package/src/exports/public.d.ts +38 -12
- package/src/exports/vite/build/build_server.js +24 -4
- package/src/exports/vite/build/build_service_worker.js +16 -6
- package/src/exports/vite/build/utils.js +18 -3
- package/src/exports/vite/index.js +336 -327
- package/src/runtime/app/paths/server.js +1 -1
- package/src/runtime/app/server/index.js +1 -1
- package/src/runtime/app/server/remote/command.js +12 -7
- package/src/runtime/app/server/remote/form.js +14 -14
- package/src/runtime/app/server/remote/index.js +1 -0
- package/src/runtime/app/server/remote/prerender.js +8 -7
- package/src/runtime/app/server/remote/query.js +141 -66
- package/src/runtime/app/server/remote/requested.js +172 -0
- package/src/runtime/app/server/remote/shared.js +32 -10
- package/src/runtime/app/state/server.js +1 -1
- package/src/runtime/client/client.js +45 -20
- package/src/runtime/client/remote-functions/command.svelte.js +39 -16
- package/src/runtime/client/remote-functions/form.svelte.js +41 -24
- package/src/runtime/client/remote-functions/prerender.svelte.js +105 -76
- package/src/runtime/client/remote-functions/query.svelte.js +408 -138
- package/src/runtime/client/remote-functions/shared.svelte.js +95 -94
- package/src/runtime/components/svelte-5/error.svelte +2 -0
- package/src/runtime/form-utils.js +3 -7
- package/src/runtime/server/endpoint.js +0 -1
- package/src/runtime/server/page/actions.js +2 -1
- package/src/runtime/server/page/load_data.js +3 -1
- package/src/runtime/server/page/render.js +38 -15
- package/src/runtime/server/remote.js +65 -50
- package/src/runtime/server/respond.js +17 -3
- package/src/runtime/server/utils.js +0 -12
- package/src/runtime/shared.js +233 -5
- package/src/types/global-private.d.ts +4 -4
- package/src/types/internal.d.ts +80 -44
- package/src/utils/css.js +0 -3
- package/src/utils/escape.js +15 -3
- package/src/version.js +1 -1
- package/types/index.d.ts +67 -13
- package/types/index.d.ts.map +6 -1
|
@@ -8,7 +8,7 @@ import { get_hooks } from '__SERVER__/internal.js';
|
|
|
8
8
|
/** @type {import('./client.js').asset} */
|
|
9
9
|
export function asset(file) {
|
|
10
10
|
// @ts-expect-error we use the `resolve` mechanism, but with the 'wrong' input
|
|
11
|
-
return assets ? assets + file : resolve(file);
|
|
11
|
+
return assets && assets !== base ? assets + file : resolve(file);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
/** @type {import('./client.js').resolve} */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** @import { RemoteCommand } from '@sveltejs/kit' */
|
|
2
|
-
/** @import {
|
|
2
|
+
/** @import { MaybePromise, RemoteCommandInternals } from 'types' */
|
|
3
3
|
/** @import { StandardSchemaV1 } from '@standard-schema/spec' */
|
|
4
4
|
import { get_request_store } from '@sveltejs/kit/internal/server';
|
|
5
5
|
import { create_validator, run_remote_function } from './shared.js';
|
|
@@ -58,21 +58,26 @@ export function command(validate_or_fn, maybe_fn) {
|
|
|
58
58
|
/** @type {(arg?: any) => MaybePromise<Input>} */
|
|
59
59
|
const validate = create_validator(validate_or_fn, maybe_fn);
|
|
60
60
|
|
|
61
|
-
/** @type {
|
|
61
|
+
/** @type {RemoteCommandInternals} */
|
|
62
62
|
const __ = { type: 'command', id: '', name: '' };
|
|
63
63
|
|
|
64
|
-
/** @type {RemoteCommand<Input, Output> & { __:
|
|
64
|
+
/** @type {RemoteCommand<Input, Output> & { __: RemoteCommandInternals }} */
|
|
65
65
|
const wrapper = (arg) => {
|
|
66
66
|
const { event, state } = get_request_store();
|
|
67
67
|
|
|
68
|
-
if (!
|
|
69
|
-
const disallowed_method = !MUTATIVE_METHODS.includes(event.request.method);
|
|
68
|
+
if (!MUTATIVE_METHODS.includes(event.request.method)) {
|
|
70
69
|
throw new Error(
|
|
71
|
-
`Cannot call a command (\`${__.name}(${maybe_fn ? '...' : ''})\`)
|
|
70
|
+
`Cannot call a command (\`${__.name}(${maybe_fn ? '...' : ''})\`) from a ${event.request.method} handler`
|
|
72
71
|
);
|
|
73
72
|
}
|
|
74
73
|
|
|
75
|
-
state.
|
|
74
|
+
if (state.is_in_render) {
|
|
75
|
+
throw new Error(
|
|
76
|
+
`Cannot call a command (\`${__.name}(${maybe_fn ? '...' : ''})\`) during server-side rendering`
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
state.remote.refreshes ??= {};
|
|
76
81
|
|
|
77
82
|
const promise = Promise.resolve(
|
|
78
83
|
run_remote_function(event, state, true, () => validate(arg), fn)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** @import { RemoteFormInput, RemoteForm, InvalidField } from '@sveltejs/kit' */
|
|
2
|
-
/** @import { InternalRemoteFormIssue, MaybePromise,
|
|
2
|
+
/** @import { InternalRemoteFormIssue, MaybePromise, RemoteFormInternals } from 'types' */
|
|
3
3
|
/** @import { StandardSchemaV1 } from '@standard-schema/spec' */
|
|
4
4
|
import { get_request_store } from '@sveltejs/kit/internal/server';
|
|
5
5
|
import { DEV } from 'esm-env';
|
|
@@ -84,7 +84,7 @@ export function form(validate_or_fn, maybe_fn) {
|
|
|
84
84
|
}
|
|
85
85
|
});
|
|
86
86
|
|
|
87
|
-
/** @type {
|
|
87
|
+
/** @type {RemoteFormInternals} */
|
|
88
88
|
const __ = {
|
|
89
89
|
type: 'form',
|
|
90
90
|
name: '',
|
|
@@ -136,7 +136,7 @@ export function form(validate_or_fn, maybe_fn) {
|
|
|
136
136
|
data = validated.value;
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
state.refreshes ??= {};
|
|
139
|
+
state.remote.refreshes ??= {};
|
|
140
140
|
|
|
141
141
|
const issue = create_issues();
|
|
142
142
|
|
|
@@ -160,7 +160,7 @@ export function form(validate_or_fn, maybe_fn) {
|
|
|
160
160
|
// We don't need to care about args or deduplicating calls, because uneval results are only relevant in full page reloads
|
|
161
161
|
// where only one form submission is active at the same time
|
|
162
162
|
if (!event.isRemoteRequest) {
|
|
163
|
-
get_cache(__, state)[''] ??= output;
|
|
163
|
+
get_cache(__, state)[''] ??= { serialize: true, data: output };
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
return output;
|
|
@@ -178,26 +178,26 @@ export function form(validate_or_fn, maybe_fn) {
|
|
|
178
178
|
get() {
|
|
179
179
|
return create_field_proxy(
|
|
180
180
|
{},
|
|
181
|
-
() => get_cache(__)?.['']?.input ?? {},
|
|
181
|
+
() => get_cache(__)?.['']?.data?.input ?? {},
|
|
182
182
|
(path, value) => {
|
|
183
183
|
const cache = get_cache(__);
|
|
184
|
-
const
|
|
184
|
+
const entry = cache[''];
|
|
185
185
|
|
|
186
|
-
if (data?.submission) {
|
|
186
|
+
if (entry?.data?.submission) {
|
|
187
187
|
// don't override a submission
|
|
188
188
|
return;
|
|
189
189
|
}
|
|
190
190
|
|
|
191
191
|
if (path.length === 0) {
|
|
192
|
-
(cache[''] ??= {}).input = value;
|
|
192
|
+
(cache[''] ??= { serialize: true, data: {} }).data.input = value;
|
|
193
193
|
return;
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
-
const input = data?.input ?? {};
|
|
196
|
+
const input = entry?.data?.input ?? {};
|
|
197
197
|
deep_set(input, path.map(String), value);
|
|
198
|
-
(cache[''] ??= {}).input = input;
|
|
198
|
+
(cache[''] ??= { serialize: true, data: {} }).data.input = input;
|
|
199
199
|
},
|
|
200
|
-
() => flatten_issues(get_cache(__)?.['']?.issues ?? [])
|
|
200
|
+
() => flatten_issues(get_cache(__)?.['']?.data?.issues ?? [])
|
|
201
201
|
);
|
|
202
202
|
}
|
|
203
203
|
});
|
|
@@ -219,7 +219,7 @@ export function form(validate_or_fn, maybe_fn) {
|
|
|
219
219
|
Object.defineProperty(instance, 'result', {
|
|
220
220
|
get() {
|
|
221
221
|
try {
|
|
222
|
-
return get_cache(__)?.['']?.result;
|
|
222
|
+
return get_cache(__)?.['']?.data?.result;
|
|
223
223
|
} catch {
|
|
224
224
|
return undefined;
|
|
225
225
|
}
|
|
@@ -248,14 +248,14 @@ export function form(validate_or_fn, maybe_fn) {
|
|
|
248
248
|
value: (key) => {
|
|
249
249
|
const { state } = get_request_store();
|
|
250
250
|
const cache_key = __.id + '|' + JSON.stringify(key);
|
|
251
|
-
let instance = (state.
|
|
251
|
+
let instance = (state.remote.forms ??= new Map()).get(cache_key);
|
|
252
252
|
|
|
253
253
|
if (!instance) {
|
|
254
254
|
instance = create_instance(key);
|
|
255
255
|
instance.__.id = `${__.id}/${encodeURIComponent(JSON.stringify(key))}`;
|
|
256
256
|
instance.__.name = __.name;
|
|
257
257
|
|
|
258
|
-
state.
|
|
258
|
+
state.remote.forms.set(cache_key, instance);
|
|
259
259
|
}
|
|
260
260
|
|
|
261
261
|
return instance;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** @import { RemoteResource, RemotePrerenderFunction } from '@sveltejs/kit' */
|
|
2
|
-
/** @import { RemotePrerenderInputsGenerator,
|
|
2
|
+
/** @import { RemotePrerenderInputsGenerator, RemotePrerenderInternals, MaybePromise } from 'types' */
|
|
3
3
|
/** @import { StandardSchemaV1 } from '@standard-schema/spec' */
|
|
4
4
|
import { error, json } from '@sveltejs/kit';
|
|
5
5
|
import { DEV } from 'esm-env';
|
|
@@ -76,7 +76,7 @@ export function prerender(validate_or_fn, fn_or_options, maybe_options) {
|
|
|
76
76
|
/** @type {(arg?: any) => MaybePromise<Input>} */
|
|
77
77
|
const validate = create_validator(validate_or_fn, maybe_fn);
|
|
78
78
|
|
|
79
|
-
/** @type {
|
|
79
|
+
/** @type {RemotePrerenderInternals} */
|
|
80
80
|
const __ = {
|
|
81
81
|
type: 'prerender',
|
|
82
82
|
id: '',
|
|
@@ -86,7 +86,7 @@ export function prerender(validate_or_fn, fn_or_options, maybe_options) {
|
|
|
86
86
|
dynamic: options?.dynamic
|
|
87
87
|
};
|
|
88
88
|
|
|
89
|
-
/** @type {RemotePrerenderFunction<Input, Output> & { __:
|
|
89
|
+
/** @type {RemotePrerenderFunction<Input, Output> & { __: RemotePrerenderInternals }} */
|
|
90
90
|
const wrapper = (arg) => {
|
|
91
91
|
/** @type {Promise<Output> & Partial<RemoteResource<Output>>} */
|
|
92
92
|
const promise = (async () => {
|
|
@@ -103,8 +103,9 @@ export function prerender(validate_or_fn, fn_or_options, maybe_options) {
|
|
|
103
103
|
|
|
104
104
|
// TODO adapters can provide prerendered data more efficiently than
|
|
105
105
|
// fetching from the public internet
|
|
106
|
-
const promise = (cache[key] ??=
|
|
107
|
-
|
|
106
|
+
const promise = (cache[key] ??= {
|
|
107
|
+
serialize: true,
|
|
108
|
+
data: fetch(new URL(url, event.url.origin).href).then(async (response) => {
|
|
108
109
|
if (!response.ok) {
|
|
109
110
|
throw new Error('Prerendered response not found');
|
|
110
111
|
}
|
|
@@ -116,8 +117,8 @@ export function prerender(validate_or_fn, fn_or_options, maybe_options) {
|
|
|
116
117
|
}
|
|
117
118
|
|
|
118
119
|
return prerendered.result;
|
|
119
|
-
}
|
|
120
|
-
)
|
|
120
|
+
})
|
|
121
|
+
}).data;
|
|
121
122
|
|
|
122
123
|
return parse_remote_response(await promise, state.transport);
|
|
123
124
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/** @import { RemoteQuery, RemoteQueryFunction } from '@sveltejs/kit' */
|
|
2
|
-
/** @import {
|
|
2
|
+
/** @import { RemoteInternals, MaybePromise, RequestState, RemoteQueryBatchInternals, RemoteQueryInternals } from 'types' */
|
|
3
3
|
/** @import { StandardSchemaV1 } from '@standard-schema/spec' */
|
|
4
4
|
import { get_request_store } from '@sveltejs/kit/internal/server';
|
|
5
|
-
import { create_remote_key, stringify_remote_arg } from '../../../shared.js';
|
|
5
|
+
import { create_remote_key, stringify, stringify_remote_arg } from '../../../shared.js';
|
|
6
6
|
import { prerendering } from '__sveltekit/environment';
|
|
7
7
|
import { create_validator, get_cache, get_response, run_remote_function } from './shared.js';
|
|
8
8
|
import { handle_error_and_jsonify } from '../../../server/utils.js';
|
|
@@ -61,10 +61,10 @@ export function query(validate_or_fn, maybe_fn) {
|
|
|
61
61
|
/** @type {(arg?: any) => MaybePromise<Input>} */
|
|
62
62
|
const validate = create_validator(validate_or_fn, maybe_fn);
|
|
63
63
|
|
|
64
|
-
/** @type {
|
|
65
|
-
const __ = { type: 'query', id: '', name: '' };
|
|
64
|
+
/** @type {RemoteQueryInternals} */
|
|
65
|
+
const __ = { type: 'query', id: '', name: '', validate };
|
|
66
66
|
|
|
67
|
-
/** @type {RemoteQueryFunction<Input, Output> & { __:
|
|
67
|
+
/** @type {RemoteQueryFunction<Input, Output> & { __: RemoteQueryInternals }} */
|
|
68
68
|
const wrapper = (arg) => {
|
|
69
69
|
if (prerendering) {
|
|
70
70
|
throw new Error(
|
|
@@ -73,34 +73,44 @@ export function query(validate_or_fn, maybe_fn) {
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
const { event, state } = get_request_store();
|
|
76
|
+
// if the user got this argument from `requested(query)`, it will have already passed validation
|
|
77
|
+
const is_validated = is_validated_argument(__, state, arg);
|
|
76
78
|
|
|
77
|
-
|
|
78
|
-
run_remote_function(event, state, false, () => validate(arg), fn)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const promise = get_response(__, arg, state, get_remote_function_result);
|
|
82
|
-
|
|
83
|
-
promise.catch(() => {});
|
|
79
|
+
return create_query_resource(__, arg, state, () =>
|
|
80
|
+
run_remote_function(event, state, false, () => (is_validated ? arg : validate(arg)), fn)
|
|
81
|
+
);
|
|
82
|
+
};
|
|
84
83
|
|
|
85
|
-
|
|
84
|
+
Object.defineProperty(wrapper, '__', { value: __ });
|
|
86
85
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const is_immediate_refresh = !refresh_context.cache[refresh_context.cache_key];
|
|
90
|
-
const value = is_immediate_refresh ? promise : get_remote_function_result();
|
|
91
|
-
return update_refresh_value(refresh_context, value, is_immediate_refresh);
|
|
92
|
-
};
|
|
86
|
+
return wrapper;
|
|
87
|
+
}
|
|
93
88
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
89
|
+
/**
|
|
90
|
+
* @param {RemoteQueryInternals} __
|
|
91
|
+
* @param {RequestState} state
|
|
92
|
+
* @param {any} arg
|
|
93
|
+
*/
|
|
94
|
+
function is_validated_argument(__, state, arg) {
|
|
95
|
+
return state.remote.validated?.get(__.id)?.has(arg) ?? false;
|
|
96
|
+
}
|
|
97
97
|
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
/**
|
|
99
|
+
* @param {RemoteQueryInternals} __
|
|
100
|
+
* @param {RequestState} state
|
|
101
|
+
* @param {any} arg
|
|
102
|
+
*/
|
|
103
|
+
export function mark_argument_validated(__, state, arg) {
|
|
104
|
+
const validated = (state.remote.validated ??= new Map());
|
|
105
|
+
let validated_args = validated.get(__.id);
|
|
100
106
|
|
|
101
|
-
|
|
107
|
+
if (!validated_args) {
|
|
108
|
+
validated_args = new Set();
|
|
109
|
+
validated.set(__.id, validated_args);
|
|
110
|
+
}
|
|
102
111
|
|
|
103
|
-
|
|
112
|
+
validated_args.add(arg);
|
|
113
|
+
return arg;
|
|
104
114
|
}
|
|
105
115
|
|
|
106
116
|
/**
|
|
@@ -145,7 +155,7 @@ function batch(validate_or_fn, maybe_fn) {
|
|
|
145
155
|
/** @type {(arg?: any) => MaybePromise<Input>} */
|
|
146
156
|
const validate = create_validator(validate_or_fn, maybe_fn);
|
|
147
157
|
|
|
148
|
-
/** @type {
|
|
158
|
+
/** @type {RemoteQueryBatchInternals} */
|
|
149
159
|
const __ = {
|
|
150
160
|
type: 'query_batch',
|
|
151
161
|
id: '',
|
|
@@ -164,7 +174,8 @@ function batch(validate_or_fn, maybe_fn) {
|
|
|
164
174
|
return Promise.all(
|
|
165
175
|
input.map(async (arg, i) => {
|
|
166
176
|
try {
|
|
167
|
-
|
|
177
|
+
const data = get_result(arg, i);
|
|
178
|
+
return { type: 'result', data: stringify(data, state.transport) };
|
|
168
179
|
} catch (error) {
|
|
169
180
|
return {
|
|
170
181
|
type: 'error',
|
|
@@ -182,10 +193,10 @@ function batch(validate_or_fn, maybe_fn) {
|
|
|
182
193
|
}
|
|
183
194
|
};
|
|
184
195
|
|
|
185
|
-
/** @type {{
|
|
186
|
-
let batching =
|
|
196
|
+
/** @type {Map<string, { arg: any, resolvers: Array<{resolve: (value: any) => void, reject: (error: any) => void}> }>} */
|
|
197
|
+
let batching = new Map();
|
|
187
198
|
|
|
188
|
-
/** @type {RemoteQueryFunction<Input, Output> & { __:
|
|
199
|
+
/** @type {RemoteQueryFunction<Input, Output> & { __: RemoteQueryBatchInternals }} */
|
|
189
200
|
const wrapper = (arg) => {
|
|
190
201
|
if (prerendering) {
|
|
191
202
|
throw new Error(
|
|
@@ -195,85 +206,146 @@ function batch(validate_or_fn, maybe_fn) {
|
|
|
195
206
|
|
|
196
207
|
const { event, state } = get_request_store();
|
|
197
208
|
|
|
198
|
-
|
|
209
|
+
return create_query_resource(__, arg, state, () => {
|
|
199
210
|
// Collect all the calls to the same query in the same macrotask,
|
|
200
211
|
// then execute them as one backend request.
|
|
201
212
|
return new Promise((resolve, reject) => {
|
|
202
|
-
|
|
203
|
-
batching.
|
|
204
|
-
batching.resolvers.push({ resolve, reject });
|
|
213
|
+
const key = stringify_remote_arg(arg, state.transport);
|
|
214
|
+
const entry = batching.get(key);
|
|
205
215
|
|
|
206
|
-
if (
|
|
216
|
+
if (entry) {
|
|
217
|
+
entry.resolvers.push({ resolve, reject });
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
batching.set(key, {
|
|
222
|
+
arg,
|
|
223
|
+
resolvers: [{ resolve, reject }]
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
if (batching.size > 1) return;
|
|
207
227
|
|
|
208
228
|
setTimeout(async () => {
|
|
209
229
|
const batched = batching;
|
|
210
|
-
batching =
|
|
230
|
+
batching = new Map();
|
|
231
|
+
const entries = Array.from(batched.values());
|
|
232
|
+
const args = entries.map((entry) => entry.arg);
|
|
211
233
|
|
|
212
234
|
try {
|
|
213
235
|
return await run_remote_function(
|
|
214
236
|
event,
|
|
215
237
|
state,
|
|
216
238
|
false,
|
|
217
|
-
async () => Promise.all(
|
|
239
|
+
async () => Promise.all(args.map(validate)),
|
|
218
240
|
async (input) => {
|
|
219
241
|
const get_result = await fn(input);
|
|
220
242
|
|
|
221
|
-
for (let i = 0; i <
|
|
243
|
+
for (let i = 0; i < entries.length; i++) {
|
|
222
244
|
try {
|
|
223
|
-
|
|
245
|
+
const result = get_result(input[i], i);
|
|
246
|
+
|
|
247
|
+
for (const resolver of entries[i].resolvers) {
|
|
248
|
+
resolver.resolve(result);
|
|
249
|
+
}
|
|
224
250
|
} catch (error) {
|
|
225
|
-
|
|
251
|
+
for (const resolver of entries[i].resolvers) {
|
|
252
|
+
resolver.reject(error);
|
|
253
|
+
}
|
|
226
254
|
}
|
|
227
255
|
}
|
|
228
256
|
}
|
|
229
257
|
);
|
|
230
258
|
} catch (error) {
|
|
231
|
-
for (const
|
|
232
|
-
resolver.
|
|
259
|
+
for (const entry of batched.values()) {
|
|
260
|
+
for (const resolver of entry.resolvers) {
|
|
261
|
+
resolver.reject(error);
|
|
262
|
+
}
|
|
233
263
|
}
|
|
234
264
|
}
|
|
235
265
|
}, 0);
|
|
236
266
|
});
|
|
237
|
-
};
|
|
267
|
+
});
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
Object.defineProperty(wrapper, '__', { value: __ });
|
|
238
271
|
|
|
239
|
-
|
|
240
|
-
|
|
272
|
+
return wrapper;
|
|
273
|
+
}
|
|
241
274
|
|
|
242
|
-
|
|
275
|
+
/**
|
|
276
|
+
* @param {RemoteInternals} __
|
|
277
|
+
* @param {any} arg
|
|
278
|
+
* @param {RequestState} state
|
|
279
|
+
* @param {() => Promise<any>} fn
|
|
280
|
+
* @returns {RemoteQuery<any>}
|
|
281
|
+
*/
|
|
282
|
+
function create_query_resource(__, arg, state, fn) {
|
|
283
|
+
/** @type {Promise<any> | null} */
|
|
284
|
+
let promise = null;
|
|
243
285
|
|
|
244
|
-
|
|
286
|
+
const get_promise = () => {
|
|
287
|
+
return (promise ??= get_response(__, arg, state, fn));
|
|
288
|
+
};
|
|
245
289
|
|
|
246
|
-
|
|
290
|
+
return {
|
|
291
|
+
/** @type {Promise<any>['catch']} */
|
|
292
|
+
catch(onrejected) {
|
|
293
|
+
return get_promise().catch(onrejected);
|
|
294
|
+
},
|
|
295
|
+
current: undefined,
|
|
296
|
+
error: undefined,
|
|
297
|
+
/** @type {Promise<any>['finally']} */
|
|
298
|
+
finally(onfinally) {
|
|
299
|
+
return get_promise().finally(onfinally);
|
|
300
|
+
},
|
|
301
|
+
loading: true,
|
|
302
|
+
ready: false,
|
|
303
|
+
refresh() {
|
|
247
304
|
const refresh_context = get_refresh_context(__, 'refresh', arg);
|
|
248
305
|
const is_immediate_refresh = !refresh_context.cache[refresh_context.cache_key];
|
|
249
|
-
const value = is_immediate_refresh ?
|
|
306
|
+
const value = is_immediate_refresh ? get_promise() : fn();
|
|
250
307
|
return update_refresh_value(refresh_context, value, is_immediate_refresh);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
|
|
308
|
+
},
|
|
309
|
+
run() {
|
|
310
|
+
// potential TODO: if we want to be able to run queries at the top level of modules / outside of the request context, we could technically remove
|
|
311
|
+
// the requirement that `state` is defined, but that's kind of an annoying change to make, so we're going to wait on that until we have any sort of
|
|
312
|
+
// concrete use case.
|
|
313
|
+
if (!state.is_in_universal_load) {
|
|
314
|
+
throw new Error(
|
|
315
|
+
'On the server, .run() can only be called in universal `load` functions. Anywhere else, just await the query directly'
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
return get_response(__, arg, state, fn);
|
|
319
|
+
},
|
|
320
|
+
/** @param {any} value */
|
|
321
|
+
set(value) {
|
|
322
|
+
return update_refresh_value(get_refresh_context(__, 'set', arg), value);
|
|
323
|
+
},
|
|
324
|
+
/** @type {Promise<any>['then']} */
|
|
325
|
+
then(onfulfilled, onrejected) {
|
|
326
|
+
return get_promise().then(onfulfilled, onrejected);
|
|
327
|
+
},
|
|
328
|
+
withOverride() {
|
|
254
329
|
throw new Error(`Cannot call '${__.name}.withOverride()' on the server`);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
|
|
330
|
+
},
|
|
331
|
+
get [Symbol.toStringTag]() {
|
|
332
|
+
return 'QueryResource';
|
|
333
|
+
}
|
|
258
334
|
};
|
|
259
|
-
|
|
260
|
-
Object.defineProperty(wrapper, '__', { value: __ });
|
|
261
|
-
|
|
262
|
-
return wrapper;
|
|
263
335
|
}
|
|
264
336
|
|
|
265
337
|
// Add batch as a property to the query function
|
|
266
338
|
Object.defineProperty(query, 'batch', { value: batch, enumerable: true });
|
|
267
339
|
|
|
268
340
|
/**
|
|
269
|
-
* @param {
|
|
341
|
+
* @param {RemoteInternals} __
|
|
270
342
|
* @param {'set' | 'refresh'} action
|
|
271
343
|
* @param {any} [arg]
|
|
272
|
-
* @returns {{ __:
|
|
344
|
+
* @returns {{ __: RemoteInternals; state: any; refreshes: Record<string, Promise<any>>; cache: Record<string, { serialize: boolean; data: any }>; refreshes_key: string; cache_key: string }}
|
|
273
345
|
*/
|
|
274
346
|
function get_refresh_context(__, action, arg) {
|
|
275
347
|
const { state } = get_request_store();
|
|
276
|
-
const { refreshes } = state;
|
|
348
|
+
const { refreshes } = state.remote;
|
|
277
349
|
|
|
278
350
|
if (!refreshes) {
|
|
279
351
|
const name = __.type === 'query_batch' ? `query.batch '${__.name}'` : `query '${__.name}'`;
|
|
@@ -290,7 +362,7 @@ function get_refresh_context(__, action, arg) {
|
|
|
290
362
|
}
|
|
291
363
|
|
|
292
364
|
/**
|
|
293
|
-
* @param {{ __:
|
|
365
|
+
* @param {{ __: RemoteInternals; refreshes: Record<string, Promise<any>>; cache: Record<string, { serialize: boolean; data: any }>; refreshes_key: string; cache_key: string }} context
|
|
294
366
|
* @param {any} value
|
|
295
367
|
* @param {boolean} [is_immediate_refresh=false]
|
|
296
368
|
* @returns {Promise<void>}
|
|
@@ -303,12 +375,15 @@ function update_refresh_value(
|
|
|
303
375
|
const promise = Promise.resolve(value);
|
|
304
376
|
|
|
305
377
|
if (!is_immediate_refresh) {
|
|
306
|
-
cache[cache_key] = promise;
|
|
378
|
+
cache[cache_key] = { serialize: true, data: promise };
|
|
307
379
|
}
|
|
308
380
|
|
|
309
381
|
if (__.id) {
|
|
310
382
|
refreshes[refreshes_key] = promise;
|
|
311
383
|
}
|
|
312
384
|
|
|
313
|
-
return promise.then(
|
|
385
|
+
return promise.then(
|
|
386
|
+
() => {},
|
|
387
|
+
() => {}
|
|
388
|
+
);
|
|
314
389
|
}
|