@xmachines/play-xstate 6.0.0 → 7.0.0

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 (45) hide show
  1. package/README.md +87 -28
  2. package/dist/capabilities.d.ts +2 -2
  3. package/dist/capabilities.js +6 -2
  4. package/dist/capabilities.js.map +1 -1
  5. package/dist/define-player.js +8 -8
  6. package/dist/define-player.js.map +1 -1
  7. package/dist/errors.js +262 -259
  8. package/dist/errors.js.map +1 -1
  9. package/dist/index.js +4 -25
  10. package/dist/player-actor.js +318 -448
  11. package/dist/player-actor.js.map +1 -1
  12. package/dist/routing/build-url.js +74 -108
  13. package/dist/routing/build-url.js.map +1 -1
  14. package/dist/routing/derive-current-route.d.ts.map +1 -1
  15. package/dist/routing/derive-current-route.js +46 -67
  16. package/dist/routing/derive-current-route.js.map +1 -1
  17. package/dist/routing/derive-initial-route.js +53 -64
  18. package/dist/routing/derive-initial-route.js.map +1 -1
  19. package/dist/routing/derive-route.js +225 -242
  20. package/dist/routing/derive-route.js.map +1 -1
  21. package/dist/routing/format-play-route-transitions.d.ts.map +1 -1
  22. package/dist/routing/format-play-route-transitions.js +192 -257
  23. package/dist/routing/format-play-route-transitions.js.map +1 -1
  24. package/dist/state-meta.d.ts +84 -28
  25. package/dist/state-meta.d.ts.map +1 -1
  26. package/dist/state-meta.js +170 -72
  27. package/dist/state-meta.js.map +1 -1
  28. package/dist/view/derive-current-view.d.ts +18 -10
  29. package/dist/view/derive-current-view.d.ts.map +1 -1
  30. package/dist/view/derive-current-view.js +249 -128
  31. package/dist/view/derive-current-view.js.map +1 -1
  32. package/dist/with-routing.js +94 -136
  33. package/dist/with-routing.js.map +1 -1
  34. package/dist/with-view.d.ts +1 -3
  35. package/dist/with-view.d.ts.map +1 -1
  36. package/dist/with-view.js +82 -152
  37. package/dist/with-view.js.map +1 -1
  38. package/package.json +19 -19
  39. package/dist/index.js.map +0 -1
  40. package/dist/routing/index.js +0 -14
  41. package/dist/routing/index.js.map +0 -1
  42. package/dist/routing/types.js +0 -2
  43. package/dist/routing/types.js.map +0 -1
  44. package/dist/types.js +0 -2
  45. package/dist/types.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"player-actor.js","sourceRoot":"","sources":["../src/player-actor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"player-actor.js","names":[],"sources":["../src/player-actor.ts"],"sourcesContent":["import {\n\tActor,\n\ttype AnyStateMachine,\n\ttype AnyActorLogic,\n\ttype AnyMachineSnapshot,\n\ttype InputFrom,\n\ttype ActorOptions,\n\ttype Observer,\n\ttype Snapshot,\n\ttype SnapshotFrom,\n\ttype Subscription,\n\ttype EventFromLogic,\n} from \"xstate\";\nimport type { PlayActor } from \"@xmachines/play-actor\";\nimport { createWritableAtom } from \"@xmachines/play-atom\";\nimport type { Atom } from \"@xmachines/play-atom\";\nimport { isError } from \"@xmachines/core/utils\";\n\nimport { ActorThrewNonErrorError, InvalidEventError, InvalidMachineError } from \"./errors.js\";\nimport type { PlayerOptions } from \"./types.js\";\n\n/**\n * Normalizes a failure of the actor for `onError`.\n *\n * @internal\n *\n * The function gives an `Error` to the handler without a change. The error of the\n * machine therefore keeps its identity: an `instanceof` test of a consumer still\n * works, and the path without an `onError` throws that same object again. Every\n * other value is ours to build, and it becomes a `PlayError` with a code. That\n * error carries the value from the throw as its `cause`.\n */\nexport const toError = (value: unknown): Error => {\n\ttry {\n\t\tif (isError(value)) {\n\t\t\treturn value;\n\t\t}\n\t} catch {\n\t\t// The classification itself can throw for a hostile value, because a revoked\n\t\t// Proxy traps instanceof and also the inspection of the brand. Continue, and wrap\n\t\t// the value.\n\t}\n\treturn new ActorThrewNonErrorError(value);\n};\n\n/**\n * Tells you if a snapshot is worth a propagation to the atoms: an active\n * snapshot, or a \"done\" snapshot, which means that the machine reached a final state\n * at the top level. The code skips an error snapshot and a stopped snapshot.\n * Therefore the atoms keep the last observable state, and they show no artifact of\n * a teardown or of an error.\n */\nconst isObservableSnapshot = (snapshot: { status: string }): boolean =>\n\tsnapshot.status === \"active\" || snapshot.status === \"done\";\n\n/**\n * The concrete XState actor. It implements the atom protocol of the Play Architecture\n *\n * The class extends the `Actor` class of XState directly, and it implements\n * {@link @xmachines/play-actor!PlayActor}. It gives you the XState v5 integration, and it keeps the\n * compatibility with the ecosystem, such as the XState inspection and the devtools.\n * The constructor of the base class receives the machine. Therefore a `PlayerActor`\n * **is** the XState actor, and it is no wrapper around one: every member of the\n * XState `Actor` class works on the state of this instance, and this class adds the\n * reactive state on the atoms for the observation by the infrastructure.\n *\n * **Capabilities:** the class implements both the\n * {@link @xmachines/play-router!index.Routable} interface and the\n * {@link @xmachines/play-view!index.Viewable} interface. It therefore supports the\n * routing and the view rendering.\n *\n * **Architectural context:** the class implements **Actor Authority (INV-01)**,\n * because the guards of the XState machine control every decision of the\n * navigation. The infrastructure observes the atoms of the actor (`state`,\n * `currentRoute`, and `currentView`), but it changes no state directly: every\n * change goes through the event handlers of the state machine.\n *\n * @typeParam TMachine - The type of the XState v5 state machine\n *\n * @example\n * The creation of an actor, and its lifecycle\n * ```typescript\n * import { setup } from \"xstate\";\n * import { definePlayer, compose, PlayerActor } from \"@xmachines/play-xstate\";\n *\n * const machine = setup({}).createMachine({\n * initial: 'idle',\n * states: {\n * idle: {\n * meta: {\n * route: '/',\n * // A view spec needs `root` and `elements`. Every other shape derives null.\n * view: {\n * root: 'home',\n * elements: { home: { type: 'HomePage', props: {}, children: [] } },\n * },\n * },\n * }\n * }\n * });\n *\n * const createPlayer = definePlayer({ machine });\n * const actor = createPlayer();\n * actor.start();\n *\n * // Observe the atoms\n * console.log(actor.currentRoute.get()); // '/'\n * console.log(actor.currentView.get()?.root); // 'home'\n * ```\n *\n * @example\n * The atom lifecycle with a watch\n * ```typescript\n * import { watchAtom } from \"@xmachines/play-atom\";\n *\n * const stop = watchAtom(actor.state, (snapshot) => {\n * console.log('State changed:', snapshot.value);\n * });\n *\n * actor.send({ type: 'play.route', to: '#about' });\n * // watchAtom delivers the new value from a microtask\n *\n * stop();\n * ```\n *\n * @see [Play RFC](../../docs/rfc/play.md)\n * @see {@link definePlayer} for the creation through a factory\n * @see {@link @xmachines/play-actor!PlayActor} for the atom protocol\n * @see {@link @xmachines/play-router!index.Routable} for the routing capability\n * @see {@link @xmachines/play-view!index.Viewable} for the view rendering capability\n *\n * @remarks\n * **The routing:** this actor supports the `route: {}` config pattern of XState and\n * also a `play.route` event with parameters. The `deriveRoute()` function reads\n * `meta.route`, which is the Stately pattern, for a URL template, and it substitutes\n * each parameter.\n *\n * **The pattern of the view atom:** `withView` of `@xmachines/play-xstate/view` adds\n * `currentView`, and that atom is a COMPUTED atom over `state`. One write for each\n * transition — `state.set(snapshot)` — therefore reaches the view and the route in one\n * flush, and no subscriber reads the new state beside an old derivation. The atom\n * memoizes the result, so a repeated read computes no view again.\n */\nexport class PlayerActor<TMachine extends AnyStateMachine>\n\textends Actor<TMachine>\n\timplements PlayActor<ReturnType<TMachine[\"transition\"]>, EventFromLogic<TMachine>>\n{\n\tprivate playerOptions?: PlayerOptions<TMachine>;\n\t/**\n\t * The three inputs of the constructor that a CAPABILITY needs.\n\t *\n\t * A mixin over a generic base cannot declare a constructor: TypeScript then demands the\n\t * signature `...args: any[]` (TS2545), which this workspace does not write. A field\n\t * initializer of a subclass runs after `super()` instead, and it reads these. The\n\t * routing capability derives `initialRoute` from all three.\n\t */\n\tprotected readonly playerMachine: TMachine;\n\t/** @see {@link playerMachine} */\n\tprotected readonly playerInput: InputFrom<TMachine> | undefined;\n\t/** @see {@link playerMachine} */\n\tprotected readonly playerRestoredSnapshot: ActorOptions<TMachine>[\"snapshot\"] | undefined;\n\t/**\n\t * Tells you if this constructor returned already.\n\t *\n\t * XState gives the actor to a context factory as `self`, and to an `inspect`\n\t * observer as `actorRef`, from inside its own constructor. No field of this class\n\t * exists at that moment, and XState itself refuses to read the snapshot there:\n\t * \"Snapshot can't be read while the actor initializes itself\". Therefore each thing\n\t * that the code can reach from that window must test this field first.\n\t */\n\tdeclare private constructed?: boolean;\n\t/**\n\t * The live options object of the caller, or an empty object during the construction.\n\t *\n\t * XState gives this actor to a context factory as `self`, and to an `inspect`\n\t * observer as `actorRef`, from inside its own constructor, before the code assigns\n\t * any field here. A read of a hook through this accessor therefore does not throw\n\t * in that window. A throw goes to the initialization of XState, which parks it as\n\t * an error snapshot. The accessor also keeps the behavior that the documentation of\n\t * the object promises: a read at the moment of the delivery.\n\t *\n\t * The fields below that this window touches have a `declare` modifier for the same\n\t * reason. This target compiles a class field into `Object.defineProperty`, which\n\t * runs after `super()` returns. A plain declaration, with an initializer or without\n\t * one, therefore resets each value of the window to `undefined`. A `declare`\n\t * modifier emits nothing, and those values survive.\n\t */\n\tprotected get hooks(): PlayerOptions<TMachine> {\n\t\treturn this.playerOptions ?? {};\n\t}\n\t/**\n\t * The record of the real lifecycle transitions, so that onStart and onStop each\n\t * fire one time. The status of XState is internal, and a machine snapshot reads\n\t * \"active\" before start() already. Therefore neither of them can separate an actor\n\t * that did not start yet from an actor that runs.\n\t */\n\tdeclare private lifecycle?: \"created\" | \"running\" | \"stopped\";\n\t/**\n\t * The subscriptions of the user code without an error listener. The dispatch of\n\t * XState throws an actor error again, globally, for them. It does this one time for\n\t * each delivery, with a shared flag. Therefore the loud default of the internal\n\t * error listener, which also throws again, must stand down while such a\n\t * subscription is active. Without this rule, the code reports the same error two\n\t * times.\n\t */\n\tdeclare private nextOnlySubscriptions?: number;\n\t// The requirements of the PlayActor contract\n\tpublic state: Atom<ReturnType<TMachine[\"transition\"]>>;\n\n\t/**\n\t * Tells you if the current state of the actor accepts the given event.\n\t *\n\t * The type is the event union of the machine. An unknown event type is therefore a\n\t * compile error. The method evaluates the event against the snapshot atom.\n\t *\n\t * @example\n\t * ```typescript\n\t * if (actor.can({ type: \"auth.logout\" })) { ... }\n\t * ```\n\t */\n\tpublic can(event: EventFromLogic<TMachine>): boolean {\n\t\t// A read of the atom keeps can() reactive: a computed atom over the atom\n\t\t// computes its value again on each transition.\n\t\tconst snapshot = this.state?.get();\n\t\t// The STATUS decides first, and the presence of the method decides second.\n\t\t//\n\t\t// An actor answers an event only while it is active. XState 5.32 made that test\n\t\t// unnecessary by accident — the error snapshot of a failed initialization carried no\n\t\t// `can` method, so a test of the method alone answered `false` for it — and 5.33\n\t\t// gives that snapshot a working `can`, which then answered `true` for an actor that\n\t\t// processes an event never. The status is what the question is really about, and a\n\t\t// `done` actor answers `false` for the same reason.\n\t\t//\n\t\t// A STOPPED actor is the exception, and it is deliberate: the subscription below\n\t\t// updates this atom on a stable state alone, so the atom keeps the last ACTIVE\n\t\t// snapshot after a teardown rather than freezing on an artifact of it. `can()`\n\t\t// therefore answers for the last live state of a stopped actor.\n\t\tif (snapshot?.status !== \"active\") return false;\n\t\treturn typeof snapshot.can === \"function\" ? snapshot.can(event) : false;\n\t}\n\n\tconstructor(\n\t\tmachine: TMachine,\n\t\toptions: PlayerOptions<TMachine>,\n\t\tinput?: InputFrom<TMachine>,\n\t\trestoredSnapshot?: ActorOptions<TMachine>[\"snapshot\"],\n\t) {\n\t\t// A defensive check before super(): a machine that is not an object fails deep\n\t\t// inside the constructor of XState, with an opaque TypeError, and not with a coded\n\t\t// error.\n\t\tif (!machine || typeof machine !== \"object\") {\n\t\t\tthrow new InvalidMachineError();\n\t\t}\n\n\t\t// THIS is the actor. The machine and its runtime options go directly to the Actor\n\t\t// constructor of XState, which receives the same arguments as `createActor`\n\t\t// forwards. Therefore no second instance answers for the real one, and every\n\t\t// Actor member without an override here works on the real state.\n\t\t//\n\t\t// XState 5.28.0: the options object has a conditional type constraint on `input`,\n\t\t// and TypeScript cannot resolve that constraint against an unbound generic\n\t\t// TMachine. The cast stays inside the type system of XState, and the signature of\n\t\t// this constructor gives `input` its type. Therefore each caller keeps the check\n\t\t// at the compile time.\n\t\t// Follow the improvements of the XState types: https://github.com/statelyai/xstate/issues\n\t\tsuper(machine, {\n\t\t\tinput,\n\t\t\tsnapshot: restoredSnapshot,\n\t\t\tinspect: options?.inspect,\n\t\t} as ActorOptions<AnyActorLogic>);\n\n\t\tthis.playerMachine = machine;\n\t\tthis.playerInput = input;\n\t\tthis.playerRestoredSnapshot = restoredSnapshot;\n\t\tthis.playerOptions = options || {};\n\n\t\t// Initialize the state atom. Each update is synchronous, with no batching in a\n\t\t// microtask: XState groups the transitions of one send() call into one\n\t\t// subscription callback already, and a synchronous update shows each guard\n\t\t// redirect to a router bridge at once.\n\t\t// `createWritableAtom`, and not `createAtom`. The overload pair of `createAtom` reads\n\t\t// a function argument as a computed atom, and `ReturnType<TMachine[\"transition\"]>` is\n\t\t// an unresolved conditional type here, so TypeScript cannot rule a function out. It\n\t\t// picks the computed signature, which returns a `ReadonlyAtom` that carries no `set`.\n\t\tthis.state = createWritableAtom(this.getSnapshot());\n\n\t\t// Observe the transitions of this actor. The code uses `super`, and not `this`, so\n\t\t// that the bookkeeping of the next-only subscriptions in the subscribe override\n\t\t// stays about the subscriptions of the user code.\n\t\tsuper.subscribe({\n\t\t\tnext: (snapshot) => {\n\t\t\t\t// Update on a stable state only: an active snapshot, and the \"done\" snapshot of a\n\t\t\t\t// final state at the top level. The code skips an error snapshot and a stopped\n\t\t\t\t// snapshot. Therefore an atom never freezes on an artifact of a teardown.\n\t\t\t\tif (isObservableSnapshot(snapshot)) {\n\t\t\t\t\t// Each state update is synchronous. Therefore a router bridge sees a guard redirect at once.\n\t\t\t\t\tthis.state.set(snapshot);\n\n\t\t\t\t\t// ONE write for each transition, and the line above is it. `currentRoute` and\n\t\t\t\t\t// `currentView` are computed atoms over `state`, so that write propagates to\n\t\t\t\t\t// both in ONE flush, in topological order. No observer therefore reads the new\n\t\t\t\t\t// state beside an old derivation, and the composition order of the capabilities\n\t\t\t\t\t// decides nothing.\n\t\t\t\t\t//\n\t\t\t\t\t// A capability that must run an EFFECT on a transition overrides\n\t\t\t\t\t// `onSnapshot`. A capability that publishes a value derives it instead.\n\t\t\t\t\t//\n\t\t\t\t\t// The whole order of one transition:\n\t\t\t\t\t// 1. state receives its new value, and every computed atom over it follows\n\t\t\t\t\t// 2. onSnapshot runs each capability, in the composition order\n\t\t\t\t\t// 3. the onStateChange hook runs\n\t\t\t\t\t// 4. send() then calls onTransition\n\t\t\t\t\tthis.onSnapshot(snapshot);\n\n\t\t\t\t\t// Call the onStateChange hook\n\t\t\t\t\tconst onStateChange = this.hooks.onStateChange;\n\t\t\t\t\tif (onStateChange) {\n\t\t\t\t\t\tonStateChange(this, snapshot);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t// The code registers the listener always, and it reads the handler at the moment\n\t\t\t// of the DELIVERY: the options object is shared by its reference. Therefore an\n\t\t\t// onError handler on that object after the construction still receives each actor\n\t\t\t// error, and the removal of a handler stops the silence again.\n\t\t\t// Without a handler, the listener throws the error again. The observer dispatch of\n\t\t\t// XState then sends it to its global unhandled rethrow, which is the same loud\n\t\t\t// default as a listener that the code registers not.\n\t\t\terror: (error: unknown) => {\n\t\t\t\tconst handler = this.hooks.onError;\n\t\t\t\tif (handler) {\n\t\t\t\t\thandler(this, toError(error));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// A next-only subscription of the user code makes XState report this delivery\n\t\t\t\t// globally already. A second throw here reports it two times.\n\t\t\t\tif ((this.nextOnlySubscriptions ?? 0) > 0) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t},\n\t\t});\n\n\t\t// The callbacks of the constructor of XState can reach everything above. After this\n\t\t// point the instance is complete.\n\t\tthis.constructed = true;\n\t}\n\n\t/**\n\t * Starts the actor.\n\t *\n\t * The method fires `onStart` on each real start, which is every transition from\n\t * \"not running\" to \"running\". A start after a stop is such a transition, and XState\n\t * permits it: its own `start()` stops only while the actor RUNS already. A second\n\t * call while the actor runs fires no hook. Therefore a defensive double mount runs\n\t * the side effects of `onStart` one time for one real start.\n\t */\n\toverride start(): this {\n\t\t// See stop(): a call that reaches in through the construction window runs an actor\n\t\t// that is not complete.\n\t\tif (!this.constructed) {\n\t\t\treturn this;\n\t\t}\n\n\t\tsuper.start();\n\n\t\tif (this.lifecycle !== \"running\") {\n\t\t\tthis.lifecycle = \"running\";\n\t\t\tconst onStart = this.hooks.onStart;\n\t\t\tif (onStart) {\n\t\t\t\tonStart(this);\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Stops the actor and cleans up.\n\t *\n\t * The method fires `onStop` only when the actor ran. This matches XState, where a\n\t * stop of an actor that never started, or of an actor that stopped already, does\n\t * nothing and tears nothing down. Therefore the paired cleanup runs never two\n\t * times, and it runs never against a resource that `onStart` did not take. A stop\n\t * does not close the actor for ever: a later `start()` is a new lifecycle, and it\n\t * fires `onStart` again.\n\t */\n\toverride stop(): this {\n\t\t// A call that reaches in through the construction window, for example a context\n\t\t// factory that stops its own `self`, marks the actor as stopped before the code\n\t\t// registers its internal subscription. XState drops each observer of a stopped\n\t\t// actor. The atoms therefore move never again. There is nothing to tear down\n\t\t// during the construction, and the code ignores such a call.\n\t\tif (!this.constructed) {\n\t\t\treturn this;\n\t\t}\n\n\t\tsuper.stop();\n\n\t\tconst wasRunning = this.lifecycle === \"running\";\n\t\tthis.lifecycle = \"stopped\";\n\t\tconst onStop = this.hooks.onStop;\n\t\tif (wasRunning && onStop) {\n\t\t\tonStop(this);\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sends an event to this actor.\n\t *\n\t * The guards of the state machine of the actor decide if the event causes a\n\t * transition. Give any event of the event union of the machine: a domain event, a\n\t * routing event, and so on.\n\t *\n\t * @param event - An event of the `EventFromLogic<TMachine>` union of the machine.\n\t *\n\t * @throws {InvalidEventError} When `event` is not a plain object, for example\n\t * `null`, `undefined`, a string, or a number. Import the class from\n\t * `@xmachines/play-xstate/errors`.\n\t *\n\t * @example\n\t * ```typescript\n\t * // A domain event, with the type of the event union of the machine\n\t * actor.send({ type: \"auth.login\", userId: \"123\" });\n\t *\n\t * // A routing event\n\t * actor.send({ type: \"play.route\", to: \"#home\" });\n\t * ```\n\t */\n\toverride send(event: EventFromLogic<TMachine>): void {\n\t\t// A defensive check: the event must not be null and not undefined\n\t\tif (!event || typeof event !== \"object\") {\n\t\t\tthrow new InvalidEventError(event);\n\t\t}\n\n\t\t// Inside the construction window there is no readable snapshot, and no hook can\n\t\t// exist yet: deliver the event and return.\n\t\tif (!this.constructed) {\n\t\t\tActor.prototype.send.call(this, event);\n\t\t\treturn;\n\t\t}\n\n\t\t// The code captures the snapshot always, because getSnapshot() is one property\n\t\t// read, and because the options object is live: an onTransition handler that\n\t\t// arrives during the processing of this event, for example from onStateChange,\n\t\t// must still run for it, with the correct snapshot from before the send.\n\t\tconst prevSnapshot = this.getSnapshot();\n\n\t\t// Send the event to the XState actor.\n\t\t// The class declares send() to narrow the\n\t\t// event type, and TypeScript forbids a super call to an abstract member.\n\t\t// Therefore the code reaches the implementation of XState directly. `this` IS the\n\t\t// actor. This call is therefore exactly the call of `super.send(event)`: the relay\n\t\t// that emits the @xstate.event inspection event and puts the event in the mailbox\n\t\t// of this actor.\n\t\tActor.prototype.send.call(this, event);\n\n\t\t// Call the onTransition hook\n\t\tconst onTransition = this.hooks.onTransition;\n\t\tif (onTransition) {\n\t\t\tconst nextSnapshot = this.getSnapshot();\n\t\t\tonTransition(this, prevSnapshot, nextSnapshot);\n\t\t}\n\t}\n\n\t// -------------------------------------------------------------------------\n\t// The inherited Actor API\n\t//\n\t// The class extends `Actor` at TMachine, so every inherited member already carries\n\t// the type of the machine. It extended `Actor` at `AnyActorLogic` before, because the\n\t// abstract base class between them could pass one logic type and passed the erased\n\t// one — and three overrides existed to narrow the result back, one of them with an\n\t// assertion on its own return.\n\t//\n\t// What stays here does real work: `subscribe` keeps the bookkeeping of the next-only\n\t// subscriptions that the error listener reads, and `getPersistedSnapshot` forwards\n\t// through a binding, because the signature of XState resists a direct `super` call.\n\t// Do NOT add a separate actor here and delegate to it: a member that the class\n\t// inherits stays correct while XState develops, and each delegated member is one more\n\t// thing to keep in step.\n\t// -------------------------------------------------------------------------\n\n\t/**\n\t * Subscribes to the snapshot updates of this actor.\n\t *\n\t * The method accepts an observer object, exactly like `Actor.subscribe` of XState.\n\t *\n\t * @param observer - The observer, with a `next`, an `error`, and a `complete` handler.\n\t * @returns The subscription, with an `unsubscribe()` method.\n\t */\n\toverride subscribe(observer: Observer<SnapshotFrom<TMachine>>): Subscription;\n\t/**\n\t * Subscribes to the snapshot updates of this actor.\n\t *\n\t * The method accepts listener functions, exactly like `Actor.subscribe` of XState.\n\t *\n\t * @param nextListener - The listener function of each snapshot.\n\t * @param errorListener - The actor calls it on an error.\n\t * @param completeListener - The actor calls it when it completes, which means that it reaches a final state.\n\t * @returns The subscription, with an `unsubscribe()` method.\n\t */\n\toverride subscribe(\n\t\tnextListener?: (snapshot: SnapshotFrom<TMachine>) => void,\n\t\terrorListener?: (error: unknown) => void,\n\t\tcompleteListener?: () => void,\n\t): Subscription;\n\toverride subscribe(\n\t\tnextListenerOrObserver?:\n\t\t\t| ((snapshot: SnapshotFrom<TMachine>) => void)\n\t\t\t| Observer<SnapshotFrom<TMachine>>,\n\t\terrorListener?: (error: unknown) => void,\n\t\tcompleteListener?: () => void,\n\t): Subscription {\n\t\t// The subscribe() method of XState accepts a function and also an observer, and it\n\t\t// normalizes them internally. The cast joins the two overload signatures only.\n\t\tconst subscription = super.subscribe(\n\t\t\tnextListenerOrObserver as (snapshot: SnapshotFrom<TMachine>) => void,\n\t\t\terrorListener,\n\t\t\tcompleteListener,\n\t\t);\n\n\t\t// An observer without an error listener makes XState throw each actor error again,\n\t\t// globally, for that observer. The code counts those observers. Therefore the loud\n\t\t// default of the internal listener, which also throws again, stands down while one\n\t\t// of them is active. See the error listener of the constructor.\n\t\tconst hasErrorListener =\n\t\t\ttypeof nextListenerOrObserver === \"object\" && nextListenerOrObserver !== null\n\t\t\t\t? typeof nextListenerOrObserver.error === \"function\"\n\t\t\t\t: typeof errorListener === \"function\";\n\t\tif (hasErrorListener) {\n\t\t\treturn subscription;\n\t\t}\n\n\t\tthis.nextOnlySubscriptions = (this.nextOnlySubscriptions ?? 0) + 1;\n\t\tlet counted = true;\n\t\treturn {\n\t\t\tunsubscribe: () => {\n\t\t\t\tif (counted) {\n\t\t\t\t\tcounted = false;\n\t\t\t\t\tthis.nextOnlySubscriptions = (this.nextOnlySubscriptions ?? 1) - 1;\n\t\t\t\t}\n\t\t\t\tsubscription.unsubscribe();\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * Returns the persisted snapshot of this actor.\n\t *\n\t * Use it to serialize the state, and to restore it later with the\n\t * `restore.snapshot` option of the factory.\n\t */\n\toverride getPersistedSnapshot(options?: unknown): Snapshot<unknown> {\n\t\tconst forward = super.getPersistedSnapshot as (options?: unknown) => Snapshot<unknown>;\n\t\treturn forward.call(this, options);\n\t}\n\t/**\n\t * The point where a capability derives its own atoms from a new snapshot.\n\t *\n\t * The base derives nothing: `PlayActor` asks for `state` and `send`, and this class\n\t * gives exactly those.\n\t *\n\t * A capability that PUBLISHES a value overrides this method NOT. It derives the value\n\t * with a computed atom over `state`, as `withRouting` and `withView` both do, and the\n\t * engine then evaluates every derivation from the one write of a transition, in\n\t * topological order. The composition order therefore decides no value.\n\t *\n\t * This method remains for a capability that must run an EFFECT on a transition. Such a\n\t * mixin overrides it and calls `super.onSnapshot(snapshot)` FIRST, so that every\n\t * capability composed before it runs its own effect first.\n\t *\n\t * The method runs after `state` holds the new snapshot and before the `onStateChange`\n\t * hook of the options.\n\t *\n\t * @param snapshot - The stable snapshot of this transition.\n\t */\n\tprotected onSnapshot(snapshot: AnyMachineSnapshot): void {\n\t\t// The base class holds no capability. A mixin overrides this method.\n\t\tvoid snapshot;\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgCA,IAAa,WAAW,UAA0B;CACjD,IAAI;EACH,IAAI,QAAQ,KAAK,GAChB,OAAO;CAET,QAAQ,CAIR;CACA,OAAO,IAAI,wBAAwB,KAAK;AACzC;;;;;;;;AASA,IAAM,wBAAwB,aAC7B,SAAS,WAAW,YAAY,SAAS,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0FrD,IAAa,cAAb,cACS,MAET;CACC;;;;;;;;;CASA;;CAEA;;CAEA;;;;;;;;;;;;;;;;;CA2BA,IAAc,QAAiC;EAC9C,OAAO,KAAK,iBAAiB,CAAC;CAC/B;CAkBA;;;;;;;;;;;;CAaA,IAAW,OAA0C;EAGpD,MAAM,WAAW,KAAK,OAAO,IAAI;EAcjC,IAAI,UAAU,WAAW,UAAU,OAAO;EAC1C,OAAO,OAAO,SAAS,QAAQ,aAAa,SAAS,IAAI,KAAK,IAAI;CACnE;CAEA,YACC,SACA,SACA,OACA,kBACC;EAID,IAAI,CAAC,WAAW,OAAO,YAAY,UAClC,MAAM,IAAI,oBAAoB;EAc/B,MAAM,SAAS;GACd;GACA,UAAU;GACV,SAAS,SAAS;EACnB,CAAgC;EAEhC,KAAK,gBAAgB;EACrB,KAAK,cAAc;EACnB,KAAK,yBAAyB;EAC9B,KAAK,gBAAgB,WAAW,CAAC;EAUjC,KAAK,QAAQ,mBAAmB,KAAK,YAAY,CAAC;EAKlD,MAAM,UAAU;GACf,OAAO,aAAa;IAInB,IAAI,qBAAqB,QAAQ,GAAG;KAEnC,KAAK,MAAM,IAAI,QAAQ;KAgBvB,KAAK,WAAW,QAAQ;KAGxB,MAAM,gBAAgB,KAAK,MAAM;KACjC,IAAI,eACH,cAAc,MAAM,QAAQ;IAE9B;GACD;GAQA,QAAQ,UAAmB;IAC1B,MAAM,UAAU,KAAK,MAAM;IAC3B,IAAI,SAAS;KACZ,QAAQ,MAAM,QAAQ,KAAK,CAAC;KAC5B;IACD;IAGA,KAAK,KAAK,yBAAyB,KAAK,GACvC;IAED,MAAM;GACP;EACD,CAAC;EAID,KAAK,cAAc;CACpB;;;;;;;;;;CAWA,QAAuB;EAGtB,IAAI,CAAC,KAAK,aACT,OAAO;EAGR,MAAM,MAAM;EAEZ,IAAI,KAAK,cAAc,WAAW;GACjC,KAAK,YAAY;GACjB,MAAM,UAAU,KAAK,MAAM;GAC3B,IAAI,SACH,QAAQ,IAAI;EAEd;EAEA,OAAO;CACR;;;;;;;;;;;CAYA,OAAsB;EAMrB,IAAI,CAAC,KAAK,aACT,OAAO;EAGR,MAAM,KAAK;EAEX,MAAM,aAAa,KAAK,cAAc;EACtC,KAAK,YAAY;EACjB,MAAM,SAAS,KAAK,MAAM;EAC1B,IAAI,cAAc,QACjB,OAAO,IAAI;EAGZ,OAAO;CACR;;;;;;;;;;;;;;;;;;;;;;;CAwBA,KAAc,OAAuC;EAEpD,IAAI,CAAC,SAAS,OAAO,UAAU,UAC9B,MAAM,IAAI,kBAAkB,KAAK;EAKlC,IAAI,CAAC,KAAK,aAAa;GACtB,MAAM,UAAU,KAAK,KAAK,MAAM,KAAK;GACrC;EACD;EAMA,MAAM,eAAe,KAAK,YAAY;EAStC,MAAM,UAAU,KAAK,KAAK,MAAM,KAAK;EAGrC,MAAM,eAAe,KAAK,MAAM;EAChC,IAAI,cAAc;GACjB,MAAM,eAAe,KAAK,YAAY;GACtC,aAAa,MAAM,cAAc,YAAY;EAC9C;CACD;CA2CA,UACC,wBAGA,eACA,kBACe;EAGf,MAAM,eAAe,MAAM,UAC1B,wBACA,eACA,gBACD;EAUA,IAHC,OAAO,2BAA2B,YAAY,2BAA2B,OACtE,OAAO,uBAAuB,UAAU,aACxC,OAAO,kBAAkB,YAE5B,OAAO;EAGR,KAAK,yBAAyB,KAAK,yBAAyB,KAAK;EACjE,IAAI,UAAU;EACd,OAAO,EACN,mBAAmB;GAClB,IAAI,SAAS;IACZ,UAAU;IACV,KAAK,yBAAyB,KAAK,yBAAyB,KAAK;GAClE;GACA,aAAa,YAAY;EAC1B,EACD;CACD;;;;;;;CAQA,qBAA8B,SAAsC;EAEnE,OADgB,MAAM,qBACP,KAAK,MAAM,OAAO;CAClC;;;;;;;;;;;;;;;;;;;;;CAqBA,WAAqB,UAAoC,CAGzD;AACD"}
