@qwik.dev/router 2.0.0-beta.45 → 2.0.0-beta.47

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.
@@ -1,7 +1,7 @@
1
- import { A as matchesRouteLoaderId, E as getRouteLoaderValues, J as QACTION_KEY, L as setRouteLoaders, M as resolveRouteLoaderByHash, Q as _asyncRequestStore, T as getRouteLoaderResponse, X as QFN_KEY, Y as QDATA_KEY, Z as Q_ROUTE, a as isPromise, f as FULLPATH_HEADER, g as clearRouteLoaderData, k as loadRouteLoader, r as resolveRouteConfig, w as getRouteLoaderCtx, x as getLoaderRequestEvent } from "./head.qwik.mjs";
2
1
  import { t as ensureSlash } from "./pathname.mjs";
2
+ import { A as loadRouteLoader, D as getRouteLoaderValues, E as getRouteLoaderResponse, N as resolveRouteLoaderByHash, R as setRouteLoaders, T as getRouteLoaderParams, a as isPromise, at as RequestEvRouterConfig, f as FULLPATH_HEADER, g as clearRouteLoaderData, it as Q_ROUTE, j as matchesRouteLoaderId, nt as QDATA_KEY, ot as _asyncRequestStore, r as resolveRouteConfig, rt as QFN_KEY, tt as QACTION_KEY, w as getRouteLoaderCtx, x as getLoaderRequestEvent } from "./head.qwik.mjs";
3
3
  import { a as QLoaderId, c as resolveValidInternalFullPathname, i as QActionId, s as recognizeRequest, t as IsQAction, u as trimRecognizedInternalPathname } from "./request-path.mjs";
4
- import { i as RedirectMessage, n as throwIfControlFlowSignal, r as AbortMessage, t as ServerError } from "./server-error.mjs";
4
+ import { a as shareClassIdentity, i as RedirectMessage, n as throwIfControlFlowSignal, r as AbortMessage, t as ServerError } from "./server-error.mjs";
5
5
  import { inlinedQrl, isDev } from "@qwik.dev/core";
6
6
  import { _deserialize, _serialize, _verifySerializable, isDev as isDev$1 } from "@qwik.dev/core/internal";
7
7
  /**
@@ -38,7 +38,7 @@ function setETagHeader(requestEv, normalizedETag) {
38
38
  * The eTag argument must already be normalized. Returns true if a 304 was sent (caller should stop
39
39
  * processing).
40
40
  */
