@rangojs/router 0.0.0-experimental.11 → 0.0.0-experimental.12
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/CLAUDE.md +1 -1
- package/dist/bin/rango.js +65 -5
- package/dist/vite/index.js +1378 -710
- package/package.json +1 -1
- package/skills/hooks/SKILL.md +5 -1
- package/skills/links/SKILL.md +12 -0
- package/skills/loader/SKILL.md +24 -0
- package/skills/mime-routes/SKILL.md +1 -1
- package/skills/prerender/SKILL.md +41 -17
- package/skills/response-routes/SKILL.md +7 -7
- package/skills/route/SKILL.md +41 -3
- package/skills/typesafety/SKILL.md +91 -0
- package/src/browser/logging.ts +44 -0
- package/src/browser/navigation-bridge.ts +17 -0
- package/src/browser/navigation-client.ts +35 -9
- package/src/browser/partial-update.ts +2 -3
- package/src/browser/react/location-state-shared.ts +3 -3
- package/src/browser/server-action-bridge.ts +37 -14
- package/src/build/generate-manifest.ts +20 -1
- package/src/build/generate-route-types.ts +235 -34
- package/src/handle.ts +3 -3
- package/src/index.rsc.ts +55 -7
- package/src/index.ts +84 -27
- package/src/internal-debug.ts +5 -0
- package/src/loader.rsc.ts +8 -51
- package/src/loader.ts +1 -1
- package/src/prerender.ts +18 -16
- package/src/reverse.ts +75 -32
- package/src/route-definition.ts +21 -2
- package/src/route-map-builder.ts +85 -0
- package/src/route-types.ts +5 -3
- package/src/router/handler-context.ts +35 -15
- package/src/router/intercept-resolution.ts +15 -12
- package/src/router/loader-resolution.ts +6 -5
- package/src/router/logging.ts +145 -0
- package/src/router/match-api.ts +29 -31
- package/src/router/match-middleware/background-revalidation.ts +12 -5
- package/src/router/match-middleware/cache-lookup.ts +124 -74
- package/src/router/match-middleware/cache-store.ts +15 -13
- package/src/router/match-middleware/intercept-resolution.ts +13 -9
- package/src/router/match-result.ts +11 -12
- package/src/router/pattern-matching.ts +27 -12
- package/src/router/revalidation.ts +35 -27
- package/src/router/segment-resolution.ts +139 -121
- package/src/router/types.ts +1 -0
- package/src/router.ts +201 -106
- package/src/rsc/handler.ts +45 -14
- package/src/search-params.ts +218 -0
- package/src/server/context.ts +24 -5
- package/src/server/fetchable-loader-store.ts +32 -0
- package/src/server/loader-registry.ts +1 -1
- package/src/server/request-context.ts +1 -2
- package/src/server.ts +20 -2
- package/src/static-handler.gen.ts +5 -0
- package/src/static-handler.ts +96 -0
- package/src/types.ts +45 -13
- package/src/urls.ts +63 -28
- package/src/vite/ast-handler-extract.ts +345 -0
- package/src/vite/expose-action-id.ts +1 -7
- package/src/vite/expose-id-utils.ts +322 -0
- package/src/vite/expose-internal-ids.ts +1167 -0
- package/src/vite/index.ts +318 -69
- package/src/vite/expose-handle-id.ts +0 -209
- package/src/vite/expose-loader-id.ts +0 -426
- package/src/vite/expose-location-state-id.ts +0 -177
- package/src/vite/expose-prerender-handler-id.ts +0 -429
package/CLAUDE.md
CHANGED
|
@@ -40,4 +40,4 @@ like `useActionState`, refs, and local state. This is extremely hard to debug.
|
|
|
40
40
|
|
|
41
41
|
4. Run `pnpm --filter @rangojs/router exec playwright test loader-behavior` after
|
|
42
42
|
any changes to these files. The skipSSR action tests specifically catch tree
|
|
43
|
-
structure regressions.
|
|
43
|
+
structure regressions.
|
package/dist/bin/rango.js
CHANGED
|
@@ -9,7 +9,7 @@ import { join, dirname, resolve, relative, basename as pathBasename } from "node
|
|
|
9
9
|
import picomatch from "picomatch";
|
|
10
10
|
function extractRoutesFromSource(code) {
|
|
11
11
|
const routes = [];
|
|
12
|
-
const regex = /\bpath(?:\.
|
|
12
|
+
const regex = /\bpath(?:\.[a-zA-Z_$][\w$]*)?\s*\(/g;
|
|
13
13
|
let match;
|
|
14
14
|
while ((match = regex.exec(code)) !== null) {
|
|
15
15
|
const result = parsePathCall(code, match.index + match[0].length);
|
|
@@ -26,12 +26,16 @@ function generatePerModuleTypesSource(routes) {
|
|
|
26
26
|
return true;
|
|
27
27
|
});
|
|
28
28
|
const deduped = /* @__PURE__ */ new Map();
|
|
29
|
-
for (const { name, pattern } of valid) {
|
|
30
|
-
deduped.set(name, pattern);
|
|
29
|
+
for (const { name, pattern, search } of valid) {
|
|
30
|
+
deduped.set(name, { pattern, search });
|
|
31
31
|
}
|
|
32
32
|
const sorted = [...deduped.entries()].sort(([a], [b]) => a.localeCompare(b));
|
|
33
|
-
const body = sorted.map(([name, pattern]) => {
|
|
33
|
+
const body = sorted.map(([name, { pattern, search }]) => {
|
|
34
34
|
const key = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ? name : `"${name}"`;
|
|
35
|
+
if (search && Object.keys(search).length > 0) {
|
|
36
|
+
const searchBody = Object.entries(search).map(([k, v]) => `${k}: "${v}"`).join(", ");
|
|
37
|
+
return ` ${key}: { path: "${pattern}", search: { ${searchBody} } },`;
|
|
38
|
+
}
|
|
35
39
|
return ` ${key}: "${pattern}",`;
|
|
36
40
|
}).join("\n");
|
|
37
41
|
return `// Auto-generated by @rangojs/router - do not edit
|
|
@@ -122,6 +126,53 @@ function extractNameValue(code, pos) {
|
|
|
122
126
|
while (pos < code.length && isWhitespace(code[pos])) pos++;
|
|
123
127
|
return readString(code, pos);
|
|
124
128
|
}
|
|
129
|
+
function matchesSearchColon(code, pos) {
|
|
130
|
+
if (code.slice(pos, pos + 6) !== "search") return false;
|
|
131
|
+
if (pos > 0 && /\w/.test(code[pos - 1])) return false;
|
|
132
|
+
const afterSearch = pos + 6;
|
|
133
|
+
if (afterSearch < code.length && /\w/.test(code[afterSearch])) return false;
|
|
134
|
+
let checkPos = afterSearch;
|
|
135
|
+
while (checkPos < code.length && isWhitespace(code[checkPos])) checkPos++;
|
|
136
|
+
return code[checkPos] === ":";
|
|
137
|
+
}
|
|
138
|
+
function extractSearchValue(code, pos) {
|
|
139
|
+
pos += 6;
|
|
140
|
+
while (pos < code.length && isWhitespace(code[pos])) pos++;
|
|
141
|
+
pos++;
|
|
142
|
+
while (pos < code.length && isWhitespace(code[pos])) pos++;
|
|
143
|
+
if (code[pos] !== "{") return null;
|
|
144
|
+
pos++;
|
|
145
|
+
const schema = {};
|
|
146
|
+
while (pos < code.length) {
|
|
147
|
+
while (pos < code.length && isWhitespace(code[pos])) pos++;
|
|
148
|
+
if (code[pos] === "}") return { value: schema, end: pos + 1 };
|
|
149
|
+
if (code[pos] === ",") {
|
|
150
|
+
pos++;
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
let key;
|
|
154
|
+
if (code[pos] === '"' || code[pos] === "'") {
|
|
155
|
+
const keyStr = readString(code, pos);
|
|
156
|
+
if (!keyStr) return null;
|
|
157
|
+
key = keyStr.value;
|
|
158
|
+
pos = keyStr.end;
|
|
159
|
+
} else {
|
|
160
|
+
const keyStart = pos;
|
|
161
|
+
while (pos < code.length && /[\w$]/.test(code[pos])) pos++;
|
|
162
|
+
if (pos === keyStart) return null;
|
|
163
|
+
key = code.slice(keyStart, pos);
|
|
164
|
+
}
|
|
165
|
+
while (pos < code.length && isWhitespace(code[pos])) pos++;
|
|
166
|
+
if (code[pos] !== ":") return null;
|
|
167
|
+
pos++;
|
|
168
|
+
while (pos < code.length && isWhitespace(code[pos])) pos++;
|
|
169
|
+
const valStr = readString(code, pos);
|
|
170
|
+
if (!valStr) return null;
|
|
171
|
+
schema[key] = valStr.value;
|
|
172
|
+
pos = valStr.end;
|
|
173
|
+
}
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
125
176
|
function parsePathCall(code, pos) {
|
|
126
177
|
while (pos < code.length && isWhitespace(code[pos])) pos++;
|
|
127
178
|
const patternStr = readString(code, pos);
|
|
@@ -130,6 +181,7 @@ function parsePathCall(code, pos) {
|
|
|
130
181
|
pos = patternStr.end;
|
|
131
182
|
let depth = 1;
|
|
132
183
|
let name = null;
|
|
184
|
+
let search;
|
|
133
185
|
while (pos < code.length && depth > 0) {
|
|
134
186
|
const ch = code[pos];
|
|
135
187
|
if (isWhitespace(ch)) {
|
|
@@ -156,6 +208,14 @@ function parsePathCall(code, pos) {
|
|
|
156
208
|
continue;
|
|
157
209
|
}
|
|
158
210
|
}
|
|
211
|
+
if (depth === 2 && ch === "s" && matchesSearchColon(code, pos)) {
|
|
212
|
+
const searchResult = extractSearchValue(code, pos);
|
|
213
|
+
if (searchResult) {
|
|
214
|
+
search = searchResult.value;
|
|
215
|
+
pos = searchResult.end;
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
159
219
|
if (ch === '"' || ch === "`" || ch === "'" && (pos === 0 || !/\w/.test(code[pos - 1]))) {
|
|
160
220
|
pos = skipStringLiteral(code, pos);
|
|
161
221
|
continue;
|
|
@@ -165,7 +225,7 @@ function parsePathCall(code, pos) {
|
|
|
165
225
|
pos++;
|
|
166
226
|
}
|
|
167
227
|
if (name === null) return null;
|
|
168
|
-
return { name, pattern };
|
|
228
|
+
return { name, pattern, ...search ? { search } : {} };
|
|
169
229
|
}
|
|
170
230
|
function findTsFiles(dir, filter) {
|
|
171
231
|
const results = [];
|