@@ -1,114 +1,80 @@
1
- import { buildPath } from "@xmachines/play-pattern";
2
- import { isAbsoluteRoute } from "./derive-route.js";
3
1
  import { InvalidRouteParamError, MissingRouteParamError } from "../errors.js";
2
+ import { isAbsoluteRoute } from "./derive-route.js";
3
+ import { buildPath } from "@xmachines/play-pattern";
4
+ //#region packages/play-xstate/src/routing/build-url.ts
4
5
  /**
5
- * Builds a complete URL from a route template and the context of the actor.
6
- *
7
- * The function replaces each `:param` placeholder and each `:param?` placeholder
8
- * with a value of `context.params`. It then appends the query params and the hash
9
- * fragment.
10
- *
11
- * Every parameter value must be in `context.params`. The function reads no flat
12
- * context field, and this is deliberate: a placeholder with a spelling error
13
- * therefore gives a compile-time error, and it does not resolve to `undefined` in
14
- * silence.
15
- *
16
- * @param routeTemplate - The template of the route path, for example
17
- * `"/profile/:userId"` or `"/settings/:section?"`.
18
- * @param context - The context object of the actor. Each route parameter must be in
19
- * `context.params`, because the function reads no flat context field. An absent
20
- * `query` field builds a URL without a query, exactly like `query: {}`.
21
- * @param options - The caches to read, as {@link ParseOptions}. The default is the cache
22
- * that `@xmachines/play-pattern` shares with every caller of the process. A parse is
23
- * deterministic, so this changes how often the parser runs and it changes no answer.
24
- * @returns The complete URL string.
25
- *
26
- * @throws {MissingRouteParamError} When a **necessary** `:param` placeholder has no
27
- * value in the context. The function omits an optional parameter (`:param?`) in
28
- * silence when its value is absent. Import the class from
29
- * `@xmachines/play-xstate/errors`.
30
- * @throws {InvalidRouteParamError} When a `:param` placeholder carries a dot segment,
31
- * which a URL resolves away. The template matches the built URL back never, so the
32
- * actor and the address bar would stay out of step.
33
- *
34
- * @example
35
- * ```typescript
36
- * buildRouteUrl("/user/:id", { params: { id: "123" }, query: { tab: "profile" }, hash: "top" });
37
- * // → "/user/123?tab=profile#top"
38
- *
39
- * buildRouteUrl("/settings/:section?", { params: {}, query: {} });
40
- * // → "/settings" (the optional param is absent, and there is no query string)
41
- * ```
42
- */
43
- export const buildRouteUrl = (routeTemplate, context = { query: {} }, options) => {
44
- // A context without a `query` field builds a URL without a query, in the same way
45
- // as an absent context. The generated play.route transitions assign `query` on
46
- // every navigation, and the shape of the initial context has no effect on that.
47
- // Therefore no query goes away here, and a throw prevents nothing. A machine that
48
- // handles play.route itself and wants the query must assign event.query to its
49
- // context itself.
50
- // Handle a relative path and an absolute path
51
- const basePath = context.basePath || "";
52
- const isAbsolute = isAbsoluteRoute(routeTemplate);
53
- // Build the base URL. Join every run of separators into one, exactly as
54
- // `buildRouteTree` of `@xmachines/play-router` does for the `fullPath` that the route
55
- // map holds: `deriveRoute` writes `${parent}/${child}`, so a parent route that ends
56
- // with a `/` gives `/app//sub` while the map holds `/app/sub`. A bridge pushed that
57
- // location, the router reported `/app/sub` back — `sanitizePathname` collapses it —
58
- // and the echo test then read its OWN push as a move of the user and sent a
59
- // `play.route` for the state the actor was in already.
60
- //
61
- // The collapse runs on the TEMPLATE, and not on the built path, so a `:path*` value
62
- // keeps every separator that it carries.
63
- let url = (isAbsolute ? routeTemplate : joinPaths(basePath, routeTemplate)).replace(/\/+/g, "/");
64
- // Replace each param with a context value. `buildPath` of `@xmachines/play-pattern`
65
- // reads the WHOLE pattern grammar, which is the same parse that the match reads, so a
66
- // route that the router matches derives a URL that the router matches back. That
67
- // package carries the language alone: no URLPattern, and no polyfill for it.
68
- const built = buildPath(url, context.params ?? {}, options);
69
- if (!built.ok) {
70
- if (built.reason === "unresolvable") {
71
- throw new InvalidRouteParamError(built.param, built.value, routeTemplate);
72
- }
73
- throw new MissingRouteParamError(built.missing, routeTemplate);
74
- }
75
- // A template of the root level with optional params only, for example `/:section?`,
76
- // builds `""`. That value makes an invalid URL, such as `""` or `"?tab=x"`.
77
- url = built.path === "" ? "/" : built.path;
78
- // Append the query params of the context. The frequent empty `query: {}` passes the
79
- // key check first. Therefore each recomputation allocates a URLSearchParams object
80
- // only when it has something to write.
81
- if (context.query && typeof context.query === "object") {
82
- const queryEntries = Object.entries(context.query);
83
- if (queryEntries.length > 0) {
84
- const params = new URLSearchParams(queryEntries.map(([k, v]) => [k, String(v)]));
85
- const queryString = params.toString();
86
- if (queryString) {
87
- url += `?${queryString}`;
88
- }
89
- }
90
- }
91
- // Append the hash of the context
92
- if (context.hash && typeof context.hash === "string") {
93
- url += `#${context.hash}`;
94
- }
95
- return url;
6
+ * Builds a complete URL from a route template and the context of the actor.
7
+ *
8
+ * The function replaces each `:param` placeholder and each `:param?` placeholder
9
+ * with a value of `context.params`. It then appends the query params and the hash
10
+ * fragment.
11
+ *
12
+ * Every parameter value must be in `context.params`. The function reads no flat
13
+ * context field, and this is deliberate: a placeholder with a spelling error
14
+ * therefore gives a compile-time error, and it does not resolve to `undefined` in
15
+ * silence.
16
+ *
17
+ * @param routeTemplate - The template of the route path, for example
18
+ * `"/profile/:userId"` or `"/settings/:section?"`.
19
+ * @param context - The context object of the actor. Each route parameter must be in
20
+ * `context.params`, because the function reads no flat context field. An absent
21
+ * `query` field builds a URL without a query, exactly like `query: {}`.
22
+ * @param options - The caches to read, as {@link ParseOptions}. The default is the cache
23
+ * that `@xmachines/play-pattern` shares with every caller of the process. A parse is
24
+ * deterministic, so this changes how often the parser runs and it changes no answer.
25
+ * @returns The complete URL string.
26
+ *
27
+ * @throws {MissingRouteParamError} When a **necessary** `:param` placeholder has no
28
+ * value in the context. The function omits an optional parameter (`:param?`) in
29
+ * silence when its value is absent. Import the class from
30
+ * `@xmachines/play-xstate/errors`.
31
+ * @throws {InvalidRouteParamError} When a `:param` placeholder carries a dot segment,
32
+ * which a URL resolves away. The template matches the built URL back never, so the
33
+ * actor and the address bar would stay out of step.
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * buildRouteUrl("/user/:id", { params: { id: "123" }, query: { tab: "profile" }, hash: "top" });
38
+ * // → "/user/123?tab=profile#top"
39
+ *
40
+ * buildRouteUrl("/settings/:section?", { params: {}, query: {} });
41
+ * // → "/settings" (the optional param is absent, and there is no query string)
42
+ * ```
43
+ */
44
+ var buildRouteUrl = (routeTemplate, context = { query: {} }, options) => {
45
+ const basePath = context.basePath || "";
46
+ let url = (isAbsoluteRoute(routeTemplate) ? routeTemplate : joinPaths(basePath, routeTemplate)).replace(/\/+/g, "/");
47
+ const built = buildPath(url, context.params ?? {}, options);
48
+ if (!built.ok) {
49
+ if (built.reason === "unresolvable") throw new InvalidRouteParamError(built.param, built.value, routeTemplate);
50
+ throw new MissingRouteParamError(built.missing, routeTemplate);
51
+ }
52
+ url = built.path === "" ? "/" : built.path;
53
+ if (context.query && typeof context.query === "object") {
54
+ const queryEntries = Object.entries(context.query);
55
+ if (queryEntries.length > 0) {
56
+ const queryString = new URLSearchParams(queryEntries.map(([k, v]) => [k, String(v)])).toString();
57
+ if (queryString) url += `?${queryString}`;
58
+ }
59
+ }
60
+ if (context.hash && typeof context.hash === "string") url += `#${context.hash}`;
61
+ return url;
96
62
  };
