vinext 0.1.5 → 0.1.7

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 (93) hide show
  1. package/README.md +2 -2
  2. package/dist/build/client-build-config.d.ts +4 -6
  3. package/dist/build/client-build-config.js +27 -7
  4. package/dist/build/google-fonts/find-font-files-in-css.d.ts +16 -0
  5. package/dist/build/google-fonts/find-font-files-in-css.js +28 -0
  6. package/dist/build/prerender.js +1 -2
  7. package/dist/build/report.d.ts +1 -2
  8. package/dist/build/report.js +2 -11
  9. package/dist/build/run-prerender.js +1 -1
  10. package/dist/check.js +3 -3
  11. package/dist/client/pages-router-link-navigation.d.ts +10 -0
  12. package/dist/client/pages-router-link-navigation.js +3 -3
  13. package/dist/deploy.js +3 -3
  14. package/dist/entries/app-rsc-entry.d.ts +2 -1
  15. package/dist/entries/app-rsc-entry.js +35 -9
  16. package/dist/entries/app-rsc-manifest.js +76 -46
  17. package/dist/entries/pages-server-entry.js +1 -0
  18. package/dist/index.js +116 -74
  19. package/dist/init.d.ts +5 -4
  20. package/dist/init.js +27 -8
  21. package/dist/plugins/fonts.js +3 -1
  22. package/dist/plugins/middleware-export-validation.d.ts +5 -0
  23. package/dist/plugins/middleware-export-validation.js +36 -0
  24. package/dist/plugins/og-asset-ownership.d.ts +27 -0
  25. package/dist/plugins/og-asset-ownership.js +285 -0
  26. package/dist/plugins/og-assets.js +28 -10
  27. package/dist/plugins/remove-console.js +1 -1
  28. package/dist/plugins/strip-server-exports.js +2 -1
  29. package/dist/server/accept-encoding.d.ts +29 -0
  30. package/dist/server/accept-encoding.js +95 -0
  31. package/dist/server/app-action-request.d.ts +4 -0
  32. package/dist/server/app-action-request.js +9 -0
  33. package/dist/server/app-bfcache-identity.d.ts +12 -2
  34. package/dist/server/app-bfcache-identity.js +52 -23
  35. package/dist/server/app-browser-entry.js +8 -5
  36. package/dist/server/app-browser-navigation-controller.js +1 -1
  37. package/dist/server/app-browser-rsc-redirect.d.ts +2 -1
  38. package/dist/server/app-browser-rsc-redirect.js +8 -1
  39. package/dist/server/app-browser-state.js +1 -1
  40. package/dist/server/app-browser-visible-commit.js +1 -1
  41. package/dist/server/app-history-state.d.ts +1 -2
  42. package/dist/server/app-history-state.js +1 -1
  43. package/dist/server/app-middleware.d.ts +1 -0
  44. package/dist/server/app-middleware.js +1 -0
  45. package/dist/server/app-page-dispatch.d.ts +2 -2
  46. package/dist/server/app-page-head.js +2 -2
  47. package/dist/server/app-page-method.js +1 -1
  48. package/dist/server/app-page-request.d.ts +7 -0
  49. package/dist/server/app-page-request.js +19 -1
  50. package/dist/server/app-page-stream.js +2 -1
  51. package/dist/server/app-prerender-endpoints.d.ts +3 -3
  52. package/dist/server/app-prerender-endpoints.js +3 -4
  53. package/dist/server/app-route-handler-cache.js +1 -1
  54. package/dist/server/app-route-handler-dispatch.js +2 -2
  55. package/dist/server/app-route-handler-execution.js +3 -2
  56. package/dist/server/app-route-handler-policy.d.ts +1 -1
  57. package/dist/server/app-route-handler-policy.js +1 -6
  58. package/dist/server/app-route-module-loader.d.ts +62 -14
  59. package/dist/server/app-route-module-loader.js +61 -10
  60. package/dist/server/app-rsc-errors.d.ts +12 -1
  61. package/dist/server/app-rsc-errors.js +22 -2
  62. package/dist/server/app-rsc-handler.d.ts +16 -14
  63. package/dist/server/app-rsc-handler.js +47 -44
  64. package/dist/server/app-rsc-response-finalizer.js +5 -1
  65. package/dist/server/app-rsc-route-matching.d.ts +9 -0
  66. package/dist/server/app-rsc-route-matching.js +13 -0
  67. package/dist/server/app-server-action-execution.js +1 -1
  68. package/dist/server/app-ssr-entry.js +9 -7
  69. package/dist/server/headers.d.ts +5 -1
  70. package/dist/server/headers.js +5 -1
  71. package/dist/server/metadata-route-response.d.ts +3 -3
  72. package/dist/server/middleware-runtime.d.ts +2 -1
  73. package/dist/server/middleware-runtime.js +19 -8
  74. package/dist/server/middleware.d.ts +2 -2
  75. package/dist/server/middleware.js +26 -11
  76. package/dist/server/pages-request-pipeline.d.ts +3 -1
  77. package/dist/server/pages-request-pipeline.js +4 -2
  78. package/dist/server/prod-server.d.ts +1 -1
  79. package/dist/server/prod-server.js +85 -72
  80. package/dist/shims/dynamic.js +1 -1
  81. package/dist/shims/font-google-base.d.ts +1 -0
  82. package/dist/shims/font-google-base.js +6 -21
  83. package/dist/shims/internal/interpolate-as.d.ts +25 -0
  84. package/dist/shims/internal/interpolate-as.js +196 -0
  85. package/dist/shims/link.js +24 -1
  86. package/dist/shims/navigation.js +1 -1
  87. package/dist/shims/navigation.react-server.js +1 -1
  88. package/dist/shims/router.d.ts +1 -3
  89. package/dist/shims/router.js +62 -18
  90. package/dist/typegen.js +2 -10
  91. package/dist/utils/project.d.ts +7 -1
  92. package/dist/utils/project.js +16 -2
  93. package/package.json +3 -3
