libcascade
v3.0.2
Published
OpenCascade CAD bindings for JavaScript and WebAssembly via Emscripten.
Maintainers
Readme
Build solids, run booleans, fillet edges, mesh, and read/write STEP — in a
browser tab, a Node CLI, or an LLM tool call. Source lives in
taucad/opencascade.js; this is not
an official Open CASCADE Technology distribution.
| I want to… | Go to | | ------------------------------ | --------------------------------------------------------------------------------- | | Use OCCT from JS or TS | Install | | Run the threaded build | Multi-threading | | Build a trimmed or custom WASM | Toolchain | | Pull a container image | Container images | | See what changed in v3 | What's new in v3 · BREAKING_CHANGES.md | | Build OCCT WASM from source | MAINTAINER.md | | Contribute | CONTRIBUTING.md |
Install
npm install libcascadeimport oc from 'libcascade';
using box = new oc.BRepPrimAPI_MakeBox(10, 10, 10);
const shape = box.Shape();The root export is an initialised instance, selected for the variant the host supports. Every bound symbol is also a named export.
Entry points
| Import | What it gives you |
| ------------------------------- | -------------------------------------------------------- |
| libcascade | Initialised instance, variant selected for the host |
| libcascade/init | Shared lazy selector |
| libcascade/single/init | Fixed single-threaded initializer |
| libcascade/multi/init | Fixed multi-threaded initializer |
| libcascade/single/wasm · libcascade/multi/wasm | Binary URL, for bundlers that relocate assets |
| libcascade/api-reference.json | Class/member hierarchy, source commit, build provenance |
Pass options through a fixed initializer when the variant is known:
// Vite / browser, with a relocated wasm asset
import { createInstance } from 'libcascade/single/init';
import wasmUrl from 'libcascade/single/wasm?url';
const oc = await createInstance({ locateFile: () => wasmUrl });The package is ESM-only. The WASM resolves on its own — reach for locateFile
only when a bundler or deployment moves the binary. Deep imports into dist/
are not a supported surface.
Distribution
The tarball ships dist/opencascade_single.{wasm,js} and
dist/opencascade_multi.{wasm,js}, each with a provenance.json sidecar naming
the exact toolchain and source commits. Both variants share one assembled
types.d.ts surface. Releases publish through GitHub OIDC Trusted Publishing
with Sigstore provenance — see the
release flow.
Multi-threading
For batch meshing, boolean grids, and STEP→glTF pipelines that use OCCT's internal thread pool, ask for the pthread build:
import { createInstance } from 'libcascade/multi/init';
const oc = await createInstance();
// Run once after init — flip OCCT global parallel defaults.
oc.BOPAlgo_Options.SetParallelMode(true); // booleans fan out
oc.BRepMesh_IncrementalMesh.SetParallelDefault(true); // meshing fans outcreateInstance owns the pthread plumbing: worker self-reference, Node path
conversion, and thread-pool sizing. Under Vite, set worker: { format: 'es' }
— Emscripten's workers are ES modules.
Browsers need Cross-Origin-Opener-Policy: same-origin and
Cross-Origin-Embedder-Policy: require-corp on every page that loads the
threaded binary. The multi-threading guide
covers activation, measured speedups, and when not to ship threaded.
Toolchain
Reach for @libcascade/toolchain when you need a binary the prebuilt one is
not: a trimmed symbol set, your own C++ wrappers, or different Emscripten link
settings. It drives digest-pinned Docker images for you, so there is no
docker run string to maintain. A container engine must be installed and
running.
npm install --save-dev @libcascade/toolchain// libcascade.config.ts
import { defineBuild } from '@libcascade/toolchain';
export default defineBuild({
name: 'myapp',
bindings: ['BRepPrimAPI_MakeBox', 'TopoDS_Shape', 'gp_Pnt'],
settings: { MODULARIZE: true, EXPORT_ES6: true, ALLOW_MEMORY_GROWTH: true },
compilerFlags: { optimize: 'O3', simd: true, exceptions: 'wasm', noEntry: true },
variants: [{ name: 'single' }],
});npx libcascade build # link each variant through the pinned image → dist/
npx libcascade assemble # shared types.d.ts + ./init entry + exports map
npx libcascade check src # CI drift guard: referenced symbols ⊆ bound symbolsSymbol names and -s settings are compile-checked against unions generated from
the pinned image, so a typo is a TypeScript error rather than a runtime
BindingError.
Container images
Images publish to
ghcr.io/taucad/opencascade.js
as multi-arch manifest lists (linux/amd64 + linux/arm64). Docker resolves the
architecture itself, Apple Silicon runs natively, and no --platform flag is
needed.
| Tag | What it points at |
| ------------------------------------------ | ------------------------------------------------------------------------ |
| :single-threaded | Latest release, single-threaded warm cache (default for browser CAD UIs) |
| :multi-threaded | Latest release, multi-threaded warm cache (requires COOP/COEP) |
| :bindgen-base | Post-PCH/generate, pre-compile — the custom-bindings starting point |
| :{{version}}-<stage> | Pinned release for any of the three stages above |
| :{{version}}-canary.<sha8>-<stage> | Immutable maintainer-dispatched canary, retained for seven days |
| :branch-main[-<full-sha>] | Current or immutable main, single-threaded |
| :multi-threaded-branch-main[-<full-sha>] | Current or immutable main, multi-threaded |
| :bindgen-base-branch-main[-<full-sha>] | Current or immutable main, bindgen-base |
Building the image, or driving it directly, is covered in MAINTAINER.md.
What's new in v3
| Change | Detail |
| ---------------------------- | ------------------------------------------------------------------------------------------ |
| OCCT 8.0.1 | 1,085+ upstream commits; 22–31% faster boolean operations |
| Emscripten 6.0.5 | LLVM 24, modern WASM features |
| Native WASM exceptions | -fwasm-exceptions replaces JS invoke trampolines; decodable via oc.getExceptionMessage |
| ESM-only distribution | "type": "module", eager root plus fixed and shared lazy entries |
| Full TypeScript bindings | Doxygen-derived JSDoc, rendered in Monaco IntelliSense |
| Suffix-free overloads | One symbol per class with val-based dispatch — no _2/_3 subclasses |
| Reproducible builds | DEPS.json pins every dependency to a commit; per-build provenance.json |
| Incremental builds | Content-addressed cache turns 10–30 minute clean builds into seconds on hit |
Overload dispatch measures ~264 ns/call, under 0.011% of wall time on typical CAD models. BENCHMARKS.md carries the evidence: CAD wall-clock against native C++, threading speedup, embind dispatch cost, and RBV overhead. CHANGELOG.md has the full entry.
Documentation
| Document | Covers |
| ------------------------------------------------------------------------------- | --------------------------------------------------- |
| libcascade.xyz | Full docs: package, toolchain, API reference |
| BREAKING_CHANGES.md | v3 consumer migration |
| BENCHMARKS.md | Measured performance, end to end |
| CHANGELOG.md | Release notes |
| MAINTAINER.md | Native build, env vars, release ownership |
| BUILD_SYSTEM.md | OCJS_* env-var matrix and configuration authoring |
| Trim symbols | Cutting the binding set to a consumer-sized build |
| Extend with C++ | customBindings scopes |
| Reproducible CI | Digest pinning, provenance, SBOM, lockfiles |
Projects using libcascade
- ArchiYou — library, code-CAD design tool, community hub
- BitByBit — code- and node-based CAD tool
- CascadeStudio — library and code-CAD design tool
- Replicad — library and code-CAD design tool
- Tau — AI-native CAD platform for the web
Contributing
Start with CONTRIBUTING.md, check TODO.md for the backlog, and use MAINTAINER.md to build from source.
License
See LICENSE.
