Abstract Class: RouterBridgeBase
API / @xmachines/play-router / RouterBridgeBase
Defined in: router-bridge-base.ts:100
Abstract base class for all @xmachines router adapter bridges.
Implements RouterBridge protocol and contains all common bridge logic. Subclasses only need to implement the 3 abstract methods that differ between frameworks.
Extended by
ReactRouterBridgeSolidRouterBridgeTanStackReactRouterBridgeTanStackSolidRouterBridgeVueRouterBridge
Implements
Constructors
Constructor
new RouterBridgeBase(actor, routeMap): RouterBridgeBase;Defined in: router-bridge-base.ts:124
Parameters
| Parameter | Type | Description |
|---|---|---|
actor | RoutableActor | A RoutableActor exposing currentRoute, initialRoute, and send. |
routeMap | { getPathByStateId: string | null | undefined; getStateIdByPath: string | null | undefined; } | Bidirectional route map for stateId ↔ path resolution. Provide getStateIdByPath and getPathByStateId. Framework adapters typically wrap the result of createRouteMap(machine) or an equivalent. |
routeMap.getPathByStateId | - | |
routeMap.getStateIdByPath | - |
Returns
RouterBridgeBase
Properties
| Property | Modifier | Type | Default value | Description | Defined in |
|---|---|---|---|---|---|
actor | readonly | RoutableActor | undefined | A RoutableActor exposing currentRoute, initialRoute, and send. | router-bridge-base.ts:125 |
hasConnectedOnce | protected | boolean | false | - | router-bridge-base.ts:103 |
isConnected | protected | boolean | false | - | router-bridge-base.ts:102 |
isProcessingNavigation | protected | boolean | false | Guards syncActorFromRouter against re-entrant calls triggered by the actor’s own guard redirects (router→actor send → signal fires → actor→router push → another syncActorFromRouter before the first one returns). NOT used for actor→router echo suppression — that is handled exclusively by lastSyncedPath, which is updated before navigateRouter() is called so any router callback for the same path short-circuits at the sanitized === lastSyncedPath check in syncActorFromRouter. | router-bridge-base.ts:115 |
lastSyncedPath | protected | string | null | null | - | router-bridge-base.ts:104 |
routeMap | readonly | object | undefined | Bidirectional route map for stateId ↔ path resolution. Provide getStateIdByPath and getPathByStateId. Framework adapters typically wrap the result of createRouteMap(machine) or an equivalent. | router-bridge-base.ts:126 |
routeMap.getPathByStateId | public | string | null | undefined | undefined | - | router-bridge-base.ts:128 |
routeMap.getStateIdByPath | public | string | null | undefined | undefined | - | router-bridge-base.ts:127 |
routeWatcher | protected | RouteWatcherHandle | null | null | - | router-bridge-base.ts:116 |
Methods
connect()
connect(): void;Defined in: router-bridge-base.ts:152
Connect the router bridge to the Actor.
Sets up the TC39 Signal watcher for actor → router direction and starts watching router changes (framework-specific).
Ordering here is part of the bridge contract:
lastSyncedPathis seeded in the constructor fromactor.currentRoute- the actor watcher is installed before adapter router subscriptions
- initial sync then resolves deep-link vs restore using
actor.initialRoute
Adapters that need custom initial-sync behavior should override
getInitialRouterPath() rather than reordering connect() steps.
Returns
void
Implementation of
disconnect()
disconnect(): void;Defined in: router-bridge-base.ts:248
Disconnect the router bridge from the Actor.
Stops signal watching and unregisters framework-specific router listener.
Returns
void
Implementation of
extractParams()
protected extractParams(pathname, stateId): Record<string, string>;Defined in: router-bridge-base.ts:402
Extract path parameters from URL using the URLPattern API.
Accesses globalThis.URLPattern at runtime — no polyfill is imported by this
library. If URLPattern is unavailable and the matched route has parameterized
segments, a URLPatternUnavailableError is thrown — callers must provide a polyfill
for environments without native URLPattern support (Node.js < 24, older browsers).
Parameters
| Parameter | Type | Description |
|---|---|---|
pathname | string | The actual URL path (e.g., ‘/profile/john’) |
stateId | string | The matched state ID for looking up the route pattern |
Returns
Record<string, string>
Extracted path parameters, or empty object if no match
Throws
When URLPattern is absent and the route is parameterized
extractQuery()
protected extractQuery(search): Record<string, string>;Defined in: router-bridge-base.ts:439
Extract query parameters from URL search string.
Parameters
| Parameter | Type | Description |
|---|---|---|
search | string | URL search string (e.g., ‘?tab=security&page=1’) |
Returns
Record<string, string>
Extracted query parameters or empty object
getInitialRouterPath()
protected getInitialRouterPath(): string | null | undefined;Defined in: router-bridge-base.ts:512
Return the router’s current pathname at connect() time.
Called once during connect() to perform the initial URL → actor sync.
router.subscribe() only fires on future navigation events; it does not
replay the already-loaded location. Subclasses that can read the router’s
current location synchronously (e.g. router.state.location.pathname)
should override this method so that deep-link / direct-URL loads drive the
actor to the correct state instead of leaving it at its machine default.
Return semantics:
string→ router has a current path; base connect() will sync actor from routernull→ router is active but has no current path yet; base connect() will sync router from actorundefined→ adapter handles initial sync itself and base connect() should stay out of the way
The default returns undefined, preserving the previous behaviour for
bridges that have not yet implemented this hook.
Returns
string | null | undefined
getInitialRouterSearch()
protected getInitialRouterSearch(): string | undefined;Defined in: router-bridge-base.ts:529
Return the router’s current search string at connect() time.
Paired with getInitialRouterPath() — called once during connect() to pass
the initial URL query string to syncActorFromRouter(). If the router’s current
URL has no search (or the subclass doesn’t override this), returns undefined
and syncActorFromRouter will produce an empty query: {} in the event.
Subclasses that override getInitialRouterPath() and have a query string
available should also override this method.
Returns
string | undefined
URL search string (e.g. "?tab=security"), or undefined if not available.
navigateRouter()
abstract protected navigateRouter(path): void;Defined in: router-bridge-base.ts:448
Must trigger the framework router’s navigation (e.g., router.navigate(path)).
Parameters
| Parameter | Type |
|---|---|
path | string |
Returns
void
resolveNavigationPath()
protected resolveNavigationPath(route): string | null;Defined in: router-bridge-base.ts:424
Resolve an actor route value to a concrete URL path for navigation.
Bridges that receive raw actor.currentRoute values in navigateRouter
can call this to normalize stateIds (with or without # prefix) to paths.
Returns null when navigation is not possible:
- unknown stateId with no route map entry
- parameterized pattern (e.g.
/profile/:id) — no concrete values available - non-path string that isn’t a known stateId
Route maps may store stateIds with or without the # prefix; both forms
are tried automatically.
Parameters
| Parameter | Type | Description |
|---|---|---|
route | string | Raw actor route value (stateId, #-stateId, or concrete path) |
Returns
string | null
Concrete URL path, or null if navigation should be skipped
sanitizePath()
protected sanitizePath(pathname): string | null;Defined in: router-bridge-base.ts:466
Sanitize and validate a raw URL pathname received from the router.
Applies the path-length cap (2048 chars), strips query strings and fragments that may have been included in the pathname segment, and normalises consecutive slashes.
Implementations that bypass syncActorFromRouter() (e.g. when using
framework-native reactive watchers that receive pre-parsed route objects)
MUST call this method before passing the path to any route-map lookup.
syncActorFromRouter() calls this internally, so bridges that delegate
to it do not need to call sanitizePath themselves.
Parameters
| Parameter | Type | Description |
|---|---|---|
pathname | string | Raw URL pathname from the framework router. |
Returns
string | null
Sanitized pathname, or null if the path is invalid / too long.
syncActorFromRouter()
protected syncActorFromRouter(pathname, search?): void;Defined in: router-bridge-base.ts:324
Sync actor state when router location changes.
Known path: sends a play.route event to the actor with the matched
stateId, params, and query. Prevents circular updates via the
isProcessingNavigation flag.
Unknown/unmapped path: does NOT send a play.route event (actor state
is unchanged). Instead, actively corrects the browser URL by calling
navigateRouter(actor.currentRoute.get()) — keeping the URL in sync with
actor state even when the user types an invalid path into the address bar
or pushes one programmatically mid-session. lastSyncedPath is set to the
resolved concrete path before calling navigateRouter so the router’s own
callback for that navigation short-circuits the echo-suppression guard and
sends no spurious event.
Parameters
| Parameter | Type |
|---|---|
pathname | string |
search? | string |
Returns
void
syncRouterFromActor()
protected syncRouterFromActor(route): void;Defined in: router-bridge-base.ts:289
Sync router location when actor route signal changes.
Calls navigateRouter() for framework-specific navigation.
Echo suppression — preventing the router’s own callback from re-driving the
actor — is handled entirely by lastSyncedPath: it is set to route before
navigateRouter() is called, so any syncActorFromRouter invocation for the
same path short-circuits at the sanitized === lastSyncedPath check and sends
no event regardless of whether the callback fires synchronously or asynchronously.
isProcessingNavigation is NOT set here — it is only used inside
syncActorFromRouter to guard against re-entrant guard-redirect loops.
Parameters
| Parameter | Type |
|---|---|
route | unknown |
Returns
void
unwatchRouterChanges()
abstract protected unwatchRouterChanges(): void;Defined in: router-bridge-base.ts:492
Stop watching for router location changes.
Called by disconnect(). Should clean up the framework-specific subscription.
Returns
void
watchRouterChanges()
abstract protected watchRouterChanges(): void;Defined in: router-bridge-base.ts:485
Start watching for router location changes.
Called by connect(). Should set up the framework-specific subscription for location changes and call syncActorFromRouter() on each change.
Implementations that call syncActorFromRouter get path sanitization
applied automatically — no extra work needed.
Implementations that bypass syncActorFromRouter (e.g. VueRouterBridge,
which builds the play.route event directly from framework-native route params)
MUST call this.sanitizePath(path) and return early when it returns null.
Skipping this allows oversized or malformed paths through without the length
and content guards that protect the route-map lookup.
Returns
void