@sveltejs/kit 3.0.0-next.3 → 3.0.0-next.6

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.
Files changed (68) hide show
  1. package/package.json +17 -17
  2. package/src/core/adapt/builder.js +18 -4
  3. package/src/core/adapt/index.js +1 -4
  4. package/src/core/config/index.js +64 -5
  5. package/src/core/config/options.js +73 -21
  6. package/src/core/env.js +35 -4
  7. package/src/core/postbuild/analyse.js +8 -12
  8. package/src/core/postbuild/crawl.js +22 -6
  9. package/src/core/postbuild/prerender.js +40 -23
  10. package/src/core/sync/create_manifest_data/index.js +23 -5
  11. package/src/core/sync/write_client_manifest.js +7 -0
  12. package/src/core/sync/write_server.js +13 -10
  13. package/src/core/sync/write_tsconfig.js +2 -4
  14. package/src/exports/index.js +32 -10
  15. package/src/exports/internal/env.js +1 -1
  16. package/src/exports/internal/index.js +6 -5
  17. package/src/exports/node/index.js +57 -6
  18. package/src/exports/public.d.ts +218 -114
  19. package/src/exports/vite/build/build_server.js +6 -1
  20. package/src/exports/vite/dev/index.js +10 -20
  21. package/src/exports/vite/index.js +306 -222
  22. package/src/exports/vite/preview/index.js +15 -7
  23. package/src/exports/vite/utils.js +8 -10
  24. package/src/runtime/app/env/types.d.ts +1 -1
  25. package/src/runtime/app/forms.js +22 -5
  26. package/src/runtime/app/paths/client.js +1 -3
  27. package/src/runtime/app/paths/public.d.ts +0 -28
  28. package/src/runtime/app/paths/server.js +7 -3
  29. package/src/runtime/app/server/remote/form.js +10 -3
  30. package/src/runtime/app/server/remote/query.js +3 -6
  31. package/src/runtime/app/server/remote/requested.js +8 -4
  32. package/src/runtime/app/server/remote/shared.js +5 -7
  33. package/src/runtime/client/client.js +190 -95
  34. package/src/runtime/client/fetcher.js +3 -2
  35. package/src/runtime/client/remote-functions/form.svelte.js +134 -24
  36. package/src/runtime/client/remote-functions/prerender.svelte.js +8 -2
  37. package/src/runtime/client/remote-functions/query/index.js +3 -2
  38. package/src/runtime/client/remote-functions/query/instance.svelte.js +26 -10
  39. package/src/runtime/client/remote-functions/query-batch.svelte.js +4 -3
  40. package/src/runtime/client/remote-functions/query-live/instance.svelte.js +26 -9
  41. package/src/runtime/client/remote-functions/shared.svelte.js +17 -7
  42. package/src/runtime/client/types.d.ts +9 -1
  43. package/src/runtime/client/utils.js +1 -1
  44. package/src/runtime/form-utils.js +84 -16
  45. package/src/runtime/server/cookie.js +22 -33
  46. package/src/runtime/server/csrf.js +65 -0
  47. package/src/runtime/server/data/index.js +7 -7
  48. package/src/runtime/server/env_module.js +0 -5
  49. package/src/runtime/server/index.js +1 -1
  50. package/src/runtime/server/page/actions.js +41 -26
  51. package/src/runtime/server/page/index.js +2 -1
  52. package/src/runtime/server/page/render.js +21 -23
  53. package/src/runtime/server/page/respond_with_error.js +7 -8
  54. package/src/runtime/server/remote.js +64 -27
  55. package/src/runtime/server/respond.js +81 -50
  56. package/src/runtime/server/utils.js +7 -7
  57. package/src/runtime/telemetry/otel.js +1 -1
  58. package/src/types/ambient.d.ts +5 -4
  59. package/src/types/global-private.d.ts +4 -4
  60. package/src/types/internal.d.ts +8 -10
  61. package/src/types/private.d.ts +33 -1
  62. package/src/types/synthetic/$lib.md +1 -1
  63. package/src/utils/error.js +11 -3
  64. package/src/utils/shared-iterator.js +5 -0
  65. package/src/utils/url.js +99 -2
  66. package/src/version.js +1 -1
  67. package/types/index.d.ts +340 -186
  68. package/types/index.d.ts.map +10 -9
