@qwik.dev/router 2.0.0-beta.36 → 2.0.0-beta.38

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 (41) hide show
  1. package/lib/adapters/cloudflare-pages/vite/index.mjs +3 -5
  2. package/lib/adapters/shared/vite/index.d.ts +3 -4
  3. package/lib/adapters/shared/vite/index.mjs +167 -155
  4. package/lib/chunks/dev-preloaded-route-loader.mjs +3 -0
  5. package/lib/chunks/format.mjs +31 -0
  6. package/lib/chunks/fs.mjs +10 -8
  7. package/lib/chunks/head.qwik.mjs +1425 -0
  8. package/lib/chunks/http-error.qwik.mjs +2 -2
  9. package/lib/chunks/pathname.mjs +3 -32
  10. package/lib/chunks/request-body-limit.mjs +37 -0
  11. package/lib/chunks/request-path.mjs +60 -0
  12. package/lib/chunks/routes.mjs +47 -0
  13. package/lib/chunks/server-error.mjs +19 -0
  14. package/lib/chunks/system.mjs +8 -8
  15. package/lib/chunks/use-functions.qwik.mjs +3 -12
  16. package/lib/chunks/user-response.mjs +1875 -0
  17. package/lib/chunks/worker-thread.mjs +317 -0
  18. package/lib/index.d.ts +251 -44
  19. package/lib/index.qwik.mjs +734 -485
  20. package/lib/middleware/aws-lambda/index.mjs +2 -1
  21. package/lib/middleware/azure-swa/index.mjs +13 -9
  22. package/lib/middleware/cloudflare-pages/index.mjs +2 -2
  23. package/lib/middleware/deno/index.d.ts +2 -0
  24. package/lib/middleware/deno/index.mjs +2 -1
  25. package/lib/middleware/netlify-edge/index.mjs +2 -2
  26. package/lib/middleware/node/index.d.ts +9 -1
  27. package/lib/middleware/node/index.mjs +28 -3
  28. package/lib/middleware/request-handler/index.d.ts +65 -26
  29. package/lib/middleware/request-handler/index.mjs +38 -1679
  30. package/lib/middleware/vercel-edge/index.mjs +2 -2
  31. package/lib/ssg/index.d.ts +5 -13
  32. package/lib/ssg/index.mjs +14 -53
  33. package/lib/vite/index.d.ts +23 -0
  34. package/lib/vite/index.mjs +533 -122
  35. package/package.json +4 -3
  36. package/lib/chunks/deepFreeze.qwik.mjs +0 -18
  37. package/lib/chunks/error-handler.mjs +0 -57
  38. package/lib/chunks/not-found-wrapper.qwik.mjs +0 -25
  39. package/lib/chunks/redirect-handler.mjs +0 -6
  40. package/lib/chunks/routing.qwik.mjs +0 -821
  41. package/lib/chunks/worker-thread.qwik.mjs +0 -2585
package/lib/index.d.ts CHANGED
@@ -1,13 +1,16 @@
1
1
  /// <reference path="./modules.d.ts" />
2
2
 
3
- import type { AsyncSignal } from '@qwik.dev/core';
3
+ import type { AbortMessage } from '@qwik.dev/router/middleware/request-handler';
4
4
  import { Component } from '@qwik.dev/core';
5
+ import type { ComputedSignal } from '@qwik.dev/core';
5
6
  import { Cookie } from '@qwik.dev/router/middleware/request-handler';
6
7
  import { CookieOptions } from '@qwik.dev/router/middleware/request-handler';
7
8
  import { CookieValue } from '@qwik.dev/router/middleware/request-handler';
8
9
  import { DeferReturn } from '@qwik.dev/router/middleware/request-handler';
9
10
  import type { EnvGetter } from '@qwik.dev/router/middleware/request-handler';
11
+ import { InternalRequest } from '@qwik.dev/router/middleware/request-handler';
10
12
  import { JSXOutput } from '@qwik.dev/core';
13
+ import { NoSerialize } from '@qwik.dev/core';
11
14
  import { QRL } from '@qwik.dev/core';
12
15
  import { QRLEventHandlerMulti } from '@qwik.dev/core';
13
16
  import { QwikIntrinsicElements } from '@qwik.dev/core';
@@ -22,6 +25,7 @@ import { RequestEventLoader } from '@qwik.dev/router/middleware/request-handler'
22
25
  import { RequestHandler } from '@qwik.dev/router/middleware/request-handler';
