@real-router/sources
v0.3.0
Published
Framework-agnostic subscription layer for Real-Router state
Downloads
1,352
Maintainers
Readme
@real-router/sources
Framework-agnostic subscription layer for Real-Router. Reactive primitives compatible with
useSyncExternalStoreand vanilla JS.
Used internally by @real-router/react. Use this package directly when building integrations for other frameworks or vanilla JS applications.
Installation
npm install @real-router/sourcesPeer dependency: @real-router/core
Quick Start
import { createRouter } from "@real-router/core";
import { createRouteSource } from "@real-router/sources";
const router = createRouter([
{ name: "home", path: "/" },
{ name: "users", path: "/users/:id" },
]);
await router.start("/");
const source = createRouteSource(router);
const unsubscribe = source.subscribe(() => {
console.log("Route:", source.getSnapshot().route?.name);
});Source Factories
| Factory | Snapshot | Updates when |
| ------------------------------------------------------- | ----------------------------------------- | --------------------------------------------------- |
| createRouteSource(router) | { route, previousRoute } | Every navigation |
| createRouteNodeSource(router, node) | { route, previousRoute } | Only when node activates/deactivates |
| createActiveRouteSource(router, name, params?, opts?) | boolean | Route active status changes |
| createTransitionSource(router) | { isTransitioning, toRoute, fromRoute } | Transition start/end/cancel/error |
| createErrorSource(router) | { error, toRoute, fromRoute, version } | Navigation error (guard rejection, route not found) |
All factories return a RouterSource<T>:
interface RouterSource<T> {
subscribe(listener: () => void): () => void; // useSyncExternalStore-compatible
getSnapshot(): T; // current value, synchronous
destroy(): void; // teardown, remove router subscription
}Lazy vs Eager Subscription
createRouteSource,createRouteNodeSource,createActiveRouteSource— lazy: subscribe to the router on first listener, unsubscribe when all removedcreateTransitionSource— eager: subscribes immediately (needs to trackTRANSITION_START)createErrorSource— eager: subscribes immediately (needs to trackTRANSITION_ERROR)
createActiveRouteSource Options
const source = createActiveRouteSource(router, "users", undefined, {
strict: false, // default: false — match descendants too
ignoreQueryParams: true, // default: true
});Usage Examples
With React (useSyncExternalStore)
import { useSyncExternalStore } from "react";
import { createRouteSource } from "@real-router/sources";
const source = createRouteSource(router);
function CurrentRoute() {
const { route } = useSyncExternalStore(source.subscribe, source.getSnapshot);
return <p>Current route: {route?.name}</p>;
}With Vanilla JS
import { createRouteNodeSource } from "@real-router/sources";
// Only fires when navigating within the "users" subtree
const source = createRouteNodeSource(router, "users");
const unsubscribe = source.subscribe(() => {
const { route } = source.getSnapshot();
console.log("Users section:", route?.name);
});
unsubscribe(); // automatically unsubscribes from routerTransition Tracking
import { createTransitionSource } from "@real-router/sources";
const source = createTransitionSource(router);
source.subscribe(() => {
const { isTransitioning, toRoute, fromRoute } = source.getSnapshot();
if (isTransitioning) {
showSpinner();
} else {
hideSpinner();
}
});Error Tracking
import { createErrorSource } from "@real-router/sources";
const source = createErrorSource(router);
source.subscribe(() => {
const { error, toRoute } = source.getSnapshot();
if (error) {
console.error(`Navigation to ${toRoute?.name} failed: ${error.code}`);
}
});Documentation
Full documentation: Wiki — sources
Related Packages
| Package | Description |
| ---------------------------------------------------------------------- | ------------------------------------------- |
| @real-router/core | Core router (required dependency) |
| @real-router/react | React integration (uses sources internally) |
| @real-router/rx | Observable API (state$, events$) |
Contributing
See contributing guidelines for development setup and PR process.
