@rangojs/router 0.0.0-experimental.0f44aca1
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.
- package/AGENTS.md +5 -0
- package/README.md +899 -0
- package/dist/bin/rango.js +1601 -0
- package/dist/vite/index.js +5214 -0
- package/package.json +176 -0
- package/skills/breadcrumbs/SKILL.md +250 -0
- package/skills/cache-guide/SKILL.md +262 -0
- package/skills/caching/SKILL.md +220 -0
- package/skills/composability/SKILL.md +172 -0
- package/skills/debug-manifest/SKILL.md +112 -0
- package/skills/document-cache/SKILL.md +182 -0
- package/skills/fonts/SKILL.md +167 -0
- package/skills/hooks/SKILL.md +704 -0
- package/skills/host-router/SKILL.md +218 -0
- package/skills/intercept/SKILL.md +313 -0
- package/skills/layout/SKILL.md +310 -0
- package/skills/links/SKILL.md +239 -0
- package/skills/loader/SKILL.md +596 -0
- package/skills/middleware/SKILL.md +339 -0
- package/skills/mime-routes/SKILL.md +128 -0
- package/skills/parallel/SKILL.md +305 -0
- package/skills/prerender/SKILL.md +643 -0
- package/skills/rango/SKILL.md +118 -0
- package/skills/response-routes/SKILL.md +411 -0
- package/skills/route/SKILL.md +385 -0
- package/skills/router-setup/SKILL.md +439 -0
- package/skills/tailwind/SKILL.md +129 -0
- package/skills/theme/SKILL.md +79 -0
- package/skills/typesafety/SKILL.md +623 -0
- package/skills/use-cache/SKILL.md +324 -0
- package/src/__internal.ts +273 -0
- package/src/bin/rango.ts +321 -0
- package/src/browser/action-coordinator.ts +97 -0
- package/src/browser/action-response-classifier.ts +99 -0
- package/src/browser/event-controller.ts +899 -0
- package/src/browser/history-state.ts +80 -0
- package/src/browser/index.ts +18 -0
- package/src/browser/intercept-utils.ts +52 -0
- package/src/browser/link-interceptor.ts +141 -0
- package/src/browser/logging.ts +55 -0
- package/src/browser/merge-segment-loaders.ts +134 -0
- package/src/browser/navigation-bridge.ts +645 -0
- package/src/browser/navigation-client.ts +215 -0
- package/src/browser/navigation-store.ts +806 -0
- package/src/browser/navigation-transaction.ts +295 -0
- package/src/browser/network-error-handler.ts +61 -0
- package/src/browser/partial-update.ts +550 -0
- package/src/browser/prefetch/cache.ts +146 -0
- package/src/browser/prefetch/fetch.ts +135 -0
- package/src/browser/prefetch/observer.ts +65 -0
- package/src/browser/prefetch/policy.ts +42 -0
- package/src/browser/prefetch/queue.ts +88 -0
- package/src/browser/rango-state.ts +112 -0
- package/src/browser/react/Link.tsx +360 -0
- package/src/browser/react/NavigationProvider.tsx +386 -0
- package/src/browser/react/ScrollRestoration.tsx +94 -0
- package/src/browser/react/context.ts +59 -0
- package/src/browser/react/filter-segment-order.ts +11 -0
- package/src/browser/react/index.ts +52 -0
- package/src/browser/react/location-state-shared.ts +162 -0
- package/src/browser/react/location-state.ts +107 -0
- package/src/browser/react/mount-context.ts +37 -0
- package/src/browser/react/nonce-context.ts +23 -0
- package/src/browser/react/shallow-equal.ts +27 -0
- package/src/browser/react/use-action.ts +218 -0
- package/src/browser/react/use-client-cache.ts +58 -0
- package/src/browser/react/use-handle.ts +162 -0
- package/src/browser/react/use-href.tsx +40 -0
- package/src/browser/react/use-link-status.ts +135 -0
- package/src/browser/react/use-mount.ts +31 -0
- package/src/browser/react/use-navigation.ts +99 -0
- package/src/browser/react/use-params.ts +65 -0
- package/src/browser/react/use-pathname.ts +47 -0
- package/src/browser/react/use-router.ts +63 -0
- package/src/browser/react/use-search-params.ts +56 -0
- package/src/browser/react/use-segments.ts +171 -0
- package/src/browser/response-adapter.ts +73 -0
- package/src/browser/rsc-router.tsx +431 -0
- package/src/browser/scroll-restoration.ts +400 -0
- package/src/browser/segment-reconciler.ts +216 -0
- package/src/browser/segment-structure-assert.ts +83 -0
- package/src/browser/server-action-bridge.ts +667 -0
- package/src/browser/shallow.ts +40 -0
- package/src/browser/types.ts +538 -0
- package/src/browser/validate-redirect-origin.ts +29 -0
- package/src/build/generate-manifest.ts +438 -0
- package/src/build/generate-route-types.ts +36 -0
- package/src/build/index.ts +35 -0
- package/src/build/route-trie.ts +265 -0
- package/src/build/route-types/ast-helpers.ts +25 -0
- package/src/build/route-types/ast-route-extraction.ts +98 -0
- package/src/build/route-types/codegen.ts +102 -0
- package/src/build/route-types/include-resolution.ts +411 -0
- package/src/build/route-types/param-extraction.ts +48 -0
- package/src/build/route-types/per-module-writer.ts +128 -0
- package/src/build/route-types/router-processing.ts +469 -0
- package/src/build/route-types/scan-filter.ts +78 -0
- package/src/build/runtime-discovery.ts +231 -0
- package/src/cache/background-task.ts +34 -0
- package/src/cache/cache-key-utils.ts +44 -0
- package/src/cache/cache-policy.ts +125 -0
- package/src/cache/cache-runtime.ts +338 -0
- package/src/cache/cache-scope.ts +382 -0
- package/src/cache/cf/cf-cache-store.ts +540 -0
- package/src/cache/cf/index.ts +25 -0
- package/src/cache/document-cache.ts +369 -0
- package/src/cache/handle-capture.ts +81 -0
- package/src/cache/handle-snapshot.ts +41 -0
- package/src/cache/index.ts +43 -0
- package/src/cache/memory-segment-store.ts +328 -0
- package/src/cache/profile-registry.ts +73 -0
- package/src/cache/read-through-swr.ts +134 -0
- package/src/cache/segment-codec.ts +256 -0
- package/src/cache/taint.ts +98 -0
- package/src/cache/types.ts +342 -0
- package/src/client.rsc.tsx +85 -0
- package/src/client.tsx +601 -0
- package/src/component-utils.ts +76 -0
- package/src/components/DefaultDocument.tsx +27 -0
- package/src/context-var.ts +86 -0
- package/src/debug.ts +243 -0
- package/src/default-error-boundary.tsx +88 -0
- package/src/deps/browser.ts +8 -0
- package/src/deps/html-stream-client.ts +2 -0
- package/src/deps/html-stream-server.ts +2 -0
- package/src/deps/rsc.ts +10 -0
- package/src/deps/ssr.ts +2 -0
- package/src/errors.ts +365 -0
- package/src/handle.ts +135 -0
- package/src/handles/MetaTags.tsx +246 -0
- package/src/handles/breadcrumbs.ts +66 -0
- package/src/handles/index.ts +7 -0
- package/src/handles/meta.ts +264 -0
- package/src/host/cookie-handler.ts +165 -0
- package/src/host/errors.ts +97 -0
- package/src/host/index.ts +53 -0
- package/src/host/pattern-matcher.ts +214 -0
- package/src/host/router.ts +352 -0
- package/src/host/testing.ts +79 -0
- package/src/host/types.ts +146 -0
- package/src/host/utils.ts +25 -0
- package/src/href-client.ts +222 -0
- package/src/index.rsc.ts +233 -0
- package/src/index.ts +277 -0
- package/src/internal-debug.ts +11 -0
- package/src/loader.rsc.ts +89 -0
- package/src/loader.ts +64 -0
- package/src/network-error-thrower.tsx +23 -0
- package/src/outlet-context.ts +15 -0
- package/src/outlet-provider.tsx +45 -0
- package/src/prerender/param-hash.ts +37 -0
- package/src/prerender/store.ts +185 -0
- package/src/prerender.ts +463 -0
- package/src/reverse.ts +330 -0
- package/src/root-error-boundary.tsx +289 -0
- package/src/route-content-wrapper.tsx +196 -0
- package/src/route-definition/dsl-helpers.ts +934 -0
- package/src/route-definition/helper-factories.ts +200 -0
- package/src/route-definition/helpers-types.ts +430 -0
- package/src/route-definition/index.ts +52 -0
- package/src/route-definition/redirect.ts +93 -0
- package/src/route-definition.ts +1 -0
- package/src/route-map-builder.ts +275 -0
- package/src/route-name.ts +53 -0
- package/src/route-types.ts +259 -0
- package/src/router/content-negotiation.ts +116 -0
- package/src/router/debug-manifest.ts +72 -0
- package/src/router/error-handling.ts +287 -0
- package/src/router/find-match.ts +158 -0
- package/src/router/handler-context.ts +451 -0
- package/src/router/intercept-resolution.ts +395 -0
- package/src/router/lazy-includes.ts +234 -0
- package/src/router/loader-resolution.ts +420 -0
- package/src/router/logging.ts +248 -0
- package/src/router/manifest.ts +267 -0
- package/src/router/match-api.ts +620 -0
- package/src/router/match-context.ts +266 -0
- package/src/router/match-handlers.ts +440 -0
- package/src/router/match-middleware/background-revalidation.ts +223 -0
- package/src/router/match-middleware/cache-lookup.ts +634 -0
- package/src/router/match-middleware/cache-store.ts +295 -0
- package/src/router/match-middleware/index.ts +81 -0
- package/src/router/match-middleware/intercept-resolution.ts +306 -0
- package/src/router/match-middleware/segment-resolution.ts +192 -0
- package/src/router/match-pipelines.ts +179 -0
- package/src/router/match-result.ts +219 -0
- package/src/router/metrics.ts +282 -0
- package/src/router/middleware-cookies.ts +55 -0
- package/src/router/middleware-types.ts +222 -0
- package/src/router/middleware.ts +748 -0
- package/src/router/pattern-matching.ts +563 -0
- package/src/router/prerender-match.ts +402 -0
- package/src/router/preview-match.ts +170 -0
- package/src/router/revalidation.ts +289 -0
- package/src/router/router-context.ts +316 -0
- package/src/router/router-interfaces.ts +452 -0
- package/src/router/router-options.ts +592 -0
- package/src/router/router-registry.ts +24 -0
- package/src/router/segment-resolution/fresh.ts +570 -0
- package/src/router/segment-resolution/helpers.ts +263 -0
- package/src/router/segment-resolution/loader-cache.ts +198 -0
- package/src/router/segment-resolution/revalidation.ts +1239 -0
- package/src/router/segment-resolution/static-store.ts +67 -0
- package/src/router/segment-resolution.ts +21 -0
- package/src/router/segment-wrappers.ts +289 -0
- package/src/router/telemetry-otel.ts +299 -0
- package/src/router/telemetry.ts +300 -0
- package/src/router/timeout.ts +148 -0
- package/src/router/trie-matching.ts +239 -0
- package/src/router/types.ts +170 -0
- package/src/router.ts +1002 -0
- package/src/rsc/handler-context.ts +45 -0
- package/src/rsc/handler.ts +1089 -0
- package/src/rsc/helpers.ts +198 -0
- package/src/rsc/index.ts +36 -0
- package/src/rsc/loader-fetch.ts +209 -0
- package/src/rsc/manifest-init.ts +86 -0
- package/src/rsc/nonce.ts +32 -0
- package/src/rsc/origin-guard.ts +141 -0
- package/src/rsc/progressive-enhancement.ts +379 -0
- package/src/rsc/response-error.ts +37 -0
- package/src/rsc/response-route-handler.ts +347 -0
- package/src/rsc/rsc-rendering.ts +235 -0
- package/src/rsc/runtime-warnings.ts +42 -0
- package/src/rsc/server-action.ts +348 -0
- package/src/rsc/ssr-setup.ts +128 -0
- package/src/rsc/types.ts +263 -0
- package/src/search-params.ts +230 -0
- package/src/segment-system.tsx +454 -0
- package/src/server/context.ts +591 -0
- package/src/server/cookie-store.ts +190 -0
- package/src/server/fetchable-loader-store.ts +37 -0
- package/src/server/handle-store.ts +308 -0
- package/src/server/loader-registry.ts +133 -0
- package/src/server/request-context.ts +914 -0
- package/src/server/root-layout.tsx +10 -0
- package/src/server/tsconfig.json +14 -0
- package/src/server.ts +51 -0
- package/src/ssr/index.tsx +365 -0
- package/src/static-handler.ts +114 -0
- package/src/theme/ThemeProvider.tsx +297 -0
- package/src/theme/ThemeScript.tsx +61 -0
- package/src/theme/constants.ts +62 -0
- package/src/theme/index.ts +48 -0
- package/src/theme/theme-context.ts +44 -0
- package/src/theme/theme-script.ts +155 -0
- package/src/theme/types.ts +182 -0
- package/src/theme/use-theme.ts +44 -0
- package/src/types/boundaries.ts +158 -0
- package/src/types/cache-types.ts +198 -0
- package/src/types/error-types.ts +192 -0
- package/src/types/global-namespace.ts +100 -0
- package/src/types/handler-context.ts +687 -0
- package/src/types/index.ts +88 -0
- package/src/types/loader-types.ts +183 -0
- package/src/types/route-config.ts +170 -0
- package/src/types/route-entry.ts +102 -0
- package/src/types/segments.ts +148 -0
- package/src/types.ts +1 -0
- package/src/urls/include-helper.ts +197 -0
- package/src/urls/index.ts +53 -0
- package/src/urls/path-helper-types.ts +339 -0
- package/src/urls/path-helper.ts +329 -0
- package/src/urls/pattern-types.ts +95 -0
- package/src/urls/response-types.ts +106 -0
- package/src/urls/type-extraction.ts +372 -0
- package/src/urls/urls-function.ts +98 -0
- package/src/urls.ts +1 -0
- package/src/use-loader.tsx +354 -0
- package/src/vite/discovery/bundle-postprocess.ts +184 -0
- package/src/vite/discovery/discover-routers.ts +344 -0
- package/src/vite/discovery/prerender-collection.ts +385 -0
- package/src/vite/discovery/route-types-writer.ts +258 -0
- package/src/vite/discovery/self-gen-tracking.ts +47 -0
- package/src/vite/discovery/state.ts +110 -0
- package/src/vite/discovery/virtual-module-codegen.ts +203 -0
- package/src/vite/index.ts +16 -0
- package/src/vite/plugin-types.ts +131 -0
- package/src/vite/plugins/cjs-to-esm.ts +93 -0
- package/src/vite/plugins/client-ref-dedup.ts +115 -0
- package/src/vite/plugins/client-ref-hashing.ts +105 -0
- package/src/vite/plugins/expose-action-id.ts +365 -0
- package/src/vite/plugins/expose-id-utils.ts +287 -0
- package/src/vite/plugins/expose-ids/export-analysis.ts +296 -0
- package/src/vite/plugins/expose-ids/handler-transform.ts +179 -0
- package/src/vite/plugins/expose-ids/loader-transform.ts +74 -0
- package/src/vite/plugins/expose-ids/router-transform.ts +110 -0
- package/src/vite/plugins/expose-ids/types.ts +45 -0
- package/src/vite/plugins/expose-internal-ids.ts +569 -0
- package/src/vite/plugins/refresh-cmd.ts +65 -0
- package/src/vite/plugins/use-cache-transform.ts +323 -0
- package/src/vite/plugins/version-injector.ts +83 -0
- package/src/vite/plugins/version-plugin.ts +254 -0
- package/src/vite/plugins/version.d.ts +12 -0
- package/src/vite/plugins/virtual-entries.ts +123 -0
- package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
- package/src/vite/rango.ts +510 -0
- package/src/vite/router-discovery.ts +785 -0
- package/src/vite/utils/ast-handler-extract.ts +517 -0
- package/src/vite/utils/banner.ts +36 -0
- package/src/vite/utils/bundle-analysis.ts +137 -0
- package/src/vite/utils/manifest-utils.ts +70 -0
- package/src/vite/utils/package-resolution.ts +121 -0
- package/src/vite/utils/prerender-utils.ts +189 -0
- package/src/vite/utils/shared-utils.ts +169 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import type { AllUseItems, IncludeItem } from "../route-types.js";
|
|
2
|
+
import {
|
|
3
|
+
getContext,
|
|
4
|
+
runWithPrefixes,
|
|
5
|
+
getUrlPrefix,
|
|
6
|
+
getNamePrefix,
|
|
7
|
+
getRootScoped,
|
|
8
|
+
} from "../server/context";
|
|
9
|
+
import {
|
|
10
|
+
INTERNAL_INCLUDE_SCOPE_PREFIX,
|
|
11
|
+
validateUserRouteName,
|
|
12
|
+
} from "../route-name.js";
|
|
13
|
+
import type { UrlPatterns, IncludeOptions } from "./pattern-types.js";
|
|
14
|
+
import type { IncludeFn } from "./path-helper-types.js";
|
|
15
|
+
|
|
16
|
+
function hasExplicitNameOption(options: IncludeOptions | undefined): boolean {
|
|
17
|
+
return !!options && Object.prototype.hasOwnProperty.call(options, "name");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function allocateInternalIncludeScopeId(
|
|
21
|
+
counters: Record<string, number>,
|
|
22
|
+
): string {
|
|
23
|
+
const key = "__include_scope__";
|
|
24
|
+
const index = counters[key] ?? 0;
|
|
25
|
+
counters[key] = index + 1;
|
|
26
|
+
return `${INTERNAL_INCLUDE_SCOPE_PREFIX}${index}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Process an IncludeItem by executing its nested patterns with prefixes
|
|
31
|
+
* This expands the include into actual route registrations
|
|
32
|
+
*/
|
|
33
|
+
function processIncludeItem(item: IncludeItem): AllUseItems[] {
|
|
34
|
+
const { prefix, patterns } = item;
|
|
35
|
+
const namePrefix =
|
|
36
|
+
(item as IncludeItem & { _lazyContext?: { namePrefix?: string } })
|
|
37
|
+
._lazyContext?.namePrefix ?? item.options?.name;
|
|
38
|
+
|
|
39
|
+
// Execute the nested patterns' handler with URL and name prefixes
|
|
40
|
+
// The urlPrefix being set tells nested urls() to skip RootLayout wrapping
|
|
41
|
+
return runWithPrefixes(prefix, namePrefix, () => {
|
|
42
|
+
// Call the nested patterns' handler - this registers routes with prefixed patterns/names
|
|
43
|
+
return (patterns as UrlPatterns).handler();
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Recursively process items, expanding any IncludeItems
|
|
49
|
+
* Returns items with IncludeItems expanded into actual route items
|
|
50
|
+
*
|
|
51
|
+
* Lazy includes are kept as-is (not expanded) for the router to handle later.
|
|
52
|
+
*/
|
|
53
|
+
export function processItems(items: readonly AllUseItems[]): AllUseItems[] {
|
|
54
|
+
const result: AllUseItems[] = [];
|
|
55
|
+
|
|
56
|
+
for (const item of items) {
|
|
57
|
+
if (!item) continue;
|
|
58
|
+
|
|
59
|
+
if (item.type === "include") {
|
|
60
|
+
const includeItem = item as IncludeItem & {
|
|
61
|
+
_expanded?: AllUseItems[];
|
|
62
|
+
lazy?: boolean;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// Lazy includes are NOT expanded here - kept for router to handle
|
|
66
|
+
if (includeItem.lazy) {
|
|
67
|
+
result.push(item);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Eager includes are already expanded during include() call
|
|
72
|
+
if (includeItem._expanded) {
|
|
73
|
+
// Items were expanded immediately - just process them recursively
|
|
74
|
+
result.push(...processItems(includeItem._expanded));
|
|
75
|
+
} else {
|
|
76
|
+
// Fallback for legacy include items without _expanded
|
|
77
|
+
const expanded = processIncludeItem(item as IncludeItem);
|
|
78
|
+
result.push(...processItems(expanded));
|
|
79
|
+
}
|
|
80
|
+
} else if (item.type === "layout" && (item as any).uses) {
|
|
81
|
+
// Process nested items in layout
|
|
82
|
+
const layoutItem = item as any;
|
|
83
|
+
layoutItem.uses = processItems(layoutItem.uses);
|
|
84
|
+
result.push(layoutItem);
|
|
85
|
+
} else {
|
|
86
|
+
result.push(item);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Create include() helper for composing URL patterns
|
|
95
|
+
*
|
|
96
|
+
* By default, include() IMMEDIATELY expands the nested patterns. This ensures
|
|
97
|
+
* that routes from included patterns inherit the correct parent context
|
|
98
|
+
* (the layout they're included in).
|
|
99
|
+
*
|
|
100
|
+
* With `lazy: true`, patterns are NOT expanded at definition time. Instead,
|
|
101
|
+
* they're evaluated on first request that matches the prefix. This improves
|
|
102
|
+
* cold start time for apps with many routes.
|
|
103
|
+
*/
|
|
104
|
+
export function createIncludeHelper<TEnv>(): IncludeFn<TEnv> {
|
|
105
|
+
return (
|
|
106
|
+
prefix: string,
|
|
107
|
+
patterns: UrlPatterns<TEnv>,
|
|
108
|
+
options?: IncludeOptions,
|
|
109
|
+
): IncludeItem => {
|
|
110
|
+
const store = getContext();
|
|
111
|
+
const ctx = store.getStore();
|
|
112
|
+
if (!ctx) throw new Error("include() must be called inside urls()");
|
|
113
|
+
|
|
114
|
+
const explicitName = options?.name;
|
|
115
|
+
const hasExplicitName = hasExplicitNameOption(options);
|
|
116
|
+
if (hasExplicitName && explicitName) {
|
|
117
|
+
validateUserRouteName(explicitName);
|
|
118
|
+
}
|
|
119
|
+
const name = `$include_${prefix.replace(/[/:*?]/g, "_")}`;
|
|
120
|
+
|
|
121
|
+
// Capture context for deferred evaluation
|
|
122
|
+
const capturedUrlPrefix = getUrlPrefix();
|
|
123
|
+
const capturedNamePrefix = getNamePrefix();
|
|
124
|
+
const capturedParent = ctx.parent;
|
|
125
|
+
const fullPrefix = capturedUrlPrefix
|
|
126
|
+
? capturedUrlPrefix.endsWith("/") && prefix.startsWith("/")
|
|
127
|
+
? capturedUrlPrefix + prefix.slice(1)
|
|
128
|
+
: capturedUrlPrefix + prefix
|
|
129
|
+
: prefix;
|
|
130
|
+
const internalScope = !hasExplicitName
|
|
131
|
+
? allocateInternalIncludeScopeId(ctx.counters)
|
|
132
|
+
: undefined;
|
|
133
|
+
const nextSegment = hasExplicitName ? explicitName : internalScope;
|
|
134
|
+
const fullNamePrefix =
|
|
135
|
+
nextSegment !== undefined && nextSegment !== ""
|
|
136
|
+
? capturedNamePrefix
|
|
137
|
+
? `${capturedNamePrefix}.${nextSegment}`
|
|
138
|
+
: nextSegment
|
|
139
|
+
: capturedNamePrefix;
|
|
140
|
+
|
|
141
|
+
// Track this include for build-time manifest generation
|
|
142
|
+
if (ctx.trackedIncludes) {
|
|
143
|
+
ctx.trackedIncludes.push({
|
|
144
|
+
prefix,
|
|
145
|
+
fullPrefix,
|
|
146
|
+
namePrefix: fullNamePrefix,
|
|
147
|
+
patterns,
|
|
148
|
+
lazy: true,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Snapshot parent's counters so lazy manifest generation starts
|
|
153
|
+
// at the correct index, preventing shortCode collisions with
|
|
154
|
+
// sibling entries (e.g., BlogLayout and ArticlesLayout under NavLayout).
|
|
155
|
+
const capturedCounters = { ...ctx.counters };
|
|
156
|
+
|
|
157
|
+
// Reserve a layout slot in the parent's counter so sibling lazy includes
|
|
158
|
+
// produce different shortCode indices for their root layout.
|
|
159
|
+
// Without this, consecutive include() calls capture identical counters
|
|
160
|
+
// and their first child layouts get the same shortCode (e.g., both M0L0L0),
|
|
161
|
+
// causing the client partial-update diff to see no changes on navigation.
|
|
162
|
+
if (capturedParent?.shortCode) {
|
|
163
|
+
const layoutCounterKey = `${capturedParent.shortCode}_layout`;
|
|
164
|
+
ctx.counters[layoutCounterKey] ??= 0;
|
|
165
|
+
ctx.counters[layoutCounterKey]++;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Compute rootScoped at capture time, mirroring the logic in runWithPrefixes.
|
|
169
|
+
// This ensures lazy evaluation restores the correct scope state.
|
|
170
|
+
const parentRootScoped = ctx.rootScoped;
|
|
171
|
+
const capturedRootScoped =
|
|
172
|
+
nextSegment === ""
|
|
173
|
+
? (parentRootScoped ?? true)
|
|
174
|
+
: nextSegment !== undefined
|
|
175
|
+
? (parentRootScoped ?? false)
|
|
176
|
+
: parentRootScoped;
|
|
177
|
+
|
|
178
|
+
// All includes are lazy - patterns are evaluated on first matching request
|
|
179
|
+
// This improves cold start time significantly for large route sets
|
|
180
|
+
return {
|
|
181
|
+
type: "include",
|
|
182
|
+
name,
|
|
183
|
+
prefix,
|
|
184
|
+
patterns,
|
|
185
|
+
options,
|
|
186
|
+
lazy: true,
|
|
187
|
+
_lazyContext: {
|
|
188
|
+
urlPrefix: capturedUrlPrefix,
|
|
189
|
+
namePrefix: fullNamePrefix,
|
|
190
|
+
parent: capturedParent,
|
|
191
|
+
counters: capturedCounters,
|
|
192
|
+
cacheProfiles: ctx.cacheProfiles,
|
|
193
|
+
rootScoped: capturedRootScoped,
|
|
194
|
+
},
|
|
195
|
+
} as IncludeItem;
|
|
196
|
+
};
|
|
197
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Response types and symbols
|
|
2
|
+
export {
|
|
3
|
+
RESPONSE_TYPE,
|
|
4
|
+
type ResponseHandler,
|
|
5
|
+
type JsonValue,
|
|
6
|
+
type JsonResponseHandler,
|
|
7
|
+
type TextResponseHandler,
|
|
8
|
+
type ResponseHandlerContext,
|
|
9
|
+
} from "./response-types.js";
|
|
10
|
+
|
|
11
|
+
// Pattern types
|
|
12
|
+
export type {
|
|
13
|
+
UnnamedRoute,
|
|
14
|
+
LocalOnlyInclude,
|
|
15
|
+
PathOptions,
|
|
16
|
+
PathDefinition,
|
|
17
|
+
UrlPatterns,
|
|
18
|
+
IncludeOptions,
|
|
19
|
+
} from "./pattern-types.js";
|
|
20
|
+
|
|
21
|
+
// Type extraction utilities
|
|
22
|
+
export type {
|
|
23
|
+
ExtractRoutes,
|
|
24
|
+
ExtractResponses,
|
|
25
|
+
ExtractRouteNames,
|
|
26
|
+
ExtractPathParams,
|
|
27
|
+
ResponseError,
|
|
28
|
+
ResponseEnvelope,
|
|
29
|
+
RouteResponse,
|
|
30
|
+
} from "./type-extraction.js";
|
|
31
|
+
|
|
32
|
+
// Path helper types
|
|
33
|
+
export type {
|
|
34
|
+
PathFn,
|
|
35
|
+
ResponsePathFn,
|
|
36
|
+
JsonResponsePathFn,
|
|
37
|
+
TextResponsePathFn,
|
|
38
|
+
IncludeFn,
|
|
39
|
+
PathHelpers,
|
|
40
|
+
} from "./path-helper-types.js";
|
|
41
|
+
|
|
42
|
+
// Main entry point
|
|
43
|
+
export { urls } from "./urls-function.js";
|
|
44
|
+
|
|
45
|
+
// Re-exports from route-types
|
|
46
|
+
export type {
|
|
47
|
+
AllUseItems,
|
|
48
|
+
IncludeItem,
|
|
49
|
+
TypedRouteItem,
|
|
50
|
+
TypedIncludeItem,
|
|
51
|
+
TypedLayoutItem,
|
|
52
|
+
TypedCacheItem,
|
|
53
|
+
} from "../route-types.js";
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type {
|
|
3
|
+
ErrorBoundaryHandler,
|
|
4
|
+
ExtractParams,
|
|
5
|
+
Handler,
|
|
6
|
+
HandlerContext,
|
|
7
|
+
LoaderDefinition,
|
|
8
|
+
MiddlewareFn,
|
|
9
|
+
NotFoundBoundaryHandler,
|
|
10
|
+
PartialCacheOptions,
|
|
11
|
+
ShouldRevalidateFn,
|
|
12
|
+
TransitionConfig,
|
|
13
|
+
} from "../types.js";
|
|
14
|
+
import type {
|
|
15
|
+
AllUseItems,
|
|
16
|
+
TypedLayoutItem,
|
|
17
|
+
ParallelItem,
|
|
18
|
+
InterceptItem,
|
|
19
|
+
MiddlewareItem,
|
|
20
|
+
RevalidateItem,
|
|
21
|
+
LoaderItem,
|
|
22
|
+
LoadingItem,
|
|
23
|
+
ErrorBoundaryItem,
|
|
24
|
+
NotFoundBoundaryItem,
|
|
25
|
+
LayoutUseItem,
|
|
26
|
+
RouteUseItem,
|
|
27
|
+
ResponseRouteUseItem,
|
|
28
|
+
ParallelUseItem,
|
|
29
|
+
InterceptUseItem,
|
|
30
|
+
LoaderUseItem,
|
|
31
|
+
WhenItem,
|
|
32
|
+
TypedCacheItem,
|
|
33
|
+
TransitionItem,
|
|
34
|
+
TypedTransitionItem,
|
|
35
|
+
TypedRouteItem,
|
|
36
|
+
TypedIncludeItem,
|
|
37
|
+
UseItems,
|
|
38
|
+
} from "../route-types.js";
|
|
39
|
+
import type { SearchSchema } from "../search-params.js";
|
|
40
|
+
import type { PrerenderHandlerDefinition } from "../prerender.js";
|
|
41
|
+
import type { StaticHandlerDefinition } from "../static-handler.js";
|
|
42
|
+
import type { InterceptWhenFn } from "../server/context";
|
|
43
|
+
import type {
|
|
44
|
+
ResponseHandler,
|
|
45
|
+
ResponseHandlerContext,
|
|
46
|
+
TextResponseHandler,
|
|
47
|
+
} from "./response-types.js";
|
|
48
|
+
import type {
|
|
49
|
+
UnnamedRoute,
|
|
50
|
+
LocalOnlyInclude,
|
|
51
|
+
PathOptions,
|
|
52
|
+
UrlPatterns,
|
|
53
|
+
IncludeOptions,
|
|
54
|
+
} from "./pattern-types.js";
|
|
55
|
+
import type { ExtractRoutes, ExtractResponses } from "./type-extraction.js";
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Base path function signature for defining routes with URL patterns.
|
|
59
|
+
*/
|
|
60
|
+
export type PathFn<TEnv> = <
|
|
61
|
+
const TPattern extends string,
|
|
62
|
+
const TName extends string = UnnamedRoute,
|
|
63
|
+
const TSearch extends SearchSchema = {},
|
|
64
|
+
TParams extends Record<string, any> = ExtractParams<TPattern>,
|
|
65
|
+
>(
|
|
66
|
+
pattern: TPattern,
|
|
67
|
+
handler:
|
|
68
|
+
| ReactNode
|
|
69
|
+
| ((
|
|
70
|
+
ctx: HandlerContext<TParams, TEnv, TSearch>,
|
|
71
|
+
) => ReactNode | Promise<ReactNode> | Response | Promise<Response>)
|
|
72
|
+
| PrerenderHandlerDefinition<TParams>
|
|
73
|
+
| StaticHandlerDefinition<TParams>,
|
|
74
|
+
optionsOrUse?: PathOptions<TName, TSearch> | (() => UseItems<RouteUseItem>),
|
|
75
|
+
use?: () => UseItems<RouteUseItem>,
|
|
76
|
+
// Generic handler bypass: when handler uses index-signature params
|
|
77
|
+
// (e.g. Handler<Record<string, any>>), skip the biconditional.
|
|
78
|
+
// `string extends keyof TParams` is true for index signatures,
|
|
79
|
+
// false for concrete params ({id: string}) and empty ({}).
|
|
80
|
+
//
|
|
81
|
+
// Subset check: pattern params must be assignable to handler params,
|
|
82
|
+
// but handler can have MORE params (e.g. from parent include() prefix).
|
|
83
|
+
// This allows Prerender<"locale.detail"> with {locale, slug} to mount
|
|
84
|
+
// on path("/blog/:slug") where the pattern only declares {slug}.
|
|
85
|
+
) => string extends keyof TParams
|
|
86
|
+
? TypedRouteItem<TName, TPattern, unknown, TSearch>
|
|
87
|
+
: TParams extends ExtractParams<TPattern>
|
|
88
|
+
? TypedRouteItem<TName, TPattern, unknown, TSearch>
|
|
89
|
+
: { __error: `Handler params do not match pattern "${TPattern}"` };
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Path function for response routes that must return Response (image, stream, any).
|
|
93
|
+
* Handler must return Response, not ReactNode. Uses lighter ResponseHandlerContext.
|
|
94
|
+
* Use items restricted to middleware() and cache() only.
|
|
95
|
+
*/
|
|
96
|
+
export type ResponsePathFn<TEnv> = <
|
|
97
|
+
const TPattern extends string,
|
|
98
|
+
const TName extends string = UnnamedRoute,
|
|
99
|
+
const TSearch extends SearchSchema = {},
|
|
100
|
+
>(
|
|
101
|
+
pattern: TPattern,
|
|
102
|
+
handler: ResponseHandler<ExtractParams<TPattern>, TEnv>,
|
|
103
|
+
optionsOrUse?:
|
|
104
|
+
| PathOptions<TName, TSearch>
|
|
105
|
+
| (() => UseItems<ResponseRouteUseItem>),
|
|
106
|
+
use?: () => UseItems<ResponseRouteUseItem>,
|
|
107
|
+
) => TypedRouteItem<TName, TPattern, unknown, TSearch>;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Path function for JSON response routes (path.json()).
|
|
111
|
+
* Handler can return plain JSON-serializable values or Response.
|
|
112
|
+
* TData is inferred from the handler's return type (excluding Response/Promise wrappers).
|
|
113
|
+
*/
|
|
114
|
+
export type JsonResponsePathFn<TEnv> = <
|
|
115
|
+
const TPattern extends string,
|
|
116
|
+
const TName extends string = UnnamedRoute,
|
|
117
|
+
const TSearch extends SearchSchema = {},
|
|
118
|
+
TData = unknown,
|
|
119
|
+
>(
|
|
120
|
+
pattern: TPattern,
|
|
121
|
+
handler: (
|
|
122
|
+
ctx: ResponseHandlerContext<ExtractParams<TPattern>, TEnv>,
|
|
123
|
+
) => TData | Response | Promise<TData | Response>,
|
|
124
|
+
optionsOrUse?:
|
|
125
|
+
| PathOptions<TName, TSearch>
|
|
126
|
+
| (() => UseItems<ResponseRouteUseItem>),
|
|
127
|
+
use?: () => UseItems<ResponseRouteUseItem>,
|
|
128
|
+
) => TypedRouteItem<TName, TPattern, TData, TSearch>;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Path function for text-based response routes (path.text(), path.html(), path.xml()).
|
|
132
|
+
* Handler can return a string or Response. TData is always `string`.
|
|
133
|
+
*/
|
|
134
|
+
export type TextResponsePathFn<TEnv> = <
|
|
135
|
+
const TPattern extends string,
|
|
136
|
+
const TName extends string = UnnamedRoute,
|
|
137
|
+
const TSearch extends SearchSchema = {},
|
|
138
|
+
>(
|
|
139
|
+
pattern: TPattern,
|
|
140
|
+
handler: TextResponseHandler<ExtractParams<TPattern>, TEnv>,
|
|
141
|
+
optionsOrUse?:
|
|
142
|
+
| PathOptions<TName, TSearch>
|
|
143
|
+
| (() => UseItems<ResponseRouteUseItem>),
|
|
144
|
+
use?: () => UseItems<ResponseRouteUseItem>,
|
|
145
|
+
) => TypedRouteItem<TName, TPattern, string, TSearch>;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Base include function signature.
|
|
149
|
+
*/
|
|
150
|
+
export type IncludeFn<TEnv> = <
|
|
151
|
+
TRoutes extends Record<string, any>,
|
|
152
|
+
const TUrlPrefix extends string,
|
|
153
|
+
const TNamePrefix extends string = LocalOnlyInclude,
|
|
154
|
+
TResponses extends Record<string, unknown> = Record<string, unknown>,
|
|
155
|
+
>(
|
|
156
|
+
prefix: TUrlPrefix,
|
|
157
|
+
patterns: UrlPatterns<TEnv, TRoutes, TResponses>,
|
|
158
|
+
options?: IncludeOptions<TNamePrefix>,
|
|
159
|
+
) => TypedIncludeItem<TRoutes, TNamePrefix, TUrlPrefix, TResponses>;
|
|
160
|
+
|
|
161
|
+
export type PathHelpers<TEnv> = {
|
|
162
|
+
/**
|
|
163
|
+
* Define a route with URL pattern at definition site
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```typescript
|
|
167
|
+
* // Pattern and component only
|
|
168
|
+
* path("/about", AboutPage)
|
|
169
|
+
*
|
|
170
|
+
* // With options
|
|
171
|
+
* path("/:slug", PostPage, { name: "post" })
|
|
172
|
+
*
|
|
173
|
+
* // With children (loaders, middleware, etc.)
|
|
174
|
+
* path("/:slug", PostPage, { name: "post" }, () => [
|
|
175
|
+
* loader(PostLoader),
|
|
176
|
+
* ])
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
path: PathFn<TEnv> & {
|
|
180
|
+
json: JsonResponsePathFn<TEnv>;
|
|
181
|
+
text: TextResponsePathFn<TEnv>;
|
|
182
|
+
html: TextResponsePathFn<TEnv>;
|
|
183
|
+
xml: TextResponsePathFn<TEnv>;
|
|
184
|
+
md: TextResponsePathFn<TEnv>;
|
|
185
|
+
image: ResponsePathFn<TEnv>;
|
|
186
|
+
stream: ResponsePathFn<TEnv>;
|
|
187
|
+
any: ResponsePathFn<TEnv>;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Define a layout that wraps child routes
|
|
192
|
+
*/
|
|
193
|
+
layout: {
|
|
194
|
+
(
|
|
195
|
+
component: ReactNode | Handler<any, any, TEnv> | StaticHandlerDefinition,
|
|
196
|
+
): TypedLayoutItem<{}, {}>;
|
|
197
|
+
<
|
|
198
|
+
const TChildren extends readonly (
|
|
199
|
+
| LayoutUseItem
|
|
200
|
+
| readonly LayoutUseItem[]
|
|
201
|
+
)[],
|
|
202
|
+
>(
|
|
203
|
+
component: ReactNode | Handler<any, any, TEnv> | StaticHandlerDefinition,
|
|
204
|
+
use: () => TChildren,
|
|
205
|
+
): TypedLayoutItem<ExtractRoutes<TChildren>, ExtractResponses<TChildren>>;
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Include nested URL patterns under a URL prefix.
|
|
210
|
+
*
|
|
211
|
+
* The `name` option controls how child route names appear in the
|
|
212
|
+
* global route map and generated types:
|
|
213
|
+
*
|
|
214
|
+
* ```typescript
|
|
215
|
+
* // Named — children become "blog.index", "blog.post", etc.
|
|
216
|
+
* // Visible in generated types and globally reversible.
|
|
217
|
+
* include("/blog", blogPatterns, { name: "blog" })
|
|
218
|
+
*
|
|
219
|
+
* // Flattened — children merge into the parent namespace as-is.
|
|
220
|
+
* // Equivalent to defining those routes inline at the include site.
|
|
221
|
+
* include("/blog", blogPatterns, { name: "" })
|
|
222
|
+
*
|
|
223
|
+
* // Local-only (default) — children are scoped privately.
|
|
224
|
+
* // Hidden from generated types and global reverse resolution.
|
|
225
|
+
* // Only dot-local reverse (reverse(".child")) works inside.
|
|
226
|
+
* include("/blog", blogPatterns)
|
|
227
|
+
* ```
|
|
228
|
+
*/
|
|
229
|
+
include: IncludeFn<TEnv>;
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Define parallel routes that render simultaneously in named slots
|
|
233
|
+
*/
|
|
234
|
+
parallel: <
|
|
235
|
+
TSlots extends Record<
|
|
236
|
+
`@${string}`,
|
|
237
|
+
Handler<any, any, TEnv> | ReactNode | StaticHandlerDefinition
|
|
238
|
+
>,
|
|
239
|
+
>(
|
|
240
|
+
slots: TSlots,
|
|
241
|
+
use?: () => ParallelUseItem[],
|
|
242
|
+
) => ParallelItem;
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Define an intercepting route for soft navigation
|
|
246
|
+
* Note: routeName must match a named path() in this urlpatterns
|
|
247
|
+
*/
|
|
248
|
+
intercept: keyof RSCRouter.GeneratedRouteMap extends never
|
|
249
|
+
? (
|
|
250
|
+
slotName: `@${string}`,
|
|
251
|
+
routeName: string,
|
|
252
|
+
handler: ReactNode | Handler<any, any, TEnv>,
|
|
253
|
+
use?: () => InterceptUseItem[],
|
|
254
|
+
) => InterceptItem
|
|
255
|
+
: (
|
|
256
|
+
slotName: `@${string}`,
|
|
257
|
+
routeName: (keyof RSCRouter.GeneratedRouteMap & string) | `.${string}`,
|
|
258
|
+
handler: ReactNode | Handler<any, any, TEnv>,
|
|
259
|
+
use?: () => InterceptUseItem[],
|
|
260
|
+
) => InterceptItem;
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Attach middleware to the current route/layout
|
|
264
|
+
*/
|
|
265
|
+
middleware: (...fns: MiddlewareFn<TEnv>[]) => MiddlewareItem;
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Control when a segment should revalidate during navigation
|
|
269
|
+
*/
|
|
270
|
+
revalidate: (fn: ShouldRevalidateFn<any, TEnv>) => RevalidateItem;
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Attach a data loader to the current route/layout
|
|
274
|
+
*/
|
|
275
|
+
loader: <TData>(
|
|
276
|
+
loaderDef: LoaderDefinition<TData>,
|
|
277
|
+
use?: () => LoaderUseItem[],
|
|
278
|
+
) => LoaderItem;
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Attach a loading component to the current route/layout
|
|
282
|
+
*/
|
|
283
|
+
loading: (component: ReactNode, options?: { ssr?: boolean }) => LoadingItem;
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Attach an error boundary to catch errors in this segment
|
|
287
|
+
*/
|
|
288
|
+
errorBoundary: (
|
|
289
|
+
fallback: ReactNode | ErrorBoundaryHandler,
|
|
290
|
+
) => ErrorBoundaryItem;
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Attach a not-found boundary to handle notFound() calls
|
|
294
|
+
*/
|
|
295
|
+
notFoundBoundary: (
|
|
296
|
+
fallback: ReactNode | NotFoundBoundaryHandler,
|
|
297
|
+
) => NotFoundBoundaryItem;
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Define a condition for when an intercept should activate
|
|
301
|
+
*/
|
|
302
|
+
when: (fn: InterceptWhenFn) => WhenItem;
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Define cache configuration for segments
|
|
306
|
+
*/
|
|
307
|
+
cache: {
|
|
308
|
+
(): TypedCacheItem<{}, {}>;
|
|
309
|
+
<const TChildren extends readonly (AllUseItems | readonly AllUseItems[])[]>(
|
|
310
|
+
children: () => TChildren,
|
|
311
|
+
): TypedCacheItem<ExtractRoutes<TChildren>, ExtractResponses<TChildren>>;
|
|
312
|
+
(options: PartialCacheOptions | false): TypedCacheItem<{}, {}>;
|
|
313
|
+
<const TChildren extends readonly (AllUseItems | readonly AllUseItems[])[]>(
|
|
314
|
+
options: PartialCacheOptions | false,
|
|
315
|
+
use: () => TChildren,
|
|
316
|
+
): TypedCacheItem<ExtractRoutes<TChildren>, ExtractResponses<TChildren>>;
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Attach a ViewTransition boundary to the current segment or a group of routes
|
|
321
|
+
*/
|
|
322
|
+
transition: {
|
|
323
|
+
(): TransitionItem;
|
|
324
|
+
(config: TransitionConfig): TransitionItem;
|
|
325
|
+
<const TChildren extends readonly (AllUseItems | readonly AllUseItems[])[]>(
|
|
326
|
+
children: () => TChildren,
|
|
327
|
+
): TypedTransitionItem<
|
|
328
|
+
ExtractRoutes<TChildren>,
|
|
329
|
+
ExtractResponses<TChildren>
|
|
330
|
+
>;
|
|
331
|
+
<const TChildren extends readonly (AllUseItems | readonly AllUseItems[])[]>(
|
|
332
|
+
config: TransitionConfig,
|
|
333
|
+
children: () => TChildren,
|
|
334
|
+
): TypedTransitionItem<
|
|
335
|
+
ExtractRoutes<TChildren>,
|
|
336
|
+
ExtractResponses<TChildren>
|
|
337
|
+
>;
|
|
338
|
+
};
|
|
339
|
+
};
|