@rangojs/router 0.0.0-experimental.d20dd405 → 0.0.0-experimental.dacec167
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 +8 -8
- package/dist/bin/rango.js +147 -57
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +914 -485
- package/package.json +55 -11
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +220 -30
- package/skills/caching/SKILL.md +116 -8
- package/skills/composability/SKILL.md +27 -2
- package/skills/document-cache/SKILL.md +78 -55
- package/skills/handler-use/SKILL.md +1 -1
- package/skills/hooks/SKILL.md +196 -21
- package/skills/host-router/SKILL.md +45 -20
- package/skills/intercept/SKILL.md +1 -4
- package/skills/layout/SKILL.md +4 -7
- package/skills/links/SKILL.md +22 -10
- package/skills/loader/SKILL.md +149 -6
- package/skills/middleware/SKILL.md +13 -9
- package/skills/migrate-nextjs/SKILL.md +1 -1
- package/skills/mime-routes/SKILL.md +27 -0
- package/skills/observability/SKILL.md +137 -0
- package/skills/parallel/SKILL.md +3 -6
- package/skills/prerender/SKILL.md +14 -33
- package/skills/rango/SKILL.md +242 -26
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +58 -9
- package/skills/route/SKILL.md +9 -4
- package/skills/router-setup/SKILL.md +3 -3
- package/skills/server-actions/SKILL.md +53 -41
- package/skills/testing/SKILL.md +778 -0
- package/skills/typesafety/SKILL.md +310 -26
- package/skills/use-cache/SKILL.md +34 -5
- package/skills/view-transitions/SKILL.md +85 -3
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +117 -0
- package/src/browser/action-coordinator.ts +53 -36
- package/src/browser/event-controller.ts +42 -66
- package/src/browser/history-state.ts +21 -0
- package/src/browser/index.ts +3 -3
- package/src/browser/navigation-bridge.ts +9 -67
- package/src/browser/navigation-client.ts +12 -15
- package/src/browser/navigation-store.ts +7 -8
- package/src/browser/navigation-transaction.ts +10 -28
- package/src/browser/partial-update.ts +8 -16
- package/src/browser/react/NavigationProvider.tsx +55 -65
- package/src/browser/react/location-state-shared.ts +175 -4
- package/src/browser/react/location-state.ts +39 -13
- package/src/browser/react/use-handle.ts +17 -9
- package/src/browser/react/use-params.ts +3 -4
- package/src/browser/react/use-reverse.ts +19 -12
- package/src/browser/react/use-router.ts +14 -1
- package/src/browser/response-adapter.ts +25 -0
- package/src/browser/rsc-router.tsx +30 -16
- package/src/browser/scroll-restoration.ts +30 -25
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +23 -30
- package/src/browser/types.ts +2 -0
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +60 -35
- package/src/build/generate-route-types.ts +2 -0
- package/src/build/index.ts +2 -0
- package/src/build/route-types/codegen.ts +4 -4
- package/src/build/route-types/include-resolution.ts +1 -1
- package/src/build/route-types/per-module-writer.ts +7 -4
- package/src/build/route-types/router-processing.ts +55 -14
- package/src/build/route-types/scan-filter.ts +1 -1
- package/src/build/route-types/source-scan.ts +118 -0
- package/src/build/runtime-discovery.ts +9 -20
- package/src/cache/cache-scope.ts +28 -42
- package/src/cache/cf/cf-cache-store.ts +49 -6
- package/src/client.tsx +5 -7
- package/src/context-var.ts +5 -5
- package/src/decode-loader-results.ts +36 -0
- package/src/errors.ts +30 -1
- package/src/handle.ts +26 -13
- package/src/host/index.ts +2 -2
- package/src/host/router.ts +129 -57
- package/src/host/types.ts +31 -2
- package/src/host/utils.ts +1 -1
- package/src/href-client.ts +136 -19
- package/src/index.rsc.ts +6 -4
- package/src/index.ts +13 -6
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +21 -6
- package/src/loader.ts +3 -10
- package/src/missing-id-error.ts +68 -0
- package/src/prerender.ts +4 -4
- package/src/response-utils.ts +9 -0
- package/src/reverse.ts +16 -13
- package/src/route-content-wrapper.tsx +6 -28
- package/src/route-definition/dsl-helpers.ts +238 -263
- package/src/route-definition/helper-factories.ts +29 -139
- package/src/route-definition/helpers-types.ts +37 -14
- package/src/route-definition/use-item-types.ts +32 -0
- package/src/route-types.ts +19 -41
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +15 -2
- package/src/router/error-handling.ts +1 -1
- package/src/router/intercept-resolution.ts +4 -18
- package/src/router/lazy-includes.ts +2 -2
- package/src/router/loader-resolution.ts +16 -2
- package/src/router/match-handlers.ts +62 -20
- package/src/router/match-middleware/cache-lookup.ts +44 -91
- package/src/router/match-middleware/cache-store.ts +3 -2
- package/src/router/match-result.ts +32 -30
- package/src/router/metrics.ts +1 -1
- package/src/router/middleware-types.ts +1 -1
- package/src/router/middleware.ts +46 -78
- package/src/router/prerender-match.ts +1 -1
- package/src/router/preview-match.ts +3 -1
- package/src/router/request-classification.ts +4 -28
- package/src/router/revalidation.ts +43 -1
- package/src/router/router-interfaces.ts +45 -28
- package/src/router/router-options.ts +40 -1
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +19 -6
- package/src/router/segment-resolution/revalidation.ts +19 -6
- package/src/router/segment-resolution/view-transition-default.ts +36 -0
- package/src/router/telemetry.ts +99 -0
- package/src/router/types.ts +8 -0
- package/src/router.ts +37 -21
- package/src/rsc/handler-context.ts +2 -2
- package/src/rsc/handler.ts +20 -65
- package/src/rsc/helpers.ts +22 -2
- package/src/rsc/index.ts +1 -1
- package/src/rsc/origin-guard.ts +28 -10
- package/src/rsc/response-route-handler.ts +32 -52
- package/src/rsc/rsc-rendering.ts +27 -53
- package/src/rsc/runtime-warnings.ts +9 -10
- package/src/rsc/server-action.ts +13 -37
- package/src/rsc/ssr-setup.ts +16 -0
- package/src/rsc/types.ts +2 -2
- package/src/search-params.ts +4 -4
- package/src/segment-system.tsx +64 -49
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +118 -51
- package/src/server/cookie-store.ts +28 -4
- package/src/server/request-context.ts +10 -0
- package/src/static-handler.ts +1 -1
- package/src/testing/cache-status.ts +166 -0
- package/src/testing/collect-handle.ts +63 -0
- package/src/testing/dispatch.ts +440 -0
- package/src/testing/dom.entry.ts +22 -0
- package/src/testing/e2e/fixture.ts +154 -0
- package/src/testing/e2e/index.ts +149 -0
- package/src/testing/e2e/matchers.ts +51 -0
- package/src/testing/e2e/page-helpers.ts +272 -0
- package/src/testing/e2e/parity.ts +306 -0
- package/src/testing/e2e/server.ts +183 -0
- package/src/testing/flight-matchers.ts +104 -0
- package/src/testing/flight-runtime.d.ts +57 -0
- package/src/testing/flight-tree.ts +320 -0
- package/src/testing/flight.entry.ts +39 -0
- package/src/testing/flight.ts +197 -0
- package/src/testing/generated-routes.ts +223 -0
- package/src/testing/index.ts +106 -0
- package/src/testing/internal/context.ts +331 -0
- package/src/testing/internal/flight-client-globals.ts +30 -0
- package/src/testing/render-route.tsx +565 -0
- package/src/testing/run-loader.ts +341 -0
- package/src/testing/run-middleware.ts +188 -0
- package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
- package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
- package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
- package/src/testing/vitest-stubs/version.ts +5 -0
- package/src/testing/vitest.ts +270 -0
- package/src/types/global-namespace.ts +39 -26
- package/src/types/handler-context.ts +56 -11
- package/src/types/index.ts +1 -0
- package/src/types/segments.ts +18 -1
- package/src/urls/include-helper.ts +10 -53
- package/src/urls/index.ts +0 -3
- package/src/urls/path-helper-types.ts +11 -3
- package/src/urls/path-helper.ts +17 -52
- package/src/urls/pattern-types.ts +36 -19
- package/src/urls/response-types.ts +20 -19
- package/src/urls/type-extraction.ts +26 -116
- package/src/urls/urls-function.ts +1 -5
- package/src/use-loader.tsx +413 -42
- package/src/vite/debug.ts +1 -0
- package/src/vite/discovery/bundle-postprocess.ts +6 -6
- package/src/vite/discovery/discover-routers.ts +70 -48
- package/src/vite/discovery/discovery-errors.ts +194 -0
- package/src/vite/discovery/prerender-collection.ts +19 -25
- package/src/vite/discovery/route-types-writer.ts +40 -84
- package/src/vite/discovery/state.ts +33 -0
- package/src/vite/discovery/virtual-module-codegen.ts +13 -23
- package/src/vite/index.ts +2 -0
- package/src/vite/plugin-types.ts +67 -0
- package/src/vite/plugins/cjs-to-esm.ts +3 -7
- package/src/vite/plugins/client-ref-hashing.ts +12 -1
- package/src/vite/plugins/cloudflare-protocol-stub.ts +1 -1
- package/src/vite/plugins/expose-action-id.ts +2 -2
- package/src/vite/plugins/expose-id-utils.ts +12 -8
- package/src/vite/plugins/expose-ids/export-analysis.ts +100 -20
- package/src/vite/plugins/expose-ids/handler-transform.ts +8 -61
- package/src/vite/plugins/expose-ids/loader-transform.ts +3 -5
- package/src/vite/plugins/expose-internal-ids.ts +47 -67
- package/src/vite/plugins/performance-tracks.ts +12 -16
- package/src/vite/plugins/use-cache-transform.ts +13 -11
- package/src/vite/plugins/version-injector.ts +2 -12
- package/src/vite/plugins/version-plugin.ts +59 -2
- package/src/vite/plugins/virtual-entries.ts +2 -2
- package/src/vite/rango.ts +67 -15
- package/src/vite/router-discovery.ts +208 -63
- package/src/vite/utils/ast-handler-extract.ts +15 -15
- package/src/vite/utils/bundle-analysis.ts +4 -2
- package/src/vite/utils/client-chunks.ts +190 -0
- package/src/vite/utils/forward-user-plugins.ts +193 -0
- package/src/vite/utils/manifest-utils.ts +21 -5
- package/src/vite/utils/shared-utils.ts +107 -26
- package/src/browser/action-response-classifier.ts +0 -99
|
@@ -32,35 +32,37 @@ Actions mutate state; route handlers and loaders read the latest state. After
|
|
|
32
32
|
an action finishes, Rango performs a server-side revalidation render for the
|
|
33
33
|
matched route so the UI receives fresh segment output and loader data.
|
|
34
34
|
|
|
35
|
-
The main control point is `revalidate((
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
The main control point is `revalidate((ctx) => ...)` on the segment that owns
|
|
36
|
+
the data. Match specific actions by imported reference with `ctx.isAction()`;
|
|
37
|
+
use raw `actionId` only when you intentionally need path or directory matching.
|
|
38
|
+
This applies to `path()` handlers, `layout()` handlers, `parallel()` slots,
|
|
39
|
+
`intercept()` routes, and loader registrations:
|
|
38
40
|
|
|
39
41
|
```typescript
|
|
40
42
|
// urls.tsx — path/layout/parallel/intercept/loader/revalidate are passed in by urls()
|
|
41
43
|
import { urls } from "@rangojs/router";
|
|
44
|
+
import * as CartActions from "./actions/cart";
|
|
42
45
|
|
|
43
46
|
export const urlpatterns = urls(({ path, loader, revalidate }) => [
|
|
44
47
|
// The loader belongs to the route that consumes its data — nest it inside
|
|
45
48
|
// the owning path() so the segment owns its data dependency.
|
|
46
49
|
path("/cart", CartPage, { name: "cart" }, () => [
|
|
47
|
-
revalidate(
|
|
48
|
-
({ actionId }) => actionId?.startsWith("src/actions/cart.ts#") ?? false,
|
|
49
|
-
),
|
|
50
|
+
revalidate((ctx) => ctx.isAction(CartActions) || undefined),
|
|
50
51
|
loader(CartLoader, () => [
|
|
51
|
-
revalidate(
|
|
52
|
-
({ actionId }) => actionId?.startsWith("src/actions/cart.ts#") ?? false,
|
|
53
|
-
),
|
|
52
|
+
revalidate((ctx) => ctx.isAction(CartActions) || undefined),
|
|
54
53
|
]),
|
|
55
54
|
]),
|
|
56
55
|
]);
|
|
57
56
|
```
|
|
58
57
|
|
|
59
|
-
|
|
58
|
+
`ctx.isAction()` resolves the imported action reference the same way the router
|
|
59
|
+
derives `actionId`, so it matches in both dev and production and survives action
|
|
60
|
+
renames/moves as type errors instead of silent substring drift.
|
|
61
|
+
|
|
62
|
+
For module-level `"use server"` files, the raw `actionId` passed to every
|
|
60
63
|
server-side `revalidate()` predicate is path-bearing in the server/RSC
|
|
61
|
-
environment in both dev and production: `src/actions/cart.ts#addToCart`. This
|
|
62
|
-
|
|
63
|
-
predicates can filter by action file, directory, or export name.
|
|
64
|
+
environment in both dev and production: `src/actions/cart.ts#addToCart`. This is
|
|
65
|
+
the escape hatch for broad filters by action file, directory, or export name.
|
|
64
66
|
|
|
65
67
|
Actions and the follow-up revalidation render share one request context.
|
|
66
68
|
Values written in the action with `ctx.set(MyVar, value)` or `ctx.set("key",
|
|
@@ -91,15 +93,18 @@ export async function switchTenant(tenantId: string) {
|
|
|
91
93
|
```typescript
|
|
92
94
|
// urls.tsx
|
|
93
95
|
import { urls } from "@rangojs/router";
|
|
96
|
+
import * as TenantActions from "./actions/tenant";
|
|
94
97
|
import { ChangedTenant } from "./context";
|
|
95
98
|
|
|
96
99
|
export const urlpatterns = urls(({ path, revalidate }) => [
|
|
97
100
|
path("/dashboard/:tenantId", DashboardPage, { name: "dashboard" }, () => [
|
|
98
|
-
revalidate(
|
|
99
|
-
(
|
|
100
|
-
|
|
101
|
-
context.get(ChangedTenant) === context.params.tenantId
|
|
102
|
-
|
|
101
|
+
revalidate((ctx) => {
|
|
102
|
+
if (!ctx.isAction(TenantActions)) return undefined;
|
|
103
|
+
return (
|
|
104
|
+
ctx.context.get(ChangedTenant) === ctx.context.params.tenantId ||
|
|
105
|
+
undefined
|
|
106
|
+
);
|
|
107
|
+
}),
|
|
103
108
|
]),
|
|
104
109
|
]);
|
|
105
110
|
```
|
|
@@ -380,13 +385,18 @@ re-render so the UI updates. Rango runs the action, then evaluates
|
|
|
380
385
|
`revalidate()` on matched segments and loaders. Each path, layout, parallel,
|
|
381
386
|
intercept, or loader rule decides whether that piece re-renders/re-resolves.
|
|
382
387
|
|
|
383
|
-
|
|
384
|
-
|
|
388
|
+
Use `ctx.isAction()` for specific actions or modules. It accepts one action,
|
|
389
|
+
several actions, or a namespace import (`import * as CartActions`). Pair it with
|
|
390
|
+
`|| undefined` for "revalidate on match, otherwise defer to defaults/downstream
|
|
391
|
+
rules."
|
|
385
392
|
|
|
386
393
|
```typescript
|
|
387
394
|
// urls.tsx — inside the urls() callback. Nest each loader inside the path(),
|
|
388
395
|
// layout(), or parallel() that owns its data so the route tree mirrors the
|
|
389
396
|
// data dependencies.
|
|
397
|
+
import * as AccountActions from "./actions/account";
|
|
398
|
+
import * as CartActions from "./actions/cart";
|
|
399
|
+
|
|
390
400
|
urls(({ path, loader, revalidate }) => [
|
|
391
401
|
path("/", HomePage, { name: "home" }, () => [
|
|
392
402
|
// Loader data re-runs by default after any action. Opt out with revalidate(() => false).
|
|
@@ -395,36 +405,37 @@ urls(({ path, loader, revalidate }) => [
|
|
|
395
405
|
|
|
396
406
|
// Re-render the cart page handler AND re-resolve its loader after cart actions
|
|
397
407
|
path("/cart", CartPage, { name: "cart" }, () => [
|
|
398
|
-
revalidate(
|
|
399
|
-
({ actionId }) => actionId?.startsWith("src/actions/cart.ts#") ?? false,
|
|
400
|
-
),
|
|
408
|
+
revalidate((ctx) => ctx.isAction(CartActions) || undefined),
|
|
401
409
|
loader(CartLoader, () => [
|
|
402
|
-
revalidate(
|
|
403
|
-
({ actionId }) => actionId?.startsWith("src/actions/cart.ts#") ?? false,
|
|
404
|
-
),
|
|
410
|
+
revalidate((ctx) => ctx.isAction(CartActions) || undefined),
|
|
405
411
|
]),
|
|
406
412
|
]),
|
|
407
413
|
|
|
408
|
-
// Re-run after any action
|
|
414
|
+
// Re-run after any action exported by the account actions module
|
|
409
415
|
path("/account", AccountPage, { name: "account" }, () => [
|
|
410
416
|
loader(AccountLoader, () => [
|
|
411
|
-
revalidate(
|
|
412
|
-
({ actionId }) => actionId?.startsWith("src/actions/account/") ?? false,
|
|
413
|
-
),
|
|
417
|
+
revalidate((ctx) => ctx.isAction(AccountActions) || undefined),
|
|
414
418
|
]),
|
|
415
419
|
]),
|
|
416
420
|
]);
|
|
417
421
|
```
|
|
418
422
|
|
|
419
|
-
`actionId`
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
423
|
+
The raw `actionId` string stays available for broad path filters:
|
|
424
|
+
|
|
425
|
+
```typescript
|
|
426
|
+
// Match any action under src/actions/account/, including modules not imported here.
|
|
427
|
+
revalidate(
|
|
428
|
+
({ actionId }) => actionId?.startsWith("src/actions/account/") || undefined,
|
|
429
|
+
);
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
For actions exported from a module-level `"use server"` file, the ID is prefixed
|
|
433
|
+
with the source file path (`src/actions/cart.ts#addToCart`). **Inline `"use
|
|
434
|
+
server"` actions** (declared inside an RSC component) intentionally keep their
|
|
435
|
+
hashed IDs — file paths are withheld from the client for security. If you need
|
|
436
|
+
file-path-based revalidation predicates, define the action in a module-level
|
|
437
|
+
`"use server"` file rather than inline. See `/loader` for the full revalidation
|
|
438
|
+
contract (deferred returns, soft suggestions).
|
|
428
439
|
|
|
429
440
|
### Cross-segment dependencies
|
|
430
441
|
|
|
@@ -434,8 +445,9 @@ stale context. Share the same `revalidate` predicate on both producer and
|
|
|
434
445
|
consumer:
|
|
435
446
|
|
|
436
447
|
```typescript
|
|
437
|
-
|
|
438
|
-
|
|
448
|
+
import * as CartActions from "./actions/cart";
|
|
449
|
+
|
|
450
|
+
const revalidateCart = (ctx) => ctx.isAction(CartActions) || undefined;
|
|
439
451
|
|
|
440
452
|
urls(({ path, layout, loader, revalidate }) => [
|
|
441
453
|
layout(CartLayout, () => [
|