flowchart TD
A["cargo build --workspace"] --> B["wasm-pack build<br>crates/panproto-wasm<br>--target web"]
B --> C["cd sdk/typescript<br>pnpm install && pnpm build"]
A --> D["cargo nextest run<br>--workspace"]
B --> E["wasm-pack test<br>--headless --chrome"]
C --> F["pnpm test"]
D --> G{"All pass?"}
E --> G
F --> G
G -->|yes| H["Ready to commit"]
G -->|no| I["Debug<br>(see chapter 4)"]
3 Building and Testing
3.1 Toolchain requirements
| Tool | Version | Purpose |
|---|---|---|
| Rust | 1.85+ (Edition 2024) | Core workspace |
wasm32-unknown-unknown target |
(via rustup) | WASM compilation |
wasm-pack |
latest | WASM packaging and JS binding generation |
| Node.js | 22+ | TypeScript SDK build and tests |
pnpm |
latest | TypeScript package management |
cargo-nextest |
latest | Test runner (required for CI parity) |
divan |
(workspace dep) | Benchmarking (no install needed) |
Install the Rust target and tools:
rustup update stable
rustup target add wasm32-unknown-unknown
cargo install wasm-pack cargo-nextest3.2 Building the Rust workspace
3.2.1 Full workspace build
cargo build --workspaceThis compiles all 10 crates and the integration test crate in debug mode. Incremental builds after the first compile are fast, typically under 5 seconds for single-crate changes.
3.2.2 Single crate
cargo build -p panproto-gatUseful when iterating on one crate. Downstream crates are not recompiled.
3.2.3 Release build
The workspace defines two release profiles:
# Workspace crates
panproto-gat = { version = "0.26.0", path = "crates/panproto-gat" }
panproto-schema = { version = "0.26.0", path = "crates/panproto-schema" }
panproto-inst = { version = "0.26.0", path = "crates/panproto-inst" }
panproto-mig = { version = "0.26.0", path = "crates/panproto-mig" }
panproto-lens = { version = "0.26.0", path = "crates/panproto-lens" }
panproto-lens-dsl = { version = "0.26.0", path = "crates/panproto-lens-dsl" }
panproto-check = { version = "0.26.0", path = "crates/panproto-check" }release enables LTO, single codegen unit, and symbol stripping for maximum performance. release-wasm inherits from release but uses opt-level = "z" to minimize binary size for the WASM target.
# Native release build
cargo build --workspace --release
# WASM release build (used by CI for npm publishing)
cargo build -p panproto-wasm --profile release-wasm --target wasm32-unknown-unknown3.3 Building the WASM target
3.3.1 For local testing
wasm-pack build crates/panproto-wasm --target webThis produces crates/panproto-wasm/pkg/ with .wasm, .js, and .d.ts files. The --target web flag generates ES module imports suitable for browsers and test runners.
3.3.2 For npm publishing
wasm-pack build crates/panproto-wasm --target bundler --releaseThe --target bundler flag generates output compatible with bundlers like webpack and Vite. CI uses this for the @panproto/core npm package.
If wasm-pack build fails with error[E0463]: can't find crate for 'core', you are missing the WASM target. Run rustup target add wasm32-unknown-unknown.
3.4 Building the TypeScript SDK
cd sdk/typescript
pnpm install
pnpm buildpnpm build runs the TypeScript compiler and produces JavaScript output in dist/. The SDK imports the WASM module generated by wasm-pack, so you must build the WASM target first.
When making changes that span Rust and TypeScript, rebuild in order:
cargo build -p panproto-wasmwasm-pack build crates/panproto-wasm --target webcd sdk/typescript && pnpm build
3.5 Test matrix
panproto has five categories of tests. CI runs all of them on every pull request.
3.5.1 Unit tests (per crate)
Each crate has unit tests in #[cfg(test)] modules within its source files. Run a single crate’s tests:
cargo nextest run -p panproto-gat
cargo nextest run -p panproto-schema
cargo nextest run -p panproto-inst
cargo nextest run -p panproto-mig
cargo nextest run -p panproto-lens
cargo nextest run -p panproto-check
cargo nextest run -p panproto-protocols
cargo nextest run -p panproto-wasm3.5.2 Full Rust test suite
cargo nextest run --workspaceThis runs every Rust test across all crates, including the integration test crate. On a modern machine this takes 30–60 seconds.
3.5.3 Integration tests
The tests/integration crate contains cross-crate tests that exercise full pipelines:
cargo nextest run -p panproto-integrationThese tests cover scenarios like:
- AT Protocol recursive schema round-trips
- Cross-protocol migration (e.g., Protobuf to SQL)
- Breaking-change detection on real schema diffs
- WASM boundary serialization fidelity
- Lens law verification on composed migrations
3.5.4 Property tests
Several crates use proptest for property-based testing. These run as part of the normal unit test suite; no special invocation is needed. To run more cases:
PROPTEST_CASES=10000 cargo nextest run -p panproto-gatTo reproduce a failure from a seed:
PROPTEST_SEED=12345678 cargo nextest run -p panproto-gat -- test_name3.5.5 Running a single test
cargo nextest run -p panproto-inst -- test_nameThe -- separator passes the filter to the test binary. Partial matches work: -- wtype runs all tests with “wtype” in their name.
3.5.6 TypeScript tests
cd sdk/typescript
pnpm testThe TypeScript test suite covers the SDK’s public API, WASM integration, and MessagePack serialization.
3.6 Build and test pipeline
3.7 Lint checks
CI enforces strict linting. Run these locally before pushing:
# Rust lints
cargo clippy --workspace -- -D warnings
# Rust formatting
cargo fmt --check
# TypeScript formatting
cd sdk/typescript && npx prettier --check 'src/**/*.ts' 'tests/**/*.ts'The workspace configures clippy at the pedantic and nursery levels (see [workspace.lints.clippy] in Cargo.toml). If a pedantic lint is a false positive for your code, use a targeted #[allow()] attribute with a comment explaining why.
unsafe_code = "deny"
The workspace denies all unsafe code. panproto achieves its performance through arena allocation (bumpalo), small-vector optimization (smallvec), and hash map selection (rustc-hash), all within safe Rust.
3.8 CI parity
To replicate exactly what CI runs:
# Step 1: Lint
cargo clippy --workspace -- -D warnings
cargo fmt --check
# Step 2: Test
cargo nextest run --workspace
# Step 3: WASM
wasm-pack build crates/panproto-wasm --target web
wasm-pack test --headless --chrome crates/panproto-wasm
# Step 4: TypeScript
cd sdk/typescript
pnpm install
pnpm build
pnpm test
npx prettier --check 'src/**/*.ts' 'tests/**/*.ts'If all four steps pass locally, CI will pass.
3.9 Quick reference
| Task | Command |
|---|---|
| Build all | cargo build --workspace |
| Build one crate | cargo build -p panproto-gat |
| Build WASM | wasm-pack build crates/panproto-wasm --target web |
| Build TS SDK | cd sdk/typescript && pnpm install && pnpm build |
| Test all Rust | cargo nextest run --workspace |
| Test one crate | cargo nextest run -p panproto-gat |
| Test one test | cargo nextest run -p panproto-gat -- test_name |
| Test TypeScript | cd sdk/typescript && pnpm test |
| Lint | cargo clippy --workspace -- -D warnings |
| Format check | cargo fmt --check |
| Bench | cargo bench -p panproto-gat |