97
63
  /**
98
- * Joins a base path and a relative path
99
- *
100
- * The function puts one slash between the two paths
101
- *
102
- * @param base - The base path
103
- * @param relative - The relative path
104
- * @returns The joined path
105
- */
106
- const joinPaths = (base, relative) => {
107
- // Remove the trailing slash of the base
108
- const normalizedBase = base.replace(/\/$/, "");
109
- // Remove the first slash of the relative path
110
- const normalizedRelative = relative.replace(/^\//, "");
111
- // Join the two paths with one slash
112
- return normalizedBase ? `${normalizedBase}/${normalizedRelative}` : `/${normalizedRelative}`;
64
+ * Joins a base path and a relative path
65
+ *
66
+ * The function puts one slash between the two paths
67
+ *
68
+ * @param base - The base path
69
+ * @param relative - The relative path
70
+ * @returns The joined path
71
+ */
72
+ var joinPaths = (base, relative) => {
73
+ const normalizedBase = base.replace(/\/$/, "");
74
+ const normalizedRelative = relative.replace(/^\//, "");
75
+ return normalizedBase ? `${normalizedBase}/${normalizedRelative}` : `/${normalizedRelative}`;
113
76
  };
77
+ //#endregion
78
+ export { buildRouteUrl };
79
+
114
80
  //# sourceMappingURL=build-url.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-url.js","sourceRoot":"","sources":["../../src/routing/build-url.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"build-url.js","names":[],"sources":["../../src/routing/build-url.ts"],"sourcesContent":["import { buildPath } from \"@xmachines/play-pattern\";\nimport type { ParseOptions } from \"@xmachines/play-pattern\";\nimport type { RouteContext } from \"./types.js\";\nimport { isAbsoluteRoute } from \"./derive-route.js\";\nimport { InvalidRouteParamError, MissingRouteParamError } from \"../errors.js\";\n\n/**\n * Builds a complete URL from a route template and the context of the actor.\n *\n * The function replaces each `:param` placeholder and each `:param?` placeholder\n * with a value of `context.params`. It then appends the query params and the hash\n * fragment.\n *\n * Every parameter value must be in `context.params`. The function reads no flat\n * context field, and this is deliberate: a placeholder with a spelling error\n * therefore gives a compile-time error, and it does not resolve to `undefined` in\n * silence.\n *\n * @param routeTemplate - The template of the route path, for example\n * `\"/profile/:userId\"` or `\"/settings/:section?\"`.\n * @param context - The context object of the actor. Each route parameter must be in\n * `context.params`, because the function reads no flat context field. An absent\n * `query` field builds a URL without a query, exactly like `query: {}`.\n * @param options - The caches to read, as {@link ParseOptions}. The default is the cache\n * that `@xmachines/play-pattern` shares with every caller of the process. A parse is\n * deterministic, so this changes how often the parser runs and it changes no answer.\n * @returns The complete URL string.\n *\n * @throws {MissingRouteParamError} When a **necessary** `:param` placeholder has no\n * value in the context. The function omits an optional parameter (`:param?`) in\n * silence when its value is absent. Import the class from\n * `@xmachines/play-xstate/errors`.\n * @throws {InvalidRouteParamError} When a `:param` placeholder carries a dot segment,\n * which a URL resolves away. The template matches the built URL back never, so the\n * actor and the address bar would stay out of step.\n *\n * @example\n * ```typescript\n * buildRouteUrl(\"/user/:id\", { params: { id: \"123\" }, query: { tab: \"profile\" }, hash: \"top\" });\n * // → \"/user/123?tab=profile#top\"\n *\n * buildRouteUrl(\"/settings/:section?\", { params: {}, query: {} });\n * // → \"/settings\" (the optional param is absent, and there is no query string)\n * ```\n */\nexport const buildRouteUrl = (\n\trouteTemplate: string,\n\tcontext: RouteContext = { query: {} },\n\toptions?: ParseOptions,\n): string => {\n\t// A context without a `query` field builds a URL without a query, in the same way\n\t// as an absent context. The generated play.route transitions assign `query` on\n\t// every navigation, and the shape of the initial context has no effect on that.\n\t// Therefore no query goes away here, and a throw prevents nothing. A machine that\n\t// handles play.route itself and wants the query must assign event.query to its\n\t// context itself.\n\n\t// Handle a relative path and an absolute path\n\tconst basePath = context.basePath || \"\";\n\tconst isAbsolute = isAbsoluteRoute(routeTemplate);\n\n\t// Build the base URL. Join every run of separators into one, exactly as\n\t// `buildRouteTree` of `@xmachines/play-router` does for the `fullPath` that the route\n\t// map holds: `deriveRoute` writes `${parent}/${child}`, so a parent route that ends\n\t// with a `/` gives `/app//sub` while the map holds `/app/sub`. A bridge pushed that\n\t// location, the router reported `/app/sub` back — `sanitizePathname` collapses it —\n\t// and the echo test then read its OWN push as a move of the user and sent a\n\t// `play.route` for the state the actor was in already.\n\t//\n\t// The collapse runs on the TEMPLATE, and not on the built path, so a `:path*` value\n\t// keeps every separator that it carries.\n\tlet url = (isAbsolute ? routeTemplate : joinPaths(basePath, routeTemplate)).replace(\n\t\t/\\/+/g,\n\t\t\"/\",\n\t);\n\n\t// Replace each param with a context value. `buildPath` of `@xmachines/play-pattern`\n\t// reads the WHOLE pattern grammar, which is the same parse that the match reads, so a\n\t// route that the router matches derives a URL that the router matches back. That\n\t// package carries the language alone: no URLPattern, and no polyfill for it.\n\tconst built = buildPath(url, context.params ?? {}, options);\n\tif (!built.ok) {\n\t\tif (built.reason === \"unresolvable\") {\n\t\t\tthrow new InvalidRouteParamError(built.param, built.value, routeTemplate);\n\t\t}\n\t\tthrow new MissingRouteParamError(built.missing, routeTemplate);\n\t}\n\t// A template of the root level with optional params only, for example `/:section?`,\n\t// builds `\"\"`. That value makes an invalid URL, such as `\"\"` or `\"?tab=x\"`.\n\turl = built.path === \"\" ? \"/\" : built.path;\n\n\t// Append the query params of the context. The frequent empty `query: {}` passes the\n\t// key check first. Therefore each recomputation allocates a URLSearchParams object\n\t// only when it has something to write.\n\tif (context.query && typeof context.query === \"object\") {\n\t\tconst queryEntries = Object.entries(context.query);\n\t\tif (queryEntries.length > 0) {\n\t\t\tconst params = new URLSearchParams(\n\t\t\t\tqueryEntries.map(([k, v]) => [k, String(v)] as [string, string]),\n\t\t\t);\n\t\t\tconst queryString = params.toString();\n\t\t\tif (queryString) {\n\t\t\t\turl += `?${queryString}`;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Append the hash of the context\n\tif (context.hash && typeof context.hash === \"string\") {\n\t\turl += `#${context.hash}`;\n\t}\n\n\treturn url;\n};\n\n/**\n * Joins a base path and a relative path\n *\n * The function puts one slash between the two paths\n *\n * @param base - The base path\n * @param relative - The relative path\n * @returns The joined path\n */\nconst joinPaths = (base: string, relative: string): string => {\n\t// Remove the trailing slash of the base\n\tconst normalizedBase = base.replace(/\\/$/, \"\");\n\n\t// Remove the first slash of the relative path\n\tconst normalizedRelative = relative.replace(/^\\//, \"\");\n\n\t// Join the two paths with one slash\n\treturn normalizedBase ? `${normalizedBase}/${normalizedRelative}` : `/${normalizedRelative}`;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,IAAa,iBACZ,eACA,UAAwB,EAAE,OAAO,CAAC,EAAE,GACpC,YACY;CASZ,MAAM,WAAW,QAAQ,YAAY;CAarC,IAAI,OAZe,gBAAgB,aAYxB,IAAa,gBAAgB,UAAU,UAAU,aAAa,EAAA,CAAG,QAC3E,QACA,GACD;CAMA,MAAM,QAAQ,UAAU,KAAK,QAAQ,UAAU,CAAC,GAAG,OAAO;CAC1D,IAAI,CAAC,MAAM,IAAI;EACd,IAAI,MAAM,WAAW,gBACpB,MAAM,IAAI,uBAAuB,MAAM,OAAO,MAAM,OAAO,aAAa;EAEzE,MAAM,IAAI,uBAAuB,MAAM,SAAS,aAAa;CAC9D;CAGA,MAAM,MAAM,SAAS,KAAK,MAAM,MAAM;CAKtC,IAAI,QAAQ,SAAS,OAAO,QAAQ,UAAU,UAAU;EACvD,MAAM,eAAe,OAAO,QAAQ,QAAQ,KAAK;EACjD,IAAI,aAAa,SAAS,GAAG;GAI5B,MAAM,cAAc,IAHD,gBAClB,aAAa,KAAK,CAAC,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAqB,CAE5C,CAAA,CAAO,SAAS;GACpC,IAAI,aACH,OAAO,IAAI;EAEb;CACD;CAGA,IAAI,QAAQ,QAAQ,OAAO,QAAQ,SAAS,UAC3C,OAAO,IAAI,QAAQ;CAGpB,OAAO;AACR;;;;;;;;;;AAWA,IAAM,aAAa,MAAc,aAA6B;CAE7D,MAAM,iBAAiB,KAAK,QAAQ,OAAO,EAAE;CAG7C,MAAM,qBAAqB,SAAS,QAAQ,OAAO,EAAE;CAGrD,OAAO,iBAAiB,GAAG,eAAe,GAAG,uBAAuB,IAAI;AACzE"}
@@ -1 +1 @@
1
- {"version":3,"file":"derive-current-route.d.ts","sourceRoot":"","sources":["../../src/routing/derive-current-route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAMjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAG5D,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,kBAAkB,GAC9B,UAAU,kBAAkB,EAC5B,UAAU,YAAY,KACpB,MAAM,GAAG,IAsCX,CAAC"}
1
+ {"version":3,"file":"derive-current-route.d.ts","sourceRoot":"","sources":["../../src/routing/derive-current-route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAMjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAG5D,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,kBAAkB,GAC9B,UAAU,kBAAkB,EAC5B,UAAU,YAAY,KACpB,MAAM,GAAG,IA0CX,CAAC"}
@@ -1,73 +1,52 @@
1
1
  import { MissingRouteParamError } from "../errors.js";
2
2
  import { deriveRoute } from "./derive-route.js";
3
3
  import { buildRouteUrl } from "./build-url.js";
4
- import { activeStateMeta } from "../state-meta.js";
5
- export { activeStateMeta, firstActiveBranchMeta } from "../state-meta.js";
4
+ import { activeStateMeta, warnStateIds } from "../state-meta.js";
5
+ //#region packages/play-xstate/src/routing/derive-current-route.ts
6
6
  /**
7
- * Derives the current URL of the actor from the state metadata and the context.
8
- *
9
- * The function resolves the route template from the `meta.route` field of the
10
- * current state. It then replaces each `:param` placeholder with a value of
11
- * `context.params`, which it prefers, or of the flat `context` object.
12
- *
13
- * The function returns `null`, and it throws no error, in two cases:
14
- * - The snapshot has no route metadata, which means a state without a route
15
- * - The context does not hold a necessary route parameter (`MissingRouteParamError`)
16
- *
17
- * The `null` value for an absent param is deliberate: the computed atom therefore
18
- * stays stable during a temporary state. Such a state appears during a transition,
19
- * before the context is complete, and also after a logout, when `context.username`
20
- * is `null` and the router bridge did not reach the new state yet. The router bridge
21
- * and the URL bar receive the new value on the next stable snapshot, when the
22
- * context is complete.
23
- *
24
- * @param snapshot - The current snapshot of the XState machine.
25
- * @param options - The caches that the parse of the route TEMPLATE reads. The default is
26
- * the cache that `@xmachines/play-pattern` shares with every caller of the process.
27
- *
28
- * `withRouting` calls this function with no options, and that is deliberate: it parses
29
- * the `meta.route` template of a state, and a machine declares a small and static set of
30
- * those. The unbounded key space that a cache of the caller answers is the one of
31
- * `RouterBridgeBase`, which parses a CONCRETE location — one for each value that an
32
- * application puts in a param — and a bridge takes its caches already.
33
- * @returns The resolved URL string, or `null` when the function cannot resolve the route.
34
- */
35
- export const deriveCurrentRoute = (snapshot, options) => {
36
- const meta = activeStateMeta(snapshot);
37
- if (!meta) {
38
- return null;
39
- }
40
- const routeTemplate = deriveRoute(meta);
41
- if (!routeTemplate) {
42
- return null;
43
- }
44
- try {
45
- return buildRouteUrl(routeTemplate, (snapshot.context ?? {}), options);
46
- }
47
- catch (error) {
48
- // MissingRouteParamError: the condition is temporary, and it resolves itself. A
49
- // necessary `:param` is absent from the context during a state of a transition, for
50
- // example an actor in the profile state before the first play.route event fills
51
- // context.params, and also after a logout, before the bridge redirects. A `null`
52
- // value is correct here:
53
- // - a router bridge reads null and skips the navigation (syncRouterFromActor, line 242)
54
- // - the atom computes its value again on the next snapshot, when the params arrive
55
- // - a report of a condition that resolves itself is worse than a null value for
56
- // one tick.
57
- // Do NOT convert this into a throw.
58
- if (error instanceof MissingRouteParamError) {
59
- return null;
60
- }
61
- // Each unexpected error goes to the caller without a change.
62
- //
63
- // This function is PURE, and it stays that way: it has no actor, so it holds no
64
- // error channel and no previous value. The CALLER decides what an unexpected error
65
- // means. `currentRoute` of `with-routing.ts` is that caller for the reactive path —
66
- // it reports through `onError` of the actor and keeps the last route, because a
67
- // throw from there would unwind into the transition. `initialRoute` is the other
68
- // caller, and a throw from it fails the construction, which is where a developer
69
- // wants to see a route template that cannot be built.
70
- throw error;
71
- }
7
+ * Derives the current URL of the actor from the state metadata and the context.
8
+ *
9
+ * The function resolves the route template from the `meta.route` field of the
10
+ * current state. It then replaces each `:param` placeholder with a value of
11
+ * `context.params`, which it prefers, or of the flat `context` object.
12
+ *
13
+ * The function returns `null`, and it throws no error, in two cases:
14
+ * - The snapshot has no route metadata, which means a state without a route
15
+ * - The context does not hold a necessary route parameter (`MissingRouteParamError`)
16
+ *
17
+ * The `null` value for an absent param is deliberate: the computed atom therefore
18
+ * stays stable during a temporary state. Such a state appears during a transition,
19
+ * before the context is complete, and also after a logout, when `context.username`
20
+ * is `null` and the router bridge did not reach the new state yet. The router bridge
21
+ * and the URL bar receive the new value on the next stable snapshot, when the
22
+ * context is complete.
23
+ *
24
+ * @param snapshot - The current snapshot of the XState machine.
25
+ * @param options - The caches that the parse of the route TEMPLATE reads. The default is
26
+ * the cache that `@xmachines/play-pattern` shares with every caller of the process.
27
+ *
28
+ * `withRouting` calls this function with no options, and that is deliberate: it parses
29
+ * the `meta.route` template of a state, and a machine declares a small and static set of
30
+ * those. The unbounded key space that a cache of the caller answers is the one of
31
+ * `RouterBridgeBase`, which parses a CONCRETE location — one for each value that an
32
+ * application puts in a param — and a bridge takes its caches already.
33
+ * @returns The resolved URL string, or `null` when the function cannot resolve the route.
34
+ */
35
+ var deriveCurrentRoute = (snapshot, options) => {
36
+ const root = snapshot?.machine?.root;
37
+ if (root) warnStateIds(root);
38
+ const meta = activeStateMeta(snapshot);
39
+ if (!meta) return null;
40
+ const routeTemplate = deriveRoute(meta);
41
+ if (!routeTemplate) return null;
42
+ try {
43
+ return buildRouteUrl(routeTemplate, snapshot.context ?? {}, options);
44
+ } catch (error) {
45
+ if (error instanceof MissingRouteParamError) return null;
46
+ throw error;
47
+ }
72
48
  };
49
+ //#endregion
50
+ export { deriveCurrentRoute };
51
+
73
52
  //# sourceMappingURL=derive-current-route.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"derive-current-route.js","sourceRoot":"","sources":["../../src/routing/derive-current-route.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAG/C,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CACjC,QAA4B,EAC5B,OAAsB,EACN,EAAE;IAClB,MAAM,IAAI,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,CAAC,IAAI,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACb,CAAC;IAED,MAAM,aAAa,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,CAAC,aAAa,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACb,CAAC;IAED,IAAI,CAAC;QACJ,OAAO,aAAa,CAAC,aAAa,EAAE,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAiB,EAAE,OAAO,CAAC,CAAC;IACxF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,gFAAgF;QAChF,oFAAoF;QACpF,gFAAgF;QAChF,iFAAiF;QACjF,yBAAyB;QACzB,0FAA0F;QAC1F,qFAAqF;QACrF,kFAAkF;QAClF,gBAAgB;QAChB,oCAAoC;QACpC,IAAI,KAAK,YAAY,sBAAsB,EAAE,CAAC;YAC7C,OAAO,IAAI,CAAC;QACb,CAAC;QACD,6DAA6D;QAC7D,EAAE;QACF,gFAAgF;QAChF,mFAAmF;QACnF,oFAAoF;QACpF,gFAAgF;QAChF,iFAAiF;QACjF,iFAAiF;QACjF,sDAAsD;QACtD,MAAM,KAAK,CAAC;IACb,CAAC;AACF,CAAC,CAAC"}
1
+ {"version":3,"file":"derive-current-route.js","names":[],"sources":["../../src/routing/derive-current-route.ts"],"sourcesContent":["import type { AnyMachineSnapshot } from \"xstate\";\n\nimport { MissingRouteParamError } from \"../errors.js\";\nimport { deriveRoute } from \"./derive-route.js\";\nimport { buildRouteUrl } from \"./build-url.js\";\nimport type { RouteContext } from \"./types.js\";\nimport type { ParseOptions } from \"@xmachines/play-pattern\";\nimport { activeStateMeta, warnStateIds, type BranchNode } from \"../state-meta.js\";\n\nexport { activeStateMeta, firstActiveBranchMeta } from \"../state-meta.js\";\n\n/**\n * Derives the current URL of the actor from the state metadata and the context.\n *\n * The function resolves the route template from the `meta.route` field of the\n * current state. It then replaces each `:param` placeholder with a value of\n * `context.params`, which it prefers, or of the flat `context` object.\n *\n * The function returns `null`, and it throws no error, in two cases:\n * - The snapshot has no route metadata, which means a state without a route\n * - The context does not hold a necessary route parameter (`MissingRouteParamError`)\n *\n * The `null` value for an absent param is deliberate: the computed atom therefore\n * stays stable during a temporary state. Such a state appears during a transition,\n * before the context is complete, and also after a logout, when `context.username`\n * is `null` and the router bridge did not reach the new state yet. The router bridge\n * and the URL bar receive the new value on the next stable snapshot, when the\n * context is complete.\n *\n * @param snapshot - The current snapshot of the XState machine.\n * @param options - The caches that the parse of the route TEMPLATE reads. The default is\n * the cache that `@xmachines/play-pattern` shares with every caller of the process.\n *\n * `withRouting` calls this function with no options, and that is deliberate: it parses\n * the `meta.route` template of a state, and a machine declares a small and static set of\n * those. The unbounded key space that a cache of the caller answers is the one of\n * `RouterBridgeBase`, which parses a CONCRETE location — one for each value that an\n * application puts in a param — and a bridge takes its caches already.\n * @returns The resolved URL string, or `null` when the function cannot resolve the route.\n */\nexport const deriveCurrentRoute = (\n\tsnapshot: AnyMachineSnapshot,\n\toptions?: ParseOptions,\n): string | null => {\n\tconst root = snapshot?.machine?.root as BranchNode | undefined;\n\tif (root) warnStateIds(root);\n\tconst meta = activeStateMeta(snapshot);\n\tif (!meta) {\n\t\treturn null;\n\t}\n\n\tconst routeTemplate = deriveRoute(meta);\n\tif (!routeTemplate) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\treturn buildRouteUrl(routeTemplate, (snapshot.context ?? {}) as RouteContext, options);\n\t} catch (error) {\n\t\t// MissingRouteParamError: the condition is temporary, and it resolves itself. A\n\t\t// necessary `:param` is absent from the context during a state of a transition, for\n\t\t// example an actor in the profile state before the first play.route event fills\n\t\t// context.params, and also after a logout, before the bridge redirects. A `null`\n\t\t// value is correct here:\n\t\t// - a router bridge reads null and skips the navigation (syncRouterFromActor, line 242)\n\t\t// - the atom computes its value again on the next snapshot, when the params arrive\n\t\t// - a report of a condition that resolves itself is worse than a null value for\n\t\t// one tick.\n\t\t// Do NOT convert this into a throw.\n\t\tif (error instanceof MissingRouteParamError) {\n\t\t\treturn null;\n\t\t}\n\t\t// Each unexpected error goes to the caller without a change.\n\t\t//\n\t\t// This function is PURE in its result, and it stays that way: it has no actor, so it\n\t\t// holds no error channel and no previous value. Its one side effect is the warning\n\t\t// of warnStateIds, one time for each machine whose state ids break a rule. The\n\t\t// CALLER decides what an unexpected error means. `currentRoute` of\n\t\t// `with-routing.ts` is that caller for the reactive path — it reports through\n\t\t// `onError` of the actor and keeps the last route, because a throw from there would\n\t\t// unwind into the transition. `initialRoute` is the other caller, and a throw from\n\t\t// it fails the construction, which is where a developer wants to see a route\n\t\t// template that cannot be built.\n\t\tthrow error;\n\t}\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,IAAa,sBACZ,UACA,YACmB;CACnB,MAAM,OAAO,UAAU,SAAS;CAChC,IAAI,MAAM,aAAa,IAAI;CAC3B,MAAM,OAAO,gBAAgB,QAAQ;CACrC,IAAI,CAAC,MACJ,OAAO;CAGR,MAAM,gBAAgB,YAAY,IAAI;CACtC,IAAI,CAAC,eACJ,OAAO;CAGR,IAAI;EACH,OAAO,cAAc,eAAgB,SAAS,WAAW,CAAC,GAAoB,OAAO;CACtF,SAAS,OAAO;EAWf,IAAI,iBAAiB,wBACpB,OAAO;EAaR,MAAM;CACP;AACD"}
@@ -1,68 +1,57 @@
1
- import { initialTransition } from "xstate";
2
1
  import { deriveCurrentRoute } from "./derive-current-route.js";
2
+ import { initialTransition } from "xstate";
3
+ //#region packages/play-xstate/src/routing/derive-initial-route.ts
3
4
  /**
4
- * Derives the initial route of the machine directly from the machine definition.
5
- *
6
- * The function uses the pure `initialTransition` helper of XState to compute the
7
- * initial snapshot of the machine. That helper resolves the complete chain of the
8
- * initial states, which includes each nested compound state, and also the real
9
- * initial context for the given `input`. It makes no actor, and it runs no entry
10
- * action.
11
- *
12
- * The resolution of the route follows the same rules as {@link deriveCurrentRoute}
13
- * for a live snapshot: the deepest state with a route wins, a relative `meta.route`
14
- * segment resolves against the ancestors with a route, and each `:param` placeholder
15
- * receives a value of the initial `context.params`.
16
- *
17
- * A router bridge compares the result with the browser URL. It therefore separates a
18
- * deep link (a URL that is not the initial one → the router wins) from a restore
19
- * (the initial URL, and the actor at a different route from the restore → the actor
20
- * wins). The derivation reads no snapshot of a restore. Therefore it always gives
21
- * the **default** initial route of the machine.
22
- *
23
- * @param machine - The definition of the XState v5 state machine.
24
- * @param input - The input of the actor. The function gives it to the context
25
- * factory of the machine, exactly like `createActor(machine, { input })`.
26
- * @returns The resolved initial URL string, or `null`. The function returns `null`
27
- * in three cases: the initial state has no `meta.route` field; the initial context
28
- * does not hold a necessary `:param`; or the context logic or the initial-transition
29
- * logic of the machine throws for the given input. The last case matches the
30
- * error-status snapshot of `createActor`, which also has no route to derive.
31
- *
32
- * @example
33
- * ```typescript
34
- * const machine = setup({}).createMachine({
35
- * context: ({ input }) => ({ params: { username: input.username }, query: {} }),
36
- * initial: "profile",
37
- * states: { profile: { meta: { route: "/profile/:username" } } },
38
- * });
39
- *
40
- * deriveInitialRoute(machine, { username: "alice" }); // "/profile/alice"
41
- * ```
42
- */
43
- export const deriveInitialRoute = (machine, input, options) => {
44
- let initialSnapshot;
45
- try {
46
- [initialSnapshot] = initialTransition(machine, input);
47
- }
48
- catch {
49
- // The context factory or the initial-transition logic threw for this input, for
50
- // example a factory that reads a necessary `input` field and receives none. This is
51
- // the equivalent of the error-status snapshot of createActor in the pure helper, and
52
- // that snapshot also has no route metadata. Report "no initial route to derive".
53
- return null;
54
- }
55
- // The SAME failure, reported the other way. XState 5.32 threw out of
56
- // `initialTransition` for a context factory that throws, and 5.33 returns an
57
- // error-status snapshot instead, with the reason on `snapshot.error`. The catch above
58
- // therefore stopped firing, and a machine whose context never built derived the route
59
- // of its initial state — `/login` for a factory that threw — which a bridge then took
60
- // as the place of the actor.
61
- //
62
- // Both shapes mean the same thing, so both answer the same way. The status is the
63
- // question, and it holds whichever way a later release reports the failure.
64
- if (initialSnapshot.status === "error")
65
- return null;
66
- return deriveCurrentRoute(initialSnapshot, options);
5
+ * Derives the initial route of the machine directly from the machine definition.
6
+ *
7
+ * The function uses the pure `initialTransition` helper of XState to compute the
8
+ * initial snapshot of the machine. That helper resolves the complete chain of the
9
+ * initial states, which includes each nested compound state, and also the real
10
+ * initial context for the given `input`. It makes no actor, and it runs no entry
11
+ * action.
12
+ *
13
+ * The resolution of the route follows the same rules as {@link deriveCurrentRoute}
14
+ * for a live snapshot: the deepest state with a route wins, a relative `meta.route`
15
+ * segment resolves against the ancestors with a route, and each `:param` placeholder
16
+ * receives a value of the initial `context.params`.
17
+ *
18
+ * A router bridge compares the result with the browser URL. It therefore separates a
19
+ * deep link (a URL that is not the initial one → the router wins) from a restore
20
+ * (the initial URL, and the actor at a different route from the restore → the actor
21
+ * wins). The derivation reads no snapshot of a restore. Therefore it always gives
22
+ * the **default** initial route of the machine.
23
+ *
24
+ * @param machine - The definition of the XState v5 state machine.
25
+ * @param input - The input of the actor. The function gives it to the context
26
+ * factory of the machine, exactly like `createActor(machine, { input })`.
27
+ * @returns The resolved initial URL string, or `null`. The function returns `null`
28
+ * in three cases: the initial state has no `meta.route` field; the initial context
29
+ * does not hold a necessary `:param`; or the context logic or the initial-transition
30
+ * logic of the machine throws for the given input. The last case matches the
31
+ * error-status snapshot of `createActor`, which also has no route to derive.
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * const machine = setup({}).createMachine({
36
+ * context: ({ input }) => ({ params: { username: input.username }, query: {} }),
37
+ * initial: "profile",
38
+ * states: { profile: { meta: { route: "/profile/:username" } } },
39
+ * });
40
+ *
41
+ * deriveInitialRoute(machine, { username: "alice" }); // "/profile/alice"
42
+ * ```
43
+ */
44
+ var deriveInitialRoute = (machine, input, options) => {
45
+ let initialSnapshot;
46
+ try {
47
+ [initialSnapshot] = initialTransition(machine, input);
48
+ } catch {
49
+ return null;
50
+ }
51
+ if (initialSnapshot.status === "error") return null;
52
+ return deriveCurrentRoute(initialSnapshot, options);
67
53
  };
54
+ //#endregion
55
+ export { deriveInitialRoute };
56
+
68
57
  //# sourceMappingURL=derive-initial-route.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"derive-initial-route.js","sourceRoot":"","sources":["../../src/routing/derive-initial-route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAiD,MAAM,QAAQ,CAAC;AAE1F,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CACjC,OAAwB,EACxB,KAAe,EACf,OAAsB,EACN,EAAE;IAClB,IAAI,eAAmC,CAAC;IACxC,IAAI,CAAC;QACJ,CAAC,eAAe,CAAC,GAAG,iBAAiB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACR,gFAAgF;QAChF,oFAAoF;QACpF,qFAAqF;QACrF,iFAAiF;QACjF,OAAO,IAAI,CAAC;IACb,CAAC;IAED,qEAAqE;IACrE,6EAA6E;IAC7E,sFAAsF;IACtF,sFAAsF;IACtF,sFAAsF;IACtF,6BAA6B;IAC7B,EAAE;IACF,kFAAkF;IAClF,4EAA4E;IAC5E,IAAI,eAAe,CAAC,MAAM,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IAEpD,OAAO,kBAAkB,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;AACrD,CAAC,CAAC"}
1
+ {"version":3,"file":"derive-initial-route.js","names":[],"sources":["../../src/routing/derive-initial-route.ts"],"sourcesContent":["import { initialTransition, type AnyMachineSnapshot, type AnyStateMachine } from \"xstate\";\n\nimport { deriveCurrentRoute } from \"./derive-current-route.js\";\nimport type { ParseOptions } from \"@xmachines/play-pattern\";\n\n/**\n * Derives the initial route of the machine directly from the machine definition.\n *\n * The function uses the pure `initialTransition` helper of XState to compute the\n * initial snapshot of the machine. That helper resolves the complete chain of the\n * initial states, which includes each nested compound state, and also the real\n * initial context for the given `input`. It makes no actor, and it runs no entry\n * action.\n *\n * The resolution of the route follows the same rules as {@link deriveCurrentRoute}\n * for a live snapshot: the deepest state with a route wins, a relative `meta.route`\n * segment resolves against the ancestors with a route, and each `:param` placeholder\n * receives a value of the initial `context.params`.\n *\n * A router bridge compares the result with the browser URL. It therefore separates a\n * deep link (a URL that is not the initial one → the router wins) from a restore\n * (the initial URL, and the actor at a different route from the restore → the actor\n * wins). The derivation reads no snapshot of a restore. Therefore it always gives\n * the **default** initial route of the machine.\n *\n * @param machine - The definition of the XState v5 state machine.\n * @param input - The input of the actor. The function gives it to the context\n * factory of the machine, exactly like `createActor(machine, { input })`.\n * @returns The resolved initial URL string, or `null`. The function returns `null`\n * in three cases: the initial state has no `meta.route` field; the initial context\n * does not hold a necessary `:param`; or the context logic or the initial-transition\n * logic of the machine throws for the given input. The last case matches the\n * error-status snapshot of `createActor`, which also has no route to derive.\n *\n * @example\n * ```typescript\n * const machine = setup({}).createMachine({\n * context: ({ input }) => ({ params: { username: input.username }, query: {} }),\n * initial: \"profile\",\n * states: { profile: { meta: { route: \"/profile/:username\" } } },\n * });\n *\n * deriveInitialRoute(machine, { username: \"alice\" }); // \"/profile/alice\"\n * ```\n */\nexport const deriveInitialRoute = (\n\tmachine: AnyStateMachine,\n\tinput?: unknown,\n\toptions?: ParseOptions,\n): string | null => {\n\tlet initialSnapshot: AnyMachineSnapshot;\n\ttry {\n\t\t[initialSnapshot] = initialTransition(machine, input);\n\t} catch {\n\t\t// The context factory or the initial-transition logic threw for this input, for\n\t\t// example a factory that reads a necessary `input` field and receives none. This is\n\t\t// the equivalent of the error-status snapshot of createActor in the pure helper, and\n\t\t// that snapshot also has no route metadata. Report \"no initial route to derive\".\n\t\treturn null;\n\t}\n\n\t// The SAME failure, reported the other way. XState 5.32 threw out of\n\t// `initialTransition` for a context factory that throws, and 5.33 returns an\n\t// error-status snapshot instead, with the reason on `snapshot.error`. The catch above\n\t// therefore stopped firing, and a machine whose context never built derived the route\n\t// of its initial state — `/login` for a factory that threw — which a bridge then took\n\t// as the place of the actor.\n\t//\n\t// Both shapes mean the same thing, so both answer the same way. The status is the\n\t// question, and it holds whichever way a later release reports the failure.\n\tif (initialSnapshot.status === \"error\") return null;\n\n\treturn deriveCurrentRoute(initialSnapshot, options);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,IAAa,sBACZ,SACA,OACA,YACmB;CACnB,IAAI;CACJ,IAAI;EACH,CAAC,mBAAmB,kBAAkB,SAAS,KAAK;CACrD,QAAQ;EAKP,OAAO;CACR;CAWA,IAAI,gBAAgB,WAAW,SAAS,OAAO;CAE/C,OAAO,mBAAmB,iBAAiB,OAAO;AACnD"}