Rxova
Skip to content

Core API

import {
createLinearJourney,
createGraphJourney,
withLinearTypes,
withGraphTypes,
analyzeStructure
} from "@rxova/journey-core";

The package also exports the definition, machine, snapshot, hook, event, navigation and plugin types used by those functions, plus the Bag types that pin them up front.

Everything Core throws itself is a JourneyError carrying a machine-readable code, plus the offending stepId, event, or pluginName where one applies:

import { createLinearJourney, isJourneyError } from "@rxova/journey-core";
try {
createLinearJourney(definition, { startAt: idFromRoute });
} catch (error) {
if (isJourneyError(error) && error.code === "unknown-step") {
redirectToFirstStep(error.stepId);
}
}

code is the stable contract and a closed union: empty-definition, duplicate-step-id, unknown-step, unknown-initial-step, dangling-transition, duplicate-plugin-name, storage-unavailable, async-commit. Messages are for humans and may be reworded in any release — never match on them.

Failures that are not Core’s own stay untyped. NavigationResult.error and the error subscription event carry whatever your navigation work or hooks threw, which Core cannot constrain.

createLinearJourney(definition, options?);
createGraphJourney(definition, options?);
withGraphTypes<Bag>()(definition, options?);

Graph options additionally allow handlers to replace handlers stored on the definition.

Both factories accept the same JourneyRuntimeOptions:

OptionMeaning
autoStartStart at creation. Defaults to true. Starting commits the initial entry synchronously, so the first stepEnter fires before the factory returns — pass false when a subscriber has to see it, then call controls.start() yourself.
startAtStart (and restart) directly at this step: only its onEnter fires, earlier steps are neither entered nor visited, and the timeline begins as [startAt]. An unknown id throws at creation. Wins over a persisted persist record.
persist{ key, storage? } sugar that registers the persistence plugin and restores: a valid non-terminal record found at creation seeds context, timeline, and position, so the first start() resumes at the persisted step. See Persistence.
defaultTimeoutMsApplies to navigation/send work and every async hook. Work timeouts block movement; post-commit hook timeouts surface as step errors.
onListenerErrorCalled when a subscriber (selector or event listener) throws. Listener failures are always isolated — this option only routes the report. Defaults to console.error; a throwing reporter falls back to that default.
pluginsObserve-only plugin instances; see Plugins.
machine.getSnapshot();
machine.controls.start();
machine.controls.pause();
machine.controls.resume();
machine.controls.complete(payload);
machine.controls.terminate(payload);
machine.controls.restart();
await machine.navigate.goToStepById(id);
await machine.navigate.goToPreviousStep(n);
await machine.navigate.goToNextStep();
await machine.navigate.goToLastVisitedStep();
machine.context.update(updater);
machine.subscriptions.subscribe(listener);
machine.subscriptions.subscribeEvent(eventName, listener);
machine.dispose();

Graph machines add:

await machine.send(type, payload?);

Registered plugins appear under machine.plugins.

ImportExport
@rxova/journey-core/connectors/immerimmerConnector and ImmerContextRecipe
@rxova/journey-core/pluginscreatePersistencePlugin and helpers/types
@rxova/journey-core/pluginscreateAnalyticsPlugin and helpers/types
@rxova/journey-core/pluginscreateReplayPlugin and helpers/types
@rxova/journey-core/pluginscreateExecutionPathsPlugin

These entry points are independently tree-shakeable. Connectors adapt optional third-party libraries to Core primitives; the Immer connector requires immer as a peer only when that entry point is used.