@@ -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, adapter) {
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
- const emulator = await adapter?.emulate?.();
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 kit.alias to a valid vite.resolve.alias array.
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.kit.alias` since it has special meaning for packaging, etc.
26
+ // `config.alias` since it has special meaning for packaging, etc.
27
27
  { find: '$lib', replacement: config.files.lib }
28
28
  ];
29
29
 
@@ -152,18 +152,16 @@ 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('instrumentation.server.js', 'kit.experimental.instrumentation.server', true)`,
155
+ * For `error_for_missing_config('instrumentation.server.js', 'experimental.instrumentation.server', true)`,
156
156
  * returns:
157
157
  *
158
158
  * ```
159
- * To enable `instrumentation.server.js`, add the following to your `svelte.config.js`:
159
+ * To enable `instrumentation.server.js`, add the following to the SvelteKit plugin in your `vite.config.js`:
160
160
  *
161
161
  *\`\`\`js
162
- * kit:
163
- * experimental:
164
- * instrumentation:
165
- * server: true
166
- * }
162
+ * experimental: {
163
+ * instrumentation: {
164
+ * server: true
167
165
  * }
168
166
  * }
169
167
  *\`\`\`
@@ -185,7 +183,7 @@ export function error_for_missing_config(feature_name, path, value) {
185
183
 
186
184
  throw stackless(
187
185
  dedent`\
188
- To enable ${feature_name}, add the following to your \`svelte.config.js\`:
186
+ To enable ${feature_name}, add the following to your SvelteKit plugin in \`vite.config.js\`:
189
187
 
190
188
  ${result}
191
189
  `
@@ -14,6 +14,6 @@ export const dev: boolean;
14
14
  export const building: boolean;
15
15
 
16
16
  /**
17
- * The value of `config.kit.version.name`.
17
+ * The value of `config.version.name`.
18
18
  */
19
19
  export const version: string;
@@ -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 `kit.output.bundleStrategy` is 'single' or 'inline'
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
- result = deserialize(await response.text());
201
- if (result.type === 'error') result.status = response.status;
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 = { type: 'error', error };
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({
@@ -5,7 +5,7 @@ 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.kit.paths.assets`](https://svelte.dev/docs/kit/configuration#paths) if configured, or otherwise by prefixing it with the base path.
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
  *
@@ -102,5 +102,3 @@ export async function match(url) {
102
102
 
103
103
  return null;
104
104
  }
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';
@@ -26,7 +27,12 @@ export function resolve(id, params) {
26
27
  const store = try_get_request_store();
27
28
 
28
29
  if (store && !store.state.prerendering?.fallback) {
29
- const after_base = store.event.url.pathname.slice(initial_base.length);
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: await handle_error_and_jsonify(event, state, options, error),
353
- status:
354
- error instanceof HttpError || error instanceof SvelteKitError
355
- ? error.status
356
- : 500
353
+ error: transformed
357
354
  };
358
355
  }
359
356
  })
@@ -8,8 +8,8 @@ import { get_cache } from './shared.js';
8
8
  import { refresh } from './query.js';
9
9
 
10
10
  /**
11
- * In the context of a remote `command` or `form` request, returns an iterable
12
- * of `{ arg, query }` entries for the refreshes requested by the client, up to
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
- * In the context of a remote `command` or `form` request, returns an iterable
58
- * of `{ arg, query }` entries for the reconnects requested by the client, up to
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
- error(
39
- 400,
40
- await state.handleValidationError({
41
- issues: result.issues,
42
- event
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;