@rangojs/router 0.0.0-experimental.122 → 0.0.0-experimental.125
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/bin/rango.js +10 -6
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +55 -48
- package/package.json +61 -21
- package/skills/caching/SKILL.md +2 -1
- package/skills/hooks/SKILL.md +40 -29
- package/skills/host-router/SKILL.md +16 -2
- package/skills/intercept/SKILL.md +4 -2
- package/skills/layout/SKILL.md +11 -6
- package/skills/loader/SKILL.md +6 -2
- package/skills/middleware/SKILL.md +4 -2
- package/skills/migrate-nextjs/SKILL.md +3 -1
- package/skills/parallel/SKILL.md +9 -4
- package/skills/rango/SKILL.md +12 -0
- package/skills/route/SKILL.md +10 -2
- package/skills/testing/SKILL.md +129 -0
- package/skills/testing/bindings.md +89 -0
- package/skills/testing/cache-prerender.md +98 -0
- package/skills/testing/client-components.md +122 -0
- package/skills/testing/e2e-parity.md +125 -0
- package/skills/testing/flight.md +89 -0
- package/skills/testing/handles.md +129 -0
- package/skills/testing/loader.md +128 -0
- package/skills/testing/middleware.md +99 -0
- package/skills/testing/render-handler.md +118 -0
- package/skills/testing/response-routes.md +95 -0
- package/skills/testing/reverse-and-types.md +84 -0
- package/skills/testing/server-actions.md +107 -0
- package/skills/testing/server-tree.md +128 -0
- package/skills/testing/setup.md +120 -0
- package/src/__internal.ts +0 -65
- package/src/browser/action-coordinator.ts +1 -1
- package/src/browser/action-fence.ts +47 -0
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +1 -83
- package/src/browser/invalidate-client-cache.ts +52 -0
- package/src/browser/navigation-bridge.ts +14 -1
- package/src/browser/navigation-client.ts +14 -1
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +26 -51
- package/src/browser/navigation-transaction.ts +0 -32
- package/src/browser/partial-update.ts +1 -83
- package/src/browser/prefetch/cache.ts +6 -45
- package/src/browser/prefetch/fetch.ts +7 -0
- package/src/browser/prefetch/queue.ts +6 -3
- package/src/browser/rango-state.ts +157 -99
- package/src/browser/react/Link.tsx +0 -2
- package/src/browser/react/NavigationProvider.tsx +2 -1
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/filter-segment-order.ts +0 -2
- package/src/browser/react/index.ts +0 -51
- package/src/browser/react/location-state-shared.ts +0 -13
- package/src/browser/react/location-state.ts +0 -1
- package/src/browser/react/use-action.ts +6 -15
- package/src/browser/react/use-handle.ts +0 -5
- package/src/browser/react/use-link-status.ts +0 -4
- package/src/browser/react/use-navigation.ts +0 -3
- package/src/browser/react/use-params.ts +0 -2
- package/src/browser/react/use-search-params.ts +0 -5
- package/src/browser/react/use-segments.ts +0 -13
- package/src/browser/rsc-router.tsx +12 -4
- package/src/browser/server-action-bridge.ts +77 -15
- package/src/browser/types.ts +7 -2
- package/src/browser/validate-redirect-origin.ts +4 -5
- package/src/build/route-trie.ts +3 -0
- package/src/build/route-types/param-extraction.ts +6 -3
- package/src/build/route-types/router-processing.ts +0 -8
- package/src/cache/cache-policy.ts +0 -54
- package/src/cache/cache-runtime.ts +27 -24
- package/src/cache/cache-scope.ts +0 -27
- package/src/cache/cache-tag.ts +0 -37
- package/src/cache/cf/cf-cache-store.ts +94 -46
- package/src/cache/cf/index.ts +0 -24
- package/src/cache/document-cache.ts +11 -36
- package/src/cache/handle-snapshot.ts +0 -40
- package/src/cache/index.ts +0 -27
- package/src/cache/memory-segment-store.ts +2 -48
- package/src/cache/profile-registry.ts +7 -3
- package/src/cache/read-through-swr.ts +41 -11
- package/src/cache/segment-codec.ts +0 -16
- package/src/cache/types.ts +0 -98
- package/src/client.rsc.tsx +1 -22
- package/src/client.tsx +14 -38
- package/src/component-utils.ts +19 -0
- package/src/deps/ssr.ts +0 -1
- package/src/handle.ts +28 -18
- package/src/handles/MetaTags.tsx +0 -14
- package/src/handles/meta.ts +0 -39
- package/src/host/cookie-handler.ts +0 -36
- package/src/host/errors.ts +0 -24
- package/src/host/index.ts +6 -0
- package/src/host/pattern-matcher.ts +7 -50
- package/src/host/router.ts +1 -65
- package/src/host/testing.ts +40 -27
- package/src/host/types.ts +6 -2
- package/src/href-client.ts +0 -4
- package/src/index.rsc.ts +42 -3
- package/src/index.ts +31 -1
- package/src/internal-debug.ts +2 -4
- package/src/loader.rsc.ts +19 -9
- package/src/loader.ts +12 -4
- package/src/network-error-thrower.tsx +1 -6
- package/src/outlet-provider.tsx +1 -5
- package/src/prerender/param-hash.ts +10 -11
- package/src/prerender/store.ts +23 -30
- package/src/prerender.ts +58 -3
- package/src/root-error-boundary.tsx +1 -19
- package/src/route-content-wrapper.tsx +1 -44
- package/src/route-definition/dsl-helpers.ts +7 -19
- package/src/route-definition/helpers-types.ts +3 -3
- package/src/route-definition/redirect.ts +11 -1
- package/src/route-map-builder.ts +0 -16
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +0 -13
- package/src/router/error-handling.ts +12 -16
- package/src/router/find-match.ts +4 -30
- package/src/router/intercept-resolution.ts +10 -1
- package/src/router/lazy-includes.ts +1 -57
- package/src/router/loader-resolution.ts +3 -2
- package/src/router/logging.ts +0 -6
- package/src/router/manifest.ts +1 -25
- package/src/router/match-api.ts +0 -20
- package/src/router/match-context.ts +0 -22
- package/src/router/match-handlers.ts +57 -58
- package/src/router/match-middleware/background-revalidation.ts +0 -7
- package/src/router/match-middleware/cache-lookup.ts +1 -54
- package/src/router/match-middleware/cache-store.ts +0 -31
- package/src/router/match-middleware/intercept-resolution.ts +0 -22
- package/src/router/match-middleware/segment-resolution.ts +0 -21
- package/src/router/match-pipelines.ts +1 -42
- package/src/router/match-result.ts +1 -52
- package/src/router/metrics.ts +0 -34
- package/src/router/middleware-cookies.ts +0 -13
- package/src/router/middleware-types.ts +0 -115
- package/src/router/middleware.ts +7 -30
- package/src/router/navigation-snapshot.ts +0 -51
- package/src/router/params-util.ts +23 -0
- package/src/router/pattern-matching.ts +1 -33
- package/src/router/prerender-match.ts +33 -45
- package/src/router/request-classification.ts +1 -38
- package/src/router/revalidation.ts +5 -58
- package/src/router/router-context.ts +0 -26
- package/src/router/router-interfaces.ts +7 -0
- package/src/router/router-options.ts +30 -0
- package/src/router/segment-resolution/fresh.ts +25 -57
- package/src/router/segment-resolution/helpers.ts +34 -0
- package/src/router/segment-resolution/loader-cache.ts +10 -13
- package/src/router/segment-resolution/revalidation.ts +5 -42
- package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
- package/src/router/segment-resolution.ts +4 -1
- package/src/router/state-cookie-name.ts +33 -0
- package/src/router/telemetry-otel.ts +0 -20
- package/src/router/telemetry.ts +96 -19
- package/src/router/timeout.ts +0 -20
- package/src/router/trie-matching.ts +63 -40
- package/src/router/types.ts +1 -63
- package/src/router/url-params.ts +0 -5
- package/src/router.ts +40 -9
- package/src/rsc/handler.ts +14 -2
- package/src/rsc/helpers.ts +34 -0
- package/src/rsc/origin-guard.ts +0 -12
- package/src/rsc/progressive-enhancement.ts +4 -1
- package/src/rsc/rsc-rendering.ts +4 -7
- package/src/rsc/runtime-warnings.ts +14 -0
- package/src/rsc/server-action.ts +30 -28
- package/src/rsc/types.ts +2 -1
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +0 -16
- package/src/segment-loader-promise.ts +14 -2
- package/src/segment-system.tsx +79 -88
- package/src/server/cookie-store.ts +52 -1
- package/src/server/handle-store.ts +7 -24
- package/src/server/loader-registry.ts +5 -24
- package/src/server/request-context.ts +74 -77
- package/src/ssr/index.tsx +14 -14
- package/src/static-handler.ts +10 -13
- package/src/testing/cache-status.ts +119 -0
- package/src/testing/collect-handle.ts +40 -0
- package/src/testing/dispatch.ts +581 -0
- package/src/testing/dom.entry.ts +22 -0
- package/src/testing/e2e/fixture.ts +188 -0
- package/src/testing/e2e/index.ts +127 -0
- package/src/testing/e2e/matchers.ts +35 -0
- package/src/testing/e2e/page-helpers.ts +272 -0
- package/src/testing/e2e/parity.ts +387 -0
- package/src/testing/e2e/server.ts +195 -0
- package/src/testing/flight-matchers.ts +97 -0
- package/src/testing/flight-normalize.ts +11 -0
- package/src/testing/flight-runtime.d.ts +57 -0
- package/src/testing/flight-tree.ts +682 -0
- package/src/testing/flight.entry.ts +52 -0
- package/src/testing/flight.ts +186 -0
- package/src/testing/generated-routes.ts +183 -0
- package/src/testing/index.ts +98 -0
- package/src/testing/internal/context.ts +348 -0
- package/src/testing/internal/flight-client-globals.ts +30 -0
- package/src/testing/internal/seed-vars.ts +54 -0
- package/src/testing/render-handler.ts +311 -0
- package/src/testing/render-route.tsx +504 -0
- package/src/testing/run-loader.ts +378 -0
- package/src/testing/run-middleware.ts +205 -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 +305 -0
- package/src/theme/ThemeProvider.tsx +0 -52
- package/src/theme/ThemeScript.tsx +0 -6
- package/src/theme/constants.ts +0 -12
- package/src/theme/index.ts +0 -7
- package/src/theme/theme-context.ts +1 -5
- package/src/theme/theme-script.ts +0 -14
- package/src/theme/use-theme.ts +0 -3
- package/src/types/boundaries.ts +0 -35
- package/src/types/error-types.ts +25 -89
- package/src/types/global-namespace.ts +15 -15
- package/src/types/handler-context.ts +16 -13
- package/src/types/index.ts +0 -10
- package/src/types/request-scope.ts +0 -19
- package/src/types/route-config.ts +6 -50
- package/src/types/route-entry.ts +0 -6
- package/src/types/segments.ts +0 -13
- package/src/urls/include-helper.ts +0 -4
- package/src/urls/index.ts +0 -6
- package/src/urls/path-helper-types.ts +2 -2
- package/src/urls/path-helper.ts +0 -54
- package/src/urls/urls-function.ts +0 -13
- package/src/use-loader.tsx +0 -186
- package/src/vite/discovery/bundle-postprocess.ts +2 -1
- package/src/vite/discovery/discover-routers.ts +6 -7
- package/src/vite/discovery/virtual-module-codegen.ts +1 -11
- package/src/vite/plugin-types.ts +3 -1
- package/src/vite/plugins/cjs-to-esm.ts +0 -11
- package/src/vite/plugins/client-ref-dedup.ts +0 -11
- package/src/vite/plugins/client-ref-hashing.ts +0 -10
- package/src/vite/plugins/cloudflare-protocol-stub.ts +0 -20
- package/src/vite/plugins/expose-action-id.ts +2 -73
- package/src/vite/plugins/expose-id-utils.ts +0 -55
- package/src/vite/plugins/expose-ids/export-analysis.ts +0 -38
- package/src/vite/plugins/expose-ids/handler-transform.ts +0 -15
- package/src/vite/plugins/expose-ids/loader-transform.ts +0 -15
- package/src/vite/plugins/expose-ids/router-transform.ts +0 -13
- package/src/vite/plugins/expose-internal-ids.ts +10 -0
- package/src/vite/plugins/performance-tracks.ts +0 -3
- package/src/vite/plugins/use-cache-transform.ts +0 -36
- package/src/vite/plugins/version-injector.ts +0 -20
- package/src/vite/plugins/version-plugin.ts +1 -49
- package/src/vite/plugins/virtual-entries.ts +0 -15
- package/src/vite/rango.ts +1 -108
- package/src/vite/router-discovery.ts +2 -1
- package/src/vite/utils/ast-handler-extract.ts +0 -16
- package/src/vite/utils/bundle-analysis.ts +6 -13
- package/src/vite/utils/client-chunks.ts +0 -6
- package/src/vite/utils/forward-user-plugins.ts +0 -22
- package/src/vite/utils/manifest-utils.ts +0 -4
- package/src/vite/utils/package-resolution.ts +1 -73
- package/src/vite/utils/prerender-utils.ts +0 -35
- package/src/vite/utils/shared-utils.ts +3 -35
- package/src/browser/react/use-client-cache.ts +0 -58
- package/src/browser/shallow.ts +0 -40
package/dist/bin/rango.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
-
var __esm = (fn, res) => function __init() {
|
|
5
|
-
|
|
4
|
+
var __esm = (fn, res, err) => function __init() {
|
|
5
|
+
if (err) throw err[0];
|
|
6
|
+
try {
|
|
7
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
8
|
+
} catch (e) {
|
|
9
|
+
throw err = [e], e;
|
|
10
|
+
}
|
|
6
11
|
};
|
|
7
12
|
var __export = (target, all) => {
|
|
8
13
|
for (var name in all)
|
|
@@ -22,10 +27,10 @@ function extractParamsFromPattern(pattern) {
|
|
|
22
27
|
function formatRouteEntry(key, pattern, _params, search) {
|
|
23
28
|
const hasSearch = search && Object.keys(search).length > 0;
|
|
24
29
|
if (!hasSearch) {
|
|
25
|
-
return ` ${key}:
|
|
30
|
+
return ` ${key}: ${JSON.stringify(pattern)},`;
|
|
26
31
|
}
|
|
27
|
-
const searchBody = Object.entries(search).map(([k, v]) => `${k}:
|
|
28
|
-
return ` ${key}: { path:
|
|
32
|
+
const searchBody = Object.entries(search).map(([k, v]) => `${k}: ${JSON.stringify(v)}`).join(", ");
|
|
33
|
+
return ` ${key}: { path: ${JSON.stringify(pattern)}, search: { ${searchBody} } },`;
|
|
29
34
|
}
|
|
30
35
|
var init_param_extraction = __esm({
|
|
31
36
|
"src/build/route-types/param-extraction.ts"() {
|
|
@@ -1287,7 +1292,6 @@ function createVersionPlugin() {
|
|
|
1287
1292
|
}
|
|
1288
1293
|
return null;
|
|
1289
1294
|
},
|
|
1290
|
-
// Track RSC module changes and update version
|
|
1291
1295
|
async hotUpdate(ctx) {
|
|
1292
1296
|
if (!isDev) return;
|
|
1293
1297
|
const isRscModule = this.environment?.name === "rsc";
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// src/testing/vitest.ts
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
function here(relativeFromRoot) {
|
|
4
|
+
return fileURLToPath(new URL(`../../${relativeFromRoot}`, import.meta.url));
|
|
5
|
+
}
|
|
6
|
+
function rangoTestAliases(opts = {}) {
|
|
7
|
+
const aliases = [
|
|
8
|
+
// Real impls (index.rsc.ts) for the bare specifier ONLY — exact regex so
|
|
9
|
+
// subpaths (/testing, /client, /cache, ...) are untouched. React stays the
|
|
10
|
+
// client build, so createContext and "use client" modules work.
|
|
11
|
+
{ find: /^@rangojs\/router$/, replacement: here("src/index.rsc.ts") },
|
|
12
|
+
{
|
|
13
|
+
find: "@rangojs/router:version",
|
|
14
|
+
replacement: here("src/testing/vitest-stubs/version.ts")
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
find: /^@vitejs\/plugin-rsc\/rsc$/,
|
|
18
|
+
replacement: here("src/testing/vitest-stubs/plugin-rsc.ts")
|
|
19
|
+
}
|
|
20
|
+
];
|
|
21
|
+
if (opts.preset === "cloudflare") {
|
|
22
|
+
aliases.push(
|
|
23
|
+
{
|
|
24
|
+
find: "cloudflare:workers",
|
|
25
|
+
replacement: here("src/testing/vitest-stubs/cloudflare-workers.ts")
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
find: "cloudflare:email",
|
|
29
|
+
replacement: here("src/testing/vitest-stubs/cloudflare-email.ts")
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return aliases;
|
|
34
|
+
}
|
|
35
|
+
var rangoInlineDeps = [/@rangojs[/\\]router/];
|
|
36
|
+
function rangoTestConfig(opts = {}) {
|
|
37
|
+
return {
|
|
38
|
+
alias: rangoTestAliases(opts),
|
|
39
|
+
// fresh copy so the shared rangoInlineDeps const is never aliased into (or
|
|
40
|
+
// mutated through) a consumer's resolved config
|
|
41
|
+
server: { deps: { inline: [...rangoInlineDeps] } }
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function rangoUseClientTransform() {
|
|
45
|
+
return {
|
|
46
|
+
name: "rango:testing-use-client",
|
|
47
|
+
async transform(code, id) {
|
|
48
|
+
if (id.includes("/node_modules/")) return void 0;
|
|
49
|
+
if (!code.includes("use client")) return void 0;
|
|
50
|
+
const { parseAstAsync } = await import("vite");
|
|
51
|
+
const { hasDirective, transformDirectiveProxyExport } = await import("@vitejs/plugin-rsc/transforms");
|
|
52
|
+
let ast;
|
|
53
|
+
try {
|
|
54
|
+
ast = await parseAstAsync(code);
|
|
55
|
+
} catch {
|
|
56
|
+
return void 0;
|
|
57
|
+
}
|
|
58
|
+
if (!hasDirective(ast.body, "use client")) return void 0;
|
|
59
|
+
const result = transformDirectiveProxyExport(ast, {
|
|
60
|
+
directive: "use client",
|
|
61
|
+
code,
|
|
62
|
+
runtime: (name) => `$$RangoRSD.registerClientReference(() => { throw new Error("client reference " + ${JSON.stringify(name)} + " is not callable on the server"); }, ${JSON.stringify(id)}, ${JSON.stringify(name)})`
|
|
63
|
+
});
|
|
64
|
+
if (!result) return void 0;
|
|
65
|
+
const { output } = result;
|
|
66
|
+
output.prepend(
|
|
67
|
+
`import * as $$RangoRSD from "@vitejs/plugin-rsc/vendor/react-server-dom/server.edge";
|
|
68
|
+
`
|
|
69
|
+
);
|
|
70
|
+
return {
|
|
71
|
+
code: output.toString(),
|
|
72
|
+
map: output.generateMap({ hires: true })
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
export {
|
|
78
|
+
rangoInlineDeps,
|
|
79
|
+
rangoTestAliases,
|
|
80
|
+
rangoTestConfig,
|
|
81
|
+
rangoUseClientTransform
|
|
82
|
+
};
|
package/dist/vite/index.js
CHANGED
|
@@ -431,7 +431,6 @@ function exposeActionId() {
|
|
|
431
431
|
counterTransform?.record(id, performance.now() - start);
|
|
432
432
|
}
|
|
433
433
|
},
|
|
434
|
-
// Build mode: renderChunk runs after all transforms and bundling complete
|
|
435
434
|
renderChunk(code, chunk) {
|
|
436
435
|
const start = counterRender ? performance.now() : 0;
|
|
437
436
|
try {
|
|
@@ -1345,6 +1344,7 @@ ${lazyImports.join(",\n")}
|
|
|
1345
1344
|
// --------------- Loader pre-scan (build mode) ---------------
|
|
1346
1345
|
async buildStart() {
|
|
1347
1346
|
if (!isBuild) return;
|
|
1347
|
+
if (this.environment && this.environment.name !== "rsc") return;
|
|
1348
1348
|
const fs2 = await import("node:fs/promises");
|
|
1349
1349
|
const SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", "dist", "build", "coverage"]);
|
|
1350
1350
|
async function scanDir(dir) {
|
|
@@ -1997,7 +1997,6 @@ function clientRefDedup() {
|
|
|
1997
1997
|
if (this.environment?.name !== "client") return;
|
|
1998
1998
|
if (!importer?.includes(CLIENT_IN_SERVER_PROXY_PREFIX)) return;
|
|
1999
1999
|
if (!source.includes("/node_modules/")) return;
|
|
2000
|
-
if (!importer) return;
|
|
2001
2000
|
const packageName = extractPackageName(source);
|
|
2002
2001
|
if (!packageName) return;
|
|
2003
2002
|
if (clientExclude.includes(packageName)) return;
|
|
@@ -2130,7 +2129,7 @@ import { resolve } from "node:path";
|
|
|
2130
2129
|
// package.json
|
|
2131
2130
|
var package_default = {
|
|
2132
2131
|
name: "@rangojs/router",
|
|
2133
|
-
version: "0.0.0-experimental.
|
|
2132
|
+
version: "0.0.0-experimental.125",
|
|
2134
2133
|
description: "Django-inspired RSC router with composable URL patterns",
|
|
2135
2134
|
keywords: [
|
|
2136
2135
|
"react",
|
|
@@ -2256,6 +2255,31 @@ var package_default = {
|
|
|
2256
2255
|
"./host/testing": {
|
|
2257
2256
|
types: "./src/host/testing.ts",
|
|
2258
2257
|
default: "./src/host/testing.ts"
|
|
2258
|
+
},
|
|
2259
|
+
"./testing": {
|
|
2260
|
+
types: "./src/testing/index.ts",
|
|
2261
|
+
default: "./src/testing/index.ts"
|
|
2262
|
+
},
|
|
2263
|
+
"./testing/vitest": {
|
|
2264
|
+
types: "./src/testing/vitest.ts",
|
|
2265
|
+
default: "./dist/testing/vitest.js"
|
|
2266
|
+
},
|
|
2267
|
+
"./testing/dom": {
|
|
2268
|
+
types: "./src/testing/dom.entry.ts",
|
|
2269
|
+
default: "./src/testing/dom.entry.ts"
|
|
2270
|
+
},
|
|
2271
|
+
"./testing/e2e": {
|
|
2272
|
+
types: "./src/testing/e2e/index.ts",
|
|
2273
|
+
default: "./src/testing/e2e/index.ts"
|
|
2274
|
+
},
|
|
2275
|
+
"./testing/flight": {
|
|
2276
|
+
types: "./src/testing/flight.entry.ts",
|
|
2277
|
+
"react-server": "./src/testing/flight.entry.ts",
|
|
2278
|
+
default: "./src/testing/flight.entry.ts"
|
|
2279
|
+
},
|
|
2280
|
+
"./testing/flight-matchers": {
|
|
2281
|
+
types: "./src/testing/flight-matchers.ts",
|
|
2282
|
+
default: "./src/testing/flight-matchers.ts"
|
|
2259
2283
|
}
|
|
2260
2284
|
},
|
|
2261
2285
|
publishConfig: {
|
|
@@ -2263,14 +2287,15 @@ var package_default = {
|
|
|
2263
2287
|
tag: "experimental"
|
|
2264
2288
|
},
|
|
2265
2289
|
scripts: {
|
|
2266
|
-
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",
|
|
2290
|
+
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/testing/vitest.ts --bundle --format=esm --outfile=dist/testing/vitest.js --platform=node --packages=external && 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",
|
|
2267
2291
|
prepublishOnly: "pnpm build",
|
|
2268
2292
|
typecheck: "tsc --noEmit && tsc -p tsconfig.strict-check.json --noEmit && tsc -p tsconfig.augment-check.json --noEmit",
|
|
2269
2293
|
test: "playwright test",
|
|
2270
2294
|
"test:ui": "playwright test --ui",
|
|
2271
2295
|
"test:hmr-local": "playwright test --project=dev-warmup --project=hmr-routes --project=hmr-basename --project=hmr-prerender --no-deps --workers=1",
|
|
2272
2296
|
"test:unit": "vitest run",
|
|
2273
|
-
"test:unit:watch": "vitest"
|
|
2297
|
+
"test:unit:watch": "vitest",
|
|
2298
|
+
"test:unit:rsc": "vitest run --config vitest.rsc.config.ts"
|
|
2274
2299
|
},
|
|
2275
2300
|
dependencies: {
|
|
2276
2301
|
"@types/debug": "^4.1.12",
|
|
@@ -2278,35 +2303,50 @@ var package_default = {
|
|
|
2278
2303
|
debug: "^4.4.1",
|
|
2279
2304
|
"magic-string": "^0.30.17",
|
|
2280
2305
|
picomatch: "^4.0.3",
|
|
2281
|
-
"rsc-html-stream": "^0.0.7"
|
|
2306
|
+
"rsc-html-stream": "^0.0.7",
|
|
2307
|
+
tinyexec: "^0.3.2"
|
|
2282
2308
|
},
|
|
2283
2309
|
devDependencies: {
|
|
2284
2310
|
"@playwright/test": "^1.49.1",
|
|
2285
2311
|
"@shared/e2e": "workspace:*",
|
|
2312
|
+
"@testing-library/dom": "^10.4.1",
|
|
2313
|
+
"@testing-library/react": "^16.3.2",
|
|
2286
2314
|
"@types/node": "^24.10.1",
|
|
2287
2315
|
"@types/react": "catalog:",
|
|
2288
2316
|
"@types/react-dom": "catalog:",
|
|
2289
2317
|
esbuild: "^0.27.0",
|
|
2318
|
+
"happy-dom": "^20.10.1",
|
|
2290
2319
|
jiti: "^2.6.1",
|
|
2291
2320
|
react: "catalog:",
|
|
2292
2321
|
"react-dom": "catalog:",
|
|
2293
|
-
tinyexec: "^0.3.2",
|
|
2294
2322
|
typescript: "^5.3.0",
|
|
2295
2323
|
vitest: "^4.0.0"
|
|
2296
2324
|
},
|
|
2297
2325
|
peerDependencies: {
|
|
2298
2326
|
"@cloudflare/vite-plugin": "^1.38.0",
|
|
2327
|
+
"@playwright/test": "^1.49.1",
|
|
2328
|
+
"@testing-library/react": ">=16",
|
|
2299
2329
|
"@vitejs/plugin-rsc": "^0.5.26",
|
|
2300
2330
|
react: ">=19.2.6 <20",
|
|
2301
2331
|
"react-dom": ">=19.2.6 <20",
|
|
2302
|
-
vite: "^8.0.0"
|
|
2332
|
+
vite: "^8.0.0",
|
|
2333
|
+
vitest: ">=3"
|
|
2303
2334
|
},
|
|
2304
2335
|
peerDependenciesMeta: {
|
|
2305
2336
|
"@cloudflare/vite-plugin": {
|
|
2306
2337
|
optional: true
|
|
2307
2338
|
},
|
|
2339
|
+
"@playwright/test": {
|
|
2340
|
+
optional: true
|
|
2341
|
+
},
|
|
2342
|
+
"@testing-library/react": {
|
|
2343
|
+
optional: true
|
|
2344
|
+
},
|
|
2308
2345
|
vite: {
|
|
2309
2346
|
optional: true
|
|
2347
|
+
},
|
|
2348
|
+
vitest: {
|
|
2349
|
+
optional: true
|
|
2310
2350
|
}
|
|
2311
2351
|
}
|
|
2312
2352
|
};
|
|
@@ -2381,10 +2421,10 @@ function extractParamsFromPattern(pattern) {
|
|
|
2381
2421
|
function formatRouteEntry(key, pattern, _params, search) {
|
|
2382
2422
|
const hasSearch = search && Object.keys(search).length > 0;
|
|
2383
2423
|
if (!hasSearch) {
|
|
2384
|
-
return ` ${key}:
|
|
2424
|
+
return ` ${key}: ${JSON.stringify(pattern)},`;
|
|
2385
2425
|
}
|
|
2386
|
-
const searchBody = Object.entries(search).map(([k, v]) => `${k}:
|
|
2387
|
-
return ` ${key}: { path:
|
|
2426
|
+
const searchBody = Object.entries(search).map(([k, v]) => `${k}: ${JSON.stringify(v)}`).join(", ");
|
|
2427
|
+
return ` ${key}: { path: ${JSON.stringify(pattern)}, search: { ${searchBody} } },`;
|
|
2388
2428
|
}
|
|
2389
2429
|
|
|
2390
2430
|
// src/build/route-types/ast-route-extraction.ts
|
|
@@ -3241,7 +3281,6 @@ function createVersionPlugin() {
|
|
|
3241
3281
|
}
|
|
3242
3282
|
return null;
|
|
3243
3283
|
},
|
|
3244
|
-
// Track RSC module changes and update version
|
|
3245
3284
|
async hotUpdate(ctx) {
|
|
3246
3285
|
if (!isDev) return;
|
|
3247
3286
|
const isRscModule = this.environment?.name === "rsc";
|
|
@@ -3318,9 +3357,6 @@ function performanceTracksOptimizeDepsPlugin() {
|
|
|
3318
3357
|
const RSDW_CLIENT_RE = /react-server-dom-webpack-client\.browser\.(development|production)\.js$/;
|
|
3319
3358
|
return {
|
|
3320
3359
|
name: "@rangojs/router:performance-tracks-optimize-deps",
|
|
3321
|
-
// Vite 8 optimizes deps with Rolldown (Rollup-style plugin pipeline), so the
|
|
3322
|
-
// pre-bundled RSDW client is patched via load() rather than esbuild's onLoad.
|
|
3323
|
-
// Returning code overrides Rolldown's default filesystem read for the module.
|
|
3324
3360
|
async load(id) {
|
|
3325
3361
|
const cleanId = id.split("?")[0] ?? id;
|
|
3326
3362
|
if (!RSDW_CLIENT_RE.test(cleanId)) return null;
|
|
@@ -3510,7 +3546,6 @@ function hashClientRefs(projectRoot) {
|
|
|
3510
3546
|
const counter = createCounter(debug7, "hash-client-refs");
|
|
3511
3547
|
return {
|
|
3512
3548
|
name: "@rangojs/router:hash-client-refs",
|
|
3513
|
-
// Run after the RSC plugin's transform (default enforce is normal)
|
|
3514
3549
|
enforce: "post",
|
|
3515
3550
|
applyToEnvironment(env) {
|
|
3516
3551
|
return env.name === "rsc";
|
|
@@ -4823,18 +4858,14 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4823
4858
|
if (manifest.routeTrailingSlash) {
|
|
4824
4859
|
Object.assign(mergedRouteTrailingSlash, manifest.routeTrailingSlash);
|
|
4825
4860
|
}
|
|
4826
|
-
flattenLeafEntries(
|
|
4827
|
-
manifest.prefixTree,
|
|
4828
|
-
manifest.routeManifest,
|
|
4829
|
-
newMergedPrecomputedEntries
|
|
4830
|
-
);
|
|
4831
|
-
newPerRouterManifestDataMap.set(id, manifest.routeManifest);
|
|
4832
4861
|
const routerPrecomputed = [];
|
|
4833
4862
|
flattenLeafEntries(
|
|
4834
4863
|
manifest.prefixTree,
|
|
4835
4864
|
manifest.routeManifest,
|
|
4836
4865
|
routerPrecomputed
|
|
4837
4866
|
);
|
|
4867
|
+
newMergedPrecomputedEntries.push(...routerPrecomputed);
|
|
4868
|
+
newPerRouterManifestDataMap.set(id, manifest.routeManifest);
|
|
4838
4869
|
newPerRouterPrecomputedMap.set(id, routerPrecomputed);
|
|
4839
4870
|
console.log(
|
|
4840
4871
|
`[rango] Router "${id}" -> ${routeCount} routes (${staticRoutes} static, ${dynamicRoutes} dynamic)`
|
|
@@ -5159,7 +5190,7 @@ function generatePerRouterModule(state, routerId) {
|
|
|
5159
5190
|
`export const precomputedEntries = ${jsonParseExpression(entries)};`
|
|
5160
5191
|
);
|
|
5161
5192
|
}
|
|
5162
|
-
return lines.join("\n") || "
|
|
5193
|
+
return lines.join("\n") || "";
|
|
5163
5194
|
}
|
|
5164
5195
|
|
|
5165
5196
|
// src/vite/discovery/bundle-postprocess.ts
|
|
@@ -5230,7 +5261,7 @@ function postprocessBundle(state) {
|
|
|
5230
5261
|
manifestMap[key] = `./assets/${assetFileName}`;
|
|
5231
5262
|
}
|
|
5232
5263
|
const manifestCode = [
|
|
5233
|
-
`const m
|
|
5264
|
+
`const m=${jsonParseExpression(manifestMap)};`,
|
|
5234
5265
|
`export function loadPrerenderAsset(s){return import(s)}`,
|
|
5235
5266
|
`export default m;`,
|
|
5236
5267
|
""
|
|
@@ -6494,8 +6525,6 @@ async function rango(options) {
|
|
|
6494
6525
|
enforce: "pre",
|
|
6495
6526
|
config() {
|
|
6496
6527
|
return {
|
|
6497
|
-
// Exclude rsc-router modules from optimization to prevent module duplication
|
|
6498
|
-
// This ensures the same Context instance is used by both browser entry and RSC proxy modules
|
|
6499
6528
|
optimizeDeps: {
|
|
6500
6529
|
exclude: excludeDeps,
|
|
6501
6530
|
rolldownOptions: sharedRolldownOptions
|
|
@@ -6518,21 +6547,12 @@ async function rango(options) {
|
|
|
6518
6547
|
client: {
|
|
6519
6548
|
build: {
|
|
6520
6549
|
rollupOptions: {
|
|
6521
|
-
// FILE_NAME_CONFLICT (and any other client-build warning) is
|
|
6522
|
-
// emitted by the CLIENT environment build, which consults THIS
|
|
6523
|
-
// env's onwarn -- Vite 8's environment builds do NOT propagate
|
|
6524
|
-
// the top-level build.rollupOptions.onwarn into the client env.
|
|
6525
|
-
// Wire it here so the suppression runs where the conflicts
|
|
6526
|
-
// originate (the top-level handler is invoked 0x for these; the
|
|
6527
|
-
// client-env handler is invoked for all of them).
|
|
6528
6550
|
onwarn,
|
|
6529
6551
|
output: {
|
|
6530
6552
|
manualChunks: getManualChunks
|
|
6531
6553
|
}
|
|
6532
6554
|
}
|
|
6533
6555
|
},
|
|
6534
|
-
// Pre-bundle rsc-html-stream to prevent discovery during first request
|
|
6535
|
-
// Exclude rsc-router modules to ensure same Context instance
|
|
6536
6556
|
optimizeDeps: {
|
|
6537
6557
|
include: [nested("rsc-html-stream/client")],
|
|
6538
6558
|
exclude: excludeDeps,
|
|
@@ -6540,12 +6560,9 @@ async function rango(options) {
|
|
|
6540
6560
|
}
|
|
6541
6561
|
},
|
|
6542
6562
|
ssr: {
|
|
6543
|
-
// Build SSR inside RSC directory so wrangler can deploy self-contained dist/rsc
|
|
6544
6563
|
build: {
|
|
6545
6564
|
outDir: "./dist/rsc/ssr"
|
|
6546
6565
|
},
|
|
6547
|
-
// Pre-bundle SSR entry and React for proper module linking with childEnvironments
|
|
6548
|
-
// All deps must be listed to avoid late discovery triggering ERR_OUTDATED_OPTIMIZED_DEP
|
|
6549
6566
|
optimizeDeps: {
|
|
6550
6567
|
entries: [finalEntries.ssr],
|
|
6551
6568
|
include: [
|
|
@@ -6565,10 +6582,7 @@ async function rango(options) {
|
|
|
6565
6582
|
}
|
|
6566
6583
|
},
|
|
6567
6584
|
rsc: {
|
|
6568
|
-
// RSC environment needs exclude list and esbuild options
|
|
6569
|
-
// Exclude rsc-router modules to prevent createContext in RSC environment
|
|
6570
6585
|
optimizeDeps: {
|
|
6571
|
-
// Pre-bundle all RSC deps to prevent late discovery triggering ERR_OUTDATED_OPTIMIZED_DEP
|
|
6572
6586
|
include: [
|
|
6573
6587
|
"react",
|
|
6574
6588
|
"react/jsx-runtime",
|
|
@@ -6654,13 +6668,6 @@ ${list}`);
|
|
|
6654
6668
|
client: {
|
|
6655
6669
|
build: {
|
|
6656
6670
|
rollupOptions: {
|
|
6657
|
-
// FILE_NAME_CONFLICT (and any other client-build warning) is
|
|
6658
|
-
// emitted by the CLIENT environment build, which consults THIS
|
|
6659
|
-
// env's onwarn -- Vite 8's environment builds do NOT propagate
|
|
6660
|
-
// the top-level build.rollupOptions.onwarn into the client env.
|
|
6661
|
-
// Wire it here so the suppression runs where the conflicts
|
|
6662
|
-
// originate (the top-level handler is invoked 0x for these; the
|
|
6663
|
-
// client-env handler is invoked for all of them).
|
|
6664
6671
|
onwarn,
|
|
6665
6672
|
output: {
|
|
6666
6673
|
manualChunks: getManualChunks
|
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.125",
|
|
4
4
|
"description": "Django-inspired RSC router with composable URL patterns",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -126,57 +126,97 @@
|
|
|
126
126
|
"./host/testing": {
|
|
127
127
|
"types": "./src/host/testing.ts",
|
|
128
128
|
"default": "./src/host/testing.ts"
|
|
129
|
+
},
|
|
130
|
+
"./testing": {
|
|
131
|
+
"types": "./src/testing/index.ts",
|
|
132
|
+
"default": "./src/testing/index.ts"
|
|
133
|
+
},
|
|
134
|
+
"./testing/vitest": {
|
|
135
|
+
"types": "./src/testing/vitest.ts",
|
|
136
|
+
"default": "./dist/testing/vitest.js"
|
|
137
|
+
},
|
|
138
|
+
"./testing/dom": {
|
|
139
|
+
"types": "./src/testing/dom.entry.ts",
|
|
140
|
+
"default": "./src/testing/dom.entry.ts"
|
|
141
|
+
},
|
|
142
|
+
"./testing/e2e": {
|
|
143
|
+
"types": "./src/testing/e2e/index.ts",
|
|
144
|
+
"default": "./src/testing/e2e/index.ts"
|
|
145
|
+
},
|
|
146
|
+
"./testing/flight": {
|
|
147
|
+
"types": "./src/testing/flight.entry.ts",
|
|
148
|
+
"react-server": "./src/testing/flight.entry.ts",
|
|
149
|
+
"default": "./src/testing/flight.entry.ts"
|
|
150
|
+
},
|
|
151
|
+
"./testing/flight-matchers": {
|
|
152
|
+
"types": "./src/testing/flight-matchers.ts",
|
|
153
|
+
"default": "./src/testing/flight-matchers.ts"
|
|
129
154
|
}
|
|
130
155
|
},
|
|
131
156
|
"publishConfig": {
|
|
132
157
|
"access": "public",
|
|
133
158
|
"tag": "experimental"
|
|
134
159
|
},
|
|
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:hmr-local": "playwright test --project=dev-warmup --project=hmr-routes --project=hmr-basename --project=hmr-prerender --no-deps --workers=1",
|
|
142
|
-
"test:unit": "vitest run",
|
|
143
|
-
"test:unit:watch": "vitest"
|
|
144
|
-
},
|
|
145
160
|
"dependencies": {
|
|
146
161
|
"@types/debug": "^4.1.12",
|
|
147
162
|
"@vitejs/plugin-rsc": "^0.5.26",
|
|
148
163
|
"debug": "^4.4.1",
|
|
149
164
|
"magic-string": "^0.30.17",
|
|
150
165
|
"picomatch": "^4.0.3",
|
|
151
|
-
"rsc-html-stream": "^0.0.7"
|
|
166
|
+
"rsc-html-stream": "^0.0.7",
|
|
167
|
+
"tinyexec": "^0.3.2"
|
|
152
168
|
},
|
|
153
169
|
"devDependencies": {
|
|
154
170
|
"@playwright/test": "^1.49.1",
|
|
155
|
-
"@
|
|
171
|
+
"@testing-library/dom": "^10.4.1",
|
|
172
|
+
"@testing-library/react": "^16.3.2",
|
|
156
173
|
"@types/node": "^24.10.1",
|
|
157
|
-
"@types/react": "
|
|
158
|
-
"@types/react-dom": "
|
|
174
|
+
"@types/react": "^19.2.7",
|
|
175
|
+
"@types/react-dom": "^19.2.3",
|
|
159
176
|
"esbuild": "^0.27.0",
|
|
177
|
+
"happy-dom": "^20.10.1",
|
|
160
178
|
"jiti": "^2.6.1",
|
|
161
|
-
"react": "
|
|
162
|
-
"react-dom": "
|
|
163
|
-
"tinyexec": "^0.3.2",
|
|
179
|
+
"react": "^19.2.6",
|
|
180
|
+
"react-dom": "^19.2.6",
|
|
164
181
|
"typescript": "^5.3.0",
|
|
165
|
-
"vitest": "^4.0.0"
|
|
182
|
+
"vitest": "^4.0.0",
|
|
183
|
+
"@shared/e2e": "0.0.1"
|
|
166
184
|
},
|
|
167
185
|
"peerDependencies": {
|
|
168
186
|
"@cloudflare/vite-plugin": "^1.38.0",
|
|
187
|
+
"@playwright/test": "^1.49.1",
|
|
188
|
+
"@testing-library/react": ">=16",
|
|
169
189
|
"@vitejs/plugin-rsc": "^0.5.26",
|
|
170
190
|
"react": ">=19.2.6 <20",
|
|
171
191
|
"react-dom": ">=19.2.6 <20",
|
|
172
|
-
"vite": "^8.0.0"
|
|
192
|
+
"vite": "^8.0.0",
|
|
193
|
+
"vitest": ">=3"
|
|
173
194
|
},
|
|
174
195
|
"peerDependenciesMeta": {
|
|
175
196
|
"@cloudflare/vite-plugin": {
|
|
176
197
|
"optional": true
|
|
177
198
|
},
|
|
199
|
+
"@playwright/test": {
|
|
200
|
+
"optional": true
|
|
201
|
+
},
|
|
202
|
+
"@testing-library/react": {
|
|
203
|
+
"optional": true
|
|
204
|
+
},
|
|
178
205
|
"vite": {
|
|
179
206
|
"optional": true
|
|
207
|
+
},
|
|
208
|
+
"vitest": {
|
|
209
|
+
"optional": true
|
|
180
210
|
}
|
|
211
|
+
},
|
|
212
|
+
"scripts": {
|
|
213
|
+
"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/testing/vitest.ts --bundle --format=esm --outfile=dist/testing/vitest.js --platform=node --packages=external && 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",
|
|
214
|
+
"typecheck": "tsc --noEmit && tsc -p tsconfig.strict-check.json --noEmit && tsc -p tsconfig.augment-check.json --noEmit",
|
|
215
|
+
"test": "playwright test",
|
|
216
|
+
"test:ui": "playwright test --ui",
|
|
217
|
+
"test:hmr-local": "playwright test --project=dev-warmup --project=hmr-routes --project=hmr-basename --project=hmr-prerender --no-deps --workers=1",
|
|
218
|
+
"test:unit": "vitest run",
|
|
219
|
+
"test:unit:watch": "vitest",
|
|
220
|
+
"test:unit:rsc": "vitest run --config vitest.rsc.config.ts"
|
|
181
221
|
}
|
|
182
|
-
}
|
|
222
|
+
}
|
package/skills/caching/SKILL.md
CHANGED
|
@@ -471,6 +471,7 @@ cache({ store: checkoutCache }, () => [
|
|
|
471
471
|
```typescript
|
|
472
472
|
import { urls } from "@rangojs/router";
|
|
473
473
|
import { MemorySegmentCacheStore } from "@rangojs/router/cache";
|
|
474
|
+
import * as CartActions from "./actions/cart";
|
|
474
475
|
|
|
475
476
|
// Custom store for checkout (short TTL)
|
|
476
477
|
const checkoutCache = new MemorySegmentCacheStore({
|
|
@@ -499,7 +500,7 @@ export const urlpatterns = urls(({ path, layout, cache, loader, revalidate }) =>
|
|
|
499
500
|
path("/shop/product/:slug", ProductPage, { name: "product" }, () => [
|
|
500
501
|
loader(ProductLoader, () => [cache({ ttl: 120 })]),
|
|
501
502
|
loader(CartLoader, () => [
|
|
502
|
-
revalidate((
|
|
503
|
+
revalidate((ctx) => ctx.isAction(CartActions) || undefined),
|
|
503
504
|
]),
|
|
504
505
|
]),
|
|
505
506
|
]),
|
package/skills/hooks/SKILL.md
CHANGED
|
@@ -89,8 +89,8 @@ import { useSegments } from "@rangojs/router/client";
|
|
|
89
89
|
function Breadcrumbs() {
|
|
90
90
|
const { path, segmentIds, location } = useSegments();
|
|
91
91
|
|
|
92
|
-
// path: ["
|
|
93
|
-
// segmentIds: ["
|
|
92
|
+
// path: ["shop", "products", "123"] (split on "/", no leading slash on any element)
|
|
93
|
+
// segmentIds: ["L0", "L0L1", "L0L1R0"] (opaque internal short-codes, not route names)
|
|
94
94
|
// location: URL object
|
|
95
95
|
|
|
96
96
|
return <nav>{path.join(" > ")}</nav>;
|
|
@@ -683,33 +683,44 @@ ProductState.delete();
|
|
|
683
683
|
| `.write()` | yes (replace this slot) | no | throws |
|
|
684
684
|
| `.delete()` | yes (remove this slot) | no | throws |
|
|
685
685
|
|
|
686
|
-
## Cache
|
|
686
|
+
## Cache Control
|
|
687
687
|
|
|
688
|
-
###
|
|
688
|
+
### invalidateClientCache()
|
|
689
689
|
|
|
690
|
-
|
|
690
|
+
Force the client's caches to miss after a mutation the router can't see (a REST
|
|
691
|
+
call, a WebSocket push, a login). It is a plain function, not a hook, so it works
|
|
692
|
+
from module-level callbacks too. Imported from the root entry `@rangojs/router`,
|
|
693
|
+
it is selected by export conditions: in a client component it marks the caches
|
|
694
|
+
stale immediately; from a handler/server component it writes a rotated
|
|
695
|
+
`Set-Cookie` for the responding client.
|
|
691
696
|
|
|
692
697
|
```tsx
|
|
693
698
|
"use client";
|
|
694
|
-
import {
|
|
699
|
+
import { invalidateClientCache } from "@rangojs/router";
|
|
695
700
|
|
|
696
701
|
function SaveButton() {
|
|
697
|
-
const { clear } = useClientCache();
|
|
698
|
-
|
|
699
702
|
const handleSave = async () => {
|
|
700
703
|
await fetch("/api/data", {
|
|
701
704
|
method: "POST",
|
|
702
705
|
body: JSON.stringify(data),
|
|
703
706
|
});
|
|
704
707
|
|
|
705
|
-
// Invalidate
|
|
706
|
-
|
|
708
|
+
// Invalidate the client's caches after the mutation
|
|
709
|
+
invalidateClientCache();
|
|
707
710
|
};
|
|
708
711
|
|
|
709
712
|
return <button onClick={handleSave}>Save</button>;
|
|
710
713
|
}
|
|
711
714
|
```
|
|
712
715
|
|
|
716
|
+
A module-level subscription works the same way (no component needed):
|
|
717
|
+
|
|
718
|
+
```ts
|
|
719
|
+
import { invalidateClientCache } from "@rangojs/router";
|
|
720
|
+
|
|
721
|
+
socket.on("catalog-updated", () => invalidateClientCache());
|
|
722
|
+
```
|
|
723
|
+
|
|
713
724
|
**Use cases**: REST API mutations, WebSocket updates, non-RSC data changes.
|
|
714
725
|
|
|
715
726
|
## Outlet Components
|
|
@@ -892,22 +903,22 @@ See `/links` for the full URL generation guide. `ctx.reverse()` is server-only;
|
|
|
892
903
|
|
|
893
904
|
## Hook Summary
|
|
894
905
|
|
|
895
|
-
| Hook
|
|
896
|
-
|
|
|
897
|
-
| `useParams()`
|
|
898
|
-
| `usePathname()`
|
|
899
|
-
| `useSearchParams()`
|
|
900
|
-
| `useHref()`
|
|
901
|
-
| `useMount()`
|
|
902
|
-
| `useReverse()`
|
|
903
|
-
| `useNavigation()`
|
|
904
|
-
| `useRouter()`
|
|
905
|
-
| `useSegments()`
|
|
906
|
-
| `useLinkStatus()`
|
|
907
|
-
| `useLoader()`
|
|
908
|
-
| `useFetchLoader()`
|
|
909
|
-
| `useRefreshLoaders()`
|
|
910
|
-
| `useHandle()`
|
|
911
|
-
| `useAction()`
|
|
912
|
-
| `useLocationState()`
|
|
913
|
-
| `
|
|
906
|
+
| Hook | Purpose | Returns |
|
|
907
|
+
| ------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------ |
|
|
908
|
+
| `useParams()` | Route params | `Readonly<T>` (default `Record<string, string>`) or selected value |
|
|
909
|
+
| `usePathname()` | Current pathname | `string` |
|
|
910
|
+
| `useSearchParams()` | URL search params | `ReadonlyURLSearchParams` |
|
|
911
|
+
| `useHref()` | Mount-aware href | `(path) => string` |
|
|
912
|
+
| `useMount()` | Current include() mount path | `string` |
|
|
913
|
+
| `useReverse()` | Local reverse for imported routes | `(name, params?, search?) => string` |
|
|
914
|
+
| `useNavigation()` | Reactive navigation state | state, location, isStreaming |
|
|
915
|
+
| `useRouter()` | Stable router actions | push, replace, refresh, prefetch, back, forward |
|
|
916
|
+
| `useSegments()` | URL path & segment IDs | path, segmentIds, location |
|
|
917
|
+
| `useLinkStatus()` | Link pending state | { pending } |
|
|
918
|
+
| `useLoader()` | Loader data (strict) | data, isLoading, error |
|
|
919
|
+
| `useFetchLoader()` | Loader with on-demand fetch | data, load, isLoading |
|
|
920
|
+
| `useRefreshLoaders()` | Refresh cross-loader group(s) | `() => (groups: string \| string[]) => Promise<void>` |
|
|
921
|
+
| `useHandle()` | Accumulated handle data | T (handle type) |
|
|
922
|
+
| `useAction()` | Server action state | state, error, result |
|
|
923
|
+
| `useLocationState()` | History state (persists or flash) | T \| undefined |
|
|
924
|
+
| `invalidateClientCache()` | Force client caches to miss (function, not a hook; root entry) | `void` |
|