@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.
Files changed (66) hide show
  1. package/CLAUDE.md +1 -1
  2. package/dist/bin/rango.js +65 -5
  3. package/dist/vite/index.js +1378 -710
  4. package/package.json +1 -1
  5. package/skills/hooks/SKILL.md +5 -1
  6. package/skills/links/SKILL.md +12 -0
  7. package/skills/loader/SKILL.md +24 -0
  8. package/skills/mime-routes/SKILL.md +1 -1
  9. package/skills/prerender/SKILL.md +41 -17
  10. package/skills/response-routes/SKILL.md +7 -7
  11. package/skills/route/SKILL.md +41 -3
  12. package/skills/typesafety/SKILL.md +91 -0
  13. package/src/browser/logging.ts +44 -0
  14. package/src/browser/navigation-bridge.ts +17 -0
  15. package/src/browser/navigation-client.ts +35 -9
  16. package/src/browser/partial-update.ts +2 -3
  17. package/src/browser/react/location-state-shared.ts +3 -3
  18. package/src/browser/server-action-bridge.ts +37 -14
  19. package/src/build/generate-manifest.ts +20 -1
  20. package/src/build/generate-route-types.ts +235 -34
  21. package/src/handle.ts +3 -3
  22. package/src/index.rsc.ts +55 -7
  23. package/src/index.ts +84 -27
  24. package/src/internal-debug.ts +5 -0
  25. package/src/loader.rsc.ts +8 -51
  26. package/src/loader.ts +1 -1
  27. package/src/prerender.ts +18 -16
  28. package/src/reverse.ts +75 -32
  29. package/src/route-definition.ts +21 -2
  30. package/src/route-map-builder.ts +85 -0
  31. package/src/route-types.ts +5 -3
  32. package/src/router/handler-context.ts +35 -15
  33. package/src/router/intercept-resolution.ts +15 -12
  34. package/src/router/loader-resolution.ts +6 -5
  35. package/src/router/logging.ts +145 -0
  36. package/src/router/match-api.ts +29 -31
  37. package/src/router/match-middleware/background-revalidation.ts +12 -5
  38. package/src/router/match-middleware/cache-lookup.ts +124 -74
  39. package/src/router/match-middleware/cache-store.ts +15 -13
  40. package/src/router/match-middleware/intercept-resolution.ts +13 -9
  41. package/src/router/match-result.ts +11 -12
  42. package/src/router/pattern-matching.ts +27 -12
  43. package/src/router/revalidation.ts +35 -27
  44. package/src/router/segment-resolution.ts +139 -121
  45. package/src/router/types.ts +1 -0
  46. package/src/router.ts +201 -106
  47. package/src/rsc/handler.ts +45 -14
  48. package/src/search-params.ts +218 -0
  49. package/src/server/context.ts +24 -5
  50. package/src/server/fetchable-loader-store.ts +32 -0
  51. package/src/server/loader-registry.ts +1 -1
  52. package/src/server/request-context.ts +1 -2
  53. package/src/server.ts +20 -2
  54. package/src/static-handler.gen.ts +5 -0
  55. package/src/static-handler.ts +96 -0
  56. package/src/types.ts +45 -13
  57. package/src/urls.ts +63 -28
  58. package/src/vite/ast-handler-extract.ts +345 -0
  59. package/src/vite/expose-action-id.ts +1 -7
  60. package/src/vite/expose-id-utils.ts +322 -0
  61. package/src/vite/expose-internal-ids.ts +1167 -0
  62. package/src/vite/index.ts +318 -69
  63. package/src/vite/expose-handle-id.ts +0 -209
  64. package/src/vite/expose-loader-id.ts +0 -426
  65. package/src/vite/expose-location-state-id.ts +0 -177
  66. 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(?:\.(?:json|text|html|xml|image|stream|any))?\s*\(/g;
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 = [];