@sveltejs/kit 3.0.0-next.11 → 3.0.0-next.12

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 (61) hide show
  1. package/package.json +1 -1
  2. package/src/cli.js +8 -8
  3. package/src/constants.js +1 -1
  4. package/src/core/config/options.js +43 -35
  5. package/src/core/env.js +25 -11
  6. package/src/core/sync/sync.js +11 -14
  7. package/src/core/sync/utils.js +21 -1
  8. package/src/core/sync/{write_non_ambient.js → write_app_types.js} +23 -21
  9. package/src/core/sync/write_client_manifest.js +4 -12
  10. package/src/core/sync/write_env.js +6 -4
  11. package/src/core/sync/write_server.js +10 -15
  12. package/src/core/sync/write_tsconfig/index.js +245 -0
  13. package/src/core/sync/write_tsconfig/utils.js +162 -0
  14. package/src/core/sync/write_types/index.js +80 -88
  15. package/src/exports/internal/server/index.js +3 -1
  16. package/src/exports/public.d.ts +28 -51
  17. package/src/exports/vite/dev/index.js +88 -76
  18. package/src/exports/vite/index.js +364 -144
  19. package/src/exports/vite/module_ids.js +3 -1
  20. package/src/exports/vite/utils.js +1 -10
  21. package/src/runner.js +13 -0
  22. package/src/runtime/app/forms.js +4 -0
  23. package/src/runtime/app/manifest/index.js +1 -0
  24. package/src/runtime/app/paths/client.js +30 -30
  25. package/src/runtime/app/paths/internal/client.js +26 -0
  26. package/src/runtime/app/paths/server.js +22 -9
  27. package/src/runtime/app/paths/types.d.ts +11 -19
  28. package/src/runtime/app/server/remote/command.js +12 -7
  29. package/src/runtime/app/server/remote/form.js +29 -26
  30. package/src/runtime/app/server/remote/prerender.js +9 -2
  31. package/src/runtime/app/server/remote/query.js +5 -4
  32. package/src/runtime/app/server/remote/shared.js +48 -30
  33. package/src/runtime/app/service-worker/index.js +24 -0
  34. package/src/runtime/app/state/index.js +1 -1
  35. package/src/runtime/client/client.js +46 -9
  36. package/src/runtime/client/remote-functions/form.svelte.js +43 -51
  37. package/src/runtime/client/remote-functions/query/index.js +2 -2
  38. package/src/runtime/client/remote-functions/query-batch.svelte.js +2 -3
  39. package/src/runtime/client/remote-functions/query-live/iterator.js +5 -2
  40. package/src/runtime/client/remote-functions/shared.svelte.js +4 -1
  41. package/src/runtime/client/state.svelte.js +54 -21
  42. package/src/runtime/form-utils.js +89 -54
  43. package/src/runtime/server/cookie.js +1 -1
  44. package/src/runtime/server/data/index.js +31 -28
  45. package/src/runtime/server/errors.js +1 -1
  46. package/src/runtime/server/page/actions.js +3 -3
  47. package/src/runtime/server/page/render.js +19 -28
  48. package/src/runtime/server/remote-functions.js +66 -35
  49. package/src/runtime/server/respond.js +56 -14
  50. package/src/runtime/server/utils.js +10 -0
  51. package/src/types/ambient-private.d.ts +8 -0
  52. package/src/types/ambient.d.ts +22 -27
  53. package/src/types/global-private.d.ts +12 -0
  54. package/src/types/internal.d.ts +13 -3
  55. package/src/utils/url.js +12 -0
  56. package/src/version.js +1 -1
  57. package/types/index.d.ts +80 -98
  58. package/types/index.d.ts.map +4 -1
  59. package/src/core/sync/write_ambient.js +0 -18
  60. package/src/core/sync/write_tsconfig.js +0 -258
  61. /package/src/core/sync/{write_tsconfig_test → write_tsconfig/test-app}/package.json +0 -0
@@ -11,7 +11,12 @@ import { respond_with_error } from './page/respond_with_error.js';
11
11
  import { get_self_origin, is_csrf_forbidden, is_remote_forbidden } from './csrf.js';
12
12
  import { has_prerendered_path, method_not_allowed, redirect_response } from './utils.js';
13
13
  import { handle_fatal_error } from './errors.js';
