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

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 (84) hide show
  1. package/package.json +10 -10
  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/postbuild/prerender.js +3 -3
  7. package/src/core/sync/sync.js +11 -14
  8. package/src/core/sync/utils.js +21 -1
  9. package/src/core/sync/{write_non_ambient.js → write_app_types.js} +24 -23
  10. package/src/core/sync/write_client_manifest.js +4 -12
  11. package/src/core/sync/write_env.js +6 -4
  12. package/src/core/sync/write_server.js +10 -15
  13. package/src/core/sync/write_tsconfig/index.js +257 -0
  14. package/src/core/sync/write_tsconfig/utils.js +162 -0
  15. package/src/core/sync/write_types/index.js +80 -88
  16. package/src/exports/index.js +23 -12
  17. package/src/exports/internal/server/index.js +3 -1
  18. package/src/exports/internal/shared.js +4 -12
  19. package/src/exports/public.d.ts +87 -62
  20. package/src/exports/vite/build/remote.js +10 -12
  21. package/src/exports/vite/dev/index.js +113 -88
  22. package/src/exports/vite/index.js +452 -237
  23. package/src/exports/vite/module_ids.js +3 -1
  24. package/src/exports/vite/utils.js +1 -10
  25. package/src/runner.js +13 -0
  26. package/src/runtime/app/forms.js +4 -0
  27. package/src/runtime/app/manifest/index.js +1 -0
  28. package/src/runtime/app/paths/client.js +30 -30
  29. package/src/runtime/app/paths/internal/client.js +26 -0
  30. package/src/runtime/app/paths/server.js +22 -9
  31. package/src/runtime/app/paths/types.d.ts +11 -19
  32. package/src/runtime/app/server/remote/command.js +12 -7
  33. package/src/runtime/app/server/remote/form.js +37 -26
  34. package/src/runtime/app/server/remote/prerender.js +22 -11
  35. package/src/runtime/app/server/remote/query.js +5 -4
  36. package/src/runtime/app/server/remote/requested.js +4 -4
  37. package/src/runtime/app/server/remote/shared.js +48 -30
  38. package/src/runtime/app/service-worker/index.js +24 -0
  39. package/src/runtime/app/state/client.js +3 -0
  40. package/src/runtime/app/state/index.js +3 -3
  41. package/src/runtime/app/state/server.js +3 -0
  42. package/src/runtime/client/client.js +627 -311
  43. package/src/runtime/client/constants.js +2 -6
  44. package/src/runtime/client/fetcher.js +27 -17
  45. package/src/runtime/client/remote-functions/form.svelte.js +82 -58
  46. package/src/runtime/client/remote-functions/prerender.svelte.js +1 -1
  47. package/src/runtime/client/remote-functions/query/index.js +2 -2
  48. package/src/runtime/client/remote-functions/query/instance.svelte.js +2 -2
  49. package/src/runtime/client/remote-functions/query-batch.svelte.js +3 -4
  50. package/src/runtime/client/remote-functions/query-live/instance.svelte.js +2 -2
  51. package/src/runtime/client/remote-functions/query-live/iterator.js +15 -10
  52. package/src/runtime/client/remote-functions/shared.svelte.js +15 -11
  53. package/src/runtime/client/state.svelte.js +54 -33
  54. package/src/runtime/client/types.d.ts +1 -2
  55. package/src/runtime/client/utils.js +21 -14
  56. package/src/runtime/components/root.svelte +4 -14
  57. package/src/runtime/form-utils.js +89 -54
  58. package/src/runtime/props.svelte.js +71 -0
  59. package/src/runtime/server/cookie.js +1 -1
  60. package/src/runtime/server/data/index.js +31 -28
  61. package/src/runtime/server/errors.js +1 -1
  62. package/src/runtime/server/fetch.js +4 -6
  63. package/src/runtime/server/page/actions.js +3 -3
  64. package/src/runtime/server/page/csp.js +86 -103
  65. package/src/runtime/server/page/index.js +1 -2
  66. package/src/runtime/server/page/load_data.js +15 -5
  67. package/src/runtime/server/page/render.js +46 -52
  68. package/src/runtime/server/page/respond_with_error.js +1 -3
  69. package/src/runtime/server/remote-functions.js +66 -35
  70. package/src/runtime/server/respond.js +56 -16
  71. package/src/runtime/server/utils.js +10 -0
  72. package/src/types/ambient-private.d.ts +9 -1
  73. package/src/types/ambient.d.ts +23 -28
  74. package/src/types/global-private.d.ts +12 -0
  75. package/src/types/internal.d.ts +15 -10
  76. package/src/types/private.d.ts +3 -12
  77. package/src/utils/url.js +12 -0
  78. package/src/version.js +1 -1
  79. package/types/index.d.ts +172 -155
  80. package/types/index.d.ts.map +5 -1
  81. package/src/core/sync/write_ambient.js +0 -18
  82. package/src/core/sync/write_tsconfig.js +0 -258
  83. package/src/runtime/types.d.ts +0 -8
  84. /package/src/core/sync/{write_tsconfig_test → write_tsconfig/test-app}/package.json +0 -0
