An Nx monorepo for running WebAssembly on NativeScript — three WASM runtime plugins built on a shared TypeScript foundation (wire protocol, adapter interfaces, base Runtime/Module/Function classes):
wasm3— lightweight interpreter (v0.5.2)- WAMR — WebAssembly Micro Runtime (2.3.0): interpreter, Fast JIT, LLVM JIT, AOT, WASI
- WasmKit — Swift-based WebAssembly runtime with WASI support, iOS-native through SwiftPM
Also in the monorepo: ns-wry — a general-purpose NativeScript
plugin scaffold built on Rust + UniFFI
(uniffi-rs) auto-generated Kotlin/Swift bindings and cargo-ndk Android pipeline.
Project status: Active development. APIs and project layout may change without notice; expect breaking changes between releases.
| Package | Description |
|---|---|
@cross-code/ns-wasm-core |
Shared foundation — wire protocol, WasmError, adapter interfaces, base WasmRuntime/WasmModule/WasmFunction classes |
@cross-code/ns-wasm3 |
NativeScript plugin — Swift Package on iOS, Kotlin + Rust JNI (cargo-ndk) on Android (wasm3 interpreter) |
@cross-code/ns-wamr |
NativeScript plugin — Swift Package on iOS, Kotlin + Rust JNI (cargo-ndk) on Android (WAMR: interpreter, Fast JIT, LLVM JIT, AOT, WASI) |
@cross-code/ns-wasm-kit-runtime |
NativeScript plugin — Swift Package on iOS (WasmKit interpreter); Android throws a clear unsupported error |
@cross-code/ns-wasm-fixture |
Rust/wasm-pack test fixtures (committed .wasm binaries) |
@cross-code/vitest-ns |
Vitest custom pool and NativeScript Worker runtime for on-device unit tests |
@cross-code/vitest-ns-ui |
Optional NativeScript Core results page for device-side Vitest progress |
@cross-code/ns-wry |
NativeScript plugin — Rust + UniFFI (uniffi-rs) Kotlin/Swift bindings, cargo-ndk Android pipeline |
@cross-code/nx-buck2 |
Nx plugin for Buck2 native builds — debug/release profiles, cross-compilation, size optimization |
ns-wasm-test |
NativeScript test app — runs the plugins on a simulator/emulator from a demo page and through Vitest + vitest-ns |
ns-wry-app |
NativeScript test app for @cross-code/ns-wry — WebView demo with google.com on iOS/Android |
The WASM runtime plugins expose the same TypeScript API — see WASM.md. All runtime
plugins (wasm3, WAMR, WasmKit) share the same foundation (@cross-code/ns-wasm-core)
which provides the wire protocol, error classes, adapter interfaces and generic
WasmRuntime/WasmModule/WasmFunction classes.
Each package README covers its own layout, development workflow and troubleshooting
(see Per-package documentation).
- Node 22.13+, pnpm (the default package manager —
packageManagerinpackage.json) - Runtime versions are pinned with mise (
.mise.toml: node 24.18.1, java temurin-21.0.2, pnpm 11.20.0) - iOS: Xcode + Swift toolchain (for
swift test) - Android: JDK 17+, Android SDK with NDK 29 (
ANDROID_HOMEset) - Buck2 (optional): only for the
nx-buck2native-build targets — see Buck2 builds
pnpm installThe NativeScript test app is not a workspace member (the ns CLI needs its
own node_modules) — it has its own pnpm-workspace.yaml and lockfile.
Before running its suite, install it separately:
cd apps/ns-wasm-test && pnpm installRun TypeScript build and unit tests (no native toolchain required):
pnpm exec nx run-many -t build testClean all build caches and generated artifacts (incl. dist, .buck-out,
test-output, Gradle/Rust targets, nx-buck2 compiled JS):
node tools/clean.mjs # build artifacts only
node tools/clean.mjs --all # also remove node_modules trees# Vitest unit tests + typecheck (no native toolchain, no device)
pnpm exec nx run-many -t test typecheck
# iOS XCTests (runs wasm3 / WAMR natively on macOS)
pnpm --filter ./packages/ns-wasm3 run test.ios
pnpm --filter ./packages/ns-wamr run test.ios
# Android JVM host tests (no emulator needed)
pnpm --filter ./packages/ns-wasm3 run test.android
pnpm --filter ./packages/ns-wamr run test.android
# The test app's Vitest suite, on a simulator / emulator
pnpm exec nx run ns-wasm-test:test.ios
pnpm exec nx run ns-wasm-test:test.android
# On-device Istanbul coverage reports
pnpm exec nx run ns-wasm-test:test.ios.coverage
pnpm exec nx run ns-wasm-test:test.android.coverageOn macOS, NativeScript's iOS build needs a UTF-8 locale (export LANG=en_US.UTF-8) —
otherwise the CLI's CocoaPods check fails before the build starts.
wamr native suites need the vendored WAMR C sources (
packages/ns-wamr/src/vendors/wamr/, WAMR-2.3.0). If the source tree is ever missing, the wamr native commands and CI jobs (wamr-ios,wamr-android) skip gracefully — they print aSKIP:message and exit 0 rather than fail. The TypeScript layer and vitest specs run normally.
# Build a single project
pnpm exec nx run ns-wasm3:build
pnpm exec nx run ns-wamr:build
# Run all affected tasks
pnpm exec nx affected -t build test
# Visualise the project graph
pnpm exec nx graphNative builds can optionally run through Buck2 via
the @cross-code/nx-buck2 plugin — debug/release profiles, per-platform
cross-compilation, size optimization, and symbol preservation:
# Release build (default: -Oz, LTO, stripped)
nx run ns-wamr:buck2-build --configuration=release
# Debug build (-O0 -g3, full DWARF)
nx run ns-wamr:buck2-build --configuration=debug
# Cross-compile for a platform/arch
nx run ns-wamr:buck2-build --platform=ios --arch=arm64
# All native projects at once
nx run-many -t buck2-build -p ns-wamr ns-wasm3 ns-wryInstall Buck2 once (it is not on crates.io — the buck2 crate is a
placeholder):
curl -fsSL https://github.com/facebook/buck2/releases/latest/download/buck2-aarch64-apple-darwin.zst \
| zstd -d | sudo tee /usr/local/bin/buck2 > /dev/null && sudo chmod +x /usr/local/bin/buck2or mise plugin install buck2 https://github.com/izaakschroeder/asdf-buck2.
Usage and API documentation for the WebAssembly plugins — install, quick start, calling exports, linear memory, globals, host imports, value marshalling, error messages, the complete API reference, and shared troubleshooting — lives in WASM.md.
All three plugins expose the same TypeScript API; only the class names differ
(Wasm3Runtime / Wasm3Module / Wasm3Function vs
WamrRuntime / WamrModule / WamrFunction vs
WasmKitRuntime / WasmKitModule / WasmKitFunction).
WasmKit is iOS-only (Swift-based runtime); Android throws a clear "not supported" error.
# Detekt (static analysis) + Ktlint (formatting) — hand-written sources only
pnpm exec nx run ns-wasm3:lint.android
pnpm exec nx run ns-wasm3:lint.android --configuration=format # auto-fix
# Config: detekt.yml + .editorconfig at the repo root (shared by both engines)# SwiftLint — hand-written sources only
pnpm exec nx run ns-wasm3:lint.ios
pnpm exec nx run ns-wamr:lint.ios
# Periphery — unused-code detection (builds the SwiftPM package)
pnpm exec nx run ns-wasm3:periphery.ios
pnpm exec nx run ns-wamr:periphery.ios
# Config: .swiftlint.yml + .periphery.yml at the repo root (shared by all engines)| Package | Docs |
|---|---|
| WebAssembly plugins (wasm3, WAMR & WasmKit) | WASM.md — shared usage, API reference, marshalling, errors, troubleshooting |
@cross-code/ns-wasm-core |
AGENTS.md — wire protocol, WasmError, adapter interfaces, base classes |
@cross-code/ns-wasm3 |
README — platform details, package layout, developing, troubleshooting, license |
@cross-code/ns-wamr |
README — execution tiers, package layout, developing, troubleshooting, license |
@cross-code/ns-wasm-kit-runtime |
README — WasmKit Swift interpreter, iOS-only adapter, developing, troubleshooting |
@cross-code/ns-wasm-fixture |
README — exported subpaths, rebuilding the .wasm fixtures |
@cross-code/vitest-ns |
README — custom pool, Worker registry, concurrency, and transport |
@cross-code/vitest-ns-ui |
README — optional NativeScript results UI |
@cross-code/ns-wry |
README — Rust + UniFFI architecture, platform stubs, developing, troubleshooting |
@cross-code/nx-buck2 |
README — Buck2 executors/generators, CLI usage |
ns-wasm-test |
README — running the demo page and the on-device Vitest suite, troubleshooting |
ns-wry-app |
README — WebView demo, build-plugin-and-run scripts, troubleshooting |