14
- import { decode_pathname, disable_search, normalize_path } from '../../utils/url.js';
14
+ import {
15
+ decode_pathname,
16
+ disable_search,
17
+ normalize_path,
18
+ relative_pathname
19
+ } from '../../utils/url.js';
15
20
  import { find_route } from '../../utils/routing.js';
16
21
  import { redirect_json_response, render_data } from './data/index.js';
17
22
  import { add_cookies_to_headers, get_cookies } from './cookie.js';
@@ -45,6 +50,28 @@ const default_filter = () => false;
45
50
  /** @type {import('types').RequiredResolveOptions['preload']} */
46
51
  const default_preload = ({ type }) => type === 'js' || type === 'css';
47
52
 
53
+ // `Sec-Fetch-Dest` values for subresource requests that can never render an HTML error page
54
+ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Sec-Fetch-Dest
55
+ const non_html_fetch_destinations = new Set([
56
+ 'audio',
57
+ 'audioworklet',
58
+ 'font',
59
+ 'image',
60
+ 'json',
61
+ 'manifest',
62
+ 'paintworklet',
63
+ 'report',
64
+ 'script',
65
+ 'serviceworker',
66
+ 'sharedworker',
67
+ 'style',
68
+ 'track',
69
+ 'video',
70
+ 'webidentity',
71
+ 'worker',
72
+ 'xslt'
73
+ ]);
74
+
48
75
  const page_methods = new Set(['GET', 'HEAD', 'POST']);
49
76
 
50
77
  const allowed_page_methods = new Set(['GET', 'HEAD', 'OPTIONS']);
