@rangojs/router 0.0.0-experimental.20 → 0.0.0-experimental.22

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/README.md CHANGED
@@ -45,6 +45,30 @@ For Cloudflare Workers:
45
45
  npm install @cloudflare/vite-plugin
46
46
  ```
47
47
 
48
+ ## Import Paths
49
+
50
+ Use these import paths consistently:
51
+
52
+ - `@rangojs/router` — server/RSC router APIs, route DSL, `createRouter`, `urls`, `redirect`, `Prerender`, `Static`, shared types
53
+ - `@rangojs/router/client` — hooks and components such as `Link`, `Outlet`, `href`, `useNavigation`, `useLoader`, `useAction`, `useLocationState`
54
+ - `@rangojs/router/cache` — public cache APIs such as `CFCacheStore`, `MemorySegmentCacheStore`, `createDocumentCacheMiddleware`
55
+ - `@rangojs/router/host`, `@rangojs/router/theme`, `@rangojs/router/vite` — specialized public subpaths
56
+ - `@rangojs/router/rsc`, `@rangojs/router/ssr` — advanced server-only integration subpaths for custom request/HTML pipelines
57
+
58
+ Use only subpaths that are explicitly exported from the package. Avoid deep imports such as `@rangojs/router/cache/cf`.
59
+
60
+ `@rangojs/router` is conditionally resolved. Server-only root APIs such as
61
+ `createRouter()`, `urls()`, `redirect()`, `Prerender()`, and `cookies()` rely on
62
+ the `react-server` export condition and are meant to run in router definitions,
63
+ handlers, and other RSC/server modules. Outside that environment the root entry
64
+ falls back to stub implementations that throw guidance errors.
65
+
66
+ If you hit a root-entrypoint stub error:
67
+
68
+ - hooks and components like `Link`, `Outlet`, `useLoader`, `useNavigation`, and `MetaTags` belong in `@rangojs/router/client`
69
+ - cache APIs like `CFCacheStore` and `createDocumentCacheMiddleware` belong in `@rangojs/router/cache`
70
+ - host-router APIs belong in `@rangojs/router/host`
71
+
48
72
  ## Quick Start
49
73
 
50
74
  ### Vite Config
@@ -62,6 +86,9 @@ export default defineConfig({
62
86
 
63
87
  ### Router
64
88
 
89
+ This file is a server/RSC module and should import router construction APIs from
90
+ `@rangojs/router`.
91
+
65
92
  ```tsx
66
93
  // src/router.tsx
67
94
  import { createRouter, urls } from "@rangojs/router";
@@ -842,16 +869,22 @@ module, use `scopedReverse<typeof localPatterns>(ctx.reverse)` or
842
869
 
843
870
  ## Subpath Exports
844
871
 
845
- | Export | Description |
846
- | ------------------------ | --------------------------------------------------------------------------------- |
847
- | `@rangojs/router` | Core: `createRouter`, `urls`, `createLoader`, `Handler`, `Prerender`, `Meta` |
848
- | `@rangojs/router/client` | Client: `Link`, `Outlet`, `href`, `useNavigation`, `useLoader`, `MetaTags` |
849
- | `@rangojs/router/cache` | Cache: `CFCacheStore`, `MemorySegmentCacheStore`, `createDocumentCacheMiddleware` |
850
- | `@rangojs/router/theme` | Theme: `useTheme`, `ThemeProvider`, `ThemeScript` |
851
- | `@rangojs/router/host` | Host routing: `createHostRouter`, `defineHosts` |
852
- | `@rangojs/router/vite` | Vite plugin: `rango()` |
853
- | `@rangojs/router/server` | Server utilities |
854
- | `@rangojs/router/build` | Build utilities |
872
+ | Export | Description |
873
+ | ------------------------ | -------------------------------------------------------------------------------------------------------- |
874
+ | `@rangojs/router` | Server/RSC core and shared types: `createRouter`, `urls`, `createLoader`, `Handler`, `Prerender`, `Meta` |
875
+ | `@rangojs/router/client` | Client: `Link`, `Outlet`, `href`, `useNavigation`, `useLoader`, `MetaTags` |
876
+ | `@rangojs/router/cache` | Cache: `CFCacheStore`, `MemorySegmentCacheStore`, `createDocumentCacheMiddleware` |
877
+ | `@rangojs/router/theme` | Theme: `useTheme`, `ThemeProvider`, `ThemeScript` |
878
+ | `@rangojs/router/host` | Host routing: `createHostRouter`, `defineHosts` |
879
+ | `@rangojs/router/vite` | Vite plugin: `rango()` |
880
+ | `@rangojs/router/rsc` | Advanced server pipeline APIs: `createRSCHandler`, request-context access |
881
+ | `@rangojs/router/ssr` | Advanced SSR bridge APIs: `createSSRHandler` |
882
+ | `@rangojs/router/server` | Internal build/runtime utilities for advanced integrations |
883
+ | `@rangojs/router/build` | Build utilities |
884
+
885
+ The root entrypoint is not a generic client/runtime barrel. If you need hooks
886
+ or components, import from `@rangojs/router/client`; if you need cache or host
887
+ APIs, use their dedicated subpaths.
855
888
 
