From c930b19dd76038ad15981dd2f7e65f736a4bf0a6 Mon Sep 17 00:00:00 2001 From: Ivan Banov Date: Fri, 9 Oct 2026 17:53:54 +0200 Subject: [PATCH 1/2] refactor(crates): name the crates after the npm packages dunky-core -> dunky-state-machine, dunky-macros -> dunky-state-machine-macros, dunky-wasm -> dunky-state-machine-wasm, dunky-uniffi -> dunky-state-machine-uniffi, matching @dunky.dev/state-machine and @dunky.dev/state-machine-wasm. Directories stay (crates/core, crates/wasm, as packages/core, packages/wasm do). The private crates (dunky-sandbox, dunky-benchmark) keep their names. Co-Authored-By: Claude Fable 5.1 --- .changeset/state-machine-wasm.md | 4 +-- ARCHITECTURE.md | 4 +-- Cargo.lock | 30 ++++++++-------- Cargo.toml | 6 ++-- TODO.md | 2 +- benchmark/README.md | 2 +- benchmark/rust/Cargo.toml | 4 +-- benchmark/rust/README.md | 2 +- benchmark/rust/benches/engine.rs | 4 +-- benchmark/rust/src/lib.rs | 2 +- crates/core/Cargo.toml | 6 ++-- crates/core/README.md | 4 +-- crates/core/SPEC.md | 4 +-- crates/core/src/lib.rs | 8 ++--- crates/core/src/ts.rs | 2 +- crates/core/tests/act.rs | 4 +-- crates/core/tests/actions.rs | 2 +- crates/core/tests/after.rs | 4 +-- crates/core/tests/bare_fn_entry.rs | 2 +- crates/core/tests/broadcast.rs | 2 +- crates/core/tests/common/mod.rs | 2 +- crates/core/tests/compose.rs | 2 +- crates/core/tests/computed.rs | 2 +- crates/core/tests/connector.rs | 2 +- crates/core/tests/derive.rs | 2 +- crates/core/tests/effects.rs | 2 +- crates/core/tests/guards.rs | 2 +- crates/core/tests/lifecycle.rs | 2 +- crates/core/tests/setup.rs | 4 +-- crates/core/tests/store.rs | 2 +- crates/core/tests/subscribe.rs | 6 ++-- crates/core/tests/transitions.rs | 2 +- crates/core/tests/watch.rs | 2 +- crates/macros/Cargo.toml | 4 +-- crates/macros/src/lib.rs | 38 ++++++++++---------- crates/macros/src/ts.rs | 20 +++++------ crates/sandbox/Cargo.toml | 6 ++-- crates/sandbox/src/dialog.rs | 2 +- crates/sandbox/src/lib.rs | 10 +++--- crates/sandbox/src/palette.rs | 6 ++-- crates/uniffi/Cargo.lock | 22 ++++++------ crates/uniffi/Cargo.toml | 6 ++-- crates/uniffi/src/lib.rs | 10 +++--- crates/wasm/Cargo.toml | 6 ++-- crates/wasm/README.md | 10 +++--- crates/wasm/SPEC.md | 6 ++-- crates/wasm/src/bridge.rs | 2 +- crates/wasm/src/lib.rs | 14 ++++---- packages/wasm/README.md | 2 +- packages/wasm/package.json | 2 +- packages/wasm/src/from-wasm.ts | 4 +-- sandbox/native/rust-bench.tsx | 2 +- website/src/content/docs/install.mdx | 2 +- website/src/content/docs/rust/index.mdx | 20 +++++------ website/src/content/docs/rust/machines.mdx | 12 +++---- website/src/content/docs/rust/typescript.mdx | 6 ++-- website/src/pages/index.astro | 2 +- 57 files changed, 172 insertions(+), 172 deletions(-) diff --git a/.changeset/state-machine-wasm.md b/.changeset/state-machine-wasm.md index 43b6617..b81797b 100644 --- a/.changeset/state-machine-wasm.md +++ b/.changeset/state-machine-wasm.md @@ -3,7 +3,7 @@ --- New package: use a machine written in Rust from TypeScript. `fromWasm` wraps a class -exported with `dunky_wasm::export_machine!` in the same `Machine` interface the TS +exported with `dunky_state_machine_wasm::export_machine!` in the same `Machine` interface the TS engine returns, so `connect()`, `useMachine` and every target take it unchanged, next to TS machines. @@ -15,7 +15,7 @@ await init() const palette = fromWasm(new PaletteMachine(commands)) // typed from the Rust types ``` -The machine runs entirely in Rust, on the Rust engine (`dunky-core`), which follows the +The machine runs entirely in Rust, on the Rust engine (`dunky-state-machine`), which follows the same spec as the TS engine. Its TS types are generated from its Rust types and inferred by `fromWasm`, so they are never written twice. In JS a TS machine is a little faster, because its context already lives in JS: write a machine in Rust to reuse it in Rust diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 1f239ed..1787c52 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -99,7 +99,7 @@ Zag, whose machines read props directly.) | `packages/shared/bindings/` | Substrate-agnostic event + attr vocabulary (onPress, role, …) | | `packages/shared/utils/` | mergeProps, composeHandlers | | `packages//` | Hook + normalize per substrate (react, solid, native, opentui, …) | -| `crates/core/` | The Rust engine: the same spec, in Rust (`dunky-core`) | +| `crates/core/` | The Rust engine: the same spec, in Rust (`dunky-state-machine`) | | `crates/macros/` | `#[derive(State, Event, Context)]` for Rust machines | | `crates/wasm/` | Rust machines as JS classes (`export_machine!`) | | `packages/wasm/` | `fromWasm`: a Rust machine behind the TS `Machine` interface | @@ -160,7 +160,7 @@ This is the target shape of the repo; the boxes marked _planned_ do not exist ye +---------------------------+ +---------------------------+ | TS engine | | Rust engine | | packages/core | | crates/core, crates/macros| -| @dunky.dev/state-machine | | dunky-core | +| @dunky.dev/state-machine | | dunky-state-machine | +---------------------------+ +---------------------------+ | | | authors | authors diff --git a/Cargo.lock b/Cargo.lock index 076a3ad..d02217b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,43 +18,43 @@ checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" name = "dunky-benchmark" version = "0.1.0" dependencies = [ - "dunky-core", + "dunky-state-machine", ] [[package]] -name = "dunky-core" +name = "dunky-sandbox" version = "0.1.0" dependencies = [ - "dunky-macros", + "dunky-state-machine", + "dunky-state-machine-wasm", "serde", "serde_json", + "wasm-bindgen", ] [[package]] -name = "dunky-macros" +name = "dunky-state-machine" version = "0.1.0" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", + "dunky-state-machine-macros", + "serde", + "serde_json", ] [[package]] -name = "dunky-sandbox" +name = "dunky-state-machine-macros" version = "0.1.0" dependencies = [ - "dunky-core", - "dunky-wasm", - "serde", - "serde_json", - "wasm-bindgen", + "proc-macro2", + "quote", + "syn 2.0.119", ] [[package]] -name = "dunky-wasm" +name = "dunky-state-machine-wasm" version = "0.1.0" dependencies = [ - "dunky-core", + "dunky-state-machine", "js-sys", "serde", "serde-wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index fad3fc5..ccfb476 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,9 +16,9 @@ repository = "https://github.com/dunky-dev/state-machine" rust-version = "1.85" [workspace.dependencies] -dunky-core = { path = "crates/core" } -dunky-macros = { path = "crates/macros" } -dunky-wasm = { path = "crates/wasm" } +dunky-state-machine = { path = "crates/core" } +dunky-state-machine-macros = { path = "crates/macros" } +dunky-state-machine-wasm = { path = "crates/wasm" } dunky-sandbox = { path = "crates/sandbox" } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/TODO.md b/TODO.md index 85dcb57..8ae1058 100644 --- a/TODO.md +++ b/TODO.md @@ -56,7 +56,7 @@ The Rust column of the architecture diagram (`ARCHITECTURE.md`), above the engin - `@dunky.dev/state-machine-wasm` (`packages/wasm`) holds `fromWasm`; the TS engine stays pure TS. `crates/wasm` is Dunky's JS binding (`export_machine!`), Dunky-specific, in this repo because its protocol and the facade change together. -- A user's crate depends on `dunky-core` + `dunky-wasm` + `wasm-bindgen` and builds its +- A user's crate depends on `dunky-state-machine` + `dunky-state-machine-wasm` + `wasm-bindgen` and builds its own `.wasm`; each module carries its own copy of the engine. - The binding hears changes through the engine's own `subscribe()` / `take_changes()` and runs timers from `take_commands()`: the engine has no hook for JS. diff --git a/benchmark/README.md b/benchmark/README.md index a9d22c6..33bdf99 100644 --- a/benchmark/README.md +++ b/benchmark/README.md @@ -5,7 +5,7 @@ Dunky has two engines that follow one spec, and each has its own suite: | Suite | What it measures | Run | | ----------------- | ------------------------------------------------------------------------------------------------------- | -------------------------------- | | [`ts/`](./ts) | The TS engine (`@dunky.dev/state-machine`) against XState and Zag, plus React rendering and a live demo | `pnpm benchmark` | -| [`rust/`](./rust) | The Rust engine (`dunky-core`), natively, on the same scenarios, plus a 60 fps frame budget | `cargo bench -p dunky-benchmark` | +| [`rust/`](./rust) | The Rust engine (`dunky-state-machine`), natively, on the same scenarios, plus a 60 fps frame budget | `cargo bench -p dunky-benchmark` | The Rust rows are twins of TS rows, so a change to one engine can be measured against the same work on the other. diff --git a/benchmark/rust/Cargo.toml b/benchmark/rust/Cargo.toml index 98e41e0..71fa31a 100644 --- a/benchmark/rust/Cargo.toml +++ b/benchmark/rust/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "dunky-benchmark" -description = "The Rust engine's benchmark: the TS suite's engine scenarios, run natively on dunky-core." +description = "The Rust engine's benchmark: the TS suite's engine scenarios, run natively on dunky-state-machine." version.workspace = true edition.workspace = true license.workspace = true publish = false [dependencies] -dunky-core = { workspace = true } +dunky-state-machine = { workspace = true } [[bench]] name = "engine" diff --git a/benchmark/rust/README.md b/benchmark/rust/README.md index e5c2536..4458af3 100644 --- a/benchmark/rust/README.md +++ b/benchmark/rust/README.md @@ -1,6 +1,6 @@ # Rust benchmark suite -The Rust engine (`dunky-core`), measured natively. Release build, Apple M5 Pro; medians are +The Rust engine (`dunky-state-machine`), measured natively. Release build, Apple M5 Pro; medians are the average of two runs, and the frame table's p99 and worst columns take the **higher** of the two runs. Absolute figures vary by machine and thermal state — **run it yourself**. diff --git a/benchmark/rust/benches/engine.rs b/benchmark/rust/benches/engine.rs index 84f21d5..b4c0c36 100644 --- a/benchmark/rust/benches/engine.rs +++ b/benchmark/rust/benches/engine.rs @@ -12,7 +12,7 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::{Duration, Instant}; use dunky_benchmark::*; -use dunky_core::Machine; +use dunky_state_machine::Machine; /// Counts live heap bytes (the memory rows) and allocations (the frame rows). struct Counting; @@ -203,7 +203,7 @@ fn frame_budget() { } fn main() { - println!("Rust engine benchmark (dunky-core, native, release build)"); + println!("Rust engine benchmark (dunky-state-machine, native, release build)"); frame_budget(); diff --git a/benchmark/rust/src/lib.rs b/benchmark/rust/src/lib.rs index 08ef462..00d4b2a 100644 --- a/benchmark/rust/src/lib.rs +++ b/benchmark/rust/src/lib.rs @@ -4,7 +4,7 @@ use std::cell::Cell; -use dunky_core::{ComputedKey, Config, Context, Event, Machine, Selection, State, Types}; +use dunky_state_machine::{ComputedKey, Config, Context, Event, Machine, Selection, State, Types}; thread_local! { static SINK: Cell = const { Cell::new(0) }; diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index 7292ccf..a312e53 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "dunky-core" +name = "dunky-state-machine" description = "Substrate-agnostic state-machine engine — the Rust port of @dunky.dev/state-machine." version.workspace = true edition.workspace = true @@ -10,12 +10,12 @@ rust-version.workspace = true [features] default = ["derive", "serde"] # #[derive(State, Event, Context)] -derive = ["dep:dunky-macros"] +derive = ["dep:dunky-state-machine-macros"] # Per-field serialization (SerializeFields) for bindings that mirror context into JS. serde = ["dep:serde"] [dependencies] -dunky-macros = { workspace = true, optional = true } +dunky-state-machine-macros = { workspace = true, optional = true } serde = { workspace = true, optional = true } [dev-dependencies] diff --git a/crates/core/README.md b/crates/core/README.md index 1adba7c..c0e4307 100644 --- a/crates/core/README.md +++ b/crates/core/README.md @@ -1,4 +1,4 @@ -# dunky-core +# dunky-state-machine Dunky's state machines in Rust: the twin of the TypeScript engine, [`@dunky.dev/state-machine`](../../packages/core). Both follow one behavior contract, @@ -6,7 +6,7 @@ Dunky's state machines in Rust: the twin of the TypeScript engine, ported from `packages/core/tests`. Use it in Rust programs and native bindings. ```rust -use dunky_core::{Config, Context, Event, Machine, State, Types}; +use dunky_state_machine::{Config, Context, Event, Machine, State, Types}; #[derive(State, Clone, Copy, PartialEq, Eq, Debug)] enum DialogState { Closed, Open } diff --git a/crates/core/SPEC.md b/crates/core/SPEC.md index d2549a6..88f4de2 100644 --- a/crates/core/SPEC.md +++ b/crates/core/SPEC.md @@ -1,8 +1,8 @@ -# SPEC - `dunky-core` +# SPEC - `dunky-state-machine` ## Overview -`dunky-core` is the Rust implementation of Dunky's state machines. The TypeScript +`dunky-state-machine` is the Rust implementation of Dunky's state machines. The TypeScript implementation is [`@dunky.dev/state-machine`](../../packages/core). They are two engines with one behavior contract, [`packages/core/SPEC.md`](../../packages/core/SPEC.md): flat states, run-to-completion, diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs index 96e828c..8d3a048 100644 --- a/crates/core/src/lib.rs +++ b/crates/core/src/lib.rs @@ -1,4 +1,4 @@ -//! `dunky-core` — the Rust implementation of Dunky's state machines, next to the TS one +//! `dunky-state-machine` — the Rust implementation of Dunky's state machines, next to the TS one //! (`@dunky.dev/state-machine`). //! //! Both implement the same behavior contract, `packages/core/SPEC.md`; what is specific @@ -13,8 +13,8 @@ //! - **Change mask**: [`Machine::take_changes`] reports which fields changed, so a binding //! can mirror only those into another runtime. -// Lets the derive macros (which emit `::dunky_core::...`) work inside this crate too. -extern crate self as dunky_core; +// Lets the derive macros (which emit `::dunky_state_machine::...`) work inside this crate too. +extern crate self as dunky_state_machine; mod broadcast; mod compose; @@ -51,7 +51,7 @@ pub use traits::{DeserializeEvent, SerializeFields}; pub use ts::TsType; #[cfg(feature = "derive")] -pub use dunky_macros::{Context, Event, State, TsType}; +pub use dunky_state_machine_macros::{Context, Event, State, TsType}; /// The `machine.init` marker name: what a boot effect or a data-reaction sees as its /// event type (`ActionParams::event()` returns `None` for it). diff --git a/crates/core/src/ts.rs b/crates/core/src/ts.rs index b80131f..03cfd5d 100644 --- a/crates/core/src/ts.rs +++ b/crates/core/src/ts.rs @@ -1,5 +1,5 @@ //! TypeScript types of the values a machine shows JS, so a binding can generate a Rust -//! machine's TS types from its Rust ones. The mapping follows how `dunky-wasm` moves +//! machine's TS types from its Rust ones. The mapping follows how `dunky-state-machine-wasm` moves //! values through serde: `None` is `null`, sequences are arrays, maps are `Map`s, and //! every number is a `number`. diff --git a/crates/core/tests/act.rs b/crates/core/tests/act.rs index a8f26b5..6d84e04 100644 --- a/crates/core/tests/act.rs +++ b/crates/core/tests/act.rs @@ -12,7 +12,7 @@ mod common; use common::{Log, build}; -use dunky_core::{Config, Context, Event, State, Types}; +use dunky_state_machine::{Config, Context, Event, State, Types}; struct M; @@ -108,7 +108,7 @@ fn composes_with_a_target_and_other_actions_in_order() { let log: Log = Log::default(); let record = |phase: &'static str| { let log = log.clone(); - move |p: &mut dunky_core::ActionParams<'_, M>| { + move |p: &mut dunky_state_machine::ActionParams<'_, M>| { log.push(format!("{phase}: hit={}", p.context().hit)); } }; diff --git a/crates/core/tests/actions.rs b/crates/core/tests/actions.rs index 5106941..cd65686 100644 --- a/crates/core/tests/actions.rs +++ b/crates/core/tests/actions.rs @@ -11,7 +11,7 @@ mod common; use common::{CounterEvent, Log, build, counter}; -use dunky_core::{ +use dunky_state_machine::{ Action, Branch, Config, Context, Event, Guard, GuardParams, Machine, State, Types, }; diff --git a/crates/core/tests/after.rs b/crates/core/tests/after.rs index 70264b5..eaa2e50 100644 --- a/crates/core/tests/after.rs +++ b/crates/core/tests/after.rs @@ -8,8 +8,8 @@ mod common; use common::{Log, build}; -use dunky_core::testing::Clock; -use dunky_core::{Command, Config, Context, Event, State, Types}; +use dunky_state_machine::testing::Clock; +use dunky_state_machine::{Command, Config, Context, Event, State, Types}; struct M; diff --git a/crates/core/tests/bare_fn_entry.rs b/crates/core/tests/bare_fn_entry.rs index 8ad70c8..d96da3f 100644 --- a/crates/core/tests/bare_fn_entry.rs +++ b/crates/core/tests/bare_fn_entry.rs @@ -13,7 +13,7 @@ mod common; use common::{Log, build}; -use dunky_core::{Config, Context, Event, State, Types}; +use dunky_state_machine::{Config, Context, Event, State, Types}; struct M; diff --git a/crates/core/tests/broadcast.rs b/crates/core/tests/broadcast.rs index 69c82cb..5e66209 100644 --- a/crates/core/tests/broadcast.rs +++ b/crates/core/tests/broadcast.rs @@ -16,7 +16,7 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; use common::{Count, CounterEvent, Log, build, counter}; -use dunky_core::{Connector, Subscription}; +use dunky_state_machine::{Connector, Subscription}; /// A slot for a subscription made after the listener that will remove it. type Slot = Rc>>; diff --git a/crates/core/tests/common/mod.rs b/crates/core/tests/common/mod.rs index 545f013..9988c65 100644 --- a/crates/core/tests/common/mod.rs +++ b/crates/core/tests/common/mod.rs @@ -5,7 +5,7 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; -use dunky_core::{ +use dunky_state_machine::{ ActionParams, Cleanup, Config, ConfigBuilder, Context, Event, Machine, State, Types, }; diff --git a/crates/core/tests/compose.rs b/crates/core/tests/compose.rs index 78ea8da..b4852d3 100644 --- a/crates/core/tests/compose.rs +++ b/crates/core/tests/compose.rs @@ -12,7 +12,7 @@ mod common; use std::rc::Rc; use common::{AbState, Calls, CounterEvent, Log, ab, build, counter}; -use dunky_core::{Composition, Config, Event, Machine, Member, State, Subscription, Types}; +use dunky_state_machine::{Composition, Config, Event, Machine, Member, State, Subscription, Types}; struct Popup; diff --git a/crates/core/tests/computed.rs b/crates/core/tests/computed.rs index 4ebd79f..3ca84fb 100644 --- a/crates/core/tests/computed.rs +++ b/crates/core/tests/computed.rs @@ -14,7 +14,7 @@ mod common; use common::{Calls, Log, build}; -use dunky_core::{ +use dunky_state_machine::{ ComputedKey, Config, ConfigBuilder, Context, Event, Machine, State, StateEnum, Types, }; diff --git a/crates/core/tests/connector.rs b/crates/core/tests/connector.rs index 8529110..b20ba60 100644 --- a/crates/core/tests/connector.rs +++ b/crates/core/tests/connector.rs @@ -12,7 +12,7 @@ use std::cell::RefCell; use std::rc::Rc; use common::{Ab, AbEvent, AbState, Calls, Log, ab, build}; -use dunky_core::{ +use dunky_state_machine::{ Config, Connector, Context, Event, Machine, Reaction, State, Subscription, Types, }; diff --git a/crates/core/tests/derive.rs b/crates/core/tests/derive.rs index 753c90c..b91a55f 100644 --- a/crates/core/tests/derive.rs +++ b/crates/core/tests/derive.rs @@ -1,7 +1,7 @@ //! Rust-only: the derive macros name events exactly like serde, so the JS side can send //! `{ type, ... }` objects that both decoders (serde and `DeserializeEvent`) accept. -use dunky_core::{Context, DeserializeEvent, Event, EventEnum, State, TsType}; +use dunky_state_machine::{Context, DeserializeEvent, Event, EventEnum, State, TsType}; use serde::{Deserialize, Serialize}; #[derive(Event, Clone, Debug, PartialEq, Deserialize)] diff --git a/crates/core/tests/effects.rs b/crates/core/tests/effects.rs index 892f211..cf5dd03 100644 --- a/crates/core/tests/effects.rs +++ b/crates/core/tests/effects.rs @@ -20,7 +20,7 @@ mod common; use std::panic::{AssertUnwindSafe, catch_unwind}; use common::{Ab, AbEvent, AbState, Count, Counter, CounterState, Log, ab, build}; -use dunky_core::{ +use dunky_state_machine::{ ActionParams, Cleanup, Config, Context, Event, EventEnum, MACHINE_INIT, State, Types, }; diff --git a/crates/core/tests/guards.rs b/crates/core/tests/guards.rs index 05ed8ab..843ad4c 100644 --- a/crates/core/tests/guards.rs +++ b/crates/core/tests/guards.rs @@ -9,7 +9,7 @@ mod common; use common::{Calls, build}; -use dunky_core::{Config, ConfigBuilder, Context, Event, Guard, State, Types}; +use dunky_state_machine::{Config, ConfigBuilder, Context, Event, Guard, State, Types}; struct M; diff --git a/crates/core/tests/lifecycle.rs b/crates/core/tests/lifecycle.rs index 286c879..77c962f 100644 --- a/crates/core/tests/lifecycle.rs +++ b/crates/core/tests/lifecycle.rs @@ -4,7 +4,7 @@ mod common; use common::{Ab, AbEvent, AbEventKind, AbState, Calls, Log, ab, build}; -use dunky_core::Config; +use dunky_state_machine::Config; #[test] fn is_built_stopped_and_start_boots_the_effects() { diff --git a/crates/core/tests/setup.rs b/crates/core/tests/setup.rs index e50a929..a3fd3d5 100644 --- a/crates/core/tests/setup.rs +++ b/crates/core/tests/setup.rs @@ -14,8 +14,8 @@ mod common; use common::{Calls, Log, build}; -use dunky_core::testing::Clock; -use dunky_core::{Config, Context, Event, State, Types}; +use dunky_state_machine::testing::Clock; +use dunky_state_machine::{Config, Context, Event, State, Types}; struct M; diff --git a/crates/core/tests/store.rs b/crates/core/tests/store.rs index 4de1eed..b1b7f8a 100644 --- a/crates/core/tests/store.rs +++ b/crates/core/tests/store.rs @@ -11,7 +11,7 @@ use std::cell::RefCell; use std::rc::Rc; use common::{Calls, Count, Log}; -use dunky_core::{Context, Store, Subscription}; +use dunky_state_machine::{Context, Store, Subscription}; #[derive(Clone, Debug, PartialEq, Context)] struct Pair { diff --git a/crates/core/tests/subscribe.rs b/crates/core/tests/subscribe.rs index 129c64e..fcb3222 100644 --- a/crates/core/tests/subscribe.rs +++ b/crates/core/tests/subscribe.rs @@ -21,7 +21,7 @@ use common::{ AbEvent, AbState, Calls, Count, Counter, CounterEvent, CounterEventKind, CounterState, Log, ab, build, counter, }; -use dunky_core::{Config, Context, Event, State, Types}; +use dunky_state_machine::{Config, Context, Event, State, Types}; /// A machine whose events write `x`, `y` and `other`. struct Plane; @@ -51,7 +51,7 @@ impl Types for Plane { type Context = Pos; } -fn plane() -> dunky_core::Machine { +fn plane() -> dunky_state_machine::Machine { build( Config::::builder(PlaneState::Idle, Pos::default()).state(PlaneState::Idle, |s| { s.on(PlaneEventKind::MoveX, |t| { @@ -260,7 +260,7 @@ fn select_field_selects_one_field_with_its_type() { // even when that first wake came from another field. #[test] fn a_field_selection_made_mid_action_reports_the_next_change() { - type Slot = std::rc::Rc>>>; + type Slot = std::rc::Rc>>>; let handle: Slot = Slot::default(); let seen: Log = Log::default(); let m = build( diff --git a/crates/core/tests/transitions.rs b/crates/core/tests/transitions.rs index a5afd78..db749c5 100644 --- a/crates/core/tests/transitions.rs +++ b/crates/core/tests/transitions.rs @@ -8,7 +8,7 @@ mod common; use common::{Calls, Count, Counter, CounterEvent, CounterEventKind, CounterState, Log, build}; -use dunky_core::{Config, ConfigBuilder, Event, State, Types}; +use dunky_state_machine::{Config, ConfigBuilder, Event, State, Types}; struct Door; diff --git a/crates/core/tests/watch.rs b/crates/core/tests/watch.rs index 57a090f..4d4c18a 100644 --- a/crates/core/tests/watch.rs +++ b/crates/core/tests/watch.rs @@ -10,7 +10,7 @@ mod common; use common::{Log, build}; -use dunky_core::{Action, Config, ConfigBuilder, Context, Event, State, Types}; +use dunky_state_machine::{Action, Config, ConfigBuilder, Context, Event, State, Types}; struct M; diff --git a/crates/macros/Cargo.toml b/crates/macros/Cargo.toml index 3e0c26c..ad03aeb 100644 --- a/crates/macros/Cargo.toml +++ b/crates/macros/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "dunky-macros" -description = "Derive macros for dunky-core: State, Event, Context, TsType." +name = "dunky-state-machine-macros" +description = "Derive macros for dunky-state-machine: State, Event, Context, TsType." version.workspace = true edition.workspace = true license.workspace = true diff --git a/crates/macros/src/lib.rs b/crates/macros/src/lib.rs index 3d34b79..549c584 100644 --- a/crates/macros/src/lib.rs +++ b/crates/macros/src/lib.rs @@ -1,4 +1,4 @@ -//! Derive macros for `dunky-core`. Use them through the re-exports in `dunky_core`. +//! Derive macros for `dunky-state-machine`. Use them through the re-exports in `dunky_state_machine`. mod ts; @@ -207,14 +207,14 @@ fn expand_state(input: DeriveInput) -> syn::Result { let indices: Vec = (0..variants.len()).collect(); let literals: Vec = names .iter() - .map(|n| quote!(::dunky_core::__private::ts_literal(#n))) + .map(|n| quote!(::dunky_state_machine::__private::ts_literal(#n))) .collect(); let ts_impl = ts::impl_ts(&input, ts::union(&literals)); let (impl_g, ty_g, where_g) = input.generics.split_for_impl(); Ok(quote! { #ts_impl - impl #impl_g ::dunky_core::StateEnum for #name #ty_g #where_g { + impl #impl_g ::dunky_state_machine::StateEnum for #name #ty_g #where_g { const NAMES: &'static [&'static str] = &[#(#names),*]; fn index(self) -> usize { match self { #(#name::#variants => #indices,)* } @@ -266,16 +266,16 @@ fn expand_event(input: DeriveInput) -> syn::Result { .map(|r| quote!(#[serde(rename_all = #r)])) .unwrap_or_default(); quote!(#index => { - #[derive(::dunky_core::__private::serde::Deserialize)] - #[serde(crate = "::dunky_core::__private::serde")] + #[derive(::dunky_state_machine::__private::serde::Deserialize)] + #[serde(crate = "::dunky_state_machine::__private::serde")] #rename struct __Payload { #( #(#field_attrs)* #field_idents: #field_tys, )* } - let p = <__Payload as ::dunky_core::__private::serde::Deserialize>::deserialize(deserializer)?; + let p = <__Payload as ::dunky_state_machine::__private::serde::Deserialize>::deserialize(deserializer)?; ::core::result::Result::Ok(#name::#ident { #(#field_idents: p.#field_idents,)* }) }) } Fields::Unnamed(_) => quote!(#index => ::core::result::Result::Err( - <__D::Error as ::dunky_core::__private::serde::de::Error>::custom( + <__D::Error as ::dunky_state_machine::__private::serde::de::Error>::custom( "tuple event variants carry no field names; use named fields" ) ),), @@ -330,8 +330,8 @@ fn expand_event(input: DeriveInput) -> syn::Result { }; let deserialize_impl = if deserialize { quote! { - impl ::dunky_core::DeserializeEvent for #name { - fn deserialize_payload<'de, __D: ::dunky_core::__private::serde::Deserializer<'de>>( + impl ::dunky_state_machine::DeserializeEvent for #name { + fn deserialize_payload<'de, __D: ::dunky_state_machine::__private::serde::Deserializer<'de>>( kind: usize, deserializer: __D, ) -> ::core::result::Result { @@ -340,7 +340,7 @@ fn expand_event(input: DeriveInput) -> syn::Result { match kind { #(#payload_arms)* _ => ::core::result::Result::Err( - <__D::Error as ::dunky_core::__private::serde::de::Error>::custom("no such event type") + <__D::Error as ::dunky_state_machine::__private::serde::de::Error>::custom("no such event type") ), } } @@ -356,7 +356,7 @@ fn expand_event(input: DeriveInput) -> syn::Result { #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] #vis enum #kind { #(#variants),* } - impl ::dunky_core::EventEnum for #name { + impl ::dunky_state_machine::EventEnum for #name { type Kind = #kind; const KIND_NAMES: &'static [&'static str] = &[#(#names),*]; fn kind(&self) -> #kind { @@ -442,8 +442,8 @@ fn expand_context(input: DeriveInput) -> syn::Result { quote! { ::std::format!( "{}: {}", - ::dunky_core::__private::ts_key(#js), - <#ty as ::dunky_core::TsType>::ts(), + ::dunky_state_machine::__private::ts_key(#js), + <#ty as ::dunky_state_machine::TsType>::ts(), ) } }) @@ -454,14 +454,14 @@ fn expand_context(input: DeriveInput) -> syn::Result { }; let serialize_impl = if serialize { quote! { - impl ::dunky_core::SerializeFields for #name { - fn serialize_field<__S: ::dunky_core::__private::serde::Serializer>( + impl ::dunky_state_machine::SerializeFields for #name { + fn serialize_field<__S: ::dunky_state_machine::__private::serde::Serializer>( &self, index: usize, serializer: __S, ) -> ::core::result::Result<__S::Ok, __S::Error> { match index { - #(#indices => ::dunky_core::__private::serde::Serialize::serialize(&self.#idents, serializer),)* + #(#indices => ::dunky_state_machine::__private::serde::Serialize::serialize(&self.#idents, serializer),)* _ => serializer.serialize_unit(), } } @@ -511,8 +511,8 @@ fn expand_context(input: DeriveInput) -> syn::Result { #[allow(dead_code)] impl #name { - #(pub const #consts: ::dunky_core::Field<#name, #tys> = - ::dunky_core::Field::new(#indices, |c: &#name| &c.#idents);)* + #(pub const #consts: ::dunky_state_machine::Field<#name, #tys> = + ::dunky_state_machine::Field::new(#indices, |c: &#name| &c.#idents);)* /// Start a patch: `Self::patch().field(value)`. pub fn patch() -> #patch { @@ -520,7 +520,7 @@ fn expand_context(input: DeriveInput) -> syn::Result { } } - impl ::dunky_core::Context for #name { + impl ::dunky_state_machine::Context for #name { type Patch = #patch; type Reader<'a> = #reader<'a>; const FIELDS: &'static [&'static str] = &[#(#js_names),*]; diff --git a/crates/macros/src/ts.rs b/crates/macros/src/ts.rs index 72acf94..357aba3 100644 --- a/crates/macros/src/ts.rs +++ b/crates/macros/src/ts.rs @@ -174,9 +174,9 @@ pub(crate) fn members<'a>( out.push(quote! { ::std::format!( "{}{}: {}", - ::dunky_core::__private::ts_key(#name), + ::dunky_state_machine::__private::ts_key(#name), #mark, - <#ty as ::dunky_core::TsType>::ts(), + <#ty as ::dunky_state_machine::TsType>::ts(), ) }); } @@ -185,7 +185,7 @@ pub(crate) fn members<'a>( /// An object type from member expressions. pub(crate) fn object(members: &[TokenStream2]) -> TokenStream2 { - quote!(::dunky_core::__private::ts_object(&[#(#members),*])) + quote!(::dunky_state_machine::__private::ts_object(&[#(#members),*])) } /// The member that names a variant of a tagged union: `type: 'open'`. @@ -193,8 +193,8 @@ pub(crate) fn tag_member(tag: &str, name: &str) -> TokenStream2 { quote! { ::std::format!( "{}: {}", - ::dunky_core::__private::ts_key(#tag), - ::dunky_core::__private::ts_literal(#name), + ::dunky_state_machine::__private::ts_key(#tag), + ::dunky_state_machine::__private::ts_literal(#name), ) } } @@ -212,11 +212,11 @@ pub(crate) fn impl_ts(input: &DeriveInput, ts: TokenStream2) -> TokenStream2 { let name = &input.ident; let mut generics = input.generics.clone(); for param in generics.type_params_mut() { - param.bounds.push(syn::parse_quote!(::dunky_core::TsType)); + param.bounds.push(syn::parse_quote!(::dunky_state_machine::TsType)); } let (impl_g, ty_g, where_g) = generics.split_for_impl(); quote! { - impl #impl_g ::dunky_core::TsType for #name #ty_g #where_g { + impl #impl_g ::dunky_state_machine::TsType for #name #ty_g #where_g { fn ts() -> ::std::string::String { #ts } @@ -236,11 +236,11 @@ pub(crate) fn expand(input: DeriveInput) -> syn::Result { )?), Fields::Named(fields) if fields.named.len() == 1 => { let ty = &fields.named[0].ty; - quote!(<#ty as ::dunky_core::TsType>::ts()) + quote!(<#ty as ::dunky_state_machine::TsType>::ts()) } Fields::Unnamed(fields) if fields.unnamed.len() == 1 => { let ty = &fields.unnamed[0].ty; - quote!(<#ty as ::dunky_core::TsType>::ts()) + quote!(<#ty as ::dunky_state_machine::TsType>::ts()) } Fields::Unit => quote!(::std::string::String::from("null")), _ => { @@ -270,7 +270,7 @@ pub(crate) fn expand(input: DeriveInput) -> syn::Result { .as_deref() .or(container.rename_all_fields.as_deref()); variants.push(match (&container.tag, &v.fields) { - (None, Fields::Unit) => quote!(::dunky_core::__private::ts_literal(#name)), + (None, Fields::Unit) => quote!(::dunky_state_machine::__private::ts_literal(#name)), (Some(tag), Fields::Unit) => object(&[tag_member(tag, &name)]), (Some(tag), Fields::Named(fields)) => { let mut all = vec![tag_member(tag, &name)]; diff --git a/crates/sandbox/Cargo.toml b/crates/sandbox/Cargo.toml index b451e7e..f5cbbfd 100644 --- a/crates/sandbox/Cargo.toml +++ b/crates/sandbox/Cargo.toml @@ -12,11 +12,11 @@ crate-type = ["cdylib", "rlib"] [features] # The JS classes (export_machine!), on for the wasm build (pnpm build:wasm) only, so # crates reusing the machines (crates/uniffi) never link the JS exports. -wasm = ["dep:dunky-wasm", "dep:wasm-bindgen"] +wasm = ["dep:dunky-state-machine-wasm", "dep:wasm-bindgen"] [dependencies] -dunky-core = { workspace = true } -dunky-wasm = { workspace = true, optional = true } +dunky-state-machine = { workspace = true } +dunky-state-machine-wasm = { workspace = true, optional = true } serde = { workspace = true } wasm-bindgen = { workspace = true, optional = true } diff --git a/crates/sandbox/src/dialog.rs b/crates/sandbox/src/dialog.rs index 0431418..c6da9d6 100644 --- a/crates/sandbox/src/dialog.rs +++ b/crates/sandbox/src/dialog.rs @@ -2,7 +2,7 @@ //! before `closed`, so a renderer can animate out. Shows `after` timers running through //! the host's clock. -use dunky_core::{Config, Context, Event, State, Types}; +use dunky_state_machine::{Config, Context, Event, State, Types}; use serde::Deserialize; #[derive(State, Clone, Copy, PartialEq, Eq, Debug)] diff --git a/crates/sandbox/src/lib.rs b/crates/sandbox/src/lib.rs index d5d24f5..cb3a44c 100644 --- a/crates/sandbox/src/lib.rs +++ b/crates/sandbox/src/lib.rs @@ -1,4 +1,4 @@ -//! The sandbox machines, written in Rust against `dunky-core` — the Rust twins of the TS +//! The sandbox machines, written in Rust against `dunky-state-machine` — the Rust twins of the TS //! machines in `sandbox/shared/src`, following the same spec: //! //! - [`palette`] — the command palette, a faithful port of `sandbox/shared/src/machine.ts` @@ -17,7 +17,7 @@ pub use exports::typescript; #[cfg(feature = "wasm")] mod exports { - use dunky_core::{Config, Machine}; + use dunky_state_machine::{Config, Machine}; use wasm_bindgen::prelude::*; use crate::{dialog, palette}; @@ -28,12 +28,12 @@ mod exports { static DIALOG: Config = dialog::config(0); } - dunky_wasm::export_machine! { + dunky_state_machine_wasm::export_machine! { /// The command palette. pub struct PaletteMachine(palette::Palette); new(commands: JsValue) { // Malformed commands throw: the host maps result indices onto its own array. - dunky_wasm::from_js::>(commands) + dunky_state_machine_wasm::from_js::>(commands) .map(|commands| PALETTE.with(|c| Machine::with_context(c, palette::context(commands)))) } computed { @@ -46,7 +46,7 @@ mod exports { } } - dunky_wasm::export_machine! { + dunky_state_machine_wasm::export_machine! { /// A dialog whose `closing` phase lasts `exitMs`. pub struct DialogMachine(dialog::Dialog); new(exit_ms: u32) { diff --git a/crates/sandbox/src/palette.rs b/crates/sandbox/src/palette.rs index cb6a8e5..b005a55 100644 --- a/crates/sandbox/src/palette.rs +++ b/crates/sandbox/src/palette.rs @@ -4,7 +4,7 @@ //! wraparound, clamp) lives in context + computed, driven by logical events. A renderer //! never computes an index: it sends `move` / `query.set` and reads `results` / `activeId`. -use dunky_core::{ComputedKey, Config, Context, Event, State, TsType, Types}; +use dunky_state_machine::{ComputedKey, Config, Context, Event, State, TsType, Types}; use serde::{Deserialize, Serialize}; #[derive(TsType, Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -248,7 +248,7 @@ pub fn demo_commands() -> Vec { #[cfg(test)] mod tests { use super::*; - use dunky_core::Machine; + use dunky_state_machine::Machine; fn open_palette() -> Machine { let m = Machine::new(&config(demo_commands())); @@ -292,7 +292,7 @@ mod tests { #[test] fn payload_events_rebuild_from_kind_and_fields_only() { - use dunky_core::{DeserializeEvent, EventEnum}; + use dunky_state_machine::{DeserializeEvent, EventEnum}; let decode = |kind: PaletteEventKind, value: serde_json::Value| { PaletteEvent::deserialize_payload(PaletteEvent::kind_index(kind), value) }; diff --git a/crates/uniffi/Cargo.lock b/crates/uniffi/Cargo.lock index ab90c1c..d39d62e 100644 --- a/crates/uniffi/Cargo.lock +++ b/crates/uniffi/Cargo.lock @@ -116,36 +116,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" [[package]] -name = "dunky-core" +name = "dunky-sandbox" version = "0.1.0" dependencies = [ - "dunky-macros", + "dunky-state-machine", "serde", ] [[package]] -name = "dunky-macros" +name = "dunky-state-machine" version = "0.1.0" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", + "dunky-state-machine-macros", + "serde", ] [[package]] -name = "dunky-sandbox" +name = "dunky-state-machine-macros" version = "0.1.0" dependencies = [ - "dunky-core", - "serde", + "proc-macro2", + "quote", + "syn 2.0.119", ] [[package]] -name = "dunky-uniffi" +name = "dunky-state-machine-uniffi" version = "0.1.0" dependencies = [ - "dunky-core", "dunky-sandbox", + "dunky-state-machine", "serde_json", "uniffi", ] diff --git a/crates/uniffi/Cargo.toml b/crates/uniffi/Cargo.toml index b476f31..278884d 100644 --- a/crates/uniffi/Cargo.toml +++ b/crates/uniffi/Cargo.toml @@ -5,7 +5,7 @@ [workspace] [package] -name = "dunky-uniffi" +name = "dunky-state-machine-uniffi" version = "0.1.0" edition = "2024" license = "MIT" @@ -13,13 +13,13 @@ repository = "https://github.com/dunky-dev/state-machine" publish = false [lib] -name = "dunky_uniffi" +name = "dunky_state_machine_uniffi" # staticlib: what ubrn links into the iOS xcframework and the Android turbo-module. # cdylib: what ubrn's `jsi2` flavour loads instead, keeping that path open. crate-type = ["cdylib", "staticlib"] [dependencies] -dunky-core = { path = "../core" } +dunky-state-machine = { path = "../core" } dunky-sandbox = { path = "../sandbox" } serde_json = "1" # Must stay on the uniffi minor that uniffi-bindgen-react-native is built with diff --git a/crates/uniffi/src/lib.rs b/crates/uniffi/src/lib.rs index deca963..330eec5 100644 --- a/crates/uniffi/src/lib.rs +++ b/crates/uniffi/src/lib.rs @@ -2,7 +2,7 @@ //! uniffi-bindgen-react-native: the sandbox palette written in Rust. //! //! Events go in by kind index; a u32 change mask comes out, and timers come out as -//! flat commands (`dunky_core::protocol`). Values cross as JSON strings instead of JS +//! flat commands (`dunky_state_machine::protocol`). Values cross as JSON strings instead of JS //! values. It still needs a TS facade over this handle (like `fromWasm` for wasm). use std::cell::RefCell; @@ -10,16 +10,16 @@ use std::mem::ManuallyDrop; use std::sync::Arc; use std::thread::{self, ThreadId}; -use dunky_core::{ +use dunky_sandbox::palette::{self, Palette, PaletteEvent}; +use dunky_state_machine::{ Command, Config, Context, DeserializeEvent, EventEnum, Machine, SerializeFields, StateEnum, Subscription, Types, }; -use dunky_sandbox::palette::{self, Palette, PaletteEvent}; uniffi::setup_scaffolding!(); -// The change mask and the command encoding: `dunky_core::protocol`. -use dunky_core::protocol::{FIELD_SHIFT, HIGH_FIELD, encode_commands, take_change_mask}; +// The change mask and the command encoding: `dunky_state_machine::protocol`. +use dunky_state_machine::protocol::{FIELD_SHIFT, HIGH_FIELD, encode_commands, take_change_mask}; /// Bad input from JS, thrown as an `Error` with this message. #[derive(Debug, uniffi::Error)] diff --git a/crates/wasm/Cargo.toml b/crates/wasm/Cargo.toml index 11ee9a4..618d5d7 100644 --- a/crates/wasm/Cargo.toml +++ b/crates/wasm/Cargo.toml @@ -1,13 +1,13 @@ [package] -name = "dunky-wasm" -description = "Run dunky-core machines from JavaScript: export a Rust machine to a JS class with one macro." +name = "dunky-state-machine-wasm" +description = "Run dunky-state-machine machines from JavaScript: export a Rust machine to a JS class with one macro." version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true [dependencies] -dunky-core = { workspace = true } +dunky-state-machine = { workspace = true } wasm-bindgen = { workspace = true } js-sys = { workspace = true } serde = { workspace = true } diff --git a/crates/wasm/README.md b/crates/wasm/README.md index 7a2b752..4298f2b 100644 --- a/crates/wasm/README.md +++ b/crates/wasm/README.md @@ -1,21 +1,21 @@ -# dunky-wasm +# dunky-state-machine-wasm -Run [`dunky-core`](../core) machines from JavaScript. Export a machine written in Rust +Run [`dunky-state-machine`](../core) machines from JavaScript. Export a machine written in Rust with one macro; wrap an instance with `fromWasm` from `@dunky.dev/state-machine-wasm`, and the connector, `useMachine` and every target consume it like a machine written in TS. ```rust -use dunky_core::{Config, Machine}; +use dunky_state_machine::{Config, Machine}; use wasm_bindgen::prelude::*; thread_local!(static CONFIG: Config = palette::config(Vec::new())); -dunky_wasm::export_machine! { +dunky_state_machine_wasm::export_machine! { /// The command palette. pub struct PaletteMachine(palette::Palette); new(commands: JsValue) { // A Result body throws its error from the JS constructor. - dunky_wasm::from_js(commands) + dunky_state_machine_wasm::from_js(commands) .map(|c| CONFIG.with(|config| Machine::with_context(config, palette::context(c)))) } computed { palette::RESULTS => Vec, palette::ACTIVE_ID => Option } diff --git a/crates/wasm/SPEC.md b/crates/wasm/SPEC.md index ab36bf4..b075210 100644 --- a/crates/wasm/SPEC.md +++ b/crates/wasm/SPEC.md @@ -1,15 +1,15 @@ -# SPEC - `dunky-wasm` +# SPEC - `dunky-state-machine-wasm` ## Overview -`dunky-wasm` runs machines written in Rust ([`dunky-core`](../core/SPEC.md)) from +`dunky-state-machine-wasm` runs machines written in Rust ([`dunky-state-machine`](../core/SPEC.md)) from JavaScript. `export_machine!` turns a machine type into a JS class, in the author's own wasm module; [`@dunky.dev/state-machine-wasm`](../../packages/wasm) wraps an instance with `fromWasm` in the `Machine` interface, so the connector and every target consume it next to the machines of the TS engine. ``` - Rust machine (dunky-core types) + Rust machine (dunky-state-machine types) | | export_machine! (your crate, your wasm module) v diff --git a/crates/wasm/src/bridge.rs b/crates/wasm/src/bridge.rs index f849271..42bf01e 100644 --- a/crates/wasm/src/bridge.rs +++ b/crates/wasm/src/bridge.rs @@ -13,7 +13,7 @@ use std::cell::{Cell, OnceCell, RefCell}; use std::rc::Rc; -use dunky_core::{Changes, Command, Machine, Types}; +use dunky_state_machine::{Changes, Command, Machine, Types}; use wasm_bindgen::prelude::*; /// A call finished. diff --git a/crates/wasm/src/lib.rs b/crates/wasm/src/lib.rs index 0e1802c..34ef316 100644 --- a/crates/wasm/src/lib.rs +++ b/crates/wasm/src/lib.rs @@ -1,4 +1,4 @@ -//! `dunky-wasm` — run `dunky-core` machines from JavaScript. +//! `dunky-state-machine-wasm` — run `dunky-state-machine` machines from JavaScript. //! //! [`export_machine!`] turns a machine written in Rust into a JS class, in your own wasm //! module. `@dunky.dev/state-machine-wasm` wraps an instance with `fromWasm`, so the @@ -19,7 +19,7 @@ use std::cell::RefCell; use std::rc::Rc; -use dunky_core::{ +use dunky_state_machine::{ ComputedKey, Context, DeserializeEvent, EventEnum, Machine, SerializeFields, StateEnum, Subscription, Types, }; @@ -35,10 +35,10 @@ pub use bridge::{Bridge, ENGINE_FAILED, FAILED, HostObject, OK}; #[doc(hidden)] pub mod __private { - pub use dunky_core::{ComputedKey, Config, TsType}; + pub use dunky_state_machine::{ComputedKey, Config, TsType}; - use dunky_core::__private::{ts_key, ts_object}; - use dunky_core::{Context, Types}; + use dunky_state_machine::__private::{ts_key, ts_object}; + use dunky_state_machine::{Context, Types}; /// The declaration that gives exported class `class` its machine's types: a /// `__types` member, only in the types, that `fromWasm` reads. `computed` holds the @@ -274,12 +274,12 @@ where /// `@dunky.dev/state-machine`. /// /// ```ignore -/// dunky_wasm::export_machine! { +/// dunky_state_machine_wasm::export_machine! { /// /// The command palette. /// pub struct PaletteMachine(palette::Palette); /// new(commands: JsValue) { /// // A `Result` body throws its error from the JS constructor. -/// dunky_wasm::from_js(commands).map(|c| Machine::new(&palette::config(c))) +/// dunky_state_machine_wasm::from_js(commands).map(|c| Machine::new(&palette::config(c))) /// } /// computed { palette::RESULTS => Vec, palette::ACTIVE_ID => Option } /// // Optional: served too, but left out of the machine's TS types. diff --git a/packages/wasm/README.md b/packages/wasm/README.md index 34d1ad1..c7580ef 100644 --- a/packages/wasm/README.md +++ b/packages/wasm/README.md @@ -1,7 +1,7 @@ # @dunky.dev/state-machine-wasm Use a Dunky machine written in **Rust** from TypeScript. `fromWasm` wraps a class -exported with `dunky_wasm::export_machine!` (see [`crates/wasm`](../../crates/wasm)) in +exported with `dunky_state_machine_wasm::export_machine!` (see [`crates/wasm`](../../crates/wasm)) in the same `Machine` interface the TS engine returns, so `connect()`, `useMachine` and every target consume it unchanged, next to your TS machines. diff --git a/packages/wasm/package.json b/packages/wasm/package.json index 052208b..2832d8d 100644 --- a/packages/wasm/package.json +++ b/packages/wasm/package.json @@ -1,7 +1,7 @@ { "name": "@dunky.dev/state-machine-wasm", "version": "0.0.0", - "description": "Run Dunky machines written in Rust from TypeScript: fromWasm wraps a class exported with dunky_wasm::export_machine! in the Machine interface.", + "description": "Run Dunky machines written in Rust from TypeScript: fromWasm wraps a class exported with dunky_state_machine_wasm::export_machine! in the Machine interface.", "license": "MIT", "repository": { "type": "git", diff --git a/packages/wasm/src/from-wasm.ts b/packages/wasm/src/from-wasm.ts index 9135f7f..56bdbfc 100644 --- a/packages/wasm/src/from-wasm.ts +++ b/packages/wasm/src/from-wasm.ts @@ -8,7 +8,7 @@ import { } from '@dunky.dev/state-machine' /** - * An instance of a class exported with `dunky_wasm::export_machine!`. Calls that run + * An instance of a class exported with `dunky_state_machine_wasm::export_machine!`. Calls that run * machine code return a status (see `OK`); the host functions run for the facade whose * call is in progress (`calling`). */ @@ -310,7 +310,7 @@ class RustMachine< /** * Wrap a Rust machine (an instance of a class exported with - * `dunky_wasm::export_machine!`) in the `Machine` interface, so the connector and every + * `dunky_state_machine_wasm::export_machine!`) in the `Machine` interface, so the connector and every * target consume it like a machine of the TS engine. Its types are the class's, * generated from the machine's Rust types. */ diff --git a/sandbox/native/rust-bench.tsx b/sandbox/native/rust-bench.tsx index d849ac1..b58b4b4 100644 --- a/sandbox/native/rust-bench.tsx +++ b/sandbox/native/rust-bench.tsx @@ -24,7 +24,7 @@ const QUERY_SET = 2 const EXECUTE = 5 const QUERY = 1 const LAST_EXECUTED = 3 -// The pull mask: field `i` is bit `2 + i` (`dunky_core::protocol`). +// The pull mask: field `i` is bit `2 + i` (`dunky_state_machine::protocol`). const FIELD_SHIFT = 2 interface Result { diff --git a/website/src/content/docs/install.mdx b/website/src/content/docs/install.mdx index 25b129d..100def3 100644 --- a/website/src/content/docs/install.mdx +++ b/website/src/content/docs/install.mdx @@ -33,5 +33,5 @@ The same machines exist in Rust, on a second engine that follows the same spec. ```toml [dependencies] -dunky-core = { git = "https://github.com/dunky-dev/state-machine" } +dunky-state-machine = { git = "https://github.com/dunky-dev/state-machine" } ``` diff --git a/website/src/content/docs/rust/index.mdx b/website/src/content/docs/rust/index.mdx index f8fdd92..f3d50b8 100644 --- a/website/src/content/docs/rust/index.mdx +++ b/website/src/content/docs/rust/index.mdx @@ -4,7 +4,7 @@ description: Dunky's state machines exist twice, in TypeScript and in Rust, and --- Dunky's state machines are implemented **twice**: in TypeScript -(`@dunky.dev/state-machine`) and in Rust (`dunky-core`). Neither engine runs on the +(`@dunky.dev/state-machine`) and in Rust (`dunky-state-machine`). Neither engine runs on the other. Each is tuned for its own runtime, and both follow one behavior contract: [`packages/core/SPEC.md`](https://github.com/dunky-dev/state-machine/blob/main/packages/core/SPEC.md). @@ -14,7 +14,7 @@ other. Each is tuned for its own runtime, and both follow one behavior contract: / \ v v TypeScript engine Rust engine -@dunky.dev/state-machine dunky-core +@dunky.dev/state-machine dunky-state-machine JS and every target Rust programs, native bindings, and JS through wasm ``` @@ -25,25 +25,25 @@ JS and every target Rust programs, native bindings, **TypeScript**. That is the default, and the fastest path in JS: the context lives in JS, so nothing crosses a boundary. - **Building in Rust** (a native app, a game, a server): write them in **Rust**, with - `dunky-core`. The same states, events, guards, effects, timers and computed values. + `dunky-state-machine`. The same states, events, guards, effects, timers and computed values. - **Sharing one machine between Rust and JS**: write it in Rust, and use it from TypeScript through wasm with [`fromWasm`](/rust/typescript) on the web, or over uniffi on React Native (in progress). The machine still runs on the Rust engine. ## The crates -| Crate | What it is | -| -------------- | --------------------------------------------------------------------------- | -| `dunky-core` | The Rust engine: machines, config builder, timers as commands, observers. | -| `dunky-macros` | `#[derive(State, Event, Context)]`, re-exported by `dunky-core`. | -| `dunky-wasm` | `export_machine!`: a Rust machine as a JS class, in your own wasm module. | -| `dunky-uniffi` | Rust machines on React Native, a turbo module through uniffi (in progress). | +| Crate | What it is | +| ---------------------------- | --------------------------------------------------------------------------- | +| `dunky-state-machine` | The Rust engine: machines, config builder, timers as commands, observers. | +| `dunky-state-machine-macros` | `#[derive(State, Event, Context)]`, re-exported by `dunky-state-machine`. | +| `dunky-state-machine-wasm` | `export_machine!`: a Rust machine as a JS class, in your own wasm module. | +| `dunky-state-machine-uniffi` | Rust machines on React Native, a turbo module through uniffi (in progress). | The crates are not on crates.io yet. Use them from the repository: ```toml [dependencies] -dunky-core = { git = "https://github.com/dunky-dev/state-machine" } +dunky-state-machine = { git = "https://github.com/dunky-dev/state-machine" } ``` ## How the two stay in sync diff --git a/website/src/content/docs/rust/machines.mdx b/website/src/content/docs/rust/machines.mdx index cfcda3b..894ef09 100644 --- a/website/src/content/docs/rust/machines.mdx +++ b/website/src/content/docs/rust/machines.mdx @@ -1,16 +1,16 @@ --- title: Machines in Rust -description: Write a Dunky machine in Rust with dunky-core. +description: Write a Dunky machine in Rust with dunky-state-machine. --- -`dunky-core` has the same machine model as the TS engine: flat states, +`dunky-state-machine` has the same machine model as the TS engine: flat states, run-to-completion, guards, actions, effects, `after` timers, computed values, watchers and subscriptions. The difference is the shape: states, events and context are Rust types, and the config is built once with a builder. ```toml [dependencies] -dunky-core = { git = "https://github.com/dunky-dev/state-machine" } +dunky-state-machine = { git = "https://github.com/dunky-dev/state-machine" } ``` ## Types @@ -18,7 +18,7 @@ dunky-core = { git = "https://github.com/dunky-dev/state-machine" } A machine names three types, and the derives generate the glue: ```rust -use dunky_core::{Config, Context, Event, Machine, State, Types}; +use dunky_state_machine::{Config, Context, Event, Machine, State, Types}; #[derive(State, Clone, Copy, PartialEq, Eq, Debug)] enum DialogState { Closed, Open, Closing } @@ -99,10 +99,10 @@ for command in dialog.take_commands() { } ``` -In tests, `dunky_core::testing::Clock` plays the host with virtual time: +In tests, `dunky_state_machine::testing::Clock` plays the host with virtual time: ```rust -let mut clock = dunky_core::testing::Clock::new(&dialog); +let mut clock = dunky_state_machine::testing::Clock::new(&dialog); dialog.send(DialogEvent::Close); // -> closing, schedules exitDelay clock.sync(); clock.advance(200); diff --git a/website/src/content/docs/rust/typescript.mdx b/website/src/content/docs/rust/typescript.mdx index 6834880..4f3ae5a 100644 --- a/website/src/content/docs/rust/typescript.mdx +++ b/website/src/content/docs/rust/typescript.mdx @@ -14,16 +14,16 @@ target take it unchanged. ## 1. Export the machine -In your Rust crate, depend on `dunky-core`, `dunky-wasm` and `wasm-bindgen`, and export +In your Rust crate, depend on `dunky-state-machine`, `dunky-state-machine-wasm` and `wasm-bindgen`, and export the machine type as a JS class: ```rust -dunky_wasm::export_machine! { +dunky_state_machine_wasm::export_machine! { /// The command palette. pub struct PaletteMachine(palette::Palette); new(commands: JsValue) { // A Result body throws its error from the JS constructor. - dunky_wasm::from_js(commands).map(|c| Machine::with_context(&config(), palette::context(c))) + dunky_state_machine_wasm::from_js(commands).map(|c| Machine::with_context(&config(), palette::context(c))) } computed { palette::RESULTS => Vec, palette::ACTIVE_ID => Option } // Optional: served too, but left out of the machine's TS types. diff --git a/website/src/pages/index.astro b/website/src/pages/index.astro index 69f8ee9..670c801 100644 --- a/website/src/pages/index.astro +++ b/website/src/pages/index.astro @@ -725,7 +725,7 @@ const shareOnX = `https://twitter.com/intent/tweet?text=${encodeURIComponent(sha })`}
-