@@ -13,6 +13,7 @@ import { check_incorrect_fail_use } from './page/actions.js';
13
13
  import { DEV } from 'esm-env';
14
14
  import { record_span } from '../telemetry/record_span.js';
15
15
  import { deserialize_binary_form } from '../form-utils.js';
16
+ import { with_version_header } from './utils.js';
16
17
 
17
18
  /**
18
19
  * How long (in milliseconds) to wait after the last message was sent before
@@ -28,11 +29,12 @@ export async function handle_remote_call(event, state, options, manifest, id) {
28
29
  attributes: {
29
30
  'sveltekit.remote.call.id': id
30
31
  },
31
- fn: (current) => {
32
+ fn: async (current) => {
32
33
  const traced_event = merge_tracing(event, current);
33
- return with_request_store({ event: traced_event, state }, () =>
34
+ const response = await with_request_store({ event: traced_event, state }, () =>
34
35
  handle_remote_call_internal(traced_event, state, options, manifest, id)
35
36
  );
37
+ return with_version_header(response);
36
38
  }
37
39
  });
38
40
  }
@@ -240,7 +242,11 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
240
242
  );
241
243
  }
242
244
 
243
- const { data: input, meta, form_data } = await deserialize_binary_form(event.request);
245
+ const {
246
+ data: input,
247
+ meta,
248
+ form_data
249
+ } = await deserialize_binary_form(event.request, internals.id);
244
250
  state.remote.requested = create_requested_map(meta.remote_refreshes);
245
251
 
246
252
  // If this is a keyed form instance (created via form.for(key)), add the key to the form data (unless already set)
@@ -368,43 +374,64 @@ export async function collect_remote_data(data, event, state, options) {
368
374
  /** @type {Promise<any>[]} */
369
375
  const promises = [];
370
376
 
