chore(wasm): move dm2-wasm's distribution from crates.io to npm #323

Merged
jqueuniet merged 1 commit from chore/unpublish-wasm into main 2026-09-05 07:37:04 +02:00
Owner

dm2-wasm 0.2.0 has been deleted from crates.io. This makes the workspace
match that, and prepares the npm package that replaces it.

Why crates.io was the wrong channel

The published page documented nothing. docs.rs builds for x86-64, where every
#[wasm_bindgen] export is compiled out, so it listed exactly one item —
WasmError. The audience for these bindings is JavaScript, which reaches them
through wasm-pack output rather than cargo.

publish = false matters beyond tidiness: the key was absent and therefore
defaulted to publishable, so the next cargo publish --workspace would have
put the crate straight back on crates.io. The unused [workspace.dependencies]
entry is dropped too — nothing declared dm2-wasm.workspace = true, and it
carried a version requirement for a crate no longer on the registry.

The npm package

crates/dm2-wasm/build-npm.sh wraps wasm-pack and patches the two things it
cannot express:

  • published as dm2-tools, matching the PyPI distribution, while the crate
    stays dm2-wasm (wasm-pack names the package after the crate)
  • repository.directory set, so npm links to the crate rather than the
    workspace root

It builds --target bundler — an ES module Vite and webpack import with no
explicit init call. --target web, which needs await init(), remains the
right choice for a checkout with no bundler; the README documents both.

Licenses are copied into the crate because wasm-pack only bundles LICENSE*
files sitting beside Cargo.toml — the same constraint that put copies in
bindings/python. The cmp guard moves from the python job to stable and
now covers both.

wasm-opt switches to -Oz. Honest number: 887,123 bytes against 912,172 with
the default -O, so 2.7% — free, but not transformative.

CI

New wasm32-unknown-unknown check. cargo check --workspace builds this crate
for the host, where the #[wasm_bindgen] layer is inert, so a break in the JS
marshalling layer could previously only surface when someone built the package
by hand.

Verification

The package was built in the CI image (rust:1-trixie + wasm-pack 0.15.0):
the wasm32 check passes, build-npm.sh produces pkg/ with the patched name
and repository.directory, and both licenses land in the package. cargo fmt
and cargo clippy --workspace --all-targets -D warnings are clean; no Rust
source changed, only manifests.

Publishing stays manual — there is no npm token in CI, so a release is
npm publish crates/dm2-wasm/pkg after the tag.

`dm2-wasm` 0.2.0 has been deleted from crates.io. This makes the workspace match that, and prepares the npm package that replaces it. ## Why crates.io was the wrong channel The published page documented nothing. docs.rs builds for x86-64, where every `#[wasm_bindgen]` export is compiled out, so it listed exactly one item — `WasmError`. The audience for these bindings is JavaScript, which reaches them through wasm-pack output rather than cargo. `publish = false` matters beyond tidiness: the key was absent and therefore defaulted to publishable, so the next `cargo publish --workspace` would have put the crate straight back on crates.io. The unused `[workspace.dependencies]` entry is dropped too — nothing declared `dm2-wasm.workspace = true`, and it carried a version requirement for a crate no longer on the registry. ## The npm package `crates/dm2-wasm/build-npm.sh` wraps wasm-pack and patches the two things it cannot express: - published as **`dm2-tools`**, matching the PyPI distribution, while the crate stays `dm2-wasm` (wasm-pack names the package after the crate) - `repository.directory` set, so npm links to the crate rather than the workspace root It builds `--target bundler` — an ES module Vite and webpack import with no explicit init call. `--target web`, which needs `await init()`, remains the right choice for a checkout with no bundler; the README documents both. Licenses are copied into the crate because wasm-pack only bundles `LICENSE*` files sitting beside `Cargo.toml` — the same constraint that put copies in `bindings/python`. The `cmp` guard moves from the `python` job to `stable` and now covers both. `wasm-opt` switches to `-Oz`. Honest number: 887,123 bytes against 912,172 with the default `-O`, so 2.7% — free, but not transformative. ## CI New `wasm32-unknown-unknown` check. `cargo check --workspace` builds this crate for the host, where the `#[wasm_bindgen]` layer is inert, so a break in the JS marshalling layer could previously only surface when someone built the package by hand. ## Verification The package was built in the CI image (`rust:1-trixie` + wasm-pack 0.15.0): the wasm32 check passes, `build-npm.sh` produces `pkg/` with the patched name and `repository.directory`, and both licenses land in the package. `cargo fmt` and `cargo clippy --workspace --all-targets -D warnings` are clean; no Rust source changed, only manifests. Publishing stays manual — there is no npm token in CI, so a release is `npm publish crates/dm2-wasm/pkg` after the tag.
chore(wasm): move dm2-wasm's distribution from crates.io to npm
All checks were successful
CI / msrv (1.90) (pull_request) Successful in 43s
CI / audit (pull_request) Successful in 22s
CI / stable (pull_request) Successful in 1m39s
CI / python bindings (3.11) (pull_request) Successful in 40s
CI / msrv (1.90) (push) Successful in 41s
CI / audit (push) Successful in 19s
CI / stable (push) Successful in 1m43s
CI / python bindings (3.11) (push) Successful in 46s
69ce421f0a
The crates.io copy served nobody. These bindings are consumed from
JavaScript, which reaches them through wasm-pack output rather than cargo,
and the published page documented nothing: docs.rs builds for x86-64, where
every `#[wasm_bindgen]` export is compiled out, so it listed only
`WasmError`. 0.2.0 has been deleted from crates.io; `publish = false` keeps a
release from silently putting it back, since the key was absent and therefore
defaulted to publishable. The unused `[workspace.dependencies]` entry goes
too — nothing declared `dm2-wasm.workspace = true`, and it carried a version
requirement for a crate that is no longer on the registry.

In its place, `build-npm.sh` produces the npm package. It wraps wasm-pack and
patches the two things wasm-pack cannot express: the package is published as
`dm2-tools`, matching the PyPI distribution rather than the crate name, and
`repository.directory` points at the crate inside this workspace. It builds
`--target bundler`, the target npm consumers expect — an ES module Vite and
webpack import with no explicit init call. The `web` target keeps its place
for a checkout with no bundler, and the README now documents both.

The crate carries copies of the two licenses because wasm-pack only bundles
`LICENSE*` files sitting beside Cargo.toml, the same reason the Python
package carries its own. The `cmp` guard that caught those drifting moves
from the `python` job to `stable` and now covers both.

CI also gains a `wasm32-unknown-unknown` check. `cargo check --workspace`
builds this crate for the host, where the `#[wasm_bindgen]` layer is inert,
so a break in the JS marshalling could only surface when someone built the
package by hand.

Publishing stays manual: there is no npm token in CI.
jqueuniet deleted branch chore/unpublish-wasm 2026-09-05 07:37:04 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
jqueuniet/dm2-tools!323
No description provided.