@rangojs/router 0.0.0-experimental.110 → 0.0.0-experimental.111
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/dist/vite/index.js +1 -1
- package/package.json +15 -14
- package/skills/handler-use/SKILL.md +1 -1
- package/skills/rango/SKILL.md +20 -0
- package/src/errors.ts +18 -0
- package/src/index.rsc.ts +1 -0
- package/src/index.ts +1 -0
- package/src/route-definition/dsl-helpers.ts +231 -259
- package/src/route-definition/helper-factories.ts +29 -139
- package/src/route-definition/use-item-types.ts +32 -0
- package/src/route-types.ts +19 -41
- package/src/server/context.ts +76 -35
- package/src/urls/include-helper.ts +10 -53
- package/src/urls/index.ts +0 -3
- package/src/urls/path-helper.ts +17 -52
- package/src/urls/pattern-types.ts +2 -19
- package/src/urls/response-types.ts +20 -19
- package/src/urls/type-extraction.ts +20 -115
- package/src/urls/urls-function.ts +1 -5
package/dist/vite/index.js
CHANGED
|
@@ -2049,7 +2049,7 @@ import { resolve } from "node:path";
|
|
|
2049
2049
|
// package.json
|
|
2050
2050
|
var package_default = {
|
|
2051
2051
|
name: "@rangojs/router",
|
|
2052
|
-
version: "0.0.0-experimental.
|
|
2052
|
+
version: "0.0.0-experimental.111",
|
|
2053
2053
|
description: "Django-inspired RSC router with composable URL patterns",
|
|
2054
2054
|
keywords: [
|
|
2055
2055
|
"react",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rangojs/router",
|
|
3
|
-
"version": "0.0.0-experimental.
|
|
3
|
+
"version": "0.0.0-experimental.111",
|
|
4
4
|
"description": "Django-inspired RSC router with composable URL patterns",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -132,6 +132,15 @@
|
|
|
132
132
|
"access": "public",
|
|
133
133
|
"tag": "experimental"
|
|
134
134
|
},
|
|
135
|
+
"scripts": {
|
|
136
|
+
"build": "pnpm dlx esbuild src/vite/index.ts --bundle --format=esm --outfile=dist/vite/index.js --platform=node --packages=external && mkdir -p dist/vite/plugins && cp src/vite/plugins/cloudflare-protocol-loader-hook.mjs dist/vite/plugins/cloudflare-protocol-loader-hook.mjs && pnpm dlx esbuild src/bin/rango.ts --bundle --format=esm --outfile=dist/bin/rango.js --platform=node --packages=external --banner:js='#!/usr/bin/env node' && chmod +x dist/bin/rango.js",
|
|
137
|
+
"prepublishOnly": "pnpm build",
|
|
138
|
+
"typecheck": "tsc --noEmit && tsc -p tsconfig.strict-check.json --noEmit && tsc -p tsconfig.augment-check.json --noEmit",
|
|
139
|
+
"test": "playwright test",
|
|
140
|
+
"test:ui": "playwright test --ui",
|
|
141
|
+
"test:unit": "vitest run",
|
|
142
|
+
"test:unit:watch": "vitest"
|
|
143
|
+
},
|
|
135
144
|
"dependencies": {
|
|
136
145
|
"@types/debug": "^4.1.12",
|
|
137
146
|
"@vitejs/plugin-rsc": "^0.5.26",
|
|
@@ -143,12 +152,12 @@
|
|
|
143
152
|
"devDependencies": {
|
|
144
153
|
"@playwright/test": "^1.49.1",
|
|
145
154
|
"@types/node": "^24.10.1",
|
|
146
|
-
"@types/react": "
|
|
147
|
-
"@types/react-dom": "
|
|
155
|
+
"@types/react": "catalog:",
|
|
156
|
+
"@types/react-dom": "catalog:",
|
|
148
157
|
"esbuild": "^0.27.0",
|
|
149
158
|
"jiti": "^2.6.1",
|
|
150
|
-
"react": "
|
|
151
|
-
"react-dom": "
|
|
159
|
+
"react": "catalog:",
|
|
160
|
+
"react-dom": "catalog:",
|
|
152
161
|
"tinyexec": "^0.3.2",
|
|
153
162
|
"typescript": "^5.3.0",
|
|
154
163
|
"vitest": "^4.0.0"
|
|
@@ -167,13 +176,5 @@
|
|
|
167
176
|
"vite": {
|
|
168
177
|
"optional": true
|
|
169
178
|
}
|
|
170
|
-
},
|
|
171
|
-
"scripts": {
|
|
172
|
-
"build": "pnpm dlx esbuild src/vite/index.ts --bundle --format=esm --outfile=dist/vite/index.js --platform=node --packages=external && mkdir -p dist/vite/plugins && cp src/vite/plugins/cloudflare-protocol-loader-hook.mjs dist/vite/plugins/cloudflare-protocol-loader-hook.mjs && pnpm dlx esbuild src/bin/rango.ts --bundle --format=esm --outfile=dist/bin/rango.js --platform=node --packages=external --banner:js='#!/usr/bin/env node' && chmod +x dist/bin/rango.js",
|
|
173
|
-
"typecheck": "tsc --noEmit && tsc -p tsconfig.strict-check.json --noEmit && tsc -p tsconfig.augment-check.json --noEmit",
|
|
174
|
-
"test": "playwright test",
|
|
175
|
-
"test:ui": "playwright test --ui",
|
|
176
|
-
"test:unit": "vitest run",
|
|
177
|
-
"test:unit:watch": "vitest"
|
|
178
179
|
}
|
|
179
|
-
}
|
|
180
|
+
}
|
|
@@ -297,7 +297,7 @@ QuickViewModal.use = () => [
|
|
|
297
297
|
|
|
298
298
|
## `loading()` is a single-assignment item — scope it correctly
|
|
299
299
|
|
|
300
|
-
Most `use` items accumulate when merged: `handler.use` `middleware()` runs _and_ explicit `middleware()` runs; both `loader()` registrations apply. `loading()` is different — it mutates `entry.loading` directly, last call wins ([dsl-helpers.ts `
|
|
300
|
+
Most `use` items accumulate when merged: `handler.use` `middleware()` runs _and_ explicit `middleware()` runs; both `loader()` registrations apply. `loading()` is different — it mutates `entry.loading` directly, last call wins ([dsl-helpers.ts `loading`](../../src/route-definition/dsl-helpers.ts)).
|
|
301
301
|
|
|
302
302
|
For pages, layouts, and intercepts that's straightforward: explicit `loading()` at the mount site replaces any `loading()` from `handler.use`. The merge order is `handler.use → explicit`, so the explicit one is the last writer and wins.
|
|
303
303
|
|
package/skills/rango/SKILL.md
CHANGED
|
@@ -142,6 +142,18 @@ by reference with `ctx.isAction(Action)` (rename-safe, where `CartActions` is an
|
|
|
142
142
|
`import * as CartActions from "./actions/cart"`); see `/typesafety` → "Stable
|
|
143
143
|
identity".
|
|
144
144
|
|
|
145
|
+
The predicate arg carries the action's full context, not just its identity. Match
|
|
146
|
+
_which_ action with `ctx.isAction(addToCart)` (rename-safe); branch on _what it
|
|
147
|
+
returned_ with `ctx.actionResult` — the value your `"use server"` function
|
|
148
|
+
returned, for outcome-conditional revalidation. The arg also exposes `actionId`
|
|
149
|
+
(raw `path#export`), `actionUrl`, `formData`, `method`, and `stale` (cross-tab
|
|
150
|
+
`_rsc_stale` signal). All are `undefined` on plain navigation (no action).
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
// re-render only when checkout actually succeeded; defer otherwise
|
|
154
|
+
revalidate((ctx) => (ctx.isAction(checkout) && ctx.actionResult?.ok) || undefined),
|
|
155
|
+
```
|
|
156
|
+
|
|
145
157
|
**The source is the source of truth.** Structure, types, and update policy are
|
|
146
158
|
visible and local in the tree — read top-down, no hidden global model to hold in
|
|
147
159
|
your head. A snippet earns its place only if, from the code alone, you can answer:
|
|
@@ -150,6 +162,14 @@ without leaving the call site?_ (type-safety), _what re-renders after this
|
|
|
150
162
|
action?_ (partial rendering). If any answer needs another file, it isn't legible
|
|
151
163
|
yet.
|
|
152
164
|
|
|
165
|
+
**Reading Rango's own source.** Rango is consumed as raw TypeScript — the
|
|
166
|
+
`exports` map resolves `@rangojs/router` and its subpaths to `./src/*.ts` for
|
|
167
|
+
both types and runtime, so a consuming app bundles Rango straight from source.
|
|
168
|
+
Only the `./vite` plugin entry and the CLI `bin` load from `dist/`. To confirm
|
|
169
|
+
any runtime or type detail against an installed copy, read the resolved source
|
|
170
|
+
under `node_modules/@rangojs/router/src/`, not `dist/` — the runtime does not
|
|
171
|
+
resolve `dist/` outside `./vite`, and it may lag `src/`.
|
|
172
|
+
|
|
153
173
|
## Skills
|
|
154
174
|
|
|
155
175
|
Grouped by concern — read when you need to…
|
package/src/errors.ts
CHANGED
|
@@ -109,6 +109,24 @@ export class BuildError extends Error {
|
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Thrown when a route-definition DSL helper (route/layout/loader/cache/…) is
|
|
114
|
+
* called outside an active urls()/map() builder, so there is no
|
|
115
|
+
* AsyncLocalStorage build context to attach to. The message names the specific
|
|
116
|
+
* helper and how to fix it; the `cause` records the mechanical reason so the
|
|
117
|
+
* failure mode is identifiable (not conflated with an unrelated throw).
|
|
118
|
+
*/
|
|
119
|
+
export class DslContextError extends Error {
|
|
120
|
+
name = "DslContextError" as const;
|
|
121
|
+
cause?: unknown;
|
|
122
|
+
|
|
123
|
+
constructor(message: string, options?: ErrorOptions) {
|
|
124
|
+
super(message);
|
|
125
|
+
Object.setPrototypeOf(this, DslContextError.prototype);
|
|
126
|
+
this.cause = options?.cause;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
112
130
|
/**
|
|
113
131
|
* Thrown when a network request fails (server unreachable, no internet, etc.)
|
|
114
132
|
* This error triggers the root error boundary with retry capability.
|
package/src/index.rsc.ts
CHANGED