Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Build and test

Every script you’ll run when working on the SDK itself.

pnpm install               # bootstrap
pnpm test                  # unit suite
pnpm typecheck             # tsc --noEmit
pnpm build                 # rollup + tsc --emitDeclarationOnly

Bootstrap

pnpm install

The repo is a pnpm workspace with two packages:

  • @koed_jang/apyx-sdk (publishable, root)
  • @apyx-labs/sdk-playground (private, example/)

pnpm install from the repo root installs both. The playground links the SDK via workspace:*.

Top-level scripts

The package.json scripts field has these entries:

ScriptWhat it does
pnpm testVitest unit suite (vitest.config.ts). Runs on every PR. Fast — typically <5s.
pnpm test:watchSame, but in watch mode.
pnpm test:e2eVitest e2e suite (vitest.e2e.config.ts) — fork tests via anvil + packaging tests. Requires TEST_ETH_RPC_URL.
pnpm test:e2e:sdkJust the SDK fork tests.
pnpm test:e2e:cliJust the CLI fork tests.
pnpm test:e2e:packagingJust the packaging tarball test. Slow — installs into a temp dir, ~3 min.
pnpm typechecktsc --noEmit over the whole package.
pnpm buildProduction build — Rollup for ESM + CJS + CLI bundles, then tsc --emitDeclarationOnly for .d.ts.
pnpm gen:abisRe-generate src/generated/* from the JSON ABIs in abis/. Run this after updating any vendored ABI JSON.

What pnpm build produces

Rollup emits three bundles plus type declarations:

dist/
├── index.browser.mjs    # ESM, browser-targeted (treeshakeable)
├── index.node.cjs       # CJS, Node-targeted
├── cli.cjs              # the apyx binary (with #!/usr/bin/env node banner)
└── index.d.ts           # type declarations

package.json exports and main / browser fields route consumers to the right bundle automatically:

CallerResolves to
import from a Vite / webpack browser appdist/index.browser.mjs
import from Node ESMdist/index.node.cjs (yes — CJS works fine in Node ESM)
require from Node CJSdist/index.node.cjs
Type-only consumersdist/index.d.ts
apyx bindist/cli.cjs (chmod 0755 by Rollup)

The dual bundle path is checked end-to-end by test/e2e/packaging/tarball.e2e.spec.ts — packs a tarball, installs it into a fresh project, asserts both import and require resolve cleanly.

Running the playground locally

pnpm --filter @apyx-labs/sdk-playground dev

See Running the playground for the full flow.

Running the docs locally

The book builds in seconds once mdBook is installed:

brew install mdbook                    # or: cargo install --locked mdbook
cargo install --locked mdbook-mermaid mdbook-toc
cd book && mdbook serve --open

mdbook serve watches src/**/*.md and rebuilds + reloads on save. For just the build (no server):

mdbook build book

CI sanity checks

Whatever you run locally, CI runs the same:

  • ci.ymlpnpm install, pnpm typecheck, pnpm test, pnpm build.
  • e2e.yml — fork suite via Foundry’s foundry-rs/foundry-toolchain action. Path-filtered to PRs that touch src/** or test/e2e/**.
  • packaging.yml — nightly pnpm test:e2e:packaging against the current main.
  • docs.ymlmdbook build book + lychee link check.

A green CI run on a PR is the fastest way to know your local env isn’t hiding a failure.

Local fork-test setup

If you want to run the e2e suite end-to-end yourself:

brew install foundryup
foundryup                              # installs anvil
export TEST_ETH_RPC_URL='https://eth-mainnet.g.alchemy.com/v2/YOURKEY'
pnpm test:e2e

The fixture pins anvil to a known-good post-deployment block so reads are deterministic. See E2E testing for the full plan.

  • Repo layout — where each script’s source lives.
  • E2E testing — what pnpm test:e2e actually verifies.
  • Releasing — what release.yml does on tag push.