23
26
  import type { ResolveSyncValue } from '@qwik.dev/router/middleware/request-handler';
24
27
  import type { SerializationStrategy } from '@qwik.dev/core/internal';
28
+ import type { ServerError } from '@qwik.dev/router/middleware/request-handler';
25
29
  import type { Signal } from '@qwik.dev/core';
26
30
  import type * as v from 'valibot';
27
31
  import type { ValueOrPromise } from '@qwik.dev/core';
@@ -36,51 +40,53 @@ export declare type Action<RETURN, INPUT = Record<string, unknown>, OPTIONAL ext
36
40
  * component$(). Like all `use-` functions and methods, it can only be invoked within a
37
41
  * `component$()`.
38
42
  */
39
- (): ActionStore<RETURN, INPUT, OPTIONAL>;
43
+ (): ActionStore<ExcludeControlFlow<RETURN>, INPUT, OPTIONAL>;
40
44
  };
41
45
 
42
46
  /** @public */
43
47
  export declare type ActionConstructor = {
44
- <OBJ extends Record<string, any> | void | null, VALIDATOR extends TypedDataValidator, REST extends [DataValidator, ...DataValidator[]]>(actionQrl: (data: GetValidatorOutputType<VALIDATOR>, event: RequestEventAction) => ValueOrPromise<OBJ>, options: {
45
- readonly id?: string;
48
+ <OBJ extends Record<string, any> | void | null, VALIDATOR extends TypedDataValidator, REST extends [DataValidator, ...DataValidator[]]>(actionQrl: (data: GetValidatorOutputType<VALIDATOR>, event: RequestEventAction) => ValueOrPromise<OBJ>, options: ActionOptions & {
46
49
  readonly validation: [VALIDATOR, ...REST];
47
50
  }): Action<StrictUnion<OBJ | FailReturn<ValidatorErrorType<GetValidatorInputType<VALIDATOR>>> | FailReturn<FailOfRest<REST>>>, GetValidatorInputType<VALIDATOR>, false>;
48
- <OBJ extends Record<string, any> | void | null, VALIDATOR extends TypedDataValidator>(actionQrl: (data: GetValidatorOutputType<VALIDATOR>, event: RequestEventAction) => ValueOrPromise<OBJ>, options: {
49
- readonly id?: string;
51
+ <OBJ extends Record<string, any> | void | null, VALIDATOR extends TypedDataValidator>(actionQrl: (data: GetValidatorOutputType<VALIDATOR>, event: RequestEventAction) => ValueOrPromise<OBJ>, options: ActionOptions & {
50
52
  readonly validation: [VALIDATOR];
51
53
  }): Action<StrictUnion<OBJ | FailReturn<ValidatorErrorType<GetValidatorInputType<VALIDATOR>>>>, GetValidatorInputType<VALIDATOR>, false>;
52
- <OBJ extends Record<string, any> | void | null, REST extends [DataValidator, ...DataValidator[]]>(actionQrl: (data: JSONObject, event: RequestEventAction) => ValueOrPromise<OBJ>, options: {
53
- readonly id?: string;
54
+ <OBJ extends Record<string, any> | void | null, REST extends [DataValidator, ...DataValidator[]]>(actionQrl: (data: JSONObject, event: RequestEventAction) => ValueOrPromise<OBJ>, options: ActionOptions & {
54
55
  readonly validation: REST;
55
56
  }): Action<StrictUnion<OBJ | FailReturn<FailOfRest<REST>>>>;
56
57
  <OBJ extends Record<string, any> | void | null, VALIDATOR extends TypedDataValidator, REST extends [DataValidator, ...DataValidator[]]>(actionQrl: (data: GetValidatorOutputType<VALIDATOR>, event: RequestEventAction) => ValueOrPromise<OBJ>, options: VALIDATOR, ...rest: REST): Action<StrictUnion<OBJ | FailReturn<ValidatorErrorType<GetValidatorInputType<VALIDATOR>>> | FailReturn<FailOfRest<REST>>>, GetValidatorInputType<VALIDATOR>, false>;
57
58
  <OBJ extends Record<string, any> | void | null, VALIDATOR extends TypedDataValidator>(actionQrl: (data: GetValidatorOutputType<VALIDATOR>, event: RequestEventAction) => ValueOrPromise<OBJ>, options: VALIDATOR): Action<StrictUnion<OBJ | FailReturn<ValidatorErrorType<GetValidatorInputType<VALIDATOR>>>>, GetValidatorInputType<VALIDATOR>, false>;
58
59
  <OBJ extends Record<string, any> | void | null, REST extends [DataValidator, ...DataValidator[]]>(actionQrl: (form: JSONObject, event: RequestEventAction) => ValueOrPromise<OBJ>, ...rest: REST): Action<StrictUnion<OBJ | FailReturn<FailOfRest<REST>>>>;
59
- <OBJ>(actionQrl: (form: JSONObject, event: RequestEventAction) => ValueOrPromise<OBJ>, options?: {
60
- readonly id?: string;
61
- }): Action<StrictUnion<OBJ>>;
60
+ <OBJ>(actionQrl: (form: JSONObject, event: RequestEventAction) => ValueOrPromise<OBJ>, options?: ActionOptions): Action<StrictUnion<OBJ>>;
62
61
  };
63
62
 
64
63
  /** @public */
65
64
  declare type ActionConstructorQRL = {
66
- <OBJ extends Record<string, any> | void | null, VALIDATOR extends TypedDataValidator, REST extends [DataValidator, ...DataValidator[]]>(actionQrl: QRL<(data: GetValidatorOutputType<VALIDATOR>, event: RequestEventAction) => ValueOrPromise<OBJ>>, options: {
67
- readonly id?: string;
65
+ <OBJ extends Record<string, any> | void | null, VALIDATOR extends TypedDataValidator, REST extends [DataValidator, ...DataValidator[]]>(actionQrl: QRL<(data: GetValidatorOutputType<VALIDATOR>, event: RequestEventAction) => ValueOrPromise<OBJ>>, options: ActionOptions & {
68
66
  readonly validation: [VALIDATOR, ...REST];
69
67
  }): Action<StrictUnion<OBJ | FailReturn<ValidatorErrorType<GetValidatorInputType<VALIDATOR>>> | FailReturn<FailOfRest<REST>>>, GetValidatorInputType<VALIDATOR>, false>;
70
- <OBJ extends Record<string, any> | void | null, VALIDATOR extends TypedDataValidator>(actionQrl: QRL<(data: GetValidatorOutputType<VALIDATOR>, event: RequestEventAction) => ValueOrPromise<OBJ>>, options: {
71
- readonly id?: string;
68
+ <OBJ extends Record<string, any> | void | null, VALIDATOR extends TypedDataValidator>(actionQrl: QRL<(data: GetValidatorOutputType<VALIDATOR>, event: RequestEventAction) => ValueOrPromise<OBJ>>, options: ActionOptions & {
72
69
  readonly validation: [VALIDATOR];
73
70
  }): Action<StrictUnion<OBJ | FailReturn<ValidatorErrorType<GetValidatorInputType<VALIDATOR>>>>, GetValidatorInputType<VALIDATOR>, false>;
74
- <OBJ extends Record<string, any> | void | null, REST extends [DataValidator, ...DataValidator[]]>(actionQrl: QRL<(data: JSONObject, event: RequestEventAction) => ValueOrPromise<OBJ>>, options: {
75
- readonly id?: string;
71
+ <OBJ extends Record<string, any> | void | null, REST extends [DataValidator, ...DataValidator[]]>(actionQrl: QRL<(data: JSONObject, event: RequestEventAction) => ValueOrPromise<OBJ>>, options: ActionOptions & {
76
72
  readonly validation: REST;
77
73
  }): Action<StrictUnion<OBJ | FailReturn<FailOfRest<REST>>>>;
78
74
  <OBJ extends Record<string, any> | void | null, VALIDATOR extends TypedDataValidator, REST extends [DataValidator, ...DataValidator[]]>(actionQrl: QRL<(data: GetValidatorOutputType<VALIDATOR>, event: RequestEventAction) => ValueOrPromise<OBJ>>, options: VALIDATOR, ...rest: REST): Action<StrictUnion<OBJ | FailReturn<ValidatorErrorType<GetValidatorInputType<VALIDATOR>>> | FailReturn<FailOfRest<REST>>>, GetValidatorInputType<VALIDATOR>, false>;
79
75
  <OBJ extends Record<string, any> | void | null, VALIDATOR extends TypedDataValidator>(actionQrl: QRL<(data: GetValidatorOutputType<VALIDATOR>, event: RequestEventAction) => ValueOrPromise<OBJ>>, options: VALIDATOR): Action<StrictUnion<OBJ | FailReturn<ValidatorErrorType<GetValidatorInputType<VALIDATOR>>>>, GetValidatorInputType<VALIDATOR>, false>;
80
76
  <OBJ extends Record<string, any> | void | null, REST extends [DataValidator, ...DataValidator[]]>(actionQrl: QRL<(form: JSONObject, event: RequestEventAction) => ValueOrPromise<OBJ>>, ...rest: REST): Action<StrictUnion<OBJ | FailReturn<FailOfRest<REST>>>>;
81
- <OBJ>(actionQrl: QRL<(form: JSONObject, event: RequestEventAction) => ValueOrPromise<OBJ>>, options?: {
82
- readonly id?: string;
83
- }): Action<StrictUnion<OBJ>>;
77
+ <OBJ>(actionQrl: QRL<(form: JSONObject, event: RequestEventAction) => ValueOrPromise<OBJ>>, options?: ActionOptions): Action<StrictUnion<OBJ>>;
78
+ };
79
+
80
+ /** @public */
81
+ export declare type ActionOptions = {
82
+ readonly id?: string;
83
+ readonly validation?: DataValidator[];
84
+ /**
85
+ * Route loaders to invalidate after this action completes. The loader hooks' hashes are sent to
86
+ * the client so it knows which loaders to re-fetch. If omitted, ALL route loaders are invalidated
87
+ * (unless `strictLoaders` is enabled globally in the Vite plugin).
88
+ */
89
+ readonly invalidate?: Loader_2<any>[];
84
90
  };
85
91
 
86
92
  /** @public */
@@ -162,15 +168,25 @@ export declare type ActionStore<RETURN, INPUT, OPTIONAL extends boolean = true>
162
168
  declare type AnchorAttributes = QwikIntrinsicElements['a'];
163
169
 
164
170
  /**
165
- * The cacheKey export type. When exported from a page module alongside eTag, enables in-memory SSR
166
- * caching.
171
+ * Cache key function. Used by `routeConfig.cacheKey` (SSR HTML cache) and by `routeLoader$`'s
172
+ * `cacheKey` option (per-loader JSON cache).
173
+ *
174
+ * - `true`: use the surface's default key.
167
175
  *
168
- * - `true`: use the default cache key `status|eTag|pathname`
169
- * - Function: receives status, eTag, and pathname; returns a cache key string or null (no cache)
176
+ * - SSR default: `${status}|${eTag}|${pathname}` when an eTag is set, otherwise
177
+ * `${status}|${pathname}`.
178
+ * - Loader default: `${pathname}|${filteredSearch}|${loaderId}|${eTag}` when an eTag is set,
179
+ * otherwise `${pathname}|${filteredSearch}|${loaderId}`.
180
+ * - Function: receives the request event and the normalized, unquoted eTag (or an empty string when
181
+ * none was provided). Return the cache key string, or `null` or `''` to skip caching for this
182
+ * request. Loader callbacks receive the loader-scoped request event, with `url`, `query`, and
183
+ * `request.url` filtered by the loader's `search` allowlist.
184
+ *
185
+ * Note: valid cacheKeys are non-empty strings.
170
186
  *
171
187
  * @public
172
188
  */
173
- export declare type CacheKeyFn = true | ((status: number, eTag: string, pathname: string) => string | null);
189
+ export declare type CacheKeyFn = true | ((requestEv: RequestEvent, eTag: string) => string | null);
174
190
 
175
191
  /** @public */
176
192
  export declare interface ContentHeading {
@@ -189,7 +205,18 @@ export declare interface ContentMenu {
189
205
  declare type ContentModule = PageModule | LayoutModule;
190
206
 
191
207
  /**
192
- * The eTag export type: a static string or a function receiving DocumentHeadProps.
208
+ * The eTag export type for routeConfig.
209
+ *
210
+ * - `string` — static ETag value.
211
+ * - `(props: DocumentHeadProps) => string | null` — compute the ETag from route context (params, URL,
212
+ * loaded data via `resolveValue`, etc.). Return `null` to skip eTag for this request.
213
+ *
214
+ * Qwik normalizes eTag values by stripping weak-form `W/` prefixes, quotes, and forbidden chars,
215
+ * then sends a strong `ETag` header. Values that normalize to an empty string are treated as
216
+ * absent.
217
+ *
218
+ * When set (and a value is produced), the server includes an `ETag` header and returns `304` if
219
+ * `If-None-Match` matches.
193
220
  *
194
221
  * @public
195
222
  */
@@ -357,10 +384,10 @@ declare type EndpointModuleLoader = () => ValueOrPromise<RouteModule>;
357
384
  declare interface EndpointResponse {
358
385
  status: number;
359
386
  statusMessage?: string;
360
- loaders: Record<string, unknown>;
361
- loadersSerializationStrategy: Map<string, SerializationStrategy>;
362
387
  formData?: FormData;
363
388
  action?: string;
389
+ actionResult?: unknown;
390
+ loaderHashes?: string[];
364
391
  }
365
392
 
366
393
  /** @public */
@@ -371,6 +398,14 @@ declare interface ErrorBoundaryProps {
371
398
  fallback$?: QRL<(error: any) => any>;
372
399
  }
373
400
 
401
+ /**
402
+ * Drops control-flow signals (`ev.redirect()`, `ev.error()`, etc.) from a loader/action return
403
+ * type: those are thrown, not surfaced as data. `ev.fail()` is plain data and is kept.
404
+ *
405
+ * @public
406
+ */
407
+ export declare type ExcludeControlFlow<T> = Exclude<T, AbortMessage | ServerError>;
408
+
374
409
  declare type Failed = {
375
410
  failed: true;
376
411
  };
@@ -411,6 +446,14 @@ export declare interface FormSubmitSuccessDetail<T> {
411
446
  value: T;
412
447
  }
413
448
 
449
+ /**
450
+ * Returns the current RequestEvent if possible. Only usable on the server, and only during request
451
+ * processing.
452
+ *
453
+ * @public
454
+ */
455
+ export declare const getRequestEvent: (thisArg?: unknown) => RequestEvent | undefined;
456
+
414
457
  /** @public */
415
458
  export declare type GetValidatorInputType<VALIDATOR extends TypedDataValidator> = VALIDATOR extends ValibotDataValidator<infer TYPE> ? v.InferInput<TYPE> : VALIDATOR extends ZodDataValidator<infer TYPE> ? z_2.input<TYPE> : never;
416
459
 
@@ -433,6 +476,8 @@ export declare type HttpErrorProps = {
433
476
  message: string;
434
477
  };
435
478
 
479
+ export { InternalRequest }
480
+
436
481
  declare type IsAny<Type> = 0 extends 1 & Type ? true : false;
437
482
 
438
483
  /** @public */
@@ -457,8 +502,8 @@ export declare const Link: Component<LinkProps>;
457
502
  /** @public */
458
503
  export declare interface LinkProps extends AnchorAttributes {
459
504
  /**
460
- * @deprecated Use `prefetchBundle` and `prefetchData` instead for more granular control over what
461
- * is prefetched and when. This prop will be removed in a future major version.
505
+ * @deprecated Use `prefetchBundles` and `prefetchData` instead for more granular control over
506
+ * what is prefetched and when. This prop will be removed in a future major version.
462
507
  *
463
508
  * Legacy prefetch control for this **`Link`**.
464
509
  *
@@ -476,7 +521,7 @@ export declare interface LinkProps extends AnchorAttributes {
476
521
  *
477
522
  * Prefetching will not occur if the user has the **data saver** setting enabled.
478
523
  */
479
- prefetchBundle?: PrefetchStrategy;
524
+ prefetchBundles?: PrefetchStrategy;
480
525
  /**
481
526
  * Controls when Qwik should prefetch and cache route data for this **`Link`** target, including
482
527
  * invoking any **`routeLoader$`**, **`onGet`**, etc.
@@ -509,8 +554,12 @@ declare interface LoadedRoute {
509
554
  $routeBundleNames$?: string[] | undefined;
510
555
  /** Whether this route is a not-found (404) route */
511
556
  $notFound$?: boolean;
512
- /** The error module loader (nearest _E ancestor), for rendering ServerErrors */
513
- $errorLoader$?: ContentModuleLoader;
557
+ /** The nearest _E (error.tsx) boundary's chain to render on a thrown ServerError (in its layouts). */
558
+ $errorLoader$?: ModuleLoader[];
559
+ /** Merged array of routeLoader$ hashes from all matched nodes (layouts + page) */
560
+ $loaders$?: string[];
561
+ /** Runtime-only mapping of routeLoader$ hashes to the matched pathname used for q-loader fetches */
562
+ $loaderPaths$?: Record<string, string>;
514
563
  }
515
564
 
516
565
  /** @public */
@@ -519,7 +568,7 @@ declare type Loader_2<RETURN> = {
519
568
  * Returns the `Signal` containing the data returned by the `loader$` function. Like all `use-`
520
569
  * functions and methods, it can only be invoked within a `component$()`.
521
570
  */
522
- (): LoaderSignal<RETURN>;
571
+ (): LoaderSignal<ExcludeControlFlow<RETURN>>;
523
572
  };
524
573
  export { Loader_2 as Loader }
525
574
 
@@ -537,13 +586,98 @@ declare type LoaderConstructorQRL = {
537
586
 
538
587
  /** @public */
539
588
  declare type LoaderOptions = {
589
+ /**
590
+ * Explicit loader id, overriding the QRL hash. Pass a distinct value (e.g. `fn.getHash()`) when
591
+ * loaders share a wrapper QRL.
592
+ */
540
593
  readonly id?: string;
541
594
  readonly validation?: DataValidator[];
542
595
  readonly serializationStrategy?: SerializationStrategy;
596
+ /**
597
+ * Time in milliseconds after which the loader data is considered stale. The server derives
598
+ * `Cache-Control: max-age` seconds from this value on loader responses.
599
+ *
600
+ * On the client, the loader's ComputedSignal `expires` is set to this value. If `poll` is true,
601
+ * the signal auto-refetches when expired. If `poll` is false (default), the data is marked stale
602
+ * but not auto-refetched.
603
+ */
604
+ readonly expires?: number;
605
+ /**
606
+ * When true AND `expires` is set, the loader data is automatically refetched when it expires
607
+ * (polling behavior). When false (default), expired data is marked stale but not auto-refetched.
608
+ */
609
+ readonly poll?: boolean;
610
+ /**
611
+ * Enable ETag-based caching for this loader's JSON responses.
612
+ *
613
+ * - `string` — static ETag value; if `If-None-Match` matches, the loader is skipped entirely
614
+ * - `(ev: RequestEvent) => string | null` — compute the ETag from the request context (params, URL,
615
+ * headers, etc.); if `If-None-Match` matches, the loader is skipped entirely. Return null to
616
+ * skip eTag for this request.
617
+ *
618
+ * Qwik normalizes eTag values by stripping weak-form `W/` prefixes, quotes, and forbidden chars,
619
+ * then sends a strong `ETag` header. Values that normalize to an empty string are treated as
620
+ * absent.
621
+ *
622
+ * When set, the server includes an `ETag` header on `q-loader-*.json` responses and returns `304`
623
+ * if the client sends a matching `If-None-Match` header.
624
+ *
625
+ * For auto-computed eTags, use `cacheKey` instead — on cache write the eTag is hashed from the
626
+ * serialized response and stored alongside it, so subsequent hits get the same eTag.
627
+ */
628
+ readonly eTag?: string | ((ev: RequestEvent) => string | null);
629
+ /**
630
+ * Enable in-memory server-side caching of this loader's serialized JSON response.
631
+ *
632
+ * - `true` — use the default key `${pathname}|${filteredSearch}|${loaderId}` (suffixed with
633
+ * `|${eTag}` when an eTag is set).
634
+ * - Function `(requestEv, eTag) => string | null` — return a custom key, or `null` to skip caching
635
+ * this request.
636
+ *
637
+ * On cache miss the loader runs, the serialized response is stored alongside its eTag (computed
638
+ * from the data when no `eTag` option is set), and the response is sent. On cache hit the stored
639
+ * `{ eTag, data }` pair is served directly — `If-None-Match` is checked against the stored eTag
640
+ * and a `304` is returned when it matches.
641
+ */
642
+ readonly cacheKey?: CacheKeyFn;
643
+ /**
644
+ * Allowlist of URL search parameter names that this loader depends on.
645
+ *
646
+ * When set, the loader only re-fetches when the listed search params change — other param changes
647
+ * are ignored. Only the listed params are sent in the loader JSON request URL. During SSR and
648
+ * loader JSON requests, the loader receives a request event with `url`, `query`, and
649
+ * `request.url` filtered to the same params.
650
+ *
651
+ * When not set, the `qwikRouter()` plugin option `strictLoaders` determines the behavior. If
652
+ * `strictLoaders` is `true` (this is the default), no search params are sent and changes do not
653
+ * trigger a re-fetch. If `strictLoaders` is `false`, all search params are sent and any change
654
+ * triggers a re-fetch.
655
+ */
656
+ readonly search?: string[];
657
+ /**
658
+ * When true (default), the previous value is kept while the loader re-fetches after navigation,
659
+ * so components see stale data until the new response arrives.
660
+ *
661
+ * When false, the value is cleared on re-fetch, causing reads to suspend (show a loading
662
+ * boundary). This is useful when showing old data during navigation would be confusing.
663
+ */
664
+ readonly allowStale?: boolean;
665
+ /**
666
+ * When true (default), the loader is awaited before SSR renders, so its redirect or error can
667
+ * short-circuit the response and its value is ready for synchronous reads (e.g. in the head).
668
+ *
669
+ * When false, the loader runs in the background without blocking SSR: rendering starts
670
+ * immediately and reading its `.value` suspends until it resolves. A background loader cannot
671
+ * redirect or error the initial SSR response; treat it as a separate request.
672
+ *
673
+ * Setting `false` is experimental and requires adding `experimental: ["blockSSR"]` to your
674
+ * qwikVite plugin options.
675
+ */
676
+ readonly blockSSR?: boolean;
543
677
  };
544
678
 
545
679
  /** @public */
546
- export declare type LoaderSignal<TYPE> = (TYPE extends () => ValueOrPromise<infer VALIDATOR> ? Signal<ValueOrPromise<VALIDATOR>> : Signal<TYPE>) & Pick<AsyncSignal, 'promise' | 'loading' | 'error'>;
680
+ export declare type LoaderSignal<TYPE> = (TYPE extends () => ValueOrPromise<infer VALIDATOR> ? Signal<ValueOrPromise<VALIDATOR>> : Signal<TYPE>) & Pick<ComputedSignal<any>, 'promise' | 'pending' | 'error' | 'loading'>;
547
681
 
548
682
  declare interface MenuModule {
549
683
  readonly default: ContentMenu;
@@ -673,6 +807,8 @@ export declare interface QwikRouterEnvData {
673
807
  params: PathParams;
674
808
  response: EndpointResponse;
675
809
  loadedRoute: LoadedRoute;
810
+ routeLoaderCtx: RouteLoaderCtx;
811
+ loaderValues: Record<string, unknown>;
676
812
  }
677
813
 
678
814
  /** @public */
@@ -739,9 +875,9 @@ export declare const QwikRouterMockProvider: Component<QwikRouterMockProps>;
739
875
  /** @public */
740
876
  export declare interface QwikRouterProps {
741
877
  /**
742
- * Enable the ViewTransition API
878
+ * Enable the ViewTransition API on SPA navigation. Opt-in: set to `true` to enable.
743
879
  *
744
- * Default: `true`
880
+ * Default: `false`
745
881
  *
746
882
  * @see https://github.com/WICG/view-transitions/blob/main/explainer.md
747
883
  * @see https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API
@@ -783,10 +919,30 @@ export declare type ResolvedDocumentHead<FrontMatter extends Record<string, any>
783
919
  readonly manifestHash: string;
784
920
  };
785
921
 
786
- /** @public */
922
+ /**
923
+ * Define a route action that handles form submissions or programmatic invocations.
924
+ *
925
+ * Actions run on the server when submitted from the client. The result is returned as an
926
+ * `ActionStore` with `.value` for success data and `.error` for errors (including validation errors
927
+ * from `zod$`/`valibot$` where `.fieldErrors` etc. are accessible directly on `.error`).
928
+ *
929
+ * By default, after an action completes, ALL current route loaders are invalidated on the client
930
+ * and re-fetched as needed (so that the browser cache is correct). This can be controlled with:
931
+ *
932
+ * - `invalidate: [loader1, loader2]`: Only invalidate specific loaders. The client re-fetches them
933
+ * individually. Other loaders keep their current data.
934
+ * - `invalidate: []`: No loaders are invalidated. The action response only contains the action
935
+ * result. Use this when the action doesn't affect any loader data.
936
+ *
937
+ * The `strictLoaders` Vite plugin option applies `invalidate: []` globally for all actions that
938
+ * don't specify an explicit `invalidate` option.
939
+ *
940
+ * @public
941
+ */
787
942
  export declare const routeAction$: ActionConstructor;
788
943
 
789
- /* Excluded from this release type: routeActionQrl */
944
+ /** @public */
945
+ export declare const routeActionQrl: ActionConstructorQRL;
790
946
 
791
947
  declare type RouteActionResolver = {
792
948
  status: number;
@@ -843,10 +999,13 @@ export declare interface RouteData {
843
999
  _G?: string;
844
1000
  /** The JS bundle names for this route (SSR only) */
845
1001
  _B?: string[];
846
- /** The not-found (404) module loader for this subtree */
847
- _4?: ContentModuleLoader;
848
- /** The error page module loader for this subtree (error.tsx, takes precedence over _4) */
849
- _E?: ContentModuleLoader;
1002
+ /**
1003
+ * Not-found (404) boundary: single loader (runtime prepends layouts) or override chain
1004
+ * (`404@layout`/`!`).
1005
+ */
1006
+ _4?: ContentModuleLoader | ModuleLoader[];
1007
+ /** Error (error.tsx) boundary, same single-or-override-chain shape as `_4`. */
1008
+ _E?: ContentModuleLoader | ModuleLoader[];
850
1009
  /** The parameter name when this node is reached via `_W` or `_A` from the parent */
851
1010
  _P?: string;
852
1011
  /** Prefix for infix params (e.g. "pre" for `pre[slug]post`) — only on `_W` nodes */
@@ -857,13 +1016,61 @@ export declare interface RouteData {
857
1016
  _M?: RouteData[];
858
1017
  /** Menu loader for this subtree (from menu.md). Runtime uses nearest ancestor during traversal. */
859
1018
  _N?: MenuModuleLoader;
1019
+ /** Array of routeLoader$ hashes for this node's loaders */
1020
+ _R?: string[];
860
1021
  /** Child route segments (any key not starting with `_`) */
861
1022
  [part: string]: RouteData | RouteData[] | ModuleLoader[] | ContentModuleLoader | MenuModuleLoader | string[] | string | undefined;
862
1023
  }
863
1024
 
864
- /** @public */
1025
+ /**
1026
+ * Define a route loader that fetches data before the route renders.
1027
+ *
1028
+ * Route loaders run on the server during SSR and return data as a `ComputedSignal`. On the client,
1029
+ * loaders automatically re-fetch when the route changes (SPA navigation). Each loader gets its own
1030
+ * JSON endpoint (`q-loader-{id}.{hash}.json`), so only the loaders present on the target route are
1031
+ * fetched.
1032
+ *
1033
+ * **Important:** Route loader data uses Qwik's custom serialization format, not standard JSON. This
1034
+ * means the data supports features like circular references, Dates, and other non-JSON types, but
1035
+ * it cannot be consumed by external clients expecting plain JSON.
1036
+ *
1037
+ * ## Options
1038
+ *
1039
+ * - `search: string[]`: Allowlist of URL search params the loader depends on. Only listed params are
1040
+ * sent in the request and changes to other params are ignored. During SSR and loader JSON
1041
+ * requests, the loader's request event is filtered to those params too. `search: []` means no
1042
+ * search params are sent and only route path changes trigger a re-fetch.
1043
+ * - `allowStale: false`: Clears the previous value when re-fetching, so components see a loading
1044
+ * state instead of stale data during navigation. Useful when old data would be confusing.
1045
+ * - `eTag`: Enable ETag-based caching. Can be `true` (auto-hash), a string, or a function.
1046
+ * - `expires` / `poll`: Control client-side caching and polling behavior.
1047
+ *
1048
+ * The `strictLoaders` Vite plugin option applies `search: []` globally for all loaders that don't
1049
+ * specify an explicit `search` option.
1050
+ *
1051
+ * @public
1052
+ */
865
1053
  export declare const routeLoader$: LoaderConstructor;
866
1054
 
1055
+ /**
1056
+ * Reactive context for route loaders. On the server this is stored in sharedMap, on the client it's
1057
+ * a store that gets updated on navigation.
1058
+ *
1059
+ * - `loaderPaths`: loader ID → fetch path (the longest route path for that loader)
1060
+ * - `pagePathname` / `pageSearch`: client-only navigation state used for loader invalidation and
1061
+ * q-loader fetches. They are intentionally omitted from SSR state and fall back to `location`
1062
+ * until the first SPA navigation.
1063
+ */
1064
+ declare type RouteLoaderCtx = {
1065
+ loaderPaths: Record<string, string | undefined>;
1066
+ pagePathname?: string;
1067
+ pageSearch?: string;
1068
+ /** SPA navigation function. Client-only and intentionally omitted from SSR state. */
1069
+ goto?: NoSerialize<RouteNavigate>;
1070
+ /** Client manifest hash for q-loader fetch URLs. */
1071
+ manifestHash?: string;
1072
+ };
1073
+
867
1074
  /* Excluded from this release type: routeLoaderQrl */
868
1075
 
869
1076
  /** @public */