41
- function performETagMatch(requestEv, normalizedETag) {
41
+ function performETagMatch(requestEv, normalizedETag, beforeNotModified) {
42
42
  setETagHeader(requestEv, normalizedETag);
43
43
  const ifNoneMatch = requestEv.request.headers.get("If-None-Match");
44
44
  if (ifNoneMatch) {
@@ -50,6 +50,7 @@ function performETagMatch(requestEv, normalizedETag) {
50
50
  }
51
51
  }
52
52
  if (found) {
53
+ beforeNotModified?.();
53
54
  requestEv.status(304);
54
55
  requestEv.send(304, "");
55
56
  return true;
@@ -213,6 +214,7 @@ var RewriteMessage = class extends AbortMessage {
213
214
  this.pathname = pathname;
214
215
  }
215
216
  };
217
+ shareClassIdentity(RewriteMessage, "RewriteMessage");
216
218
  var encoder = /*#__PURE__*/ new TextEncoder();
217
219
  function getContentType(headers) {
218
220
  return (headers.get("content-type")?.split(/[;,]/, 1)[0].trim() ?? "").toLowerCase();
@@ -231,9 +233,9 @@ var RequestEvSharedNonce = "@nonce";
231
233
  var RequestEvIsRewrite = "@rewrite";
232
234
  var RequestEvShareServerTiming = "@serverTiming";
233
235
  var RequestEvETagCacheKey = "@eTagCacheKey";
234
- var RequestEvErrorBoundaryCaught = "@errorBoundaryCaught";
236
+ var RequestEvCaughtError = "@caughtError";
235
237
  var RequestEvHttpStatusMessage = "@httpStatusMessage";
236
- function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, basePathname, resolved) {
238
+ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, basePathname, resolved, routerConfig) {
237
239
  const { request, platform, env } = serverRequestEv;
238
240
  const sharedMap = /* @__PURE__ */ new Map();
239
241
  const cookie = new Cookie(request.headers.get("cookie"));
@@ -311,6 +313,7 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, baseP
311
313
  };
312
314
  const requestEv = {
313
315
  [RequestEvMode]: serverRequestEv.mode,
316
+ [RequestEvRouterConfig]: routerConfig,
314
317
  get [RequestEvRoute]() {
315
318
  return loadedRoute;
316
319
  },
@@ -592,7 +595,7 @@ function resolveCacheKey(cacheKeyExport, defaultKey, requestEv, eTag) {
592
595
  /** Build the default SSR cache key. eTag slot is dropped when no eTag was resolved. */
593
596
  function defaultSsrCacheKey(requestEv, eTag) {
594
597
  const status = requestEv.status();
595
- const pathname = requestEv.url.pathname;
598
+ const pathname = requestEv.originalUrl.pathname;
596
599
  return eTag ? `${status}|${eTag}|${pathname}` : `${status}|${pathname}`;
597
600
  }
598
601
  /** Build the default loader cache key. eTag slot is dropped when no eTag was resolved. */
@@ -668,15 +671,18 @@ function loaderHandler(routeLoaders, loaderPaths) {
668
671
  await runBlockingLoadersBeforeTarget(routeLoaders, loader, requestEv);
669
672
  const loaderRequestEv = createLoaderRequestEventFactory(requestEv)(loader);
670
673
  const cacheControl = resolveLoaderCacheControl(loader.__cacheControl, loaderRequestEv);
674
+ const applyCacheControl = () => {
675
+ if (cacheControl !== null && !requestEv.headers.has("Cache-Control")) requestEv.cacheControl(cacheControl);
676
+ };
671
677
  const normalizedETag = loader.__eTag !== void 0 ? resolvePreETag(loader.__eTag, loaderRequestEv) : "";
672
- if (normalizedETag && performETagMatch(loaderRequestEv, normalizedETag)) return;
678
+ if (normalizedETag && performETagMatch(loaderRequestEv, normalizedETag, applyCacheControl)) return;
673
679
  let cacheKey = "";
674
680
  if (loader.__cacheKey) cacheKey = resolveCacheKey(loader.__cacheKey, defaultLoaderCacheKey, loaderRequestEv, normalizedETag);
675
681
  if (cacheKey) {
676
682
  const cached = getCachedLoader(cacheKey);
677
683
  if (cached) {
678
684
  if (!normalizedETag) {
679
- if (performETagMatch(loaderRequestEv, cached.eTag)) return;
685
+ if (performETagMatch(loaderRequestEv, cached.eTag, applyCacheControl)) return;
680
686
  } else setETagHeader(loaderRequestEv, cached.eTag);
681
687
  await sendLoaderResponse(requestEv, cached.body, cacheControl);
682
688
  return;
@@ -691,18 +697,17 @@ function loaderHandler(routeLoaders, loaderPaths) {
691
697
  eTag: finalETag,
692
698
  body: data
693
699
  });
694
- if (!normalizedETag && finalETag && performETagMatch(loaderRequestEv, finalETag)) return;
700
+ if (!normalizedETag && finalETag && performETagMatch(loaderRequestEv, finalETag, applyCacheControl)) return;
695
701
  await sendLoaderResponse(requestEv, data, cacheControl);
696
702
  };
697
703
  }
698
704
  /**
699
- * Resolve the loader's cacheControl option. Loaders default to `no-cache` so the browser always
700
- * revalidates; pair with `eTag` for cheap 304s. A function form may return `null` to skip the
701
- * header entirely.
705
+ * Resolve the loader's cacheControl option. Loaders default to private revalidation; pair with
706
+ * `eTag` for cheap 304s. A function form may return `null` to skip the header entirely.
702
707
  */
703
708
  function resolveLoaderCacheControl(option, requestEv) {
704
709
  const value = typeof option === "function" ? option(requestEv) : option;
705
- return value === void 0 ? "no-cache" : value;
710
+ return value === void 0 ? "private" : value;
706
711
  }
707
712
  async function runBlockingLoadersBeforeTarget(routeLoaders, targetLoader, requestEv) {
708
713
  for (const loader of routeLoaders) {
@@ -738,6 +743,7 @@ function addVaryHeader(requestEv, value) {
738
743
  async function sendJsonResponse(requestEv, responseData, status = 200) {
739
744
  const data = await _serialize(responseData);
740
745
  requestEv.headers.set("Content-Type", "application/json; charset=utf-8");
746
+ if (!requestEv.headers.has("Cache-Control")) requestEv.cacheControl("private");
741
747
  requestEv.send(status, data);
742
748
  }
743
749
  async function sendActionResponse(requestEv, responseData) {
@@ -1223,7 +1229,20 @@ var HttpStatus = /* @__PURE__ */ function(HttpStatus) {
1223
1229
  HttpStatus[HttpStatus["NetworkAuthenticationRequired"] = 511] = "NetworkAuthenticationRequired";
1224
1230
  return HttpStatus;
1225
1231
  }({});
1226
- function getQwikRouterServerData(requestEv) {
1232
+ /** Client-controlled forwarded headers only override the URL when the proxy is trusted. */
1233
+ function getServerDataUrl(originalUrl, headers, trustForwardedHeaders) {
1234
+ const url = new URL(originalUrl.pathname + originalUrl.search, originalUrl);
1235
+ if (!trustForwardedHeaders) return url.href;
1236
+ const host = headers.get("X-Forwarded-Host");
1237
+ const protocol = headers.get("X-Forwarded-Proto");
1238
+ if (host) {
1239
+ url.port = "";
1240
+ url.host = host;
1241
+ }
1242
+ if (protocol) url.protocol = protocol;
1243
+ return url.href;
1244
+ }
1245
+ function getQwikRouterServerData(requestEv, trustForwardedHeaders) {
1227
1246
  const { params, request, status, locale, originalUrl } = requestEv;
1228
1247
  const requestHeaders = {};
1229
1248
  request.headers.forEach((value, key) => requestHeaders[key] = value);
@@ -1232,19 +1251,10 @@ function getQwikRouterServerData(requestEv) {
1232
1251
  const formData = requestEv.sharedMap.get(RequestEvSharedActionFormData);
1233
1252
  const routeName = requestEv.sharedMap.get(RequestRouteName);
1234
1253
  const nonce = requestEv.sharedMap.get(RequestEvSharedNonce);
1235
- const headers = requestEv.request.headers;
1236
- const reconstructedUrl = new URL(originalUrl.pathname + originalUrl.search, originalUrl);
1237
- const host = headers.get("X-Forwarded-Host");
1238
- const protocol = headers.get("X-Forwarded-Proto");
1239
- if (host) {
1240
- reconstructedUrl.port = "";
1241
- reconstructedUrl.host = host;
1242
- }
1243
- if (protocol) reconstructedUrl.protocol = protocol;
1244
1254
  const routeLoaderCtx = getRouteLoaderCtx(requestEv);
1245
1255
  const loaderValues = getRouteLoaderValues(requestEv);
1246
1256
  return {
1247
- url: reconstructedUrl.href,
1257
+ url: getServerDataUrl(originalUrl, request.headers, trustForwardedHeaders),
1248
1258
  requestHeaders,
1249
1259
  renderMode: getRequestMode(requestEv),
1250
1260
  locale: locale(),
@@ -1427,6 +1437,7 @@ function createResolveRequestHandlers() {
1427
1437
  if (routeLoaders.length === 0) return;
1428
1438
  const routeLoaderCtx = getRouteLoaderCtx(requestEv);
1429
1439
  if (route.$loaderPaths$) Object.assign(routeLoaderCtx.loaderPaths, route.$loaderPaths$);
1440
+ if (route.$loaderParams$) Object.assign(getRouteLoaderParams(requestEv), route.$loaderParams$);
1430
1441
  setRouteLoaders(requestEv, routeLoaders);
1431
1442
  }
1432
1443
  function eTagMiddleware(route) {
@@ -1629,7 +1640,7 @@ function createResolveRequestHandlers() {
1629
1640
  The request origin "${inputOrigin}" does not match the server origin "${origin}".`);
1630
1641
  }
1631
1642
  }
1632
- function renderQwikMiddleware(render) {
1643
+ function renderQwikMiddleware(render, trustForwardedHeaders = false) {
1633
1644
  return async (requestEv) => {
1634
1645
  if (requestEv.headersSent) return;
1635
1646
  const responseHeaders = requestEv.headers;
@@ -1661,7 +1672,7 @@ The request origin "${inputOrigin}" does not match the server origin "${origin}"
1661
1672
  const stream = writable.getWriter();
1662
1673
  try {
1663
1674
  const isStatic = getRequestMode(requestEv) === "static";
1664
- const serverData = getQwikRouterServerData(requestEv);
1675
+ const serverData = getQwikRouterServerData(requestEv, trustForwardedHeaders);
1665
1676
  const result = await render({
1666
1677
  base: requestEv.basePathname + "build/",
1667
1678
  stream,
@@ -1672,7 +1683,7 @@ The request origin "${inputOrigin}" does not match the server origin "${origin}"
1672
1683
  ...serverData.containerAttributes
1673
1684
  },
1674
1685
  onBeforeFirstFlush: (info) => {
1675
- if (info.errorBoundaryCaught) {
1686
+ if (info.hasCaughtError) {
1676
1687
  boundaryErrored = true;
1677
1688
  noStoreSent = true;
1678
1689
  overrodeCacheControl = responseHeaders.has("Cache-Control");
@@ -1681,8 +1692,8 @@ The request origin "${inputOrigin}" does not match the server origin "${origin}"
1681
1692
  }
1682
1693
  });
1683
1694
  if (typeof result.html === "string") await stream.write(result.html);
1684
- boundaryErrored ||= result.errorBoundaryCaught === true;
1685
- if (boundaryErrored) requestEv.sharedMap.set(RequestEvErrorBoundaryCaught, true);
1695
+ boundaryErrored ||= result.hasCaughtError === true;
1696
+ if (boundaryErrored) requestEv.sharedMap.set(RequestEvCaughtError, true);
1686
1697
  } finally {
1687
1698
  try {
1688
1699
  await stream.ready;
@@ -1693,7 +1704,7 @@ The request origin "${inputOrigin}" does not match the server origin "${origin}"
1693
1704
  }
1694
1705
  }
1695
1706
  if (pipeError) throw pipeError;
1696
- if (boundaryErrored && (noStoreSent ? cachePlan || overrodeCacheControl : !!cachePlan)) console.warn(`An <ErrorBoundary> caught during SSR of ${requestEv.url.pathname} — configured caching disabled: ` + (noStoreSent ? "the response was sent with Cache-Control: no-store." : "the SSR cache was skipped (response headers were already sent)."));
1707
+ if (boundaryErrored && (noStoreSent ? cachePlan || overrodeCacheControl : !!cachePlan)) console.warn(`A <Catch> caught during SSR of ${requestEv.url.pathname} — configured caching disabled: ` + (noStoreSent ? "the response was sent with Cache-Control: no-store." : "the SSR cache was skipped (response headers were already sent)."));
1697
1708
  if (cachePlan && cacheChunks && cacheChunks.length > 0 && !boundaryErrored) {
1698
1709
  const totalLength = cacheChunks.reduce((sum, chunk) => sum + chunk.length, 0);
1699
1710
  const combined = new Uint8Array(totalLength);
@@ -1789,11 +1800,11 @@ var escapeHtml = (s) => {
1789
1800
  var COLOR_400 = "#006ce9";
1790
1801
  var COLOR_500 = "#713fc2";
1791
1802
  var ensureError = (e) => e instanceof Error || typeof e === "object" && e !== null ? e : new Error(String(e));
1792
- function runQwikRouter(serverRequestEv, loadedRoute, requestHandlers, rebuildRouteInfo, basePathname = "/") {
1803
+ function runQwikRouter(serverRequestEv, loadedRoute, requestHandlers, rebuildRouteInfo, basePathname = "/", routerConfig) {
1793
1804
  let resolve;
1794
1805
  const responsePromise = new Promise((r) => resolve = r);
1795
1806
  try {
1796
- const requestEv = createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, basePathname, resolve);
1807
+ const requestEv = createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, basePathname, resolve, routerConfig);
1797
1808
  return {
1798
1809
  response: responsePromise,
1799
1810
  requestEv,
@@ -1869,4 +1880,4 @@ async function runNext(requestEv, rebuildRouteInfo, resolve) {
1869
1880
  if (!requestEv.isDirty()) resolve(null);
1870
1881
  }
1871
1882
  }
1872
- export { getStaticPathRedirect as a, clearSsrCache as c, mergeHeadersCookies as d, resolveRequestHandlers as i, RequestEvErrorBoundaryCaught as l, getErrorHtml as n, isStaticPath as o, renderQwikMiddleware as r, clearLoaderCache as s, runQwikRouter as t, RewriteMessage as u };
1883
+ export { getStaticPathRedirect as a, clearSsrCache as c, mergeHeadersCookies as d, resolveRequestHandlers as i, RequestEvCaughtError as l, getErrorHtml as n, isStaticPath as o, renderQwikMiddleware as r, clearLoaderCache as s, runQwikRouter as t, RewriteMessage as u };
@@ -1,4 +1,4 @@
1
- import { D as getRouteLoaders, E as getRouteLoaderValues, d as loadRoute } from "./head.qwik.mjs";
1
+ import { D as getRouteLoaderValues, O as getRouteLoaders, d as loadRoute } from "./head.qwik.mjs";
2
2
  import { l as trimInternalPathname } from "./request-path.mjs";
3
3
  import { i as resolveRequestHandlers, r as renderQwikMiddleware, t as runQwikRouter } from "./user-response.mjs";
4
4
  import { _serialize } from "@qwik.dev/core/internal";
@@ -75,6 +75,7 @@ async function workerThread(sys) {
75
75
  }
76
76
  if (msg.type === "close") parentPort?.close();
77
77
  });
78
+ parentPort?.postMessage({ type: "ready" });
78
79
  }
79
80
  async function workerRender(sys, opts, staticRoute, pendingPromises, callback, deps) {
80
81
  const url = new URL(staticRoute.pathname, opts.origin);
@@ -199,10 +200,10 @@ async function workerRender(sys, opts, staticRoute, pendingPromises, callback, d
199
200
  }, opts, deps).then((rsp) => {
200
201
  if (rsp != null) return rsp.completion.then((r) => {
201
202
  const failRouteOnCaughtBoundary = (completion) => {
202
- if (completion === void 0 && rsp.requestEv.sharedMap.get("@errorBoundaryCaught")) {
203
+ if (completion === void 0 && rsp.requestEv.sharedMap.get("@caughtError")) {
203
204
  result.ok = false;
204
205
  result.filePath = null;
205
- return /* @__PURE__ */ new Error(`An <ErrorBoundary> caught an error while rendering ${staticRoute.pathname}`);
206
+ return /* @__PURE__ */ new Error(`A <Catch> caught an error while rendering ${staticRoute.pathname}`);
206
207
  }
207
208
  return completion;
208
209
  };
@@ -268,6 +269,6 @@ async function requestHandlerForSsg(serverRequestEv, opts, deps) {
268
269
  requestHandlers: deps.resolveRequestHandlers(serverPlugins, loadedRoute, serverRequestEv.request.method, checkOrigin ?? true, deps.renderQwikMiddleware(render))
269
270
  };
270
271
  };
271
- return deps.runQwikRouter(serverRequestEv, loadedRoute, requestHandlers, rebuildRouteInfo, qwikRouterConfig.basePathname);
272
+ return deps.runQwikRouter(serverRequestEv, loadedRoute, requestHandlers, rebuildRouteInfo, qwikRouterConfig.basePathname, qwikRouterConfig);
272
273
  }
273
274
  export { workerThread };
package/lib/index.d.ts CHANGED
@@ -427,6 +427,13 @@ export declare interface FormSubmitSuccessDetail<T> {
427
427
  value: T;
428
428
  }
429
429
 
430
+ /**
431
+ * The base pathname the app is served under, such as `/` or `/docs/`.
432
+ *
433
+ * @public
434
+ */
435
+ export declare const getBasePathname: () => string;
436
+
430
437
  /**
431
438
  * Returns the current RequestEvent if possible. Only usable on the server, and only during request
432
439
  * processing.
@@ -435,6 +442,32 @@ export declare interface FormSubmitSuccessDetail<T> {
435
442
  */
436
443
  export declare const getRequestEvent: (thisArg?: unknown) => RequestEvent | undefined;
437
444
 
445
+ /**
446
+ * The app's route config: the route trie, server plugins and build options that the Qwik Router
447
+ * Vite plugin generated. Resolves once the config is loaded and its `server$` modules are
448
+ * registered. On the server, the router copy of a Qwik library kept external reads the config of
449
+ * the app serving the current request.
450
+ *
451
+ * @public
452
+ */
453
+ export declare const getRouterConfig: () => Promise<QwikRouterConfig>;
454
+
455
+ /**
456
+ * The route trie of the app, as generated by the Qwik Router Vite plugin.
457
+ *
458
+ * @public
459
+ */
460
+ export declare const getRoutes: () => Promise<RouteData>;
461
+
462
+ /* Excluded from this release type: _getServiceWorkerScript */
463
+
464
+ /**
465
+ * Whether the app's URLs end with a trailing slash.
466
+ *
467
+ * @public
468
+ */
469
+ export declare const getTrailingSlash: () => boolean;
470
+
438
471
  /** @public */
439
472
  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;
440
473
 
@@ -541,6 +574,8 @@ declare interface LoadedRoute {
541
574
  $loaders$?: string[];
542
575
  /** Runtime-only mapping of routeLoader$ hashes to the matched pathname used for q-loader fetches */
543
576
  $loaderPaths$?: Record<string, string>;
577
+ /** Runtime-only mapping of routeLoader$ hashes to params matched at their loader path */
578
+ $loaderParams$?: Record<string, PathParams>;
544
579
  }
545
580
 
546
581
  /** @public */
@@ -591,7 +626,9 @@ declare type LoaderOptions = {
591
626
  * object) or a function of the request event; the function may return `null` to skip the header.
592
627
  * A `Cache-Control` header set inside the loader function wins over this option.
593
628
  *
594
- * Defaults to `no-cache` (always revalidate; combine with `eTag` for cheap 304s).
629
+ * Defaults to `private, no-cache` (browser revalidation without shared caching; combine with
630
+ * `eTag` for cheap 304s). Explicit `'no-cache'` and numeric values allow shared caching; numeric
631
+ * values include `s-maxage`.
595
632
  *
596
633
  * The literal value `'immutable'` also marks the loader's data as static, so SSG writes a
597
634
  * per-loader JSON file at build time.
@@ -622,7 +659,8 @@ declare type LoaderOptions = {
622
659
  * - `true` — use the default key `${pathname}|${filteredSearch}|${loaderId}` (suffixed with
623
660
  * `|${eTag}` when an eTag is set).
624
661
  * - Function `(requestEv, eTag) => string | null` — return a custom key, or `null` to skip caching
625
- * this request.
662
+ * this request. For user-specific data, include user identity and relevant permissions in the
663
+ * key or disable this cache.
626
664
  *
627
665
  * On cache miss the loader runs, the serialized response is stored alongside its eTag (computed
628
666
  * from the data when no `eTag` option is set), and the response is sent. On cache hit the stored
@@ -786,6 +824,8 @@ export declare interface QwikRouterConfig {
786
824
  * evaluates without touching the runtime (see the import-cycle notes in `route-loaders.ts`).
787
825
  */
788
826
  readonly importEagerModules?: () => Promise<unknown>;
827
+ /** URL of the app's service worker, when the routes define one. */
828
+ readonly serviceWorkerUrl?: string;
789
829
  }
790
830
 
791
831
  /** @public */
@@ -930,9 +970,9 @@ export declare type ResolvedDocumentHead<FrontMatter extends Record<string, any>
930
970
  export declare const routeAction$: ActionConstructor;
931
971
 
932
972
  /**
933
- * Hoisted function declarations (not consts) on purpose, like `routeLoaderQrl`: generated route
934
- * modules call these factories back during their own evaluation via the `@qwik-router-config`
935
- * cycle, where a `const` binding would throw a TDZ ReferenceError.
973
+ * Hoisted function declarations (not consts) on purpose, like `routeLoaderQrl`: the app's route
974
+ * modules call these factories during their own evaluation, which a bundle may run before this
975
+ * module, where a `const` binding would throw a TDZ ReferenceError.
936
976
  *
937
977
  * @public
938
978
  */
@@ -975,7 +1015,8 @@ export declare interface RouteConfigValue {
975
1015
  /**
976
1016
  * A nested route trie structure. The root represents `/` and each level represents a URL segment.
977
1017
  *
978
- * Keys starting with `_` are metadata; all other keys are child route segments.
1018
+ * Keys starting with a single `_` are metadata; all other keys are child route segments. A static
1019
+ * segment that starts with `_` is stored with an extra `_` (`_drafts` → `__drafts`).
979
1020
  *
980
1021
  * - Use `_W` as the key for a single dynamic segment (param); `_P` on that node names the param.
981
1022
  * - Use `_A` as the key for a rest/catch-all segment; `_P` on that node names the param.
@@ -1021,7 +1062,7 @@ export declare interface RouteData {
1021
1062
  _R?: string[];
1022
1063
  /** Page loader hashes; override pages include their selected layouts and plugins. */
1023
1064
  _D?: string[];
1024
- /** Child route segments (any key not starting with `_`) */
1065
+ /** Child route segments (any key not starting with a single `_`) */
1025
1066
  [part: string]: RouteData | RouteData[] | ModuleLoader[] | ContentModuleLoader | MenuModuleLoader | string[] | string | undefined;
1026
1067
  }
1027
1068
 
@@ -1152,6 +1193,8 @@ export declare const ServiceWorkerRegister: (props: {
1152
1193
  nonce?: string;
1153
1194
  }) => JSXOutput;
1154
1195
 
1196
+ /* Excluded from this release type: _setRouterConfig */
1197
+
1155
1198
  /** @public */
1156
1199
  export declare interface StaticGenerate {
1157
1200
  params?: PathParams[];