@@ -3,7 +3,6 @@ import { normalizePath } from "./normalize-path.js";
3
3
  import { AppElementsWire } from "./app-elements-wire.js";
4
4
  import "./app-elements.js";
5
5
  import "./app-bfcache-id.js";
6
- import { isBfcacheSegmentId } from "./app-history-state.js";
7
6
  //#region src/server/app-bfcache-identity.ts
8
7
  let nextBfcacheId = 0;
9
8
  function rememberBfcacheId(value) {
@@ -24,6 +23,14 @@ function getTreePathIdentityPrefix(pathname, treePath) {
24
23
  if (consumedPathnameSegments === 0) return "/";
25
24
  return `/${pathnameSegments.slice(0, consumedPathnameSegments).join("/")}`;
26
25
  }
26
+ function indexAppElementsMetadata(metadata) {
27
+ const slotBindingsBySlotId = /* @__PURE__ */ new Map();
28
+ for (const binding of metadata.slotBindings) slotBindingsBySlotId.set(binding.slotId, binding);
29
+ return {
30
+ metadata,
31
+ slotBindingsBySlotId
32
+ };
33
+ }
27
34
  function readAppElementsMetadata(elements) {
28
35
  let metadata;
29
36
  try {
@@ -31,12 +38,11 @@ function readAppElementsMetadata(elements) {
31
38
  } catch {
32
39
  return null;
33
40
  }
34
- const slotBindingsBySlotId = /* @__PURE__ */ new Map();
35
- for (const binding of metadata.slotBindings) slotBindingsBySlotId.set(binding.slotId, binding);
36
- return {
37
- metadata,
38
- slotBindingsBySlotId
39
- };
41
+ return indexAppElementsMetadata(metadata);
42
+ }
43
+ function parseBfcacheSegmentKey(id) {
44
+ const parsed = AppElementsWire.parseElementKey(id);
45
+ return parsed !== null && parsed.kind !== "route" ? parsed : null;
40
46
  }
41
47
  function createActiveSlotIdentity(id, parsed) {
42
48
  const activeSlotBinding = parsed?.slotBindingsBySlotId.get(id);
@@ -50,9 +56,7 @@ function createActiveSlotIdentity(id, parsed) {
50
56
  * contained here until vinext has a route-manifest authority equivalent to
51
57
  * Next.js CacheNode or segment-cache state.
52
58
  */
53
- function createBfcacheSegmentIdentity(id, options) {
54
- const parsed = AppElementsWire.parseElementKey(id);
55
- if (!parsed) return null;
59
+ function createBfcacheSegmentIdentity(id, parsed, options) {
56
60
  if (parsed.kind === "page") return `${id}@${options.pathname}`;
57
61
  if (parsed.kind === "slot") {
58
62
  const activeSlotIdentity = createActiveSlotIdentity(id, options.metadata);
@@ -62,16 +66,15 @@ function createBfcacheSegmentIdentity(id, options) {
62
66
  if (parsed.kind === "layout" || parsed.kind === "template") return `${id}@${getTreePathIdentityPrefix(options.pathname, parsed.treePath)}`;
63
67
  return null;
64
68
  }
65
- function collectBfcacheSegmentIds(elements, parsed) {
69
+ function collectBfcacheSegmentIdCandidates(elements, metadata = readAppElementsMetadata(elements)) {
66
70
  const ids = new Set(Object.keys(elements));
67
- const metadata = parsed === void 0 ? readAppElementsMetadata(elements) : parsed;
68
71
  for (const layoutId of metadata?.metadata.layoutIds ?? []) ids.add(layoutId);
69
- return Array.from(ids).filter(isBfcacheSegmentId);
72
+ return ids;
70
73
  }
71
74
  function createInitialBfcacheIdMap(elements) {
72
- const ids = {};
73
- for (const id of collectBfcacheSegmentIds(elements)) ids[id] = "0";
74
- return ids;
75
+ const bfcacheIds = {};
76
+ for (const id of collectBfcacheSegmentIdCandidates(elements)) if (parseBfcacheSegmentKey(id) !== null) bfcacheIds[id] = "0";
77
+ return bfcacheIds;
75
78
  }
76
79
  function normalizeBfcachePathname(pathname) {
77
80
  const normalized = normalizePath(normalizePathnameForRouteMatch(pathname));
@@ -81,8 +84,10 @@ function createBfcacheSegmentStateKeyMap(options) {
81
84
  const metadata = readAppElementsMetadata(options.elements);
82
85
  const normalizedPathname = normalizeBfcachePathname(options.pathname);
83
86
  const stateKeys = {};
84
- for (const id of collectBfcacheSegmentIds(options.elements, metadata)) {
85
- const stateKey = createBfcacheSegmentIdentity(id, {
87
+ for (const id of collectBfcacheSegmentIdCandidates(options.elements, metadata)) {
88
+ const parsed = parseBfcacheSegmentKey(id);
89
+ if (parsed === null) continue;
90
+ const stateKey = createBfcacheSegmentIdentity(id, parsed, {
86
91
  metadata,
87
92
  pathname: normalizedPathname
88
93
  });
@@ -90,6 +95,27 @@ function createBfcacheSegmentStateKeyMap(options) {
90
95
  }
91
96
  return stateKeys;
92
97
  }
98
+ function createInitialBfcacheMaps(options) {
99
+ const metadata = indexAppElementsMetadata(options.metadata);
100
+ const ids = collectBfcacheSegmentIdCandidates(options.elements, metadata);
101
+ const normalizedPathname = normalizeBfcachePathname(options.pathname);
102
+ const bfcacheIds = {};
103
+ const stateKeys = {};
104
+ for (const id of ids) {
105
+ const parsed = parseBfcacheSegmentKey(id);
106
+ if (parsed === null) continue;
107
+ bfcacheIds[id] = "0";
108
+ const stateKey = createBfcacheSegmentIdentity(id, parsed, {
109
+ metadata,
110
+ pathname: normalizedPathname
111
+ });
112
+ if (stateKey !== null) stateKeys[id] = stateKey;
113
+ }
114
+ return {
115
+ bfcacheIds,
116
+ stateKeys
117
+ };
118
+ }
93
119
  function createNextBfcacheIdMap(options) {
94
120
  const current = options.reuseCurrent === false ? {} : options.current;
95
121
  for (const value of Object.values(current)) rememberBfcacheId(value);
@@ -99,11 +125,13 @@ function createNextBfcacheIdMap(options) {
99
125
  const currentPathname = normalizeBfcachePathname(options.currentPathname);
100
126
  const nextPathname = normalizeBfcachePathname(options.nextPathname);
101
127
  const ids = {};
102
- for (const id of collectBfcacheSegmentIds(options.elements, nextMetadata)) {
103
- const currentValue = createBfcacheSegmentIdentity(id, {
128
+ for (const id of collectBfcacheSegmentIdCandidates(options.elements, nextMetadata)) {
129
+ const parsed = parseBfcacheSegmentKey(id);
130
+ if (parsed === null) continue;
131
+ const currentValue = createBfcacheSegmentIdentity(id, parsed, {
104
132
  metadata: currentMetadata,
105
133
  pathname: currentPathname
106
- }) === createBfcacheSegmentIdentity(id, {
134
+ }) === createBfcacheSegmentIdentity(id, parsed, {
107
135
  metadata: nextMetadata,
108
136
  pathname: nextPathname
109
137
  }) ? current[id] : void 0;
@@ -115,7 +143,8 @@ function createNextBfcacheIdMap(options) {
115
143
  }
116
144
  function preserveBfcacheIdsForMergedElements(options) {
117
145
  const ids = {};
118
- for (const id of collectBfcacheSegmentIds(options.elements)) {
146
+ for (const id of collectBfcacheSegmentIdCandidates(options.elements)) {
147
+ if (parseBfcacheSegmentKey(id) === null) continue;
119
148
  const value = options.next[id] ?? options.previous[id];
120
149
  if (value === void 0) continue;
121
150
  ids[id] = value;
@@ -124,4 +153,4 @@ function preserveBfcacheIdsForMergedElements(options) {
124
153
  return ids;
125
154
  }
126
155
  //#endregion
127
- export { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements };
156
+ export { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap, createInitialBfcacheMaps, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements };
@@ -18,14 +18,15 @@ import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscR
18
18
  import { getNavigationRuntime, registerNavigationRuntimeBootstrap, registerNavigationRuntimeFunctions } from "../client/navigation-runtime.js";
19
19
  import { notifyAppRouterTransitionStart } from "../client/instrumentation-client-state.js";
20
20
  import "../client/instrumentation-client.js";
21
- import { readHistoryStatePreviousNextUrl } from "./app-history-state.js";
22
- import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap } from "./app-bfcache-identity.js";
23
- import { createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot, createServerActionResultFacts, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError, shouldClearClientNavigationCachesForServerActionResult } from "./app-browser-action-result.js";
24
- import { createClientReuseManifestHeaderFromVisibleAppState } from "./app-browser-client-reuse-manifest.js";
25
21
  import { resolveManifestNavigationInterceptionContext, resolveMiddlewareRewriteNavigationInterceptionContext } from "./app-browser-interception-context.js";
22
+ import { readHistoryStatePreviousNextUrl } from "./app-history-state.js";
26
23
  import { AppBrowserMpaNavigationScheduler } from "./app-browser-mpa-navigation.js";
24
+ import { blockDangerousStreamedRscRedirect } from "./app-browser-rsc-redirect.js";
27
25
  import { navigationPlanner } from "./navigation-planner.js";
28
26
  import { __basePath, appRouterInstance, commitClientNavigationState, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, getClientNavigationRenderContext, getPrefetchCache, hasPrefetchCacheEntryForNavigation, invalidatePrefetchCache, pushHistoryStateWithoutNotify, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, setClientParams, setMountedSlotsHeader, setPendingPathname, useRouter } from "../shims/navigation.js";
27
+ import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap } from "./app-bfcache-identity.js";
28
+ import { createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot, createServerActionResultFacts, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError, shouldClearClientNavigationCachesForServerActionResult } from "./app-browser-action-result.js";
29
+ import { createClientReuseManifestHeaderFromVisibleAppState } from "./app-browser-client-reuse-manifest.js";
29
30
  import { chunksToReadableStream, createProgressiveRscStream, getVinextBrowserGlobal } from "./app-browser-stream.js";
30
31
  import { FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, isCacheRestorableAppPayloadMetadata, resolveInterceptionContextFromPreviousNextUrl, resolveServerActionRequestState } from "./app-browser-state.js";
31
32
  import { clearHardNavigationLoopGuard, createAppBrowserNavigationController, createBasePathStrippedPathAndSearch } from "./app-browser-navigation-controller.js";
@@ -1032,6 +1033,8 @@ function bootstrapHydration(rscStream) {
1032
1033
  }
1033
1034
  if (!browserNavigationController.isCurrentNavigation(navId)) return;
1034
1035
  const navContentType = navResponse.headers.get("content-type") ?? "";
1036
+ const streamedRedirectTarget = navResponse.headers.get(VINEXT_RSC_REDIRECT_HEADER);
1037
+ if (blockDangerousStreamedRscRedirect(navResponse, streamedRedirectTarget)) return;
1035
1038
  const liveFetchDecision = navigationPlanner.classifyRscFetchResult({
1036
1039
  clientCompatibilityId: CLIENT_RSC_COMPATIBILITY_ID,
1037
1040
  compatibilityIdHeader: navResponse.headers.get(VINEXT_RSC_COMPATIBILITY_ID_HEADER),
@@ -1045,7 +1048,7 @@ function bootstrapHydration(rscStream) {
1045
1048
  responseOk: navResponse.ok,
1046
1049
  responseUrl: navResponseUrl ?? navResponse.url,
1047
1050
  source: "live",
1048
- streamedRedirectTarget: navResponse.headers.get(VINEXT_RSC_REDIRECT_HEADER)
1051
+ streamedRedirectTarget
1049
1052
  });
1050
1053
  if (liveFetchDecision.kind === "hardNavigate") {
1051
1054
  if (liveFetchDecision.discardBody) navResponse.body?.cancel().catch(() => {});
@@ -1,8 +1,8 @@
1
1
  import { stripBasePath } from "../utils/base-path.js";
2
2
  import { clearAppNavigationFailureTarget, getAppNavigationFailureTarget } from "../client/app-nav-failure-handler.js";
3
3
  import { claimAppRouterScrollIntentForCommit, consumeAppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
4
- import { shouldScheduleRefreshForDiscardedServerAction } from "./app-browser-action-result.js";
5
4
  import { activateNavigationSnapshot, clearPendingPathname, commitClientNavigationState, createSnapshotPathAndSearch } from "../shims/navigation.js";
5
+ import { shouldScheduleRefreshForDiscardedServerAction } from "./app-browser-action-result.js";
6
6
  import { FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, createPendingNavigationCommit } from "./app-browser-state.js";
7
7
  import { applyApprovedVisibleCommit, approveHmrVisibleCommit, approvePendingNavigationCommit, resolveAndClassifyNavigationCommit } from "./app-browser-visible-commit.js";
8
8
  import { startTransition, useInsertionEffect, useLayoutEffect } from "react";
@@ -1,4 +1,5 @@
1
1
  //#region src/server/app-browser-rsc-redirect.d.ts
2
+ declare function blockDangerousStreamedRscRedirect(response: Response, streamedRedirectTarget: string | null): boolean;
2
3
  type RscRedirectHistoryUpdateMode = "push" | "replace" | undefined;
3
4
  type RscRedirectLifecycleDecision = {
4
5
  href: string;
@@ -34,4 +35,4 @@ declare function resolveStreamedRscRedirectLifecycleHop(options: {
34
35
  streamedRedirectTarget: string;
35
36
  }): RscRedirectLifecycleDecision;
36
37
  //#endregion
37
- export { resolveRscRedirectLifecycleHop, resolveStreamedRscRedirectLifecycleHop };
38
+ export { blockDangerousStreamedRscRedirect, resolveRscRedirectLifecycleHop, resolveStreamedRscRedirectLifecycleHop };
@@ -1,6 +1,13 @@
1
+ import { isDangerousScheme, reportBlockedDangerousNavigation } from "../shims/url-safety.js";
1
2
  import { resolveHardNavigationTargetFromRscResponse, stripRscCacheBustingSearchParam, stripRscSuffix } from "./app-rsc-cache-busting.js";
2
3
  //#region src/server/app-browser-rsc-redirect.ts
3
4
  const MAX_RSC_REDIRECT_DEPTH = 10;
5
+ function blockDangerousStreamedRscRedirect(response, streamedRedirectTarget) {
6
+ if (streamedRedirectTarget === null || !isDangerousScheme(streamedRedirectTarget)) return false;
7
+ response.body?.cancel().catch(() => {});
8
+ reportBlockedDangerousNavigation();
9
+ return true;
10
+ }
4
11
  function toVisibleAppHref(href, origin) {
5
12
  const url = new URL(href, origin);
6
13
  stripRscCacheBustingSearchParam(url);
@@ -54,4 +61,4 @@ function resolveStreamedRscRedirectLifecycleHop(options) {
54
61
  });
55
62
  }
56
63
  //#endregion
57
- export { resolveRscRedirectLifecycleHop, resolveStreamedRscRedirectLifecycleHop };
64
+ export { blockDangerousStreamedRscRedirect, resolveRscRedirectLifecycleHop, resolveStreamedRscRedirectLifecycleHop };
@@ -7,11 +7,11 @@ import { getMountedSlotIds, getMountedSlotIdsHeader } from "./app-elements.js";
7
7
  import { createRscRequestHeaders } from "./app-rsc-cache-busting.js";
8
8
  import { createCacheEntryReuseProof } from "./cache-proof.js";
9
9
  import { createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, isHistoryStateBfcacheVersionCurrent, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent } from "./app-history-state.js";
10
- import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
11
10
  import { NavigationTraceReasonCodes, createNavigationLifecycleTraceFields, createNavigationTrace } from "./navigation-trace.js";
12
11
  import { verifyOperationTokenForCommit } from "./operation-token.js";
13
12
  import { navigationPlanner, resolveDefaultOrUnmatchedSlotPersistenceForLayouts } from "./navigation-planner.js";
14
13
  import { createSnapshotPathAndSearch } from "../shims/navigation.js";
14
+ import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
15
15
  //#region src/server/app-browser-state.ts
16
16
  const FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN = { origin: "fresh" };
17
17
  const VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN = { origin: "visited-cache" };
@@ -1,8 +1,8 @@
1
1
  import { normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
2
2
  import "./app-elements.js";
3
3
  import { mergeElements } from "../shims/slot.js";
4
- import { preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
5
4
  import { NavigationTraceReasonCodes, NavigationTraceTransactionCodes, createNavigationTrace, prependNavigationTraceEntry } from "./navigation-trace.js";
5
+ import { preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
6
6
  import { createPendingNavigationCommit, resolvePendingNavigationCommitDispositionDecision } from "./app-browser-state.js";
7
7
  //#region src/server/app-browser-visible-commit.ts
8
8
  const approvedVisibleCommitBrand = Symbol("ApprovedVisibleCommit");
@@ -63,7 +63,6 @@ declare function createHistoryStateWithNavigationMetadata(state: unknown, metada
63
63
  }): HistoryStateRecord | null;
64
64
  declare function createExternalHistoryStatePreservingMetadata(callerState: unknown, currentHistoryState: unknown): unknown;
65
65
  declare function readHistoryStatePreviousNextUrl(state: unknown): string | null;
66
- declare function isBfcacheSegmentId(id: string): boolean;
67
66
  declare function readHistoryStateBfcacheIds(state: unknown): BfcacheIdMap | null;
68
67
  declare function readHistoryStateBfcacheVersion(state: unknown): number | null;
69
68
  /**
@@ -83,4 +82,4 @@ declare function resolveHistoryTraversalIntent(options: {
83
82
  historyState: unknown;
84
83
  }): HistoryTraversalIntent;
85
84
  //#endregion
86
- export { BfcacheIdMap, HistoryStateSnapshotCache, HistoryTraversalIntent, RestorableClientStateController, createExternalHistoryStatePreservingMetadata, createHashOnlyHistoryStatePreservingNavigationMetadata, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, isBfcacheSegmentId, isHistoryStateBfcacheVersionCurrent, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent };
85
+ export { BfcacheIdMap, HistoryStateSnapshotCache, HistoryTraversalIntent, RestorableClientStateController, createExternalHistoryStatePreservingMetadata, createHashOnlyHistoryStatePreservingNavigationMetadata, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, isHistoryStateBfcacheVersionCurrent, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent };
@@ -220,4 +220,4 @@ function resolveHistoryTraversalIntent(options) {
220
220
  };
221
221
  }
222
222
  //#endregion
223
- export { HistoryStateSnapshotCache, RestorableClientStateController, createExternalHistoryStatePreservingMetadata, createHashOnlyHistoryStatePreservingNavigationMetadata, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, isBfcacheSegmentId, isHistoryStateBfcacheVersionCurrent, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent };
223
+ export { HistoryStateSnapshotCache, RestorableClientStateController, createExternalHistoryStatePreservingMetadata, createHashOnlyHistoryStatePreservingNavigationMetadata, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, isHistoryStateBfcacheVersionCurrent, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent };
@@ -19,6 +19,7 @@ type ApplyAppMiddlewareOptions = {
19
19
  * INTERNAL_HEADERS and is stripped before this function runs.
20
20
  */
21
21
  isDataRequest?: boolean;
22
+ filePath?: string;
22
23
  isProxy: boolean;
23
24
  module: MiddlewareModule;
24
25
  request: Request;
@@ -117,6 +117,7 @@ async function applyAppMiddleware(options) {
117
117
  const result = await executeMiddleware({
118
118
  basePath: options.basePath,
119
119
  hadBasePath: true,
120
+ filePath: options.filePath,
120
121
  i18nConfig: options.i18nConfig,
121
122
  isDataRequest: options.isDataRequest,
122
123
  isProxy: options.isProxy,
@@ -31,7 +31,7 @@ type AppPageBackgroundRegenerationErrorContext = {
31
31
  };
32
32
  type AppPageBackgroundRegenerator = (key: string, renderFn: () => Promise<void>, errorContext?: AppPageBackgroundRegenerationErrorContext) => void;
33
33
  type AppPageDispatchIntercept<TPage = unknown> = {
34
- interceptLayouts?: readonly AppPageModule[] | null;
34
+ interceptLayouts?: readonly unknown[] | null;
35
35
  matchedParams: AppPageParams;
36
36
  page: TPage;
37
37
  slotId?: string | null;
@@ -41,7 +41,7 @@ type AppPageDispatchIntercept<TPage = unknown> = {
41
41
  };
42
42
  type AppPageDispatchInterceptOptions<TPage = unknown> = {
43
43
  interceptionContext: string | null;
44
- interceptLayouts?: readonly AppPageModule[] | null;
44
+ interceptLayouts?: readonly unknown[] | null;
45
45
  interceptPage: TPage;
46
46
  interceptParams: AppPageParams;
47
47
  interceptSlotId?: string | null;
@@ -1,7 +1,6 @@
1
1
  import { runWithFetchDedupe } from "../shims/fetch-cache.js";
2
2
  import { mergeMetadataEntries, mergeViewport, postProcessMetadata, resolveModuleMetadata as resolveModuleMetadata$1, resolveModuleViewport } from "../shims/metadata.js";
3
3
  import { resolveAppPageSegmentParams } from "./app-page-params.js";
4
- import { applyFileBasedMetadata } from "./file-based-metadata.js";
5
4
  import { tagAppPageMetadataError } from "./app-page-execution.js";
6
5
  //#region src/server/app-page-head.ts
7
6
  /**
@@ -206,7 +205,8 @@ async function resolveAppPageHeadInner(options) {
206
205
  const metadataSources = createMetadataSources(layoutMetadataResults, routeSegments, layoutSourcePositions, pageMetadata, Boolean(options.pageModule));
207
206
  metadataSources.push(...parallelMetadataSources);
208
207
  let metadata = resolvedMetadataBase;
209
- try {
208
+ if (options.metadataRoutes.length > 0) try {
209
+ const { applyFileBasedMetadata } = await import("./file-based-metadata.js");
210
210
  metadata = await applyFileBasedMetadata(resolvedMetadataBase, options.routePath, options.params, options.metadataRoutes, {
211
211
  routeSegments,
212
212
  metadataSources,
@@ -1,6 +1,6 @@
1
1
  import { methodNotAllowedResponse } from "./http-error-responses.js";
2
2
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
3
- import { isPossibleAppRouteActionRequest } from "./app-route-handler-policy.js";
3
+ import { isPossibleAppRouteActionRequest } from "./app-action-request.js";
4
4
  //#region src/server/app-page-method.ts
5
5
  function isNonGetOrHead(method) {
6
6
  const normalizedMethod = method.toUpperCase();
@@ -39,9 +39,16 @@ type BuildAppPageElementResult<TElement> = {
39
39
  response: Response | null;
40
40
  };
41
41
  type AppPageInterceptMatch<TPage = unknown> = {
42
+ interceptLayouts?: readonly unknown[] | null;
43
+ __loadInterceptLayouts?: readonly (() => Promise<unknown>)[] | null;
42
44
  matchedParams: AppPageParams;
43
45
  page: TPage;
44
46
  __pageLoader?: (() => Promise<TPage>) | null;
47
+ __loadState?: {
48
+ page: TPage;
49
+ pageLoading: Promise<TPage> | null;
50
+ interceptLayoutsLoading: Promise<readonly unknown[]> | null;
51
+ };
45
52
  slotId?: string | null;
46
53
  slotKey: string;
47
54
  sourceRouteIndex: number;
@@ -1,6 +1,7 @@
1
1
  import { notFoundResponse } from "./http-error-responses.js";
2
2
  import { runWithFetchDedupe } from "../shims/fetch-cache.js";
3
3
  import { getAppPageSegmentParamName } from "./app-page-params.js";
4
+ import { loadAppInterceptLayouts } from "./app-route-module-loader.js";
4
5
  //#region src/server/app-page-request.ts
5
6
  function pickRouteParams(matchedParams, routeParamNames) {
6
7
  const params = {};
@@ -104,7 +105,24 @@ async function resolveAppPageInterceptState(options) {
104
105
  if (!options.isRscRequest) return { kind: "none" };
105
106
  const intercept = options.findIntercept(options.cleanPathname);
106
107
  if (!intercept) return { kind: "none" };
107
- if (intercept.__pageLoader && intercept.page == null) intercept.page = await intercept.__pageLoader();
108
+ const loadState = intercept.__loadState;
109
+ if (loadState?.page != null) intercept.page = loadState.page;
110
+ if (intercept.__pageLoader && intercept.page == null) {
111
+ const loading = loadState?.pageLoading ?? intercept.__pageLoader().then((page) => {
112
+ intercept.page = page;
113
+ if (loadState) {
114
+ loadState.page = page;
115
+ loadState.pageLoading = null;
116
+ }
117
+ return page;
118
+ }).catch((error) => {
119
+ if (loadState) loadState.pageLoading = null;
120
+ throw error;
121
+ });
122
+ if (loadState) loadState.pageLoading = loading;
123
+ await loading;
124
+ }
125
+ if (intercept.__loadInterceptLayouts) await loadAppInterceptLayouts(intercept);
108
126
  const sourceRoute = await options.getSourceRoute(intercept.sourceRouteIndex);
109
127
  if (!sourceRoute) return { kind: "none" };
110
128
  if (sourceRoute === options.currentRoute) return {
@@ -1,3 +1,4 @@
1
+ import { isNavigationSignalError } from "../utils/navigation-signal.js";
1
2
  import { VINEXT_RSC_VARY_HEADER } from "./app-rsc-cache-busting.js";
2
3
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
3
4
  import { applyEdgeRuntimeHeader } from "./app-page-response.js";
@@ -131,7 +132,7 @@ function createAppPageRscErrorTracker(baseOnError) {
131
132
  return capturedSpecialError;
132
133
  },
133
134
  onRenderError(error, requestInfo, errorContext) {
134
- if (error && typeof error === "object" && "digest" in error) {
135
+ if (isNavigationSignalError(error)) {
135
136
  if (capturedSpecialError === null) capturedSpecialError = error;
136
137
  } else capturedError = error;
137
138
  return baseOnError(error, requestInfo, errorContext);
@@ -5,14 +5,14 @@ type GenerateStaticParams = (args: {
5
5
  params: RootParams;
6
6
  }) => unknown;
7
7
  type AppPrerenderStaticParamsMap = Record<string, GenerateStaticParams | null | undefined>;
8
- type RootParamNamesMap = Record<string, readonly string[] | undefined>;
8
+ type AppPrerenderRootParamNamesMap = Record<string, readonly string[] | undefined>;
9
9
  type HandleAppPrerenderEndpointOptions = {
10
10
  isPrerenderEnabled?: () => boolean;
11
11
  loadPagesRoutes?: () => Promise<unknown>;
12
12
  pathname: string;
13
- rootParamNamesByPattern?: RootParamNamesMap;
13
+ rootParamNamesByPattern?: AppPrerenderRootParamNamesMap;
14
14
  staticParamsMap: AppPrerenderStaticParamsMap;
15
15
  };
16
16
  declare function handleAppPrerenderEndpoint(request: Request, options: HandleAppPrerenderEndpointOptions): Promise<Response | null>;
17
17
  //#endregion
18
- export { handleAppPrerenderEndpoint };
18
+ export { AppPrerenderRootParamNamesMap, AppPrerenderStaticParamsMap, handleAppPrerenderEndpoint };
@@ -1,12 +1,11 @@
1
+ import "./headers.js";
1
2
  import { notFoundResponse } from "./http-error-responses.js";
2
3
  import { callAppPrerenderStaticParams } from "./app-prerender-static-params.js";
3
4
  //#region src/server/app-prerender-endpoints.ts
4
- const STATIC_PARAMS_ENDPOINT = "/__vinext/prerender/static-params";
5
- const PAGES_STATIC_PATHS_ENDPOINT = "/__vinext/prerender/pages-static-paths";
6
5
  const JSON_HEADERS = { "content-type": "application/json" };
7
6
  async function handleAppPrerenderEndpoint(request, options) {
8
- if (options.pathname === STATIC_PARAMS_ENDPOINT) return handleStaticParamsEndpoint(request, options);
9
- if (options.pathname === PAGES_STATIC_PATHS_ENDPOINT) {
7
+ if (options.pathname === "/__vinext/prerender/static-params") return handleStaticParamsEndpoint(request, options);
8
+ if (options.pathname === "/__vinext/prerender/pages-static-paths") {
10
9
  if (!options.loadPagesRoutes) return null;
11
10
  return handlePagesStaticPathsEndpoint(request, options);
12
11
  }
@@ -1,6 +1,6 @@
1
1
  import { makeThenableParams } from "../shims/thenable-params.js";
2
- import { markKnownDynamicAppRoute } from "./app-route-handler-runtime.js";
3
2
  import { applyRouteHandlerMiddlewareContext, assertSupportedAppRouteHandlerResponse, buildAppRouteCacheValue, buildRouteHandlerCachedResponse } from "./app-route-handler-response.js";
3
+ import { markKnownDynamicAppRoute } from "./app-route-handler-runtime.js";
4
4
  import { runAppRouteHandler } from "./app-route-handler-execution.js";
5
5
  //#region src/server/app-route-handler-cache.ts
6
6
  const EMPTY_PARAMS = Object.freeze({});
@@ -7,10 +7,10 @@ import { setNavigationContext } from "../shims/navigation-context-state.js";
7
7
  import { makeThenableParams } from "../shims/thenable-params.js";
8
8
  import "../shims/navigation.js";
9
9
  import { buildPageCacheTags } from "./implicit-tags.js";
10
- import { isKnownDynamicAppRoute, isValidHTTPMethod } from "./app-route-handler-runtime.js";
11
- import { getAppRouteHandlerRevalidateSeconds, hasAppRouteHandlerDefaultExport, resolveAppRouteHandlerMethod, shouldReadAppRouteHandlerCache } from "./app-route-handler-policy.js";
12
10
  import { applyRouteHandlerMiddlewareContext } from "./app-route-handler-response.js";
11
+ import { isKnownDynamicAppRoute, isValidHTTPMethod } from "./app-route-handler-runtime.js";
13
12
  import { createStaticGenerationHeadersContext } from "./app-static-generation.js";
13
+ import { getAppRouteHandlerRevalidateSeconds, hasAppRouteHandlerDefaultExport, resolveAppRouteHandlerMethod, shouldReadAppRouteHandlerCache } from "./app-route-handler-policy.js";
14
14
  import { executeAppRouteHandler } from "./app-route-handler-execution.js";
15
15
  import { readAppRouteHandlerCacheResponse } from "./app-route-handler-cache.js";
16
16
  import { resolveAppRouteHandlerFetchCacheMode } from "./app-segment-config.js";
@@ -1,8 +1,9 @@
1
1
  import { setHeadersContext } from "../shims/headers.js";
2
- import { createTrackedAppRouteRequest, markKnownDynamicAppRoute } from "./app-route-handler-runtime.js";
3
- import { isPossibleAppRouteActionRequest, resolveAppRouteHandlerSpecialError, shouldApplyAppRouteHandlerRevalidateHeader, shouldWriteAppRouteHandlerCache } from "./app-route-handler-policy.js";
2
+ import { isPossibleAppRouteActionRequest } from "./app-action-request.js";
4
3
  import { applyRouteHandlerMiddlewareContext, applyRouteHandlerRevalidateHeader, assertSupportedAppRouteHandlerResponse, buildAppRouteCacheValue, finalizeRouteHandlerResponse, markRouteHandlerCacheMiss } from "./app-route-handler-response.js";
4
+ import { createTrackedAppRouteRequest, markKnownDynamicAppRoute } from "./app-route-handler-runtime.js";
5
5
  import { createStaticGenerationHeadersContext, getAppRouteStaticGenerationErrorMessage } from "./app-static-generation.js";
6
+ import { resolveAppRouteHandlerSpecialError, shouldApplyAppRouteHandlerRevalidateHeader, shouldWriteAppRouteHandlerCache } from "./app-route-handler-policy.js";
6
7
  //#region src/server/app-route-handler-execution.ts
7
8
  function configureAppRouteStaticGenerationContext(options) {
8
9
  if (options.dynamicConfig === "force-static" || options.dynamicConfig === "error") {
@@ -1,3 +1,4 @@
1
+ import { isPossibleAppRouteActionRequest } from "./app-action-request.js";
1
2
  import { RouteHandlerHttpMethod, RouteHandlerModule } from "./app-route-handler-runtime.js";
2
3
 
3
4
  //#region src/server/app-route-handler-policy.d.ts
@@ -43,7 +44,6 @@ type AppRouteHandlerSpecialError = {
43
44
  type AppRouteHandlerSpecialErrorOptions = {
44
45
  isAction: boolean;
45
46
  };
46
- declare function isPossibleAppRouteActionRequest(request: Pick<Request, "headers" | "method">): boolean;
47
47
  declare function getAppRouteHandlerRevalidateSeconds(handler: Pick<AppRouteHandlerModule, "revalidate">): number | null;
48
48
  declare function hasAppRouteHandlerDefaultExport(handler: RouteHandlerModule): boolean;
49
49
  declare function resolveAppRouteHandlerMethod(handler: AppRouteHandlerModule, method: string): ResolvedAppRouteHandlerMethod;
@@ -1,12 +1,7 @@
1
- import "./headers.js";
2
1
  import { parseNextHttpErrorDigest, parseNextRedirectDigest } from "./next-error-digest.js";
2
+ import { isPossibleAppRouteActionRequest } from "./app-action-request.js";
3
3
  import { buildRouteHandlerAllowHeader, collectRouteHandlerMethods } from "./app-route-handler-runtime.js";
4
4
  //#region src/server/app-route-handler-policy.ts
5
- function isPossibleAppRouteActionRequest(request) {
6
- if (request.method.toUpperCase() !== "POST") return false;
7
- const contentType = request.headers.get("content-type");
8
- return request.headers.has("x-rsc-action") || request.headers.has("next-action") || contentType === "application/x-www-form-urlencoded" || contentType?.startsWith("multipart/form-data") === true;
9
- }
10
5
  function getAppRouteHandlerRevalidateSeconds(handler) {
11
6
  const { revalidate } = handler;
12
7
  if (revalidate === false) return Infinity;
@@ -10,34 +10,82 @@
10
10
  * module at Worker startup. Only the module(s) for the matched route are
11
11
  * evaluated, on demand.
12
12
  *
13
- * `ensureAppRouteModulesLoaded` resolves a route's lazy thunks and populates the
14
- * synchronous `page` / `routeHandler` fields that the rest of the request
15
- * pipeline reads directly. It is:
13
+ * `ensureAppRouteModulesLoaded` resolves a route's lazy thunks and populates
14
+ * the synchronous module fields that the rest of the request pipeline reads
15
+ * directly (`page`, `routeHandler`, layouts, templates, boundaries, and
16
+ * parallel-slot modules). It is:
16
17
  *
17
18
  * - idempotent: once a route is loaded it returns immediately;
18
19
  * - dedup'd: concurrent calls for the same route share one in-flight promise,
19
20
  * so a burst of requests to the same route triggers a single import.
20
21
  *
21
- * Callers must `await` it before any synchronous read of `route.page` or
22
- * `route.routeHandler` (segment config, fetch-cache mode, runtime resolution,
23
- * dispatch branch, element building, etc.).
22
+ * Callers must `await` it before any synchronous read of route modules
23
+ * (segment config, fetch-cache mode, runtime resolution, dispatch branch,
24
+ * element building, etc.).
24
25
  */
25
26
  type LazyModuleThunk = () => Promise<unknown>;
27
+ type LazyModuleLoaderArray = readonly (LazyModuleThunk | null | undefined)[];
28
+ type LazyLoadableIntercept = {
29
+ interceptLayouts?: readonly unknown[] | null;
30
+ __loadInterceptLayouts?: LazyModuleLoaderArray | null;
31
+ __loadState?: {
32
+ interceptLayoutsLoading: Promise<readonly unknown[]> | null;
33
+ };
34
+ };
35
+ type LazyLoadableSlot = {
36
+ page?: unknown;
37
+ default?: unknown;
38
+ layout?: unknown;
39
+ loading?: unknown;
40
+ error?: unknown;
41
+ __loadPage?: LazyModuleThunk | null;
42
+ __loadDefault?: LazyModuleThunk | null;
43
+ __loadLayout?: LazyModuleThunk | null;
44
+ __loadLoading?: LazyModuleThunk | null;
45
+ __loadError?: LazyModuleThunk | null; /** Hydrated only after an intercept matches, not with the slot's base modules. */
46
+ intercepts?: LazyLoadableIntercept[];
47
+ };
26
48
  type LazyLoadableRoute = {
27
49
  page?: unknown;
28
- routeHandler?: unknown; /** Lazy loader for the page module; `null`/absent when the page is eager. */
50
+ routeHandler?: unknown;
51
+ layouts?: unknown[];
52
+ templates?: unknown[];
53
+ errors?: unknown[];
54
+ errorPaths?: unknown[];
55
+ notFounds?: unknown[];
56
+ forbiddens?: unknown[];
57
+ unauthorizeds?: unknown[];
58
+ loading?: unknown;
59
+ error?: unknown;
60
+ notFound?: unknown;
61
+ forbidden?: unknown;
62
+ unauthorized?: unknown;
63
+ slots?: Record<string, LazyLoadableSlot>;
64
+ siblingIntercepts?: LazyLoadableIntercept[]; /** Lazy loader for the page module; `null`/absent when the page is eager. */
29
65
  __loadPage?: LazyModuleThunk | null; /** Lazy loader for the route-handler module; `null`/absent when none. */
30
- __loadRouteHandler?: LazyModuleThunk | null; /** Set once the lazy modules have been resolved onto `page`/`routeHandler`. */
66
+ __loadRouteHandler?: LazyModuleThunk | null;
67
+ __loadLayouts?: LazyModuleLoaderArray | null;
68
+ __loadTemplates?: LazyModuleLoaderArray | null;
69
+ __loadErrors?: LazyModuleLoaderArray | null;
70
+ __loadErrorPaths?: LazyModuleLoaderArray | null;
71
+ __loadNotFounds?: LazyModuleLoaderArray | null;
72
+ __loadForbiddens?: LazyModuleLoaderArray | null;
73
+ __loadUnauthorizeds?: LazyModuleLoaderArray | null;
74
+ __loadLoading?: LazyModuleThunk | null;
75
+ __loadError?: LazyModuleThunk | null;
76
+ __loadNotFound?: LazyModuleThunk | null;
77
+ __loadForbidden?: LazyModuleThunk | null;
78
+ __loadUnauthorized?: LazyModuleThunk | null; /** Set once the route's lazy module fields have been resolved. */
31
79
  __loaded?: boolean; /** In-flight hydration promise, used to dedup concurrent loads. */
32
80
  __loading?: Promise<unknown> | null;
33
81
  };
82
+ declare function loadAppInterceptLayouts(intercept: LazyLoadableIntercept): Promise<readonly unknown[]>;
34
83
  /**
35
- * Resolve a route's lazy page/route-handler modules and assign them onto the
36
- * route's synchronous `page` / `routeHandler` fields. Returns the same route
37
- * reference (synchronously when already loaded, otherwise after the in-flight
38
- * import resolves). Safe to call on `null`/`undefined` routes and on eager
39
- * routes that have no lazy thunks.
84
+ * Resolve a route's lazy modules and assign them onto the route's synchronous
85
+ * module fields. Returns the same route reference (synchronously when already
86
+ * loaded, otherwise after the in-flight import resolves). Safe to call on
87
+ * `null`/`undefined` routes and on eager routes that have no lazy thunks.
40
88
  */
41
89
  declare function ensureAppRouteModulesLoaded<TRoute extends LazyLoadableRoute>(route: TRoute | null | undefined): TRoute | Promise<TRoute>;
42
90
  //#endregion
43
- export { LazyLoadableRoute, ensureAppRouteModulesLoaded };
91
+ export { LazyLoadableRoute, ensureAppRouteModulesLoaded, loadAppInterceptLayouts };