377
+ // Keys the explicit pass has serialized. Invoking a query's `fn` there can, as a
378
+ // side effect, register the same query in `state.remote.implicit` (via
379
+ // `get_response`), so we skip those keys in the implicit pass below to avoid
380
+ // processing them twice.
381
+ /** @type {Set<string>} */
382
+ const processed = new Set();
383
+
371
384
  if (state.remote.explicit) {
372
- for (const [remote_key, { internals, fn }] of state.remote.explicit) {
373
- // there were explicit refreshes/reconnects (via `refresh()`/`set()`/`reconnect()`),
374
- // so the client should apply these single-flight updates instead of calling `invalidateAll()`
375
- data.r = true;
385
+ const { explicit } = state.remote;
376
386
 
377
- const type = /** @type {'p' | 'q' | 'l'} */ (
378
- internals.type === 'query_live' ? 'l' : internals.type[0]
379
- );
387
+ /** @type {Promise<void>[]} */
388
+ const inflight = [];
389
+
390
+ const drain = () => {
391
+ for (const [remote_key, { internals, fn }] of explicit) {
392
+ explicit.delete(remote_key);
393
+ if (processed.has(remote_key)) continue;
394
+ processed.add(remote_key);
395
+
396
+ // there were explicit refreshes/reconnects (via `refresh()`/`set()`/`reconnect()`),
397
+ // so the client should apply these single-flight updates instead of calling `invalidateAll()`
398
+ data.r = true;
380
399
 
381
- // `fn` is deferred until now so the query runs after any state mutations
382
- // in the command/form body. If the query was re-awaited in the meantime,
383
- // `fn` returns the existing (fresh) cache entry rather than re-running.
384
- // Kick off the query immediately and collect the promise so that multiple
385
- // explicit refreshes run concurrently rather than serially.
386
- const promise = fn();
387
-
388
- promises.push(
389
- promise.then(
390
- (v) => {
391
- ((data[type] ??= {})[remote_key] ??= {}).v = v;
392
- },
393
- async (e) => {
394
- if (e instanceof Redirect) {
395
- // already handled elsewhere
396
- return;
400
+ const type = /** @type {'p' | 'q' | 'l'} */ (
401
+ internals.type === 'query_live' ? 'l' : internals.type[0]
402
+ );
403
+
404
+ // `fn` is deferred until now so the query runs after any state mutations
405
+ // in the command/form body. If the query was re-awaited in the meantime,
406
+ // `fn` returns the existing (fresh) cache entry rather than re-running.
407
+ inflight.push(
408
+ fn().then(
409
+ (v) => {
410
+ // a fresh value replaces the node entirely, so a re-run can't leave
411
+ // a stale error from a previous run alongside the new value
412
+ (data[type] ??= {})[remote_key] = { v };
413
+ drain();
414
+ },
415
+ async (e) => {
416
+ if (!(e instanceof Redirect)) {
417
+ // (a Redirect is already handled elsewhere)
418
+ (data[type] ??= {})[remote_key] = { e: await convert_error(e) };
419
+ }
420
+ drain();
397
421
  }
422
+ )
423
+ );
424
+ }
425
+ };
398
426
 
399
- ((data[type] ??= {})[remote_key] ??= {}).e = await convert_error(e);
400
- }
401
- )
402
- );
427
+ drain();
428
+
429
+ // `inflight` grows as settles drain newly-refreshed queries
430
+ for (const promise of inflight) {
431
+ await promise;
403
432
  }
404
433
  }
405
434
 
406
- await Promise.all(promises);
407
-
408
435
  if (state.remote.implicit) {
409
436
  for (const [internals, record] of state.remote.implicit) {
410
437
  // Private (non-exported) remote functions have no `id` and must never be
@@ -416,6 +443,10 @@ export async function collect_remote_data(data, event, state, options) {
416
443
  // form outputs are registered under the client-side action id directly
417
444
  const remote_key = internals.type === 'form' ? key : create_remote_key(internals.id, key);
418
445
 
446
+ // already serialized by the explicit pass (which always awaits and wins),
447
+ // so don't reprocess it here with the implicit "still loading" heuristic
448
+ if (processed.has(remote_key)) continue;
449
+
419
450
  const type = /** @type {'p' | 'q' | 'l' | 'f'} */ (
420
451
  internals.type === 'query_live' ? 'l' : internals.type[0]
421
452
  );
@@ -540,9 +571,9 @@ async function handle_remote_form_post_internal(event, state, manifest, id) {
540
571
  }
541
572
 
542
573
  try {
543
- const fn = /** @type {RemoteFormInternals} */ (/** @type {any} */ (form).__).fn;
574
+ const __ = /** @type {RemoteFormInternals} */ (/** @type {any} */ (form).__);
544
575
 
545
- const { data, meta, form_data } = await deserialize_binary_form(event.request);
576
+ const { data, meta, form_data } = await deserialize_binary_form(event.request, __.id);
546
577
 
547
578
  if (action_id && !('id' in data)) {
548
579
  data.id = JSON.parse(decodeURIComponent(action_id));
@@ -550,7 +581,7 @@ async function handle_remote_form_post_internal(event, state, manifest, id) {
550
581
 
551
582
  await with_request_store(
552
583
  { event, state: { ...state, is_in_remote_form_or_command: true } },
553
- () => fn(data, meta, form_data)
584
+ () => __.fn(data, meta, form_data)
554
585
  );
555
586
 
556
587
  // We don't want the data to appear on `let { form } = $props()`, which is why we're not returning it.
@@ -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
  }
@@ -568,7 +604,6 @@ export async function internal_respond(request, options, manifest, state) {
568
604
  options,
569
605
  manifest,
570
606
  state,
571
- status: 400,
572
607
  error: new SvelteKitError(
573
608
  400,
574
609
  'Malformed URI',
@@ -631,13 +666,12 @@ export async function internal_respond(request, options, manifest, state) {
631
666
  ) {
632
667
  endpoint = await route.endpoint();
633
668
 
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
- );
669
+ // Prefer rendering the page if the endpoint can't handle this GET, HEAD, or POST request
670
+ if (route.page && (method === 'GET' || method === 'HEAD' || method === 'POST')) {
671
+ const endpoint_can_handle =
672
+ method === 'POST'
673
+ ? !!(endpoint.POST || endpoint.fallback)
674
+ : !!(endpoint.GET || endpoint.fallback || (method === 'HEAD' && endpoint.HEAD));
641
675
  if (!endpoint_can_handle) {
642
676
  endpoint = undefined;
643
677
  }
@@ -733,13 +767,19 @@ export async function internal_respond(request, options, manifest, state) {
733
767
  // if this request came direct from the user, rather than
734
768
  // via our own `fetch`, render a 404 page
735
769
  if (state.depth === 0) {
770
+ if (non_html_fetch_destinations.has(event.request.headers.get('sec-fetch-dest') ?? '')) {
771
+ return text('Not Found', {
772
+ status: 404,
773
+ headers: { vary: 'Sec-Fetch-Dest' }
774
+ });
775
+ }
776
+
736
777
  return await respond_with_error({
737
778
  event,
738
779
  event_state,
739
780
  options,
740
781
  manifest,
741
782
  state,
742
- status: 404,
743
783
  error: new SvelteKitError(404, 'Not Found', `Not found: ${event.url.pathname}`),
744
784
  resolve_opts
745
785
  });
@@ -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
@@ -25,7 +25,7 @@ declare module '__sveltekit/env' {
25
25
  // exported environment variables are defined in env.d.ts
26
26
 
27
27
  /** Populate exported environment variables */
28
- export function set_env(environment: Record<string, string>): void;
28
+ export function set_env(environment: Record<string, string | undefined>): void;
29
29
 
30
30
  /** public env vars */
31
31
  export const explicit_public_env: Record<string, any>;
@@ -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
+ }
@@ -44,7 +44,7 @@ declare namespace App {
44
44
  export interface PageData {}
45
45
 
46
46
  /**
47
- * The shape of the `page.state` object, which can be manipulated using the [`pushState`](https://svelte.dev/docs/kit/$app-navigation#pushState) and [`replaceState`](https://svelte.dev/docs/kit/$app-navigation#replaceState) functions from `$app/navigation`.
47
+ * The shape of the `page.state` object, which can be manipulated using [`goto`](https://svelte.dev/docs/kit/$app-navigation#goto).
48
48
  */
49
49
  // eslint-disable-next-line @typescript-eslint/no-empty-object-type
50
50
  export interface PageState {}
@@ -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
 
@@ -658,15 +659,10 @@ export interface RemotePrerenderInternals extends BaseRemoteInternals {
658
659
  }
659
660
 
660
661
  export type RemoteAnyQueryInternals =
661
- | RemoteQueryInternals
662
- | RemoteQueryBatchInternals
663
- | RemoteQueryLiveInternals;
662
+ RemoteQueryInternals | RemoteQueryBatchInternals | RemoteQueryLiveInternals;
664
663
 
665
664
  export type RemoteInternals =
666
- | RemoteAnyQueryInternals
667
- | RemoteCommandInternals
668
- | RemoteFormInternals
669
- | RemotePrerenderInternals;
665
+ RemoteAnyQueryInternals | RemoteCommandInternals | RemoteFormInternals | RemotePrerenderInternals;
670
666
 
671
667
  export interface InternalRemoteFormIssue extends RemoteFormIssue {
672
668
  name: string;
@@ -700,8 +696,11 @@ export interface RequestState {
700
696
  */
701
697
  implicit: null | Map<RemoteInternals, Record<string, () => MaybePromise<any>>>;
702
698
  /**
703
- * Data that is explicitly included because of a `set(...)` or `refresh()`.
704
- * This is always awaited
699
+ * Data that is explicitly included because of a `set(...)`, `refresh()` or
700
+ * `reconnect()`. The stored function is invoked lazily at the end of the
701
+ * request by `collect_remote_data`; if the query was already read (and thus
702
+ * cached) earlier in the request, invoking it does no additional work. This
703
+ * is always awaited and serialized.
705
704
  */
706
705
  explicit: null | Map<
707
706
  string,
@@ -736,8 +735,14 @@ export interface RequestState {
736
735
  readonly is_in_remote_function: boolean;
737
736
  readonly is_in_remote_form_or_command: boolean;
738
737
  readonly is_in_remote_query: boolean;
738
+ readonly is_in_remote_prerender: boolean;
739
739
  readonly is_in_render: boolean;
740
740
  readonly is_in_universal_load: boolean;
741
+ /**
742
+ * The event before `derive_remote_function_event` hid or stubbed properties.
743
+ * Hooks like `handleValidationError` receive this so `url` etc. stay accessible
744
+ */
745
+ readonly original_event?: RequestEvent;
741
746
  }
742
747
 
743
748
  export interface RequestStore {
@@ -239,20 +239,11 @@ export interface PrerenderInvalidUrlHandler {
239
239
  export type PrerenderHttpErrorHandlerValue = 'fail' | 'warn' | 'ignore' | PrerenderHttpErrorHandler;
240
240
  export type PrerenderMissingIdHandlerValue = 'fail' | 'warn' | 'ignore' | PrerenderMissingIdHandler;
241
241
  export type PrerenderUnseenRoutesHandlerValue =
242
- | 'fail'
243
- | 'warn'
244
- | 'ignore'
245
- | PrerenderUnseenRoutesHandler;
242
+ 'fail' | 'warn' | 'ignore' | PrerenderUnseenRoutesHandler;
246
243
  export type PrerenderEntryGeneratorMismatchHandlerValue =
247
- | 'fail'
248
- | 'warn'
249
- | 'ignore'
250
- | PrerenderEntryGeneratorMismatchHandler;
244
+ 'fail' | 'warn' | 'ignore' | PrerenderEntryGeneratorMismatchHandler;
251
245
  export type PrerenderInvalidUrlHandlerValue =
252
- | 'fail'
253
- | 'warn'
254
- | 'ignore'
255
- | PrerenderInvalidUrlHandler;
246
+ 'fail' | 'warn' | 'ignore' | PrerenderInvalidUrlHandler;
256
247
 
257
248
  export type PrerenderOption = boolean | 'auto';
258
249
 
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.13';