@@ -109,6 +136,8 @@ export async function internal_respond(request, options, manifest, state) {
109
136
  /** @type {boolean[] | undefined} */
110
137
  let invalidated_data_nodes;
111
138
 
139
+ let skip_route_resolution = false;
140
+
112
141
  if (is_route_resolution_request) {
113
142
  /**
114
143
  * If the request is for a route resolution, first modify the URL, then continue as normal
@@ -126,8 +155,15 @@ export async function internal_respond(request, options, manifest, state) {
126
155
  .map((node) => node === '1');
127
156
  url.searchParams.delete(INVALIDATED_PARAM);
128
157
  } else if (remote_id) {
129
- url.pathname = request.headers.get('x-sveltekit-pathname') ?? base;
130
- url.search = request.headers.get('x-sveltekit-search') ?? '';
158
+ // query clients don't send these headers, leaving `event.url` as the endpoint URL
159
+ const pathname = request.headers.get('x-sveltekit-pathname');
160
+
161
+ if (pathname === null) {
162
+ skip_route_resolution = true;
163
+ } else {
164
+ url.pathname = pathname;
165
+ url.search = request.headers.get('x-sveltekit-search') ?? '';
166
+ }
131
167
  }
132
168
 
133
169
  /** @type {Record<string, string>} */
@@ -158,6 +194,7 @@ export async function internal_respond(request, options, manifest, state) {
158
194
  is_in_remote_function: false,
159
195
  is_in_remote_form_or_command: false,
160
196
  is_in_remote_query: false,
197
+ is_in_remote_prerender: false,
161
198
  is_in_render: false,
162
199
  is_in_universal_load: false
163
200
  };
@@ -331,7 +368,7 @@ export async function internal_respond(request, options, manifest, state) {
331
368
  return text('Not found', { status: 404, headers });
332
369
  }
333
370
 
334
- if (!state.prerendering?.fallback) {
371
+ if (!state.prerendering?.fallback && !skip_route_resolution) {
335
372
  try {
336
373
  const matchers = await manifest._.matchers();
337
374
  const result = find_route(resolved_path, manifest._.routes, matchers);
@@ -378,10 +415,9 @@ export async function internal_respond(request, options, manifest, state) {
378
415
  status: 308,
379
416
  headers: {
380
417
  'x-sveltekit-normalize': '1',
418
+ // relative so (possibly invisible) path prefixes are preserved
381
419
  location:
382
- // ensure paths starting with '//' are not treated as protocol-relative
383
- (normalized.startsWith('//') ? url.origin + normalized : normalized) +
384
- (url.search === '?' ? '' : url.search)
420
+ relative_pathname(url.pathname, normalized) + (url.search === '?' ? '' : url.search)
385
421
  }
386
422
  });
387
423
  }
@@ -631,13 +667,12 @@ export async function internal_respond(request, options, manifest, state) {
631
667
  ) {
632
668
  endpoint = await route.endpoint();
633
669
 
634
- // Prefer rendering the page if the endpoint can't handle this GET or HEAD request
635
- if (route.page && (method === 'GET' || method === 'HEAD')) {
636
- const endpoint_can_handle = !!(
637
- endpoint.GET ||
638
- endpoint.fallback ||
639
- (method === 'HEAD' && endpoint.HEAD)
640
- );
670
+ // Prefer rendering the page if the endpoint can't handle this GET, HEAD, or POST request
671
+ if (route.page && (method === 'GET' || method === 'HEAD' || method === 'POST')) {
672
+ const endpoint_can_handle =
673
+ method === 'POST'
674
+ ? !!(endpoint.POST || endpoint.fallback)
675
+ : !!(endpoint.GET || endpoint.fallback || (method === 'HEAD' && endpoint.HEAD));
641
676
  if (!endpoint_can_handle) {
642
677
  endpoint = undefined;
643
678
  }
@@ -733,6 +768,13 @@ export async function internal_respond(request, options, manifest, state) {
733
768
  // if this request came direct from the user, rather than
734
769
  // via our own `fetch`, render a 404 page
735
770
  if (state.depth === 0) {
771
+ if (non_html_fetch_destinations.has(event.request.headers.get('sec-fetch-dest') ?? '')) {
772
+ return text('Not Found', {
773
+ status: 404,
774
+ headers: { vary: 'Sec-Fetch-Dest' }
775
+ });
776
+ }
777
+
736
778
  return await respond_with_error({
737
779
  event,
738
780
  event_state,
@@ -50,6 +50,16 @@ export function redirect_response(status, location) {
50
50
  return response;
51
51
  }
52
52
 
53
+ /**
54
+ * @param {Response} response
55
+ */
56
+ export function with_version_header(response) {
57
+ if (__SVELTEKIT_APP_VERSION_CHECKS_ENABLED__) {
58
+ response.headers.set('x-sveltekit-version', __SVELTEKIT_APP_VERSION__);
59
+ }
60
+ return response;
61
+ }
62
+
53
63
  /**
54
64
  * @param {import('@sveltejs/kit').RequestEvent} event
55
65
  * @param {Error & { path: string }} error
@@ -45,3 +45,11 @@ declare module '__sveltekit/env/public/client' {
45
45
  declare module '__sveltekit/env/public/server' {
46
46
  // exported environment variables are defined in env.d.ts
47
47
  }
48
+
49
+ /** Internal version of $app/manifest */
50
+ declare module '__sveltekit/manifest-data' {
51
+ export const immutable: Array<{ path: string }>;
52
+ export const assets: Array<{ path: string }>;
53
+ export const prerendered: Array<{ path: string }>;
54
+ export const routes: Array<{ id: string }>;
55
+ }
@@ -57,32 +57,30 @@ declare namespace App {
57
57
  }
58
58
 
59
59
  /**
60
- * This module is only available to [service workers](https://svelte.dev/docs/kit/service-workers).
60
+ * This module is available to [service workers](https://svelte.dev/docs/kit/service-workers) and other contexts.
61
+ * It exports information about the build output, static files, prerendered pages, and routes.
61
62
  */
62
- declare module '$service-worker' {
63
+ declare module '$app/manifest' {
63
64
  /**
64
- * The `base` path of the deployment. Typically this is equivalent to `config.paths.base`, but it is calculated from `location.pathname` meaning that it will continue to work correctly if the site is deployed to a subdirectory.
65
- * Note that there is a `base` but no `assets`, since service workers cannot be used if `config.paths.assets` is specified.
66
- */
67
- export const base: string;
68
- /**
69
- * An array of URL strings representing the files generated by Vite, suitable for caching with `cache.addAll(build)`.
65
+ * An array of `{ path: string }` objects representing the files generated by Vite.
66
+ * The path is relative to the [base path](https://svelte.dev/docs/kit/configuration#paths), and is intended for use with `cache.add(...)` inside a [service worker](https://svelte.dev/docs/kit/service-workers).
70
67
  * During development, this is an empty array.
71
68
  */
72
- export const build: string[];
69
+ export const immutable: Array<{ path: string }>;
73
70
  /**
74
- * An array of URL strings representing the files in your static directory, or whatever directory is specified by `config.files.assets`. You can customize which files are included from `static` directory using [`config.serviceWorker.files`](https://svelte.dev/docs/kit/configuration#serviceWorker)
71
+ * An array of `{ path: AssetPath }` objects representing the files in your `static` directory, or whatever directory is specified by `config.files.assets`.
72
+ * The path is relative to the [base path](https://svelte.dev/docs/kit/configuration#paths), and can be used with [`asset(...)`](https://svelte.dev/docs/kit/$app-paths#asset).
75
73
  */
76
- export const files: string[];
74
+ export const assets: Array<{ path: import('$app/types').AssetPath }>;
77
75
  /**
78
- * An array of pathnames corresponding to prerendered pages and endpoints.
76
+ * An array of `{ path: Path }` objects representing prerendered pages and endpoints, relative to the [base path](https://svelte.dev/docs/kit/configuration#paths).
79
77
  * During development, this is an empty array.
80
78
  */
81
- export const prerendered: string[];
79
+ export const prerendered: Array<{ path: import('$app/types').Path }>;
82
80
  /**
83
- * See [`config.version`](https://svelte.dev/docs/kit/configuration#version). It's useful for generating unique cache names inside your service worker, so that a later deployment of your app can invalidate old caches.
81
+ * An array of objects with an `id` property representing the routes in your app.
84
82
  */
85
- export const version: string;
83
+ export const routes: Array<{ id: import('$app/types').RouteId }>;
86
84
  }
87
85
 
88
86
  /**
@@ -99,9 +97,9 @@ declare module '$app/types' {
99
97
  RouteId(): string;
100
98
  RouteParams(): Record<string, Record<string, string>>;
101
99
  LayoutParams(): Record<string, Record<string, string>>;
102
- Pathname(): string;
100
+ Path(): string;
103
101
  ResolvedPathname(): string;
104
- Asset(): string;
102
+ AssetPath(): string;
105
103
  }
106
104
 
107
105
  /**
@@ -129,25 +127,22 @@ declare module '$app/types' {
129
127
  : Record<string, never>;
130
128
 
131
129
  /**
132
- * A union of all valid pathnames in your app.
130
+ * A union of all valid paths in your app, relative to the `base` path.
133
131
  */
134
- export type Pathname = ReturnType<AppTypes['Pathname']>;
132
+ export type Path = ReturnType<AppTypes['Path']>;
135
133
 
136
134
  /**
137
- * `Pathname`, but possibly suffixed with a search string and/or hash.
135
+ * `Path`, but possibly suffixed with a search string and/or hash.
138
136
  */
139
- export type PathnameWithSearchOrHash =
140
- | Pathname
141
- | `${Pathname}?${string}`
142
- | `${Pathname}#${string}`;
137
+ export type PathnameWithSearchOrHash = Path | `${Path}?${string}` | `${Path}#${string}`;
143
138
 
144
139
  /**
145
- * `Pathname`, but possibly prefixed with a base path. Used for `page.url.pathname`.
140
+ * `Path`, but prefixed with a base path. Used for `page.url.pathname`.
146
141
  */
147
142
  export type ResolvedPathname = ReturnType<AppTypes['ResolvedPathname']>;
148
143
 
149
144
  /**
150
- * A union of all the filenames of assets contained in your `static` directory.
145
+ * A union of all the filenames of assets contained in your `static` directory, relative to the `base` path.
151
146
  */
152
- export type Asset = ReturnType<AppTypes['Asset']>;
147
+ export type AssetPath = ReturnType<AppTypes['AssetPath']>;
153
148
  }
@@ -6,6 +6,8 @@ declare global {
6
6
  const __SVELTEKIT_APP_VERSION__: string;
7
7
  const __SVELTEKIT_APP_VERSION_FILE__: string;
8
8
  const __SVELTEKIT_APP_VERSION_POLL_INTERVAL__: number;
9
+ /** True if version checks are enabled (i.e. `bundleStrategy !== 'inline'`) */
10
+ const __SVELTEKIT_APP_VERSION_CHECKS_ENABLED__: boolean;
9
11
  /**
10
12
  * True if the user ran `vite dev`. This is different from `esm-env` because
11
13
  * it is influenced by `NODE_ENV` which can still be true during `vite preview`
@@ -42,6 +44,16 @@ declare global {
42
44
  * Whether the `experimental.async` flag is applied
43
45
  */
44
46
  const __SVELTEKIT_SUPPORTS_ASYNC__: boolean;
47
+ /**
48
+ * Manifest data placeholders used by `$app/manifest`. During build, these
49
+ * are bare identifiers (fake globals) that the bundler leaves as unresolved
50
+ * references. They are replaced with real values by scanning the output
51
+ * chunks after each build completes.
52
+ */
53
+ const __SVELTEKIT_MANIFEST_IMMUTABLE__: string[];
54
+ const __SVELTEKIT_MANIFEST_ASSETS__: string[];
55
+ const __SVELTEKIT_MANIFEST_PRERENDERED__: string[];
56
+ const __SVELTEKIT_MANIFEST_ROUTES__: { id: string }[];
45
57
  /**
46
58
  * This makes the use of specific features visible at both dev and build time, in such a
47
59
  * way that we can error when they are not supported by the target platform.
@@ -496,6 +496,7 @@ export interface SSROptions {
496
496
  }): string;
497
497
  error(values: { message: string; status: number }): string;
498
498
  };
499
+ version: string;
499
500
  version_hash: string;
500
501
  }
501
502
 
@@ -646,7 +647,7 @@ export interface RemoteFormInternals extends BaseRemoteInternals {
646
647
  * For keyed (`form.for(key)`) instances: the id as the client computes it
647
648
  * (the key is JSON-stringified but not URI-encoded, unlike `id`)
648
649
  */
649
- action_id?: string;
650
+ key?: string;
650
651
  fn(body: Record<string, any>, meta: BinaryFormMeta, form_data: FormData | null): Promise<any>;
651
652
  }
652
653
 
@@ -700,8 +701,11 @@ export interface RequestState {
700
701
  */
701
702
  implicit: null | Map<RemoteInternals, Record<string, () => MaybePromise<any>>>;
702
703
  /**
703
- * Data that is explicitly included because of a `set(...)` or `refresh()`.
704
- * This is always awaited
704
+ * Data that is explicitly included because of a `set(...)`, `refresh()` or
705
+ * `reconnect()`. The stored function is invoked lazily at the end of the
706
+ * request by `collect_remote_data`; if the query was already read (and thus
707
+ * cached) earlier in the request, invoking it does no additional work. This
708
+ * is always awaited and serialized.
705
709
  */
706
710
  explicit: null | Map<
707
711
  string,
@@ -736,8 +740,14 @@ export interface RequestState {
736
740
  readonly is_in_remote_function: boolean;
737
741
  readonly is_in_remote_form_or_command: boolean;
738
742
  readonly is_in_remote_query: boolean;
743
+ readonly is_in_remote_prerender: boolean;
739
744
  readonly is_in_render: boolean;
740
745
  readonly is_in_universal_load: boolean;
746
+ /**
747
+ * The event before `derive_remote_function_event` hid or stubbed properties.
748
+ * Hooks like `handleValidationError` receive this so `url` etc. stay accessible
749
+ */
750
+ readonly original_event?: RequestEvent;
741
751
  }
742
752
 
743
753
  export interface RequestStore {
package/src/utils/url.js CHANGED
@@ -27,6 +27,18 @@ export function is_root_relative(path) {
27
27
  return path[0] === '/' && path[1] !== '/';
28
28
  }
29
29
 
30
+ /**
31
+ * Relative reference from `from` to `to`, which must differ only by a trailing slash
32
+ * @param {string} from
33
+ * @param {string} to
34
+ * @returns {string}
35
+ */
36
+ export function relative_pathname(from, to) {
37
+ const segment = to.replace(/\/$/, '').split('/').at(-1);
38
+
39
+ return from.endsWith('/') ? `../${segment}` : `${segment}/`;
40
+ }
41
+
30
42
  /**
31
43
  * @param {string} location
32
44
  * @param {string} allowed
package/src/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  // generated during release, do not modify
2
2
 
3
3
  /** @type {string} */
4
- export const VERSION = '3.0.0-next.11';
4
+ export const VERSION = '3.0.0-next.12';