@sveltejs/kit 3.0.0-next.4 → 3.0.0-next.7
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 +23 -18
- package/src/core/adapt/builder.js +29 -43
- package/src/core/adapt/index.js +1 -4
- package/src/core/config/index.js +135 -71
- package/src/core/config/options.js +291 -244
- package/src/core/config/types.d.ts +1 -1
- package/src/core/env.js +120 -5
- package/src/core/generate_manifest/index.js +12 -15
- package/src/core/postbuild/analyse.js +8 -12
- package/src/core/postbuild/crawl.js +22 -6
- package/src/core/postbuild/prerender.js +40 -23
- package/src/core/sync/create_manifest_data/index.js +29 -49
- package/src/core/sync/write_client_manifest.js +14 -14
- package/src/core/sync/write_non_ambient.js +10 -7
- package/src/core/sync/write_root.js +9 -30
- package/src/core/sync/write_server.js +13 -11
- package/src/core/sync/write_tsconfig.js +2 -4
- package/src/core/sync/write_types/index.js +11 -10
- package/src/exports/index.js +34 -12
- package/src/exports/internal/client.js +5 -0
- package/src/exports/internal/env.js +1 -1
- package/src/exports/internal/index.js +1 -90
- package/src/exports/internal/{event.js → server/event.js} +1 -2
- package/src/exports/internal/server/index.js +33 -0
- package/src/exports/internal/shared.js +89 -0
- package/src/exports/node/index.js +58 -7
- package/src/exports/params.js +63 -0
- package/src/exports/public.d.ts +299 -145
- package/src/exports/url.js +84 -0
- package/src/exports/vite/build/build_server.js +6 -1
- package/src/exports/vite/dev/index.js +38 -37
- package/src/exports/vite/index.js +498 -353
- package/src/exports/vite/preview/index.js +16 -8
- package/src/exports/vite/utils.js +7 -11
- package/src/runtime/app/env/types.d.ts +1 -1
- package/src/runtime/app/forms.js +22 -5
- package/src/runtime/app/paths/client.js +4 -10
- package/src/runtime/app/paths/public.d.ts +0 -28
- package/src/runtime/app/paths/server.js +8 -4
- package/src/runtime/app/server/remote/form.js +10 -3
- package/src/runtime/app/server/remote/query.js +9 -18
- package/src/runtime/app/server/remote/requested.js +8 -4
- package/src/runtime/app/server/remote/shared.js +5 -7
- package/src/runtime/app/state/client.js +1 -2
- package/src/runtime/app/stores.js +13 -76
- package/src/runtime/client/client.js +205 -167
- package/src/runtime/client/fetcher.js +3 -2
- package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
- package/src/runtime/client/remote-functions/form.svelte.js +122 -31
- package/src/runtime/client/remote-functions/prerender.svelte.js +17 -4
- package/src/runtime/client/remote-functions/query/index.js +3 -2
- package/src/runtime/client/remote-functions/query/instance.svelte.js +27 -11
- package/src/runtime/client/remote-functions/query-batch.svelte.js +4 -3
- package/src/runtime/client/remote-functions/query-live/instance.svelte.js +42 -15
- package/src/runtime/client/remote-functions/shared.svelte.js +18 -9
- package/src/runtime/client/state.svelte.js +66 -49
- package/src/runtime/client/types.d.ts +10 -2
- package/src/runtime/client/utils.js +0 -96
- package/src/runtime/form-utils.js +99 -18
- package/src/runtime/server/cookie.js +22 -33
- package/src/runtime/server/csrf.js +65 -0
- package/src/runtime/server/data/index.js +7 -7
- package/src/runtime/server/env_module.js +0 -5
- package/src/runtime/server/index.js +2 -2
- package/src/runtime/server/page/actions.js +41 -26
- package/src/runtime/server/page/index.js +2 -1
- package/src/runtime/server/page/load_data.js +1 -1
- package/src/runtime/server/page/render.js +36 -47
- package/src/runtime/server/page/respond_with_error.js +7 -8
- package/src/runtime/server/page/server_routing.js +13 -9
- package/src/runtime/server/remote.js +85 -39
- package/src/runtime/server/respond.js +92 -58
- package/src/runtime/server/utils.js +7 -7
- package/src/runtime/telemetry/otel.js +1 -1
- package/src/types/ambient.d.ts +10 -5
- package/src/types/global-private.d.ts +4 -4
- package/src/types/internal.d.ts +17 -20
- package/src/types/private.d.ts +33 -1
- package/src/types/synthetic/$lib.md +1 -1
- package/src/utils/error.js +12 -4
- package/src/utils/mime.js +9 -0
- package/src/utils/params.js +66 -0
- package/src/utils/routing.js +84 -38
- package/src/utils/shared-iterator.js +5 -0
- package/src/utils/streaming.js +14 -4
- package/src/utils/url.js +20 -2
- package/src/version.js +1 -1
- package/types/index.d.ts +434 -269
- package/types/index.d.ts.map +19 -15
- package/src/exports/internal/server.js +0 -22
- /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { pathToFileURL } from 'node:url';
|
|
4
|
-
import { lookup } from '
|
|
4
|
+
import { lookup } from '../../../utils/mime.js';
|
|
5
5
|
import sirv from 'sirv';
|
|
6
6
|
import { loadEnv, normalizePath } from 'vite';
|
|
7
7
|
import { createReadableStream, getRequest, setResponse } from '../../../exports/node/index.js';
|
|
@@ -16,9 +16,8 @@ import { is_chrome_devtools_request, not_found } from '../utils.js';
|
|
|
16
16
|
* @param {import('vite').PreviewServer} vite
|
|
17
17
|
* @param {import('vite').ResolvedConfig} vite_config
|
|
18
18
|
* @param {import('types').ValidatedConfig} svelte_config
|
|
19
|
-
* @param {import('@sveltejs/kit').Adapter | undefined} adapter
|
|
20
19
|
*/
|
|
21
|
-
export async function preview(vite, vite_config, svelte_config
|
|
20
|
+
export async function preview(vite, vite_config, svelte_config) {
|
|
22
21
|
const { paths } = svelte_config.kit;
|
|
23
22
|
const base = paths.base;
|
|
24
23
|
const assets = paths.assets ? SVELTE_KIT_ASSETS : paths.base;
|
|
@@ -49,12 +48,21 @@ export async function preview(vite, vite_config, svelte_config, adapter) {
|
|
|
49
48
|
set_assets(assets);
|
|
50
49
|
|
|
51
50
|
const server = new Server(manifest);
|
|
52
|
-
await server.init({
|
|
53
|
-
env: loadEnv(vite_config.mode, svelte_config.kit.env.dir, ''),
|
|
54
|
-
read: (file) => createReadableStream(`${dir}/${file}`)
|
|
55
|
-
});
|
|
56
51
|
|
|
57
|
-
|
|
52
|
+
try {
|
|
53
|
+
await server.init({
|
|
54
|
+
env: loadEnv(vite_config.mode, svelte_config.kit.env.dir, ''),
|
|
55
|
+
read: (file) => createReadableStream(`${dir}/${file}`)
|
|
56
|
+
});
|
|
57
|
+
} catch (error) {
|
|
58
|
+
// Vite erases the error message when starting the preview server so we store
|
|
59
|
+
// it in the stack instead. This ensures errors thrown using `stackless`
|
|
60
|
+
// are still readable
|
|
61
|
+
if (error instanceof Error) error.stack = error.message;
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const emulator = await svelte_config.kit.adapter?.emulate?.();
|
|
58
66
|
|
|
59
67
|
return () => {
|
|
60
68
|
// Remove the base middleware. It screws with the URL.
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from './module_ids.js';
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* Transforms
|
|
15
|
+
* Transforms alias to a valid vite.resolve.alias array.
|
|
16
16
|
*
|
|
17
17
|
* Related to tsconfig path alias creation.
|
|
18
18
|
*
|
|
@@ -23,7 +23,7 @@ export function get_config_aliases(config, root) {
|
|
|
23
23
|
/** @type {import('vite').Alias[]} */
|
|
24
24
|
const alias = [
|
|
25
25
|
// For now, we handle `$lib` specially here rather than make it a default value for
|
|
26
|
-
// `config.
|
|
26
|
+
// `config.alias` since it has special meaning for packaging, etc.
|
|
27
27
|
{ find: '$lib', replacement: config.files.lib }
|
|
28
28
|
];
|
|
29
29
|
|
|
@@ -152,19 +152,15 @@ export function normalize_id(id, lib, cwd) {
|
|
|
152
152
|
export const strip_virtual_prefix = /** @param {string} id */ (id) => id.replace('\0virtual:', '');
|
|
153
153
|
|
|
154
154
|
/**
|
|
155
|
-
* For `error_for_missing_config('
|
|
155
|
+
* For `error_for_missing_config('remote functions', 'experimental.remoteFunctions', 'true')`,
|
|
156
156
|
* returns:
|
|
157
157
|
*
|
|
158
158
|
* ```
|
|
159
|
-
* To enable
|
|
159
|
+
* To enable remote functions, add the following to the SvelteKit plugin in your `vite.config.js`:
|
|
160
160
|
*
|
|
161
161
|
*\`\`\`js
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
* instrumentation:
|
|
165
|
-
* server: true
|
|
166
|
-
* }
|
|
167
|
-
* }
|
|
162
|
+
* experimental: {
|
|
163
|
+
* remoteFunctions: true
|
|
168
164
|
* }
|
|
169
165
|
*\`\`\`
|
|
170
166
|
*```
|
|
@@ -185,7 +181,7 @@ export function error_for_missing_config(feature_name, path, value) {
|
|
|
185
181
|
|
|
186
182
|
throw stackless(
|
|
187
183
|
dedent`\
|
|
188
|
-
To enable ${feature_name}, add the following to your \`
|
|
184
|
+
To enable ${feature_name}, add the following to your SvelteKit plugin in \`vite.config.js\`:
|
|
189
185
|
|
|
190
186
|
${result}
|
|
191
187
|
`
|
package/src/runtime/app/forms.js
CHANGED
|
@@ -2,7 +2,7 @@ import * as devalue from 'devalue';
|
|
|
2
2
|
import { BROWSER, DEV } from 'esm-env';
|
|
3
3
|
import { noop } from '../../utils/functions.js';
|
|
4
4
|
import { invalidateAll } from './navigation.js';
|
|
5
|
-
import { app as client_app, applyAction } from '../client/client.js';
|
|
5
|
+
import { app as client_app, applyAction, handle_error } from '../client/client.js';
|
|
6
6
|
import { app as server_app } from '../server/app.js';
|
|
7
7
|
|
|
8
8
|
export { applyAction };
|
|
@@ -30,11 +30,15 @@ export { applyAction };
|
|
|
30
30
|
* @returns {import('@sveltejs/kit').ActionResult<Success, Failure>}
|
|
31
31
|
*/
|
|
32
32
|
export function deserialize(result) {
|
|
33
|
+
if (result === '') {
|
|
34
|
+
return { type: 'success', status: 204, data: undefined };
|
|
35
|
+
}
|
|
36
|
+
|
|
33
37
|
const parsed = JSON.parse(result);
|
|
34
38
|
|
|
35
39
|
if (parsed.data) {
|
|
36
40
|
// the decoders should never be initialised at the top-level because `app`
|
|
37
|
-
// will not be initialised yet if `
|
|
41
|
+
// will not be initialised yet if `output.bundleStrategy` is 'single' or 'inline'
|
|
38
42
|
parsed.data = devalue.parse(parsed.data, BROWSER ? client_app.decoders : server_app.decoders);
|
|
39
43
|
}
|
|
40
44
|
|
|
@@ -197,11 +201,24 @@ export function enhance(form_element, submit = noop) {
|
|
|
197
201
|
signal: controller.signal
|
|
198
202
|
});
|
|
199
203
|
|
|
200
|
-
|
|
201
|
-
|
|
204
|
+
if (response.status === 204) {
|
|
205
|
+
result = { type: 'success', status: 204 };
|
|
206
|
+
} else {
|
|
207
|
+
result = deserialize(await response.text());
|
|
208
|
+
if (result.type === 'error' || result.type === 'failure') {
|
|
209
|
+
result.status = response.status;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
202
212
|
} catch (error) {
|
|
203
213
|
if (/** @type {any} */ (error)?.name === 'AbortError') return;
|
|
204
|
-
result = {
|
|
214
|
+
result = {
|
|
215
|
+
type: 'error',
|
|
216
|
+
error: await handle_error(error, {
|
|
217
|
+
params: {},
|
|
218
|
+
route: { id: null },
|
|
219
|
+
url: new URL(location.href)
|
|
220
|
+
})
|
|
221
|
+
};
|
|
205
222
|
}
|
|
206
223
|
|
|
207
224
|
await callback({
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
/** @import { Asset, RouteId, RouteIdWithSearchOrHash, Pathname, PathnameWithSearchOrHash, ResolvedPathname } from '$app/types' */
|
|
1
|
+
/** @import { Asset, RouteId, RouteIdWithSearchOrHash, Pathname, PathnameWithSearchOrHash, ResolvedPathname, RouteParams } from '$app/types' */
|
|
2
2
|
/** @import { ResolveArgs } from './types.js' */
|
|
3
3
|
import { base, assets, hash_routing } from './internal/client.js';
|
|
4
4
|
import { resolve_route } from '../../../utils/routing.js';
|
|
5
5
|
import { get_navigation_intent } from '../../client/client.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Resolve the URL of an asset in your `static` directory, by prefixing it with [`config.
|
|
8
|
+
* Resolve the URL of an asset in your `static` directory, by prefixing it with [`config.paths.assets`](https://svelte.dev/docs/kit/configuration#paths) if configured, or otherwise by prefixing it with the base path.
|
|
9
9
|
*
|
|
10
10
|
* During server rendering, the base path is relative and depends on the page currently being rendered.
|
|
11
11
|
*
|
|
@@ -59,11 +59,7 @@ export function resolve(...args) {
|
|
|
59
59
|
);
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
// but we don't want to adjust the internal resolve_route function to accept `undefined`, hence the type cast.
|
|
64
|
-
return (
|
|
65
|
-
base + pathname_prefix + resolve_route(args[0], /** @type {Record<string, string>} */ (args[1]))
|
|
66
|
-
);
|
|
62
|
+
return base + pathname_prefix + resolve_route(args[0], args[1] ?? {});
|
|
67
63
|
}
|
|
68
64
|
|
|
69
65
|
/**
|
|
@@ -84,7 +80,7 @@ export function resolve(...args) {
|
|
|
84
80
|
* @since 2.52.0
|
|
85
81
|
*
|
|
86
82
|
* @param {Pathname | URL | (string & {})} url
|
|
87
|
-
* @returns {Promise<{ id:
|
|
83
|
+
* @returns {Promise<{ [K in RouteId]: { id: K; params: RouteParams<K>; } }[RouteId] | null>}
|
|
88
84
|
*/
|
|
89
85
|
export async function match(url) {
|
|
90
86
|
if (typeof url === 'string') {
|
|
@@ -102,5 +98,3 @@ export async function match(url) {
|
|
|
102
98
|
|
|
103
99
|
return null;
|
|
104
100
|
}
|
|
105
|
-
|
|
106
|
-
export { base, assets, resolve as resolveRoute };
|
|
@@ -1,29 +1 @@
|
|
|
1
|
-
import { RouteIdWithSearchOrHash, PathnameWithSearchOrHash, ResolvedPathname } from '$app/types';
|
|
2
|
-
import { ResolveArgs } from './types.js';
|
|
3
|
-
|
|
4
1
|
export { resolve, asset, match } from './client.js';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* A string that matches [`config.kit.paths.base`](https://svelte.dev/docs/kit/configuration#paths).
|
|
8
|
-
*
|
|
9
|
-
* Example usage: `<a href="{base}/your-page">Link</a>`
|
|
10
|
-
*
|
|
11
|
-
* @deprecated Use [`resolve(...)`](https://svelte.dev/docs/kit/$app-paths#resolve) instead
|
|
12
|
-
*/
|
|
13
|
-
export let base: '' | `/${string}`;
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* An absolute path that matches [`config.kit.paths.assets`](https://svelte.dev/docs/kit/configuration#paths).
|
|
17
|
-
*
|
|
18
|
-
* > [!NOTE] If a value for `config.kit.paths.assets` is specified, it will be replaced with `'/_svelte_kit_assets'` during `vite dev` or `vite preview`, since the assets don't yet live at their eventual URL.
|
|
19
|
-
*
|
|
20
|
-
* @deprecated Use [`asset(...)`](https://svelte.dev/docs/kit/$app-paths#asset) instead
|
|
21
|
-
*/
|
|
22
|
-
export let assets: '' | `https://${string}` | `http://${string}` | '/_svelte_kit_assets';
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* @deprecated Use [`resolve(...)`](https://svelte.dev/docs/kit/$app-paths#resolve) instead
|
|
26
|
-
*/
|
|
27
|
-
export function resolveRoute<T extends RouteIdWithSearchOrHash | PathnameWithSearchOrHash>(
|
|
28
|
-
...args: ResolveArgs<T>
|
|
29
|
-
): ResolvedPathname;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { base, assets, relative, initial_base } from './internal/server.js';
|
|
2
2
|
import { resolve_route, find_route } from '../../../utils/routing.js';
|
|
3
3
|
import { decode_pathname } from '../../../utils/url.js';
|
|
4
|
+
import { add_data_suffix } from '../../pathname.js';
|
|
4
5
|
import { try_get_request_store } from '@sveltejs/kit/internal/server';
|
|
5
6
|
import { manifest } from '__sveltekit/server';
|
|
6
7
|
import { get_hooks } from '__SERVER__/internal.js';
|
|
@@ -20,13 +21,18 @@ export function resolve(id, params) {
|
|
|
20
21
|
);
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
const resolved = resolve_route(id,
|
|
24
|
+
const resolved = resolve_route(id, params ?? {});
|
|
24
25
|
|
|
25
26
|
if (relative) {
|
|
26
27
|
const store = try_get_request_store();
|
|
27
28
|
|
|
28
29
|
if (store && !store.state.prerendering?.fallback) {
|
|
29
|
-
|
|
30
|
+
// the relative path depth must reflect the URL the browser is actually at, which
|
|
31
|
+
// for a data request includes the `__data.json` suffix that was stripped during routing
|
|
32
|
+
const pathname = store.event.isDataRequest
|
|
33
|
+
? add_data_suffix(store.event.url.pathname)
|
|
34
|
+
: store.event.url.pathname;
|
|
35
|
+
const after_base = pathname.slice(initial_base.length);
|
|
30
36
|
const segments = after_base.split('/').slice(2);
|
|
31
37
|
const prefix = segments.map(() => '..').join('/') || '.';
|
|
32
38
|
|
|
@@ -74,5 +80,3 @@ export async function match(url) {
|
|
|
74
80
|
|
|
75
81
|
return null;
|
|
76
82
|
}
|
|
77
|
-
|
|
78
|
-
export { base, assets, resolve as resolveRoute };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** @import { RemoteFormInput, RemoteForm, InvalidField } from '@sveltejs/kit' */
|
|
2
|
-
/** @import { InternalRemoteFormIssue, MaybePromise, RemoteFormInternals } from 'types' */
|
|
2
|
+
/** @import { InternalRemoteFormIssue, MaybePromise, HasNonOptionalBoolean, 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 {
|
|
@@ -44,7 +44,7 @@ import { ValidationError } from '@sveltejs/kit/internal';
|
|
|
44
44
|
* @template {StandardSchemaV1<RemoteFormInput, Record<string, any>>} Schema
|
|
45
45
|
* @template Output
|
|
46
46
|
* @overload
|
|
47
|
-
* @param {Schema} validate
|
|
47
|
+
* @param {true extends HasNonOptionalBoolean<StandardSchemaV1.InferInput<Schema>> ? 'Error: All booleans in form schemas must be optional (e.g. `v.optional(v.boolean(), false)`) because checkbox inputs do not send a false value when unchecked.' : Schema} validate
|
|
48
48
|
* @param {(data: StandardSchemaV1.InferOutput<Schema>, issue: InvalidField<StandardSchemaV1.InferInput<Schema>>) => MaybePromise<Output>} fn
|
|
49
49
|
* @returns {RemoteForm<StandardSchemaV1.InferInput<Schema>, Output>}
|
|
50
50
|
* @since 2.27
|
|
@@ -174,7 +174,10 @@ export function form(validate_or_fn, maybe_fn) {
|
|
|
174
174
|
deep_set(input, path.map(String), value);
|
|
175
175
|
(cache[''] ??= {}).input = input;
|
|
176
176
|
},
|
|
177
|
-
() => flatten_issues(get_cache(__, get_request_store().state)?.['']?.issues ?? [])
|
|
177
|
+
() => flatten_issues(get_cache(__, get_request_store().state)?.['']?.issues ?? []),
|
|
178
|
+
() => ({}),
|
|
179
|
+
() => ({}),
|
|
180
|
+
[]
|
|
178
181
|
);
|
|
179
182
|
}
|
|
180
183
|
});
|
|
@@ -194,6 +197,10 @@ export function form(validate_or_fn, maybe_fn) {
|
|
|
194
197
|
get: () => 0
|
|
195
198
|
});
|
|
196
199
|
|
|
200
|
+
Object.defineProperty(instance, 'submitted', {
|
|
201
|
+
get: () => false
|
|
202
|
+
});
|
|
203
|
+
|
|
197
204
|
Object.defineProperty(instance, 'preflight', {
|
|
198
205
|
// preflight is a noop on the server
|
|
199
206
|
value: () => instance
|
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
import { noop } from '../../../../utils/functions.js';
|
|
15
15
|
import { SharedIterator } from '../../../../utils/shared-iterator.js';
|
|
16
16
|
import { handle_error_and_jsonify } from '../../../server/utils.js';
|
|
17
|
-
import { HttpError, SvelteKitError } from '@sveltejs/kit/internal';
|
|
18
17
|
|
|
19
18
|
/**
|
|
20
19
|
* Creates a remote query. When called from the browser, the function will be invoked on the server via a `fetch` call.
|
|
@@ -347,13 +346,11 @@ function batch(validate_or_fn, maybe_fn) {
|
|
|
347
346
|
const data = get_result(arg, i);
|
|
348
347
|
return { type: 'result', data };
|
|
349
348
|
} catch (error) {
|
|
349
|
+
const transformed = await handle_error_and_jsonify(event, state, options, error);
|
|
350
|
+
|
|
350
351
|
return {
|
|
351
352
|
type: 'error',
|
|
352
|
-
error:
|
|
353
|
-
status:
|
|
354
|
-
error instanceof HttpError || error instanceof SvelteKitError
|
|
355
|
-
? error.status
|
|
356
|
-
: 500
|
|
353
|
+
error: transformed
|
|
357
354
|
};
|
|
358
355
|
}
|
|
359
356
|
})
|
|
@@ -414,20 +411,14 @@ export function refresh(event, state, internals, payload, fn) {
|
|
|
414
411
|
|
|
415
412
|
const key = create_remote_key(internals.id, payload);
|
|
416
413
|
|
|
417
|
-
// `fn
|
|
418
|
-
//
|
|
419
|
-
//
|
|
420
|
-
//
|
|
421
|
-
//
|
|
422
|
-
// unhandled promise rejection (which crashes the process on modern Node).
|
|
423
|
-
// We still store the original promise so `collect_remote_data` can serialize
|
|
424
|
-
// either its value or its error as before.
|
|
425
|
-
const promise = fn();
|
|
426
|
-
promise.catch(() => {});
|
|
427
|
-
|
|
414
|
+
// `fn` is stored rather than invoked eagerly. The query is run at the end of
|
|
415
|
+
// the command/form (in `collect_remote_data`), so that it observes any state
|
|
416
|
+
// mutations that happen after `refresh()` is called. If the developer re-awaits
|
|
417
|
+
// the query before the command finishes, the cache entry created by that await
|
|
418
|
+
// is reused instead of re-running the query.
|
|
428
419
|
(state.remote.explicit ??= new Map()).set(key, {
|
|
429
420
|
internals,
|
|
430
|
-
|
|
421
|
+
fn
|
|
431
422
|
});
|
|
432
423
|
}
|
|
433
424
|
|
|
@@ -8,8 +8,8 @@ import { get_cache } from './shared.js';
|
|
|
8
8
|
import { refresh } from './query.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
* 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
|
|
13
13
|
* the supplied `limit`. Each `query` is a `RemoteQuery` bound to the original
|
|
14
14
|
* client-side cache key, so `refresh()` / `set()` propagate correctly even when
|
|
15
15
|
* the query's schema transforms the input. `arg` is the *validated* argument,
|
|
@@ -18,6 +18,8 @@ import { refresh } from './query.js';
|
|
|
18
18
|
*
|
|
19
19
|
* Arguments that fail validation or exceed `limit` are recorded as failures in
|
|
20
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`.
|
|
21
23
|
*
|
|
22
24
|
* @example
|
|
23
25
|
* ```ts
|
|
@@ -54,14 +56,16 @@ import { refresh } from './query.js';
|
|
|
54
56
|
* @returns {QueryRequestedResult<Validated, Output>}
|
|
55
57
|
*/
|
|
56
58
|
/**
|
|
57
|
-
*
|
|
58
|
-
* 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
|
|
59
61
|
* the supplied `limit`. Each `query` is a `RemoteLiveQuery` bound to the original
|
|
60
62
|
* client-side cache key, so `reconnect()` propagates correctly even when
|
|
61
63
|
* the query's schema transforms the input. `arg` is the *validated* argument.
|
|
62
64
|
*
|
|
63
65
|
* Arguments that fail validation or exceed `limit` are recorded as failures in
|
|
64
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`.
|
|
65
69
|
*
|
|
66
70
|
* @example
|
|
67
71
|
* ```ts
|
|
@@ -35,13 +35,11 @@ export function create_validator(validate_or_fn, maybe_fn) {
|
|
|
35
35
|
|
|
36
36
|
// if the `issues` field exists, the validation failed
|
|
37
37
|
if (result.issues) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
})
|
|
44
|
-
);
|
|
38
|
+
const body = await state.handleValidationError({
|
|
39
|
+
issues: result.issues,
|
|
40
|
+
event
|
|
41
|
+
});
|
|
42
|
+
error(body.status ?? 400, body);
|
|
45
43
|
}
|
|
46
44
|
|
|
47
45
|
return result.value;
|
|
@@ -3,7 +3,6 @@ import {
|
|
|
3
3
|
navigating as _navigating,
|
|
4
4
|
updated as _updated
|
|
5
5
|
} from '../../client/state.svelte.js';
|
|
6
|
-
import { stores } from '../../client/client.js';
|
|
7
6
|
|
|
8
7
|
export const page = {
|
|
9
8
|
get data() {
|
|
@@ -57,5 +56,5 @@ export const updated = {
|
|
|
57
56
|
get current() {
|
|
58
57
|
return _updated.current;
|
|
59
58
|
},
|
|
60
|
-
check:
|
|
59
|
+
check: _updated.check
|
|
61
60
|
};
|
|
@@ -1,101 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
// TODO: remove this file when enough people have migrated to Kit 3
|
|
2
|
+
|
|
3
|
+
/** @returns {never} */
|
|
4
|
+
function removed() {
|
|
5
|
+
throw new Error(
|
|
6
|
+
'`$app/stores` has been removed in favour of `$app/state`. See https://svelte.dev/docs/kit/migrating-to-sveltekit-2#SvelteKit-2.12:-$app-stores-deprecated'
|
|
7
|
+
);
|
|
8
|
+
}
|
|
4
9
|
|
|
5
10
|
/**
|
|
6
|
-
* A function that returns all of the contextual stores. On the server, this must be called during component initialization.
|
|
7
|
-
* Only use this if you need to defer store subscription until after the component has mounted, for some reason.
|
|
8
|
-
*
|
|
9
11
|
* @deprecated Use `$app/state` instead (requires Svelte 5, [see docs for more info](https://svelte.dev/docs/kit/migrating-to-sveltekit-2#SvelteKit-2.12:-$app-stores-deprecated))
|
|
10
12
|
*/
|
|
11
|
-
export const getStores =
|
|
12
|
-
const stores = BROWSER ? browser_stores : getContext('__svelte__');
|
|
13
|
-
|
|
14
|
-
return {
|
|
15
|
-
/** @type {typeof page} */
|
|
16
|
-
page: {
|
|
17
|
-
subscribe: stores.page.subscribe
|
|
18
|
-
},
|
|
19
|
-
/** @type {typeof navigating} */
|
|
20
|
-
navigating: {
|
|
21
|
-
subscribe: stores.navigating.subscribe
|
|
22
|
-
},
|
|
23
|
-
/** @type {typeof updated} */
|
|
24
|
-
updated: stores.updated
|
|
25
|
-
};
|
|
26
|
-
};
|
|
13
|
+
export const getStores = removed;
|
|
27
14
|
|
|
28
15
|
/**
|
|
29
|
-
* A readable store whose value contains page data.
|
|
30
|
-
*
|
|
31
|
-
* On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time.
|
|
32
|
-
*
|
|
33
16
|
* @deprecated Use `page` from `$app/state` instead (requires Svelte 5, [see docs for more info](https://svelte.dev/docs/kit/migrating-to-sveltekit-2#SvelteKit-2.12:-$app-stores-deprecated))
|
|
34
17
|
* @type {import('svelte/store').Readable<import('@sveltejs/kit').Page>}
|
|
35
18
|
*/
|
|
36
19
|
export const page = {
|
|
37
|
-
subscribe
|
|
38
|
-
const store = DEV ? get_store('page') : getStores().page;
|
|
39
|
-
return store.subscribe(fn);
|
|
40
|
-
}
|
|
20
|
+
subscribe: removed
|
|
41
21
|
};
|
|
42
22
|
|
|
43
23
|
/**
|
|
44
|
-
* A readable store.
|
|
45
|
-
* When navigating starts, its value is a `Navigation` object with `from`, `to`, `type` and (if `type === 'popstate'`) `delta` properties.
|
|
46
|
-
* When navigating finishes, its value reverts to `null`.
|
|
47
|
-
*
|
|
48
|
-
* On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time.
|
|
49
|
-
*
|
|
50
24
|
* @deprecated Use `navigating` from `$app/state` instead (requires Svelte 5, [see docs for more info](https://svelte.dev/docs/kit/migrating-to-sveltekit-2#SvelteKit-2.12:-$app-stores-deprecated))
|
|
51
25
|
* @type {import('svelte/store').Readable<import('@sveltejs/kit').Navigation | null>}
|
|
52
26
|
*/
|
|
53
27
|
export const navigating = {
|
|
54
|
-
subscribe
|
|
55
|
-
const store = DEV ? get_store('navigating') : getStores().navigating;
|
|
56
|
-
return store.subscribe(fn);
|
|
57
|
-
}
|
|
28
|
+
subscribe: removed
|
|
58
29
|
};
|
|
59
30
|
|
|
60
31
|
/**
|
|
61
|
-
* A readable store whose initial value is `false`. If [`version.pollInterval`](https://svelte.dev/docs/kit/configuration#version) is a non-zero value, SvelteKit will poll for new versions of the app and update the store value to `true` when it detects one. `updated.check()` will force an immediate check, regardless of polling.
|
|
62
|
-
*
|
|
63
|
-
* On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time.
|
|
64
|
-
*
|
|
65
32
|
* @deprecated Use `updated` from `$app/state` instead (requires Svelte 5, [see docs for more info](https://svelte.dev/docs/kit/migrating-to-sveltekit-2#SvelteKit-2.12:-$app-stores-deprecated))
|
|
66
33
|
* @type {import('svelte/store').Readable<boolean> & { check(): Promise<boolean> }}
|
|
67
34
|
*/
|
|
68
35
|
export const updated = {
|
|
69
|
-
subscribe
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (BROWSER) {
|
|
73
|
-
updated.check = store.check;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return store.subscribe(fn);
|
|
77
|
-
},
|
|
78
|
-
check: () => {
|
|
79
|
-
throw new Error(
|
|
80
|
-
BROWSER
|
|
81
|
-
? 'Cannot check updated store before subscribing'
|
|
82
|
-
: 'Can only check updated store in browser'
|
|
83
|
-
);
|
|
84
|
-
}
|
|
36
|
+
subscribe: removed,
|
|
37
|
+
check: removed
|
|
85
38
|
};
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* @template {keyof ReturnType<typeof getStores>} Name
|
|
89
|
-
* @param {Name} name
|
|
90
|
-
* @returns {ReturnType<typeof getStores>[Name]}
|
|
91
|
-
*/
|
|
92
|
-
function get_store(name) {
|
|
93
|
-
try {
|
|
94
|
-
return getStores()[name];
|
|
95
|
-
} catch {
|
|
96
|
-
throw new Error(
|
|
97
|
-
`Cannot subscribe to '${name}' store on the server outside of a Svelte component, as it is bound to the current request via component context. This prevents state from leaking between users.` +
|
|
98
|
-
'For more information, see https://svelte.dev/docs/kit/state-management#avoid-shared-state-on-the-server'
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
}
|