@rangojs/router 0.1.0 → 0.1.1

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 (89) hide show
  1. package/dist/bin/rango.js +11 -1
  2. package/dist/types/browser/dev-discovery.d.ts +11 -0
  3. package/dist/types/browser/navigation-store.d.ts +3 -13
  4. package/dist/types/browser/prefetch/loader.d.ts +10 -0
  5. package/dist/types/browser/prefetch/runtime.d.ts +3 -0
  6. package/dist/types/browser/types.d.ts +4 -16
  7. package/dist/types/build/generate-manifest.d.ts +6 -0
  8. package/dist/types/cache/cache-scope.d.ts +7 -5
  9. package/dist/types/cache/cf/cf-cache-store.d.ts +10 -9
  10. package/dist/types/cache/memory-segment-store.d.ts +6 -6
  11. package/dist/types/cache/shell-snapshot.d.ts +21 -8
  12. package/dist/types/cache/types.d.ts +24 -7
  13. package/dist/types/cache/vercel/vercel-cache-store.d.ts +9 -8
  14. package/dist/types/dev-discovery-protocol.d.ts +5 -0
  15. package/dist/types/prerender/store.d.ts +1 -0
  16. package/dist/types/route-map-builder.d.ts +4 -29
  17. package/dist/types/router/prerender-match.d.ts +4 -1
  18. package/dist/types/router/router-interfaces.d.ts +3 -1
  19. package/dist/types/rsc/handler-context.d.ts +1 -0
  20. package/dist/types/rsc/render-pipeline.d.ts +3 -2
  21. package/dist/types/rsc/rsc-rendering.d.ts +5 -10
  22. package/dist/types/rsc/shell-capture.d.ts +4 -8
  23. package/dist/types/rsc/types.d.ts +2 -0
  24. package/dist/types/server/context.d.ts +16 -0
  25. package/dist/types/server/request-context.d.ts +18 -8
  26. package/dist/types/server.d.ts +1 -1
  27. package/dist/types/types/route-entry.d.ts +3 -0
  28. package/dist/types/vite/discovery/state.d.ts +3 -2
  29. package/dist/types/vite/utils/manifest-utils.d.ts +1 -1
  30. package/dist/vite/index.js +194 -107
  31. package/package.json +7 -2
  32. package/skills/caching/SKILL.md +1 -1
  33. package/skills/ppr/SKILL.md +48 -4
  34. package/src/browser/dev-discovery.ts +66 -0
  35. package/src/browser/navigation-client.ts +6 -0
  36. package/src/browser/navigation-store.ts +4 -271
  37. package/src/browser/partial-update.ts +7 -14
  38. package/src/browser/prefetch/cache.ts +1 -1
  39. package/src/browser/prefetch/loader.ts +110 -0
  40. package/src/browser/prefetch/runtime.ts +7 -0
  41. package/src/browser/react/Link.tsx +7 -10
  42. package/src/browser/react/NavigationProvider.tsx +1 -1
  43. package/src/browser/react/use-router.ts +1 -1
  44. package/src/browser/rsc-router.tsx +4 -2
  45. package/src/browser/types.ts +4 -27
  46. package/src/build/generate-manifest.ts +11 -0
  47. package/src/cache/cache-scope.ts +17 -6
  48. package/src/cache/cf/cf-cache-store.ts +63 -39
  49. package/src/cache/memory-segment-store.ts +17 -6
  50. package/src/cache/shell-snapshot.ts +45 -15
  51. package/src/cache/types.ts +23 -6
  52. package/src/cache/vercel/vercel-cache-store.ts +52 -22
  53. package/src/dev-discovery-protocol.ts +11 -0
  54. package/src/prerender/build-shell-capture.ts +7 -1
  55. package/src/prerender/store.ts +5 -0
  56. package/src/route-definition/dsl-helpers.ts +7 -2
  57. package/src/route-map-builder.ts +56 -49
  58. package/src/router/handler-context.ts +13 -5
  59. package/src/router/lazy-includes.ts +1 -0
  60. package/src/router/match-api.ts +8 -4
  61. package/src/router/prerender-match.ts +19 -2
  62. package/src/router/router-interfaces.ts +4 -0
  63. package/src/router/segment-resolution/static-store.ts +36 -10
  64. package/src/router.ts +34 -3
  65. package/src/rsc/handler-context.ts +1 -0
  66. package/src/rsc/handler.ts +3 -1
  67. package/src/rsc/loader-fetch.ts +2 -2
  68. package/src/rsc/manifest-init.ts +4 -11
  69. package/src/rsc/render-pipeline.ts +10 -2
  70. package/src/rsc/rsc-rendering.ts +207 -146
  71. package/src/rsc/shell-capture.ts +34 -11
  72. package/src/rsc/types.ts +2 -0
  73. package/src/server/context.ts +28 -0
  74. package/src/server/request-context.ts +32 -10
  75. package/src/server.ts +0 -2
  76. package/src/testing/dispatch.ts +1 -0
  77. package/src/types/route-entry.ts +3 -0
  78. package/src/urls/include-helper.ts +1 -0
  79. package/src/urls/path-helper.ts +8 -4
  80. package/src/vite/discovery/bundle-postprocess.ts +10 -7
  81. package/src/vite/discovery/discover-routers.ts +7 -66
  82. package/src/vite/discovery/prerender-collection.ts +13 -2
  83. package/src/vite/discovery/state.ts +4 -4
  84. package/src/vite/discovery/virtual-module-codegen.ts +75 -42
  85. package/src/vite/plugins/version-injector.ts +0 -1
  86. package/src/vite/plugins/virtual-entries.ts +11 -1
  87. package/src/vite/router-discovery.ts +132 -22
  88. package/src/vite/utils/manifest-utils.ts +1 -4
  89. package/src/vite/utils/shared-utils.ts +7 -0