856
889
  ## Examples
857
890
 
@@ -1,6 +1,6 @@
1
1
  // src/vite/rango.ts
2
2
  import { readFileSync as readFileSync7 } from "node:fs";
3
- import { resolve as resolve8 } from "node:path";
3
+ import { resolve as resolve9 } from "node:path";
4
4
 
5
5
  // src/vite/plugins/expose-action-id.ts
6
6
  import MagicString from "magic-string";
@@ -1745,7 +1745,7 @@ import { resolve } from "node:path";
1745
1745
  // package.json
1746
1746
  var package_default = {
1747
1747
  name: "@rangojs/router",
1748
- version: "0.0.0-experimental.20",
1748
+ version: "0.0.0-experimental.22",
1749
1749
  description: "Django-inspired RSC router with composable URL patterns",
1750
1750
  keywords: [
1751
1751
  "react",
@@ -3024,7 +3024,7 @@ function createCjsToEsmPlugin() {
3024
3024
 
3025
3025
  // src/vite/router-discovery.ts
3026
3026
  import { createServer as createViteServer } from "vite";
3027
- import { resolve as resolve7 } from "node:path";
3027
+ import { resolve as resolve8 } from "node:path";
3028
3028
  import { readFileSync as readFileSync6 } from "node:fs";
3029
3029
 
3030
3030
  // src/vite/plugins/virtual-stub-plugin.ts
@@ -3207,8 +3207,8 @@ function createDiscoveryState(entryPath, opts) {
3207
3207
  perRouterTrieMap: /* @__PURE__ */ new Map(),
3208
3208
  perRouterPrecomputedMap: /* @__PURE__ */ new Map(),
3209
3209
  perRouterManifestDataMap: /* @__PURE__ */ new Map(),
3210
- prerenderCollectedData: null,
3211
- staticCollectedData: null,
3210
+ prerenderManifestEntries: null,
3211
+ staticManifestEntries: null,
3212
3212
  handlerChunkInfo: null,
3213
3213
  staticHandlerChunkInfo: null,
3214
3214
  rscEntryFileName: null,
@@ -3308,6 +3308,16 @@ function contextSet(variables, keyOrVar, value) {
3308
3308
  }
3309
3309
 
3310
3310
  // src/vite/utils/prerender-utils.ts
3311
+ import { createHash as createHash4 } from "node:crypto";
3312
+ import {
3313
+ copyFileSync,
3314
+ existsSync as existsSync4,
3315
+ mkdirSync,
3316
+ rmSync,
3317
+ statSync,
3318
+ writeFileSync as writeFileSync2
3319
+ } from "node:fs";
3320
+ import { resolve as resolve5 } from "node:path";
3311
3321
  function escapeRegExp2(str) {
3312
3322
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3313
3323
  }
@@ -3386,6 +3396,37 @@ function notifyOnError(registry, error, phase, routeKey, pathname, skipped) {
3386
3396
  break;
3387
3397
  }
3388
3398
  }
3399
+ function getStagedAssetDir(projectRoot) {
3400
+ return resolve5(projectRoot, "node_modules/.rangojs-router-build/rsc-assets");
3401
+ }
3402
+ function resetStagedBuildAssets(projectRoot) {
3403
+ rmSync(getStagedAssetDir(projectRoot), { recursive: true, force: true });
3404
+ }
3405
+ function stageBuildAssetModule(projectRoot, prefix, exportValue) {
3406
+ const stagedDir = getStagedAssetDir(projectRoot);
3407
+ mkdirSync(stagedDir, { recursive: true });
3408
+ const contentHash = createHash4("sha256").update(exportValue).digest("hex").slice(0, 8);
3409
+ const fileName = `${prefix}-${contentHash}.js`;
3410
+ const filePath = resolve5(stagedDir, fileName);
3411
+ if (!existsSync4(filePath)) {
3412
+ writeFileSync2(filePath, `export default ${exportValue};
3413
+ `);
3414
+ }
3415
+ return fileName;
3416
+ }
3417
+ function copyStagedBuildAssets(projectRoot, fileNames) {
3418
+ const stagedDir = getStagedAssetDir(projectRoot);
3419
+ const distAssetsDir = resolve5(projectRoot, "dist/rsc/assets");
3420
+ mkdirSync(distAssetsDir, { recursive: true });
3421
+ let totalBytes = 0;
3422
+ for (const fileName of new Set(fileNames)) {
3423
+ const stagedPath = resolve5(stagedDir, fileName);
3424
+ const distPath = resolve5(distAssetsDir, fileName);
3425
+ copyFileSync(stagedPath, distPath);
3426
+ totalBytes += statSync(stagedPath).size;
3427
+ }
3428
+ return totalBytes;
3429
+ }
3389
3430
 
3390
3431
  // src/vite/discovery/prerender-collection.ts
3391
3432
  async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
@@ -3487,7 +3528,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
3487
3528
  `[rsc-router] Pre-rendering ${entries.length} URL(s)${concurrencyNote}...`
3488
3529
  );
3489
3530
  const { hashParams } = await rscEnv.runner.import("@rangojs/router/build");
3490
- const collectedData = {};
3531
+ const manifestEntries = {};
3491
3532
  let doneCount = 0;
3492
3533
  let skipCount = 0;
3493
3534
  const startTotal = performance.now();
@@ -3517,18 +3558,30 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
3517
3558
  break;
3518
3559
  }
3519
3560
  const paramHash = hashParams(result.params || {});
3520
- collectedData[`${result.routeName}/${paramHash}`] = {
3561
+ const mainKey = `${result.routeName}/${paramHash}`;
3562
+ const mainValue = JSON.stringify({
3521
3563
  segments: result.segments,
3522
3564
  handles: result.handles
3523
- };
3565
+ });
3566
+ manifestEntries[mainKey] = stageBuildAssetModule(
3567
+ state.projectRoot,
3568
+ "__pr",
3569
+ mainValue
3570
+ );
3524
3571
  if (result.interceptSegments?.length) {
3525
- collectedData[`${result.routeName}/${paramHash}/i`] = {
3572
+ const interceptKey = `${result.routeName}/${paramHash}/i`;
3573
+ const interceptValue = JSON.stringify({
3526
3574
  segments: [...result.segments, ...result.interceptSegments],
3527
3575
  handles: {
3528
3576
  ...result.handles,
3529
3577
  ...result.interceptHandles || {}
3530
3578
  }
3531
- };
3579
+ });
3580
+ manifestEntries[interceptKey] = stageBuildAssetModule(
3581
+ state.projectRoot,
3582
+ "__pr",
3583
+ interceptValue
3584
+ );
3532
3585
  }
3533
3586
  const elapsed = (performance.now() - startUrl).toFixed(0);
3534
3587
  console.log(
@@ -3572,7 +3625,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
3572
3625
  }
3573
3626
  const totalElapsed = (performance.now() - startTotal).toFixed(0);
3574
3627
  if (doneCount > 0) {
3575
- state.prerenderCollectedData = collectedData;
3628
+ state.prerenderManifestEntries = manifestEntries;
3576
3629
  }
3577
3630
  const parts = [`${doneCount} done`];
3578
3631
  if (skipCount > 0) parts.push(`${skipCount} skipped`);
@@ -3583,7 +3636,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
3583
3636
  async function renderStaticHandlers(state, rscEnv, registry) {
3584
3637
  if (!state.opts?.enableBuildPrerender || !state.isBuildMode || !state.resolvedStaticModules?.size)
3585
3638
  return;
3586
- const collected = {};
3639
+ const manifestEntries = {};
3587
3640
  let staticDone = 0;
3588
3641
  let staticSkip = 0;
3589
3642
  let totalStaticCount = 0;
@@ -3620,7 +3673,13 @@ async function renderStaticHandlers(state, rscEnv, registry) {
3620
3673
  def.$$routePrefix
3621
3674
  );
3622
3675
  if (result) {
3623
- collected[def.$$id] = result;
3676
+ const hasHandles = Object.keys(result.handles).length > 0;
3677
+ const exportValue = hasHandles ? JSON.stringify(result) : JSON.stringify(result.encoded);
3678
+ manifestEntries[def.$$id] = stageBuildAssetModule(
3679
+ state.projectRoot,
3680
+ "__st",
3681
+ exportValue
3682
+ );
3624
3683
  const elapsed = (performance.now() - startHandler).toFixed(0);
3625
3684
  console.log(
3626
3685
  `[rsc-router] OK ${name.padEnd(40)} (${elapsed}ms)`
@@ -3657,7 +3716,7 @@ async function renderStaticHandlers(state, rscEnv, registry) {
3657
3716
  }
3658
3717
  const totalStaticElapsed = (performance.now() - startStatic).toFixed(0);
3659
3718
  if (staticDone > 0) {
3660
- state.staticCollectedData = collected;
3719
+ state.staticManifestEntries = manifestEntries;
3661
3720
  }
3662
3721
  const staticParts = [`${staticDone} done`];
3663
3722
  if (staticSkip > 0) staticParts.push(`${staticSkip} skipped`);
@@ -3674,8 +3733,7 @@ async function discoverRouters(state, rscEnv) {
3674
3733
  let registry = serverMod.RouterRegistry;
3675
3734
  if (!registry || registry.size === 0) {
3676
3735
  try {
3677
- const hostMod = await rscEnv.runner.import("@rangojs/router/host");
3678
- const hostRegistry = hostMod.HostRouterRegistry;
3736
+ const hostRegistry = serverMod.HostRouterRegistry;
3679
3737
  if (hostRegistry && hostRegistry.size > 0) {
3680
3738
  console.log(
3681
3739
  `[rsc-router] Found ${hostRegistry.size} host router(s), resolving lazy handlers...`
@@ -3879,8 +3937,8 @@ async function discoverRouters(state, rscEnv) {
3879
3937
  }
3880
3938
 
3881
3939
  // src/vite/discovery/route-types-writer.ts
3882
- import { dirname as dirname3, basename, join as join3, resolve as resolve5 } from "node:path";
3883
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, existsSync as existsSync4, unlinkSync as unlinkSync2 } from "node:fs";
3940
+ import { dirname as dirname3, basename, join as join3, resolve as resolve6 } from "node:path";
3941
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync5, unlinkSync as unlinkSync2 } from "node:fs";
3884
3942
  function filterUserNamedRoutes(manifest) {
3885
3943
  const filtered = {};
3886
3944
  for (const [name, pattern] of Object.entries(manifest)) {
@@ -3914,7 +3972,7 @@ function writeCombinedRouteTypesWithTracking(state, opts) {
3914
3972
  ""
3915
3973
  );
3916
3974
  const outPath = join3(routerDir, `${routerBasename}.named-routes.gen.ts`);
3917
- if (!existsSync4(outPath)) continue;
3975
+ if (!existsSync5(outPath)) continue;
3918
3976
  try {
3919
3977
  const content = readFileSync4(outPath, "utf-8");
3920
3978
  if (content !== preContent.get(outPath)) {
@@ -3928,10 +3986,10 @@ function writeRouteTypesFiles(state) {
3928
3986
  if (state.perRouterManifests.length === 0) return;
3929
3987
  try {
3930
3988
  const entryDir = dirname3(
3931
- resolve5(state.projectRoot, state.resolvedEntryPath)
3989
+ resolve6(state.projectRoot, state.resolvedEntryPath)
3932
3990
  );
3933
3991
  const oldCombinedPath = join3(entryDir, "named-routes.gen.ts");
3934
- if (existsSync4(oldCombinedPath)) {
3992
+ if (existsSync5(oldCombinedPath)) {
3935
3993
  unlinkSync2(oldCombinedPath);
3936
3994
  console.log(
3937
3995
  `[rsc-router] Removed stale combined route types: ${oldCombinedPath}`
@@ -3975,10 +4033,10 @@ Set an explicit \`id\` on createRouter() or check the call site.`
3975
4033
  userRoutes,
3976
4034
  effectiveSearchSchemas && Object.keys(effectiveSearchSchemas).length > 0 ? effectiveSearchSchemas : void 0
3977
4035
  );
3978
- const existing = existsSync4(outPath) ? readFileSync4(outPath, "utf-8") : null;
4036
+ const existing = existsSync5(outPath) ? readFileSync4(outPath, "utf-8") : null;
3979
4037
  if (existing !== source) {
3980
4038
  markSelfGenWrite(state, outPath, source);
3981
- writeFileSync2(outPath, source);
4039
+ writeFileSync3(outPath, source);
3982
4040
  console.log(`[rsc-router] Generated route types -> ${outPath}`);
3983
4041
  }
3984
4042
  }
@@ -4025,10 +4083,10 @@ function supplementGenFilesWithRuntimeRoutes(state) {
4025
4083
  mergedRoutes,
4026
4084
  Object.keys(mergedSearchSchemas).length > 0 ? mergedSearchSchemas : void 0
4027
4085
  );
4028
- const existing = existsSync4(outPath) ? readFileSync4(outPath, "utf-8") : null;
4086
+ const existing = existsSync5(outPath) ? readFileSync4(outPath, "utf-8") : null;
4029
4087
  if (existing !== source) {
4030
4088
  markSelfGenWrite(state, outPath, source);
4031
- writeFileSync2(outPath, source);
4089
+ writeFileSync3(outPath, source);
4032
4090
  }
4033
4091
  }
4034
4092
  }
@@ -4173,14 +4231,13 @@ function generatePerRouterModule(state, routerId) {
4173
4231
  }
4174
4232
 
4175
4233
  // src/vite/discovery/bundle-postprocess.ts
4176
- import { resolve as resolve6 } from "node:path";
4177
- import { createHash as createHash4 } from "node:crypto";
4178
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync5, mkdirSync } from "node:fs";
4234
+ import { resolve as resolve7 } from "node:path";
4235
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync6 } from "node:fs";
4179
4236
  function postprocessBundle(state) {
4180
- const hasPrerenderData = state.prerenderCollectedData && Object.keys(state.prerenderCollectedData).length > 0;
4181
- const hasStaticData = state.staticCollectedData && Object.keys(state.staticCollectedData).length > 0;
4237
+ const hasPrerenderData = state.prerenderManifestEntries && Object.keys(state.prerenderManifestEntries).length > 0;
4238
+ const hasStaticData = state.staticManifestEntries && Object.keys(state.staticManifestEntries).length > 0;
4182
4239
  if (!hasPrerenderData && !hasStaticData) return;
4183
- const rscEntryPath = resolve6(
4240
+ const rscEntryPath = resolve7(
4184
4241
  state.projectRoot,
4185
4242
  "dist/rsc",
4186
4243
  state.rscEntryFileName ?? "index.js"
@@ -4201,7 +4258,7 @@ function postprocessBundle(state) {
4201
4258
  ];
4202
4259
  for (const target of evictionTargets) {
4203
4260
  if (!target.info) continue;
4204
- const chunkPath = resolve6(
4261
+ const chunkPath = resolve7(
4205
4262
  state.projectRoot,
4206
4263
  "dist/rsc",
4207
4264
  target.info.fileName
@@ -4215,7 +4272,7 @@ function postprocessBundle(state) {
4215
4272
  target.brand
4216
4273
  );
4217
4274
  if (result) {
4218
- writeFileSync3(chunkPath, result.code);
4275
+ writeFileSync4(chunkPath, result.code);
4219
4276
  const savedKB = (result.savedBytes / 1024).toFixed(1);
4220
4277
  console.log(
4221
4278
  `[rsc-router] Evicted ${target.label} (${savedKB} KB saved): ${target.info.fileName}`
@@ -4229,44 +4286,38 @@ function postprocessBundle(state) {
4229
4286
  }
4230
4287
  state.handlerChunkInfo = null;
4231
4288
  state.staticHandlerChunkInfo = null;
4232
- if (hasPrerenderData && existsSync5(rscEntryPath)) {
4289
+ if (hasPrerenderData && existsSync6(rscEntryPath)) {
4233
4290
  const rscCode = readFileSync5(rscEntryPath, "utf-8");
4234
4291
  if (!rscCode.includes("__prerender-manifest.js")) {
4235
4292
  try {
4236
- const assetsDir = resolve6(state.projectRoot, "dist/rsc/assets");
4237
- mkdirSync(assetsDir, { recursive: true });
4238
- const manifestEntries = [];
4239
- let totalBytes = 0;
4240
- for (const [key, entry] of Object.entries(
4241
- state.prerenderCollectedData
4293
+ let totalBytes = copyStagedBuildAssets(
4294
+ state.projectRoot,
4295
+ Object.values(state.prerenderManifestEntries)
4296
+ );
4297
+ const manifestMap = {};
4298
+ for (const [key, assetFileName] of Object.entries(
4299
+ state.prerenderManifestEntries
4242
4300
  )) {
4243
- const entryJson = JSON.stringify(entry);
4244
- const contentHash = createHash4("sha256").update(entryJson).digest("hex").slice(0, 8);
4245
- const assetFileName = `__pr-${contentHash}.js`;
4246
- const assetPath = resolve6(assetsDir, assetFileName);
4247
- const assetCode = `export default ${entryJson};
4248
- `;
4249
- writeFileSync3(assetPath, assetCode);
4250
- totalBytes += Buffer.byteLength(assetCode);
4251
- manifestEntries.push(
4252
- `${JSON.stringify(key)}:()=>import("./assets/${assetFileName}")`
4253
- );
4301
+ manifestMap[key] = `./assets/${assetFileName}`;
4254
4302
  }
4255
- const manifestCode = `const m={${manifestEntries.join(",")}};export default m;
4256
- `;
4257
- const manifestPath = resolve6(
4303
+ const manifestCode = [
4304
+ `const m=JSON.parse('${JSON.stringify(manifestMap).replace(/'/g, "\\'")}');`,
4305
+ `export function loadPrerenderAsset(s){return import(s)}`,
4306
+ `export default m;`,
4307
+ ""
4308
+ ].join("\n");
4309
+ const manifestPath = resolve7(
4258
4310
  state.projectRoot,
4259
4311
  "dist/rsc/__prerender-manifest.js"
4260
4312
  );
4261
- writeFileSync3(manifestPath, manifestCode);
4313
+ writeFileSync4(manifestPath, manifestCode);
4262
4314
  totalBytes += Buffer.byteLength(manifestCode);
4263
- const injection = `import __pm from "./__prerender-manifest.js";
4264
- globalThis.__PRERENDER_MANIFEST = __pm;
4315
+ const injection = `globalThis.__loadPrerenderManifestModule = () => import("./__prerender-manifest.js");
4265
4316
  `;
4266
- writeFileSync3(rscEntryPath, injection + rscCode);
4317
+ writeFileSync4(rscEntryPath, injection + rscCode);
4267
4318
  const totalKB = (totalBytes / 1024).toFixed(1);
4268
4319
  console.log(
4269
- `[rsc-router] Wrote prerender assets (${totalKB} KB total, ${Object.keys(state.prerenderCollectedData).length} entries)`
4320
+ `[rsc-router] Wrote prerender assets (${totalKB} KB total, ${Object.keys(state.prerenderManifestEntries).length} entries)`
4270
4321
  );
4271
4322
  } catch (err) {
4272
4323
  throw new Error(
@@ -4275,44 +4326,36 @@ globalThis.__PRERENDER_MANIFEST = __pm;
4275
4326
  }
4276
4327
  }
4277
4328
  }
4278
- if (hasStaticData && existsSync5(rscEntryPath)) {
4329
+ if (hasStaticData && existsSync6(rscEntryPath)) {
4279
4330
  const rscCode = readFileSync5(rscEntryPath, "utf-8");
4280
4331
  if (!rscCode.includes("__STATIC_MANIFEST")) {
4281
4332
  try {
4282
- const assetsDir = resolve6(state.projectRoot, "dist/rsc/assets");
4283
- mkdirSync(assetsDir, { recursive: true });
4284
4333
  const manifestEntries = [];
4285
- let totalBytes = 0;
4286
- for (const [handlerId, { encoded, handles }] of Object.entries(
4287
- state.staticCollectedData
4334
+ let totalBytes = copyStagedBuildAssets(
4335
+ state.projectRoot,
4336
+ Object.values(state.staticManifestEntries)
4337
+ );
4338
+ for (const [handlerId, assetFileName] of Object.entries(
4339
+ state.staticManifestEntries
4288
4340
  )) {
4289
- const hasHandles = Object.keys(handles).length > 0;
4290
- const exportValue = hasHandles ? JSON.stringify({ encoded, handles }) : JSON.stringify(encoded);
4291
- const contentHash = createHash4("sha256").update(exportValue).digest("hex").slice(0, 8);
4292
- const assetFileName = `__st-${contentHash}.js`;
4293
- const assetPath = resolve6(assetsDir, assetFileName);
4294
- const assetCode = `export default ${exportValue};
4295
- `;
4296
- writeFileSync3(assetPath, assetCode);
4297
- totalBytes += Buffer.byteLength(assetCode);
4298
4341
  manifestEntries.push(
4299
4342
  `${JSON.stringify(handlerId)}:()=>import("./assets/${assetFileName}")`
4300
4343
  );
4301
4344
  }
4302
4345
  const manifestCode = `const m={${manifestEntries.join(",")}};globalThis.__STATIC_MANIFEST=m;export default m;
4303
4346
  `;
4304
- const manifestPath = resolve6(
4347
+ const manifestPath = resolve7(
4305
4348
  state.projectRoot,
4306
4349
  "dist/rsc/__static-manifest.js"
4307
4350
  );
4308
- writeFileSync3(manifestPath, manifestCode);
4351
+ writeFileSync4(manifestPath, manifestCode);
4309
4352
  totalBytes += Buffer.byteLength(manifestCode);
4310
4353
  const injection = `import "./__static-manifest.js";
4311
4354
  `;
4312
- writeFileSync3(rscEntryPath, injection + rscCode);
4355
+ writeFileSync4(rscEntryPath, injection + rscCode);
4313
4356
  const totalKB = (totalBytes / 1024).toFixed(1);
4314
4357
  console.log(
4315
- `[rsc-router] Wrote static assets (${totalKB} KB total, ${Object.keys(state.staticCollectedData).length} entries)`
4358
+ `[rsc-router] Wrote static assets (${totalKB} KB total, ${Object.keys(state.staticManifestEntries).length} entries)`
4316
4359
  );
4317
4360
  } catch (err) {
4318
4361
  throw new Error(
@@ -4427,8 +4470,8 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
4427
4470
  if (globalThis.__rscRouterDiscoveryActive) return;
4428
4471
  s.devServer = server;
4429
4472
  let resolveDiscovery;
4430
- const discoveryPromise = new Promise((resolve9) => {
4431
- resolveDiscovery = resolve9;
4473
+ const discoveryPromise = new Promise((resolve10) => {
4474
+ resolveDiscovery = resolve10;
4432
4475
  });
4433
4476
  const getDevServerOrigin = () => server.resolvedUrls?.local?.[0]?.replace(/\/$/, "") || `http://localhost:${server.config.server.port || 5173}`;
4434
4477
  let prerenderTempServer = null;
@@ -4503,8 +4546,8 @@ ${err.stack}`
4503
4546
  resolveDiscovery();
4504
4547
  }
4505
4548
  };
4506
- s.discoveryDone = new Promise((resolve9) => {
4507
- setTimeout(() => discover().then(resolve9, resolve9), 0);
4549
+ s.discoveryDone = new Promise((resolve10) => {
4550
+ setTimeout(() => discover().then(resolve10, resolve10), 0);
4508
4551
  });
4509
4552
  let mainRegistry = null;
4510
4553
  const propagateDiscoveryState = async (rscEnv) => {
@@ -4673,7 +4716,7 @@ ${err.stack}`
4673
4716
  if (hasCreateRouter) {
4674
4717
  const nestedRouterConflict = findNestedRouterConflict([
4675
4718
  ...s.cachedRouterFiles ?? [],
4676
- resolve7(filePath)
4719
+ resolve8(filePath)
4677
4720
  ]);
4678
4721
  if (nestedRouterConflict) {
4679
4722
  server.config.logger.error(
@@ -4703,6 +4746,9 @@ ${err.stack}`
4703
4746
  async buildStart() {
4704
4747
  if (!s.isBuildMode) return;
4705
4748
  if (s.mergedRouteManifest !== null) return;
4749
+ resetStagedBuildAssets(s.projectRoot);
4750
+ s.prerenderManifestEntries = null;
4751
+ s.staticManifestEntries = null;
4706
4752
  let tempServer = null;
4707
4753
  globalThis.__rscRouterDiscoveryActive = true;
4708
4754
  try {
@@ -4944,7 +4990,7 @@ async function rango(options) {
4944
4990
  name: "@rangojs/router:auto-discover",
4945
4991
  config(userConfig) {
4946
4992
  if (routerRef.path) return;
4947
- const root = userConfig.root ? resolve8(process.cwd(), userConfig.root) : process.cwd();
4993
+ const root = userConfig.root ? resolve9(process.cwd(), userConfig.root) : process.cwd();
4948
4994
  const filter = createScanFilter(root, {
4949
4995
  include: resolvedOptions.include,
4950
4996
  exclude: resolvedOptions.exclude
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rangojs/router",
3
- "version": "0.0.0-experimental.20",
3
+ "version": "0.0.0-experimental.22",
4
4
  "description": "Django-inspired RSC router with composable URL patterns",
5
5
  "keywords": [
6
6
  "react",
@@ -89,7 +89,7 @@ Configure a cache store in the router:
89
89
 
90
90
  ```typescript
91
91
  import { createRouter } from "@rangojs/router";
92
- import { MemorySegmentCacheStore } from "@rangojs/router/rsc";
92
+ import { MemorySegmentCacheStore } from "@rangojs/router/cache";
93
93
 
94
94
  const store = new MemorySegmentCacheStore({
95
95
  defaults: { ttl: 60, swr: 300 },
@@ -112,7 +112,7 @@ const router = createRouter({
112
112
  For single-instance deployments:
113
113
 
114
114
  ```typescript
115
- import { MemorySegmentCacheStore } from "@rangojs/router/rsc";
115
+ import { MemorySegmentCacheStore } from "@rangojs/router/cache";
116
116
 
117
117
  const store = new MemorySegmentCacheStore({
118
118
  defaults: { ttl: 60, swr: 300 },
@@ -125,7 +125,7 @@ const store = new MemorySegmentCacheStore({
125
125
  For distributed caching on Cloudflare Workers:
126
126
 
127
127
  ```typescript
128
- import { CFCacheStore } from "@rangojs/router/cache/cf";
128
+ import { CFCacheStore } from "@rangojs/router/cache";
129
129
 
130
130
  const router = createRouter<AppBindings>({
131
131
  document: Document,
@@ -175,7 +175,7 @@ cache({ store: checkoutCache }, () => [
175
175
 
176
176
  ```typescript
177
177
  import { urls } from "@rangojs/router";
178
- import { MemorySegmentCacheStore } from "@rangojs/router/rsc";
178
+ import { MemorySegmentCacheStore } from "@rangojs/router/cache";
179
179
 
180
180
  // Custom store for checkout (short TTL)
181
181
  const checkoutCache = new MemorySegmentCacheStore({
@@ -14,7 +14,7 @@ Configure document cache in router:
14
14
 
15
15
  ```typescript
16
16
  import { createRouter } from "@rangojs/router";
17
- import { CFCacheStore } from "@rangojs/router/cache/cf";
17
+ import { CFCacheStore } from "@rangojs/router/cache";
18
18
  import { urlpatterns } from "./urls";
19
19
 
20
20
  const router = createRouter<AppBindings>({
@@ -134,7 +134,7 @@ Segment hash ensures different cached responses for navigations from different s
134
134
  ```typescript
135
135
  // router.tsx
136
136
  import { createRouter } from "@rangojs/router";
137
- import { CFCacheStore } from "@rangojs/router/cache/cf";
137
+ import { CFCacheStore } from "@rangojs/router/cache";
138
138
  import { urlpatterns } from "./urls";
139
139
 
140
140
  const router = createRouter<AppBindings>({