@exodus/device-reactivity
v0.1.1
Published
Small observable and sequential state-machine primitives for device integrations
Maintainers
Keywords
Readme
@exodus/device-reactivity
Small observable and sequential state-machine primitives for device integrations, extracted from the Exodus Ledger SDK fork. Not an official Ledger package.
The implementation and differential tests originated in Ledger SDK PR #2.
The only runtime dependency is @nx-js/[email protected]. RxJS and XState are
development-only reference implementations for differential tests. This package
does not depend on Ledger SDK packages or their build tooling.
import { of, take, toArray, lastValueFrom } from "@exodus/device-reactivity";
import {
createActor,
createMachine,
} from "@exodus/device-reactivity/state-machine";
await lastValueFrom(of(1, 2, 3).pipe(take(2), toArray()));
const actor = createActor(
createMachine({
initial: "idle",
states: { idle: { on: { FINISH: "done" } }, done: { type: "final" } },
}),
);
actor.start();
actor.send({ type: "FINISH" });CommonJS require() is also supported. Both entry points include TypeScript declarations.
Supported subset
Streams provide observables, subjects, subscriptions, synchronous delivery,
completion/error handling, cancellation, timers, replay and reference-counted
sharing. Supported operators are catchError, debounceTime, delay, distinct,
distinctUntilChanged, filter, finalize, first, map, mergeMap, retry,
scan, share, startWith, switchMap, take, tap, throttleTime, timeout,
toArray and withLatestFrom. Creation helpers are concat, defer,
firstValueFrom, from, interval, lastValueFrom, merge, of, throwError
and timer.
State machines support sequential states, entry/exit actions, ordered guards, eventless transitions, delays, raised events, invoked children, snapshots, final output and cancellation. Promise actors receive an abort signal; stopped actors cannot deliver stale results.
These are deliberately not complete RxJS/XState replacements. Custom schedulers, time-windowed replay, hierarchical/parallel/history states, persistence, spawning and inspector integration are unsupported. Only the API forms used and tested by the device SDK are implemented. Values retain their identity and are not proxied.
Migration
- Replace imports from
rxjsandrxjs/operatorswith@exodus/device-reactivity. - Replace imports from
xstatewith@exodus/device-reactivity/state-machine. - Do not mix RxJS operators with these observables or pass XState machine objects to this interpreter. Consumers need the supported API, not just renamed imports.
- To bridge to RxJS, explicitly adapt with
new RxObservable(sink => source.subscribe(sink)).
Development
corepack pnpm install --frozen-lockfile
pnpm lint
pnpm typecheck
pnpm test
pnpm build
pnpm test:package
pnpm packThe build emits separate ESM and CommonJS modules and declarations. Tests and development dependencies are excluded from the npm tarball.
CI and publishing
Checks runs lint, formatting, type checks, and tests on pull requests and pushes
to main. Tests, builds, and package checks run on Node.js 20, 22, and 24.
Publish follows the assets/exodus release-commit and manual-dispatch pattern,
without their monorepo-specific Lerna tooling. It reruns Checks, builds from a
fresh checkout without a dependency cache, and publishes only from main.
- Restrict the GitHub
Publishenvironment to themainbranch. Provide an npm trusted publisher in the package's npm settings: GitHub Actions, organizationExodusMovement, repositorydevice-reactivity, workflow filenamepublish.yml, environmentPublish. Allow direct publishing withnpm publish. - Run Actions → Publish → Run workflow on
main. Keepdry-runenabled to validate without publishing; disable it to publish the current package version. - For later releases, update
package.jsonwithpnpm version patch --no-git-tag-version(orminor/major) and land the version change onmainwith a commit message beginningchore: release. This publishes automatically using thelatestdist-tag. Already-published versions cannot be republished. - Publish prerelease versions manually with
next,alpha,beta, orrc; prereleases cannot uselatest.
Only the publish job can request a GitHub OIDC token. npm uses that identity to publish; no npm token secret is required. A dry run validates packaging, not the npm trusted-publisher configuration. The workflow does not bump versions or create Git tags or GitHub releases.
Initial npm setup
npm requires the package to exist before a trusted publisher can be added. An
authorized maintainer of the npm exodus organization must publish the initial
version from a clean checkout using their interactive npm login and 2FA:
npm login
pnpm install --frozen-lockfile --ignore-scripts
pnpm build
pnpm test:package
npm publish --ignore-scripts --access publicThen configure the trusted publisher above. Later CI releases must use a new, unpublished version; the initial version cannot be published again. Complete the first OIDC release within npm's trusted-publisher validation window. GitHub repository admin access does not grant npm organization permissions.