@@ -148,6 +148,8 @@ export interface ShellCaptureDebugEvent {
148
148
  snapshotBytes?: number;
149
149
  /** True when the snapshot exceeded maxSnapshotBytes and was dropped. */
150
150
  snapshotSkipped?: boolean;
151
+ /** Outcome reported by a store that supports shell-write acknowledgements. */
152
+ storeWrite?: "stored" | "invalidated";
151
153
  /** Consecutive failure count in the key's backoff entry, when one exists. */
152
154
  backoffFailures?: number;
153
155
  /** Ms remaining in the key's backoff window, when one exists. */
@@ -308,13 +310,7 @@ type CaptureAttemptOutcome = "stored" | "redirect" | "no-shell" | "refused";
308
310
  * bag, not a return value: captureAndStoreShell's outcome type stays a string
309
311
  * union its existing callers (producer B, tests) consume unchanged.
310
312
  */
311
- interface CaptureAttemptStats {
312
- barrierWaitMs?: number;
313
- writeSettleMs?: number;
314
- preludeBytes?: number;
315
- snapshotBytes?: number;
316
- snapshotSkipped?: boolean;
317
- }
313
+ type CaptureAttemptStats = Pick<ShellCaptureDebugEvent, "barrierWaitMs" | "writeSettleMs" | "preludeBytes" | "snapshotBytes" | "snapshotSkipped" | "storeWrite">;
318
314
  /**
319
315
  * Run the shell capture with a single in-place retry, then store the result.
320
316
  *
@@ -369,6 +365,6 @@ export declare function deriveShellCaptureContext(reqCtx: RequestContext<any>, d
369
365
  * retryable outcome; a genuine (non-abort) captureShellHTML error propagates so it
370
366
  * reaches reportCacheError and is NOT retried.
371
367
  */
372
- declare function captureAndStoreShell(ssrModule: SSRModule, rscStream: ReadableStream<Uint8Array>, handleStore: HandleStore, reqCtx: RequestContext<any>, capture: ShellCaptureDescriptor, stats?: CaptureAttemptStats): Promise<Exclude<CaptureAttemptOutcome, "redirect">>;
368
+ declare function captureAndStoreShell(ssrModule: SSRModule, rscStream: ReadableStream<Uint8Array>, handleStore: HandleStore, reqCtx: RequestContext<any>, capture: ShellCaptureDescriptor, stats?: CaptureAttemptStats, captureStartedAt?: number): Promise<Exclude<CaptureAttemptOutcome, "redirect">>;
373
369
  export { runShellCapture, captureAndStoreShell, delay, SHELL_CAPTURE_RETRY_DELAY_MS, };
374
370
  export { isCaptureBackedOff, markCaptureBackoff, clearCaptureBackoff, REFUSED_CAPTURE_BASE_MS, REFUSED_CAPTURE_MAX_MS, REFUSED_CAPTURE_DEV_MAX_MS, };
@@ -41,6 +41,8 @@ export interface RscPayload {
41
41
  handles?: AsyncGenerator<HandleData, void, unknown>;
42
42
  /** RSC version string for cache invalidation */
43
43
  version?: string;
44
+ /** Cloudflare dev worker generation used for stale-document convergence. */
45
+ devDiscoveryEpoch?: number;
44
46
  /** TTL in milliseconds for the client-side in-memory prefetch cache */
45
47
  prefetchCacheTTL?: number;
46
48
  /** Max entries in the client-side in-memory prefetch cache (FIFO eviction) */
@@ -248,6 +248,10 @@ interface HelperContext {
248
248
  counters: Record<string, number>;
249
249
  forRoute?: string;
250
250
  mountIndex?: number;
251
+ /** Owning router id, when known (threaded by generateManifestFull). Scopes
252
+ * the search-schema/root-scope registries so same-named routes in
253
+ * different routers don't clobber each other (route-map-builder.ts). */
254
+ routerId?: string;
251
255
  metrics?: MetricsStore;
252
256
  /** True when rendering for SSR (document requests) */
253
257
  isSSR?: boolean;
@@ -337,6 +341,18 @@ export declare function getNamePrefix(): string | undefined;
337
341
  * Returns true at root or inside { name: "" } includes, false inside named includes.
338
342
  */
339
343
  export declare function getRootScoped(): boolean;
344
+ /**
345
+ * Stamp build-time scope identity onto a Static() definition at mount time.
346
+ * The bake collector (prerender-collection.ts) renders defs OUTSIDE any
347
+ * evaluation scope and used to iterate the registry first-non-null, so these
348
+ * are the ONLY reliable carriers of the def's owning router, root-scope, and
349
+ * full route name — a name-keyed registry lookup at bake time reproduces the
350
+ * cross-router collision #757/#762 fixed (and the collector's historical
351
+ * `$$routePrefix` argument is a name PREFIX, which the root-scope registry
352
+ * never contains, silently degrading to the dot-heuristic).
353
+ * A definition mounted more than once is stamped each time; the last mount wins.
354
+ */
355
+ export declare function stampStaticDefScope(handler: unknown, routeName?: string): void;
340
356
  export type { HelperContext };
341
357
  /**
342
358
  * Return an isolated copy of a lazy include's captured parent entry.
@@ -180,21 +180,28 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
180
180
  */
181
181
  _shellLoaderSeed?: Map<string, import("../cache/shell-snapshot.js").ShellLoaderSeedEntry>;
182
182
  /**
183
- * @internal Shell fast-path marker: makes the NEXT full match treat the whole
184
- * matched route as an implicit doc-level cache() boundary (see
183
+ * @internal Shell fast-path marker: makes the next eligible match treat the
184
+ * whole matched route as an implicit doc-level cache() boundary (see
185
185
  * resolveShellImplicitCacheScope in cache/cache-scope.ts). Set ONLY on
186
186
  * (a) the capture's derived context — with a record-only store so the
187
187
  * capture's cacheRoute write lands in the snapshot, never the real store —
188
- * and (b) a HIT tail's seeded context when the entry is eligible
189
- * (!handlerLiveHoles), where the SeededShellStore serves the recorded doc
190
- * entry and the match skips handler execution entirely. Routes with their
191
- * own cache() config (including cache(false)) are never overridden: the
192
- * marker only applies when the route tree derived NO cache scope.
188
+ * (b) a HIT tail's seeded context, and (c) an eligible normal-route partial
189
+ * replay, where `store` is a request-local segment overlay. Handler-live holes
190
+ * and conditional transitions decline replay.
191
+ * Routes with their own cache() config (including cache(false)) are never
192
+ * overridden: the marker only applies when the route tree derived NO cache
193
+ * scope.
193
194
  */
194
195
  _shellImplicitCache?: {
195
196
  ttl?: number;
196
197
  swr?: number;
197
198
  store?: SegmentCacheStore;
199
+ /**
200
+ * @internal Override the implicit scope's default cache namespace. Shell
201
+ * captures and navigation replay both consume the canonical document
202
+ * segment record even when the triggering request is partial.
203
+ */
204
+ keyPrefix?: "doc";
198
205
  };
199
206
  /**
200
207
  * @internal Shell-HIT tail marker: cache/prerender-store hits during THIS
@@ -484,6 +491,9 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
484
491
  _tracing?: ResolvedTracing;
485
492
  /** @internal Router basename for this request (used by redirect()) */
486
493
  _basename?: string;
494
+ /** @internal Owning router id; scopes the search-schema/root-scope registry
495
+ * lookups per router (route-map-builder.ts) */
496
+ _routerId?: string;
487
497
  /**
488
498
  * @internal RouteSnapshot from classifyRequest, reused by match/matchPartial
489
499
  * to avoid a second resolveRoute call. Cleared on HMR invalidation.
@@ -504,7 +514,7 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
504
514
  * This is the type exported to library consumers. Internal code should
505
515
  * use the full RequestContext interface directly.
506
516
  */
507
- export type PublicRequestContext<TEnv = DefaultEnv, TParams = Record<string, string>> = Omit<RequestContext<TEnv, TParams>, "cookie" | "cookies" | "setCookie" | "deleteCookie" | "_handleStore" | "_transitionWhen" | "_cacheStore" | "_shellCaptureRun" | "_shellFragmentPayload" | "_shellCaptureGuardTrippedLoaderId" | "_explicitTaggedStores" | "_requestTags" | "_cacheProfiles" | "_onResponseCallbacks" | "_themeConfig" | "_locationState" | "_routeName" | "_prevRouteKey" | "_gateCurrentUrl" | "_gateCurrentParams" | "_gateActionId" | "_gateActionUrl" | "_gateActionResult" | "_gateFormData" | "_inActionRevalidation" | "_reportedErrors" | "_renderBarrier" | "_resolveRenderBarrier" | "_renderBarrierSegmentOrder" | "_treeHasStreaming" | "_renderBarrierWaiters" | "_handlerLoaderDeps" | "_renderBarrierHandleSnapshot" | "_renderBarrierGuardClosed" | "_reportBackgroundError" | "_debugPerformance" | "_metricsStore" | "_renderForeground" | "_renderDiagnosticsEnabled" | "_handlerStart" | "_basename" | "_setStatus" | "_rotateStateCookie" | "_setKeepCacheDirective" | "_variables" | "_classifiedRoute" | "_cacheSignal" | "_dynamic" | "res">;
517
+ export type PublicRequestContext<TEnv = DefaultEnv, TParams = Record<string, string>> = Omit<RequestContext<TEnv, TParams>, "cookie" | "cookies" | "setCookie" | "deleteCookie" | "_handleStore" | "_transitionWhen" | "_cacheStore" | "_shellCaptureRun" | "_shellImplicitCache" | "_shellLoaderSeed" | "_shellCaptureLoaderRecords" | "_shellCaptureHandleLiveness" | "_shellCaptureLoaderHandleValues" | "_shellFragmentPayload" | "_shellCaptureGuardTripped" | "_shellCaptureGuardTrippedLoaderId" | "_explicitTaggedStores" | "_requestTags" | "_cacheProfiles" | "_onResponseCallbacks" | "_pendingBackgroundTasks" | "_themeConfig" | "_locationState" | "_routeName" | "_prevRouteKey" | "_gateCurrentUrl" | "_gateCurrentParams" | "_gateActionId" | "_gateActionUrl" | "_gateActionResult" | "_gateFormData" | "_inActionRevalidation" | "_reportedErrors" | "_renderBarrier" | "_resolveRenderBarrier" | "_renderBarrierSegmentOrder" | "_treeHasStreaming" | "_renderBarrierWaiters" | "_handlerLoaderDeps" | "_renderBarrierHandleSnapshot" | "_renderBarrierGuardClosed" | "_reportBackgroundError" | "_debugPerformance" | "_metricsStore" | "_renderForeground" | "_renderDiagnosticsEnabled" | "_handlerStart" | "_tracing" | "_basename" | "_routerId" | "_setStatus" | "_rotateStateCookie" | "_setKeepCacheDirective" | "_variables" | "_classifiedRoute" | "_cacheSignal" | "_dynamic" | "res">;
508
518
  /**
509
519
  * Marker for a waitUntil-scheduled fn whose task promise must NOT enter
510
520
  * _pendingBackgroundTasks. Used by the PPR shell capture for its own task:
@@ -9,7 +9,7 @@
9
9
  */
10
10
  export { RSC_ROUTER_BRAND, RouterRegistry } from "./router.js";
11
11
  export { HostRouterRegistry, type HostRouterRegistryEntry, } from "./host/router.js";
12
- export { registerRouteMap, setCachedManifest, clearCachedManifest, clearAllRouterData, getGlobalRouteMap, getRouterManifest, setPrecomputedEntries, setRouteTrie, setManifestReadyPromise, setRouterManifest, setRouterTrie, setRouterPrecomputedEntries, registerRouterManifestLoader, ensureRouterManifest, } from "./route-map-builder.js";
12
+ export { registerRouteMap, setCachedManifest, clearCachedManifest, clearAllRouterData, getGlobalRouteMap, getRouterManifest, setManifestReadyPromise, setRouterManifest, setRouterTrie, setRouterPrecomputedEntries, registerRouterManifestLoader, ensureRouterManifest, } from "./route-map-builder.js";
13
13
  export { registerLoaderById, setLoaderImports, } from "./server/loader-registry.js";
14
14
  export { createRequestContext, type CreateRequestContextOptions, } from "./server/request-context.js";
15
15
  export { isClientComponent, assertClientComponent } from "./component-utils.js";
@@ -9,6 +9,9 @@ export interface LazyIncludeContext {
9
9
  cacheProfiles?: Record<string, import("../cache/profile-registry.js").CacheProfile>;
10
10
  /** Root scope flag for dot-local reverse resolution */
11
11
  rootScoped?: boolean;
12
+ /** Owning router id; scopes search-schema/root-scope registration during
13
+ * lazy include evaluation (route-map-builder.ts registries) */
14
+ routerId?: string;
12
15
  /**
13
16
  * Positional include scope token composed from the parent scope plus this
14
17
  * include's sibling index (`${parentScope}I${idx}`). Applied to direct-
@@ -60,6 +60,7 @@ export interface ChunkInfo {
60
60
  export interface PerRouterManifestEntry {
61
61
  id: string;
62
62
  routeManifest: Record<string, string>;
63
+ routeTrailingSlash?: Record<string, string>;
63
64
  routeSearchSchemas?: Record<string, Record<string, string>>;
64
65
  sourceFile?: string;
65
66
  factoryOnlyPrefixes?: Set<string>;
@@ -103,8 +104,6 @@ export interface DiscoveryState {
103
104
  opts: PluginOptions | undefined;
104
105
  mergedRouteManifest: Record<string, string> | null;
105
106
  perRouterManifests: PerRouterManifestEntry[];
106
- mergedPrecomputedEntries: PrecomputedEntry[] | null;
107
- mergedRouteTrie: any;
108
107
  perRouterTrieMap: Map<string, any>;
109
108
  perRouterPrecomputedMap: Map<string, PrecomputedEntry[]>;
110
109
  perRouterManifestDataMap: Map<string, Record<string, string>>;
@@ -137,6 +136,8 @@ export interface DiscoveryState {
137
136
  resolvedPrerenderModules: Map<string, string[]> | undefined;
138
137
  resolvedStaticModules: Map<string, string[]> | undefined;
139
138
  discoveryDone: Promise<void> | null;
139
+ /** Monotonic Cloudflare-dev generation installed by the routes manifest. */
140
+ devDiscoveryEpoch?: number;
140
141
  devServerOrigin: string | null;
141
142
  devServer: any;
142
143
  selfWrittenGenFiles: Map<string, {
@@ -1,4 +1,4 @@
1
- export { flattenLeafEntries, buildRouteToStaticPrefix, } from "../../build/prefix-tree-utils.js";
1
+ export { flattenLeafEntries } from "../../build/prefix-tree-utils.js";
2
2
  /**
3
3
  * Wrap a value as `JSON.parse('...')` instead of a JS object literal.
4
4
  * V8's JSON parser is significantly faster than its full JS parser for large