@sveltejs/kit 2.55.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_tsconfig.js +3 -1
- 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/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,18 +8,6 @@ import { fix_stack_trace } from '../shared-server.js';
|
|
|
8
8
|
import { ENDPOINT_METHODS } from '../../constants.js';
|
|
9
9
|
import { escape_html } from '../../utils/escape.js';
|
|
10
10
|
|
|
11
|
-
/** @param {any} body */
|
|
12
|
-
export function is_pojo(body) {
|
|
13
|
-
if (typeof body !== 'object') return false;
|
|
14
|
-
|
|
15
|
-
if (body) {
|
|
16
|
-
if (body instanceof Uint8Array) return false;
|
|
17
|
-
if (body instanceof ReadableStream) return false;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
11
|
/**
|
|
24
12
|
* @param {Partial<Record<import('types').HttpMethod, any>>} mod
|
|
25
13
|
* @param {import('types').HttpMethod} method
|
package/src/runtime/shared.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** @import { Transport } from '@sveltejs/kit' */
|
|
2
2
|
import * as devalue from 'devalue';
|
|
3
3
|
import { base64_decode, base64_encode, text_decoder } from './utils.js';
|
|
4
|
+
import * as svelte from 'svelte';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @param {string} route_id
|
|
@@ -50,17 +51,215 @@ export function stringify(data, transport) {
|
|
|
50
51
|
return devalue.stringify(data, encoders);
|
|
51
52
|
}
|
|
52
53
|
|
|
54
|
+
const object_proto_names = /* @__PURE__ */ Object.getOwnPropertyNames(Object.prototype)
|
|
55
|
+
.sort()
|
|
56
|
+
.join('\0');
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @param {unknown} thing
|
|
60
|
+
* @returns {thing is Record<PropertyKey, unknown>}
|
|
61
|
+
*/
|
|
62
|
+
function is_plain_object(thing) {
|
|
63
|
+
if (typeof thing !== 'object' || thing === null) return false;
|
|
64
|
+
const proto = Object.getPrototypeOf(thing);
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
proto === Object.prototype ||
|
|
68
|
+
proto === null ||
|
|
69
|
+
Object.getPrototypeOf(proto) === null ||
|
|
70
|
+
Object.getOwnPropertyNames(proto).sort().join('\0') === object_proto_names
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @param {Record<string, any>} value
|
|
76
|
+
* @param {Map<object, any>} clones
|
|
77
|
+
*/
|
|
78
|
+
function to_sorted(value, clones) {
|
|
79
|
+
const clone = Object.getPrototypeOf(value) === null ? Object.create(null) : {};
|
|
80
|
+
clones.set(value, clone);
|
|
81
|
+
Object.defineProperty(clone, remote_arg_marker, { value: true });
|
|
82
|
+
|
|
83
|
+
for (const key of Object.keys(value).sort()) {
|
|
84
|
+
const property = value[key];
|
|
85
|
+
Object.defineProperty(clone, key, {
|
|
86
|
+
value: clones.get(property) ?? property,
|
|
87
|
+
enumerable: true,
|
|
88
|
+
configurable: true,
|
|
89
|
+
writable: true
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return clone;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// "sveltekit remote arg"
|
|
97
|
+
const remote_object = '__skrao';
|
|
98
|
+
const remote_map = '__skram';
|
|
99
|
+
const remote_set = '__skras';
|
|
100
|
+
const remote_regex_guard = '__skrag';
|
|
101
|
+
const remote_arg_marker = Symbol(remote_object);
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* @param {Transport} transport
|
|
105
|
+
* @param {boolean} sort
|
|
106
|
+
* @param {Map<any, any>} remote_arg_clones
|
|
107
|
+
*/
|
|
108
|
+
function create_remote_arg_reducers(transport, sort, remote_arg_clones) {
|
|
109
|
+
/** @type {Record<string, (value: unknown) => unknown>} */
|
|
110
|
+
const remote_fns_reducers = {
|
|
111
|
+
[remote_regex_guard]:
|
|
112
|
+
/** @type {(value: unknown) => void} */
|
|
113
|
+
(value) => {
|
|
114
|
+
if (value instanceof RegExp) {
|
|
115
|
+
throw new Error('Regular expressions are not valid remote function arguments');
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
if (sort) {
|
|
121
|
+
/** @type {(value: unknown) => Array<[unknown, unknown]> | undefined} */
|
|
122
|
+
remote_fns_reducers[remote_map] = (value) => {
|
|
123
|
+
if (!(value instanceof Map)) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** @type {Array<[string, string]>} */
|
|
128
|
+
const entries = [];
|
|
129
|
+
|
|
130
|
+
for (const [key, val] of value) {
|
|
131
|
+
entries.push([stringify(key), stringify(val)]);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return entries.sort(([a1, a2], [b1, b2]) => {
|
|
135
|
+
if (a1 < b1) return -1;
|
|
136
|
+
if (a1 > b1) return 1;
|
|
137
|
+
if (a2 < b2) return -1;
|
|
138
|
+
if (a2 > b2) return 1;
|
|
139
|
+
return 0;
|
|
140
|
+
});
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
/** @type {(value: unknown) => unknown[] | undefined} */
|
|
144
|
+
remote_fns_reducers[remote_set] = (value) => {
|
|
145
|
+
if (!(value instanceof Set)) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** @type {string[]} */
|
|
150
|
+
const items = [];
|
|
151
|
+
|
|
152
|
+
for (const item of value) {
|
|
153
|
+
items.push(stringify(item));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
items.sort();
|
|
157
|
+
return items;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
/** @type {(value: unknown) => Record<PropertyKey, unknown> | undefined} */
|
|
161
|
+
remote_fns_reducers[remote_object] = (value) => {
|
|
162
|
+
if (!is_plain_object(value)) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (Object.hasOwn(value, remote_arg_marker)) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (remote_arg_clones.has(value)) {
|
|
171
|
+
return remote_arg_clones.get(value);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return to_sorted(value, remote_arg_clones);
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const user_reducers = Object.fromEntries(
|
|
179
|
+
Object.entries(transport).map(([k, v]) => [k, v.encode])
|
|
180
|
+
);
|
|
181
|
+
const all_reducers = { ...user_reducers, ...remote_fns_reducers };
|
|
182
|
+
|
|
183
|
+
/** @type {(value: unknown) => string} */
|
|
184
|
+
const stringify = (value) => devalue.stringify(value, all_reducers);
|
|
185
|
+
|
|
186
|
+
return all_reducers;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** @param {Transport} transport */
|
|
190
|
+
function create_remote_arg_revivers(transport) {
|
|
191
|
+
const remote_fns_revivers = {
|
|
192
|
+
/** @type {(value: unknown) => unknown} */
|
|
193
|
+
[remote_object]: (value) => value,
|
|
194
|
+
/** @type {(value: unknown) => Map<unknown, unknown>} */
|
|
195
|
+
[remote_map]: (value) => {
|
|
196
|
+
if (!Array.isArray(value)) {
|
|
197
|
+
throw new Error('Invalid data for Map reviver');
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const map = new Map();
|
|
201
|
+
|
|
202
|
+
for (const item of value) {
|
|
203
|
+
if (
|
|
204
|
+
!Array.isArray(item) ||
|
|
205
|
+
item.length !== 2 ||
|
|
206
|
+
typeof item[0] !== 'string' ||
|
|
207
|
+
typeof item[1] !== 'string'
|
|
208
|
+
) {
|
|
209
|
+
throw new Error('Invalid data for Map reviver');
|
|
210
|
+
}
|
|
211
|
+
const [key, val] = item;
|
|
212
|
+
map.set(parse(key), parse(val));
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return map;
|
|
216
|
+
},
|
|
217
|
+
/** @type {(value: unknown) => Set<unknown>} */
|
|
218
|
+
[remote_set]: (value) => {
|
|
219
|
+
if (!Array.isArray(value)) {
|
|
220
|
+
throw new Error('Invalid data for Set reviver');
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const set = new Set();
|
|
224
|
+
|
|
225
|
+
for (const item of value) {
|
|
226
|
+
if (typeof item !== 'string') {
|
|
227
|
+
throw new Error('Invalid data for Set reviver');
|
|
228
|
+
}
|
|
229
|
+
set.add(parse(item));
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return set;
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const user_revivers = Object.fromEntries(
|
|
237
|
+
Object.entries(transport).map(([k, v]) => [k, v.decode])
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
const all_revivers = { ...user_revivers, ...remote_fns_revivers };
|
|
241
|
+
|
|
242
|
+
/** @type {(data: string) => unknown} */
|
|
243
|
+
const parse = (data) => devalue.parse(data, all_revivers);
|
|
244
|
+
|
|
245
|
+
return all_revivers;
|
|
246
|
+
}
|
|
247
|
+
|
|
53
248
|
/**
|
|
54
249
|
* Stringifies the argument (if any) for a remote function in such a way that
|
|
55
250
|
* it is both a valid URL and a valid file name (necessary for prerendering).
|
|
56
251
|
* @param {any} value
|
|
57
252
|
* @param {Transport} transport
|
|
253
|
+
* @param {boolean} [sort]
|
|
58
254
|
*/
|
|
59
|
-
export function stringify_remote_arg(value, transport) {
|
|
255
|
+
export function stringify_remote_arg(value, transport, sort = true) {
|
|
60
256
|
if (value === undefined) return '';
|
|
61
257
|
|
|
62
258
|
// If people hit file/url size limits, we can look into using something like compress_and_encode_text from svelte.dev beyond a certain size
|
|
63
|
-
const json_string = stringify(
|
|
259
|
+
const json_string = devalue.stringify(
|
|
260
|
+
value,
|
|
261
|
+
create_remote_arg_reducers(transport, sort, new Map())
|
|
262
|
+
);
|
|
64
263
|
|
|
65
264
|
const bytes = new TextEncoder().encode(json_string);
|
|
66
265
|
return base64_encode(bytes).replaceAll('=', '').replaceAll('+', '-').replaceAll('/', '_');
|
|
@@ -79,9 +278,7 @@ export function parse_remote_arg(string, transport) {
|
|
|
79
278
|
base64_decode(string.replaceAll('-', '+').replaceAll('_', '/'))
|
|
80
279
|
);
|
|
81
280
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return devalue.parse(json_string, decoders);
|
|
281
|
+
return devalue.parse(json_string, create_remote_arg_revivers(transport));
|
|
85
282
|
}
|
|
86
283
|
|
|
87
284
|
/**
|
|
@@ -91,3 +288,34 @@ export function parse_remote_arg(string, transport) {
|
|
|
91
288
|
export function create_remote_key(id, payload) {
|
|
92
289
|
return id + '/' + payload;
|
|
93
290
|
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* @param {string} key
|
|
294
|
+
* @returns {{ id: string; payload: string }}
|
|
295
|
+
*/
|
|
296
|
+
export function split_remote_key(key) {
|
|
297
|
+
const i = key.lastIndexOf('/');
|
|
298
|
+
|
|
299
|
+
if (i === -1) {
|
|
300
|
+
throw new Error(`Invalid remote key: ${key}`);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return {
|
|
304
|
+
id: key.slice(0, i),
|
|
305
|
+
payload: key.slice(i + 1)
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* @template T
|
|
311
|
+
* @param {string} key
|
|
312
|
+
* @param {() => T} fn
|
|
313
|
+
* @returns {T}
|
|
314
|
+
* @deprecated TODO remove in SvelteKit 3.0
|
|
315
|
+
*/
|
|
316
|
+
export function unfriendly_hydratable(key, fn) {
|
|
317
|
+
if (!svelte.hydratable) {
|
|
318
|
+
throw new Error('Remote functions require Svelte 5.44.0 or later');
|
|
319
|
+
}
|
|
320
|
+
return svelte.hydratable(key, fn);
|
|
321
|
+
}
|
|
@@ -9,8 +9,6 @@ declare global {
|
|
|
9
9
|
const __SVELTEKIT_PATHS_RELATIVE__: boolean;
|
|
10
10
|
/** True if `config.kit.experimental.instrumentation.server` is `true` */
|
|
11
11
|
const __SVELTEKIT_SERVER_TRACING_ENABLED__: boolean;
|
|
12
|
-
/** true if corresponding config option is set to true */
|
|
13
|
-
const __SVELTEKIT_EXPERIMENTAL__REMOTE_FUNCTIONS__: boolean;
|
|
14
12
|
/** True if `config.kit.experimental.forkPreloads` is `true` */
|
|
15
13
|
const __SVELTEKIT_FORK_PRELOADS__: boolean;
|
|
16
14
|
/** True if `config.kit.router.resolution === 'client'` */
|
|
@@ -35,8 +33,10 @@ declare global {
|
|
|
35
33
|
assets?: string;
|
|
36
34
|
/** Public environment variables */
|
|
37
35
|
env?: Record<string, string>;
|
|
38
|
-
/** Serialized data from
|
|
39
|
-
|
|
36
|
+
/** Serialized data from query/form/command functions */
|
|
37
|
+
query?: Record<string, any>;
|
|
38
|
+
/** Serialized data from prerender functions */
|
|
39
|
+
prerender?: Record<string, any>;
|
|
40
40
|
/** Create a placeholder promise */
|
|
41
41
|
defer?: (id: number) => Promise<any>;
|
|
42
42
|
/** Resolve a placeholder promise */
|
package/src/types/internal.d.ts
CHANGED
|
@@ -312,6 +312,21 @@ export type RemoteFunctionResponse =
|
|
|
312
312
|
refreshes: string | undefined;
|
|
313
313
|
};
|
|
314
314
|
|
|
315
|
+
export type RemoteRefreshResult = {
|
|
316
|
+
type: 'result';
|
|
317
|
+
data: any;
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
export type RemoteRefreshError = {
|
|
321
|
+
type: 'error';
|
|
322
|
+
status?: number;
|
|
323
|
+
error: App.Error;
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
export type RemoteRefreshEntry = RemoteRefreshResult | RemoteRefreshError;
|
|
327
|
+
|
|
328
|
+
export type RemoteRefreshMap = Record<string, RemoteRefreshEntry>;
|
|
329
|
+
|
|
315
330
|
/**
|
|
316
331
|
* Signals a successful response of the server `load` function.
|
|
317
332
|
* The `uses` property tells the client when it's possible to reuse this data
|
|
@@ -379,7 +394,7 @@ export interface ServerMetadata {
|
|
|
379
394
|
}>;
|
|
380
395
|
routes: Map<string, ServerMetadataRoute>;
|
|
381
396
|
/** For each hashed remote file, a map of export name -> { type, dynamic }, where `dynamic` is `false` for non-dynamic prerender functions */
|
|
382
|
-
remotes: Map<string, Map<string, { type:
|
|
397
|
+
remotes: Map<string, Map<string, { type: RemoteInternals['type']; dynamic: boolean }>>;
|
|
383
398
|
}
|
|
384
399
|
|
|
385
400
|
export interface SSRComponent {
|
|
@@ -569,40 +584,53 @@ export type BinaryFormMeta = {
|
|
|
569
584
|
validate_only?: boolean;
|
|
570
585
|
};
|
|
571
586
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
587
|
+
interface BaseRemoteInternals {
|
|
588
|
+
type: string;
|
|
589
|
+
id: string;
|
|
590
|
+
name: string;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
export interface RemoteQueryInternals extends BaseRemoteInternals {
|
|
594
|
+
type: 'query';
|
|
595
|
+
validate: (arg?: any) => MaybePromise<any>;
|
|
596
|
+
}
|
|
597
|
+
export interface RemoteQueryLiveInternals extends BaseRemoteInternals {
|
|
598
|
+
type: 'query_live';
|
|
599
|
+
run(
|
|
600
|
+
event: RequestEvent,
|
|
601
|
+
state: RequestState,
|
|
602
|
+
arg: any
|
|
603
|
+
): Promise<{ iterator: AsyncIterator<any>; cancel: () => void }>;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
export interface RemoteQueryBatchInternals extends BaseRemoteInternals {
|
|
607
|
+
type: 'query_batch';
|
|
608
|
+
run: (args: any[], options: SSROptions) => Promise<any[]>;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
export interface RemoteCommandInternals extends BaseRemoteInternals {
|
|
612
|
+
type: 'command';
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
export interface RemoteFormInternals extends BaseRemoteInternals {
|
|
616
|
+
type: 'form';
|
|
617
|
+
fn(body: Record<string, any>, meta: BinaryFormMeta, form_data: FormData | null): Promise<any>;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
export interface RemotePrerenderInternals extends BaseRemoteInternals {
|
|
621
|
+
type: 'prerender';
|
|
622
|
+
has_arg: boolean;
|
|
623
|
+
dynamic?: boolean;
|
|
624
|
+
inputs?: RemotePrerenderInputsGenerator;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
export type RemoteInternals =
|
|
628
|
+
| RemoteQueryInternals
|
|
629
|
+
| RemoteQueryLiveInternals
|
|
630
|
+
| RemoteQueryBatchInternals
|
|
631
|
+
| RemoteCommandInternals
|
|
632
|
+
| RemoteFormInternals
|
|
633
|
+
| RemotePrerenderInternals;
|
|
606
634
|
|
|
607
635
|
export interface InternalRemoteFormIssue extends RemoteFormIssue {
|
|
608
636
|
name: string;
|
|
@@ -621,17 +649,25 @@ export type RecordSpan = <T>(options: {
|
|
|
621
649
|
* used for tracking things like remote function calls
|
|
622
650
|
*/
|
|
623
651
|
export interface RequestState {
|
|
624
|
-
prerendering: PrerenderOptions | undefined;
|
|
625
|
-
transport: ServerHooks['transport'];
|
|
626
|
-
handleValidationError: ServerHooks['handleValidationError'];
|
|
627
|
-
tracing: {
|
|
652
|
+
readonly prerendering: PrerenderOptions | undefined;
|
|
653
|
+
readonly transport: ServerHooks['transport'];
|
|
654
|
+
readonly handleValidationError: ServerHooks['handleValidationError'];
|
|
655
|
+
readonly tracing: {
|
|
628
656
|
record_span: RecordSpan;
|
|
629
657
|
};
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
658
|
+
readonly remote: {
|
|
659
|
+
data: null | Map<
|
|
660
|
+
RemoteInternals,
|
|
661
|
+
Record<string, { serialize: boolean; data: MaybePromise<any> }>
|
|
662
|
+
>;
|
|
663
|
+
forms: null | Map<any, any>;
|
|
664
|
+
refreshes: null | Record<string, Promise<any>>;
|
|
665
|
+
requested: null | Map<string, string[]>;
|
|
666
|
+
validated: null | Map<string, Set<any>>;
|
|
667
|
+
};
|
|
668
|
+
readonly is_in_remote_function: boolean;
|
|
669
|
+
readonly is_in_render: boolean;
|
|
670
|
+
readonly is_in_universal_load: boolean;
|
|
635
671
|
}
|
|
636
672
|
|
|
637
673
|
export interface RequestStore {
|
package/src/utils/css.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import MagicString from 'magic-string';
|
|
2
2
|
import * as svelte from 'svelte/compiler';
|
|
3
|
-
import { escape_for_interpolation } from './escape.js';
|
|
4
3
|
|
|
5
4
|
/** @typedef {ReturnType<typeof import('svelte/compiler').parseCss>['children']} StyleSheetChildren */
|
|
6
5
|
|
|
@@ -60,8 +59,6 @@ export function fix_css_urls({
|
|
|
60
59
|
return css;
|
|
61
60
|
}
|
|
62
61
|
|
|
63
|
-
css = escape_for_interpolation(css);
|
|
64
|
-
|
|
65
62
|
// safe guard in case of trailing slashes (but this should never happen)
|
|
66
63
|
if (paths_assets.endsWith('/')) {
|
|
67
64
|
paths_assets = paths_assets.slice(0, -1);
|
package/src/utils/escape.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { s } from './misc.js';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* When inside a double-quoted attribute value, only `&` and `"` hold special meaning.
|
|
3
5
|
* @see https://html.spec.whatwg.org/multipage/parsing.html#attribute-value-(double-quoted)-state
|
|
@@ -61,11 +63,21 @@ export function escape_html(str, is_attr) {
|
|
|
61
63
|
return escaped_str;
|
|
62
64
|
}
|
|
63
65
|
|
|
66
|
+
/** @typedef {{ placeholder: string, replacement: string }} Replacement */
|
|
67
|
+
|
|
64
68
|
/**
|
|
65
|
-
* Escapes backticks and dollar signs so that
|
|
69
|
+
* Escapes backslashes, backticks, and dollar signs so that the string can be
|
|
70
|
+
* safely used as part of a template literal.
|
|
66
71
|
* @param {string} str
|
|
72
|
+
* @param {Replacement[]} replacements Placeholders to replace after escaping.
|
|
73
|
+
* This is necessary when the string contains
|
|
74
|
+
* placeholders that we want to preserve, such as `${assets}`
|
|
67
75
|
* @returns {string} escaped string
|
|
68
76
|
*/
|
|
69
|
-
export function escape_for_interpolation(str) {
|
|
70
|
-
|
|
77
|
+
export function escape_for_interpolation(str, replacements) {
|
|
78
|
+
let escaped = s(str).slice(1, -1).replaceAll('`', '\\`').replaceAll('$', '\\$');
|
|
79
|
+
for (const { placeholder, replacement } of replacements) {
|
|
80
|
+
escaped = escaped.replaceAll(placeholder, replacement);
|
|
81
|
+
}
|
|
82
|
+
return escaped;
|
|
71
83
|
}
|
package/src/version.js
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -1426,6 +1426,22 @@ declare module '@sveltejs/kit' {
|
|
|
1426
1426
|
*/
|
|
1427
1427
|
export type ParamMatcher = (param: string) => boolean;
|
|
1428
1428
|
|
|
1429
|
+
export type RequestedResult<T> = Iterable<T> &
|
|
1430
|
+
AsyncIterable<T> & {
|
|
1431
|
+
/**
|
|
1432
|
+
* Call `refresh` on all queries selected by this `requested` invocation.
|
|
1433
|
+
* This is identical to:
|
|
1434
|
+
* ```ts
|
|
1435
|
+
* import { requested } from '$app/server';
|
|
1436
|
+
*
|
|
1437
|
+
* for await (const arg of requested(query, ...) {
|
|
1438
|
+
* void query(arg).refresh();
|
|
1439
|
+
* }
|
|
1440
|
+
* ```
|
|
1441
|
+
*/
|
|
1442
|
+
refreshAll: () => Promise<void>;
|
|
1443
|
+
};
|
|
1444
|
+
|
|
1429
1445
|
export interface RequestEvent<
|
|
1430
1446
|
Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>,
|
|
1431
1447
|
RouteId extends AppRouteId | null = AppRouteId | null
|
|
@@ -1888,10 +1904,12 @@ declare module '@sveltejs/kit' {
|
|
|
1888
1904
|
type AsArgs<Type extends keyof InputTypeMap, Value> = Type extends 'checkbox'
|
|
1889
1905
|
? Value extends string[]
|
|
1890
1906
|
? [type: Type, value: Value[number] | (string & {})]
|
|
1891
|
-
: [type: Type]
|
|
1907
|
+
: [type: Type] | [type: Type, value: Value | (string & {})]
|
|
1892
1908
|
: Type extends 'radio' | 'submit' | 'hidden'
|
|
1893
1909
|
? [type: Type, value: Value | (string & {})]
|
|
1894
|
-
:
|
|
1910
|
+
: Type extends 'file' | 'file multiple'
|
|
1911
|
+
? [type: Type]
|
|
1912
|
+
: [type: Type] | [type: Type, value: Value | (string & {})];
|
|
1895
1913
|
|
|
1896
1914
|
/**
|
|
1897
1915
|
* Form field accessor type that provides name(), value(), and issues() methods
|
|
@@ -2032,7 +2050,7 @@ declare module '@sveltejs/kit' {
|
|
|
2032
2050
|
form: HTMLFormElement;
|
|
2033
2051
|
data: Input;
|
|
2034
2052
|
submit: () => Promise<void> & {
|
|
2035
|
-
updates: (...
|
|
2053
|
+
updates: (...updates: RemoteQueryUpdate[]) => Promise<void>;
|
|
2036
2054
|
};
|
|
2037
2055
|
}) => void | Promise<void>
|
|
2038
2056
|
): {
|
|
@@ -2076,14 +2094,19 @@ declare module '@sveltejs/kit' {
|
|
|
2076
2094
|
* The return value of a remote `command` function. See [Remote functions](https://svelte.dev/docs/kit/remote-functions#command) for full documentation.
|
|
2077
2095
|
*/
|
|
2078
2096
|
export type RemoteCommand<Input, Output> = {
|
|
2079
|
-
(arg: undefined extends Input ? Input | void : Input): Promise<
|
|
2080
|
-
updates(...
|
|
2097
|
+
(arg: undefined extends Input ? Input | void : Input): Promise<Output> & {
|
|
2098
|
+
updates(...updates: RemoteQueryUpdate[]): Promise<Output>;
|
|
2081
2099
|
};
|
|
2082
2100
|
/** The number of pending command executions */
|
|
2083
2101
|
get pending(): number;
|
|
2084
2102
|
};
|
|
2085
2103
|
|
|
2086
|
-
export type
|
|
2104
|
+
export type RemoteQueryUpdate =
|
|
2105
|
+
| RemoteQuery<any>
|
|
2106
|
+
| RemoteQueryFunction<any, any>
|
|
2107
|
+
| RemoteQueryOverride;
|
|
2108
|
+
|
|
2109
|
+
export type RemoteResource<T> = Promise<T> & {
|
|
2087
2110
|
/** The error in case the query fails. Most often this is a [`HttpError`](https://svelte.dev/docs/kit/@sveltejs-kit#HttpError) but it isn't guaranteed to be. */
|
|
2088
2111
|
get error(): any;
|
|
2089
2112
|
/** `true` before the first result is available and during refreshes */
|
|
@@ -2096,12 +2119,18 @@ declare module '@sveltejs/kit' {
|
|
|
2096
2119
|
}
|
|
2097
2120
|
| {
|
|
2098
2121
|
/** The current value of the query. Undefined until `ready` is `true` */
|
|
2099
|
-
get current():
|
|
2122
|
+
get current(): T;
|
|
2100
2123
|
ready: true;
|
|
2101
2124
|
}
|
|
2102
2125
|
);
|
|
2103
2126
|
|
|
2104
2127
|
export type RemoteQuery<T> = RemoteResource<T> & {
|
|
2128
|
+
/**
|
|
2129
|
+
* Returns a plain promise with the result.
|
|
2130
|
+
* Unlike awaiting the resource directly, this can only be used _outside_ render
|
|
2131
|
+
* (i.e. in load functions, event handlers and so on)
|
|
2132
|
+
*/
|
|
2133
|
+
run(): Promise<T>;
|
|
2105
2134
|
/**
|
|
2106
2135
|
* On the client, this function will update the value of the query without re-fetching it.
|
|
2107
2136
|
*
|
|
@@ -2135,13 +2164,10 @@ declare module '@sveltejs/kit' {
|
|
|
2135
2164
|
* </form>
|
|
2136
2165
|
* ```
|
|
2137
2166
|
*/
|
|
2138
|
-
withOverride(update: (current:
|
|
2167
|
+
withOverride(update: (current: T) => T): RemoteQueryOverride;
|
|
2139
2168
|
};
|
|
2140
2169
|
|
|
2141
|
-
export
|
|
2142
|
-
_key: string;
|
|
2143
|
-
release(): void;
|
|
2144
|
-
}
|
|
2170
|
+
export type RemoteQueryOverride = () => void;
|
|
2145
2171
|
|
|
2146
2172
|
/**
|
|
2147
2173
|
* The return value of a remote `prerender` function. See [Remote functions](https://svelte.dev/docs/kit/remote-functions#prerender) for full documentation.
|
|
@@ -3221,7 +3247,7 @@ declare module '$app/paths' {
|
|
|
3221
3247
|
}
|
|
3222
3248
|
|
|
3223
3249
|
declare module '$app/server' {
|
|
3224
|
-
import type { RequestEvent, RemoteCommand, RemoteForm, RemoteFormInput, InvalidField, RemotePrerenderFunction, RemoteQueryFunction } from '@sveltejs/kit';
|
|
3250
|
+
import type { RequestEvent, RemoteCommand, RemoteForm, RemoteFormInput, InvalidField, RemotePrerenderFunction, RemoteQueryFunction, RequestedResult } from '@sveltejs/kit';
|
|
3225
3251
|
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
3226
3252
|
/**
|
|
3227
3253
|
* Read the contents of an imported asset from the filesystem
|
|
@@ -3367,6 +3393,34 @@ declare module '$app/server' {
|
|
|
3367
3393
|
*/
|
|
3368
3394
|
function batch<Schema extends StandardSchemaV1, Output>(schema: Schema, fn: (args: StandardSchemaV1.InferOutput<Schema>[]) => MaybePromise<(arg: StandardSchemaV1.InferOutput<Schema>, idx: number) => Output>): RemoteQueryFunction<StandardSchemaV1.InferInput<Schema>, Output>;
|
|
3369
3395
|
}
|
|
3396
|
+
/**
|
|
3397
|
+
* In the context of a remote `command` or `form` request, returns an iterable
|
|
3398
|
+
* of the client-requested refreshes' validated arguments up to the supplied limit.
|
|
3399
|
+
* Arguments that fail validation or exceed the limit are recorded as failures in
|
|
3400
|
+
* the response to the client.
|
|
3401
|
+
*
|
|
3402
|
+
* @example
|
|
3403
|
+
* ```ts
|
|
3404
|
+
* import { requested } from '$app/server';
|
|
3405
|
+
*
|
|
3406
|
+
* for (const arg of requested(getPost, 5)) {
|
|
3407
|
+
* // it's safe to throw away this promise -- SvelteKit
|
|
3408
|
+
* // will await it for us and handle any errors by sending
|
|
3409
|
+
* // them to the client.
|
|
3410
|
+
* void getPost(arg).refresh();
|
|
3411
|
+
* }
|
|
3412
|
+
* ```
|
|
3413
|
+
*
|
|
3414
|
+
* As a shorthand for the above, you can also call `refreshAll` on the result:
|
|
3415
|
+
*
|
|
3416
|
+
* ```ts
|
|
3417
|
+
* import { requested } from '$app/server';
|
|
3418
|
+
*
|
|
3419
|
+
* await requested(getPost, 5).refreshAll();
|
|
3420
|
+
* ```
|
|
3421
|
+
*
|
|
3422
|
+
* */
|
|
3423
|
+
export function requested<Input, Output>(query: RemoteQueryFunction<Input, Output>, limit?: number): RequestedResult<Input>;
|
|
3370
3424
|
type RemotePrerenderInputsGenerator<Input = any> = () => MaybePromise<Input[]>;
|
|
3371
3425
|
type MaybePromise<T> = T | Promise<T>;
|
|
3372
3426
|
|