Rust · dunky-core

+

Rust · dunky-state-machine

{`let mut b = Config::::builder(
     Closed, DialogCtx { open_count: 0 });
 b.state(Closed, |s| s.on(E::Open,

From 661cd7ed7fde9d42d75ca890aee046af7e3ea356 Mon Sep 17 00:00:00 2001
From: Ivan Banov 
Date: Mon, 12 Oct 2026 10:29:00 +0200
Subject: [PATCH 2/2] style(macros): rustfmt after the crate rename

Co-Authored-By: Claude Fable 5.1 
---
 crates/core/tests/compose.rs | 4 +++-
 crates/macros/src/ts.rs      | 4 +++-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/crates/core/tests/compose.rs b/crates/core/tests/compose.rs
index b4852d3..de777a1 100644
--- a/crates/core/tests/compose.rs
+++ b/crates/core/tests/compose.rs
@@ -12,7 +12,9 @@ mod common;
 use std::rc::Rc;
 
 use common::{AbState, Calls, CounterEvent, Log, ab, build, counter};
-use dunky_state_machine::{Composition, Config, Event, Machine, Member, State, Subscription, Types};
+use dunky_state_machine::{
+    Composition, Config, Event, Machine, Member, State, Subscription, Types,
+};
 
 struct Popup;
 
diff --git a/crates/macros/src/ts.rs b/crates/macros/src/ts.rs
index 357aba3..041c44a 100644
--- a/crates/macros/src/ts.rs
+++ b/crates/macros/src/ts.rs
@@ -212,7 +212,9 @@ pub(crate) fn impl_ts(input: &DeriveInput, ts: TokenStream2) -> TokenStream2 {
     let name = &input.ident;
     let mut generics = input.generics.clone();
     for param in generics.type_params_mut() {
-        param.bounds.push(syn::parse_quote!(::dunky_state_machine::TsType));
+        param
+            .bounds
+            .push(syn::parse_quote!(::dunky_state_machine::TsType));
     }
     let (impl_g, ty_g, where_g) = generics.split_for_impl();
     quote! {