5bed43ef32
A new `cdylib + rlib` workspace member that wraps `solitaire_core::
GameState` for use from JavaScript. The web replay viewer fetches a
replay JSON, hands it to `ReplayPlayer::new`, and steps through
moves one at a time — same Rust rules engine the desktop client
uses, so the two implementations cannot drift.
The crate intentionally does NOT depend on `solitaire_data` (which
pulls dirs/keyring/reqwest, none wasm-friendly). Instead it defines
a minimal `Replay` mirror with the same serde shape; the JSON wire
format is the contract.
Public surface (#[wasm_bindgen]):
- `ReplayPlayer::new(json)` — parse + rebuild deal from seed/mode
- `state()` / `step()` — return JS-friendly StateSnapshot
- `total_steps()` / `step_idx()` / `is_finished()` — progress helpers
Native-callable mirror (`from_json`, `step_native`) lets unit tests
exercise the state machine without going through `serde_wasm_bindgen`,
which panics off-target. 3 tests cover construction, step advance,
and invalid-JSON handling.
`getrandom` needs the `wasm_js` feature on the wasm32 target;
configured via the cfg target dep table so non-wasm builds aren't
affected.
Build pipeline (executed from the repo root):
rustup target add wasm32-unknown-unknown
RUSTFLAGS='--cfg getrandom_backend="wasm_js"' \
cargo build -p solitaire_wasm \
--target wasm32-unknown-unknown --release
wasm-bindgen --target web \
--out-dir solitaire_server/web/pkg --no-typescript \
target/wasm32-unknown-unknown/release/solitaire_wasm.wasm
The generated bindings land in solitaire_server/web/pkg/ and are
committed alongside the web UI (next commit).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
30 lines
978 B
TOML
30 lines
978 B
TOML
[package]
|
|
name = "solitaire_wasm"
|
|
version.workspace = true
|
|
license.workspace = true
|
|
edition.workspace = true
|
|
|
|
[lib]
|
|
crate-type = ["cdylib", "rlib"]
|
|
|
|
[dependencies]
|
|
solitaire_core = { path = "../solitaire_core" }
|
|
serde = { workspace = true }
|
|
serde_json = { workspace = true }
|
|
chrono = { workspace = true }
|
|
wasm-bindgen = "0.2"
|
|
serde-wasm-bindgen = "0.6"
|
|
console_error_panic_hook = { version = "0.1", optional = true }
|
|
|
|
# `getrandom` is pulled in transitively via `rand` (used by
|
|
# `solitaire_core::Deck::shuffle`). On `wasm32-unknown-unknown` it
|
|
# needs an explicit JS-backend feature, otherwise the build aborts
|
|
# with a "wasm32-unknown-unknown is not a supported target" error.
|
|
# Pinning here forces the feature on without us having to pollute
|
|
# `solitaire_core`'s deps with wasm-only flags.
|
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
|
getrandom = { version = "0.3", features = ["wasm_js"] }
|
|
|
|
[features]
|
|
default = ["console_error_panic_hook"]
|