@teacss/engine
v0.10.11
Published
In-process Rust engine for TeaCSS (napi-rs binding, contract types and the project helper the shells share)
Readme
@teacss/engine
What this package is
@teacss/engine is the in-process Rust engine for TeaCSS: a napi-rs binding, the contract types (contract.d.ts) and the project helper (createProject) that the shells published from this repository (@teacss/vite, @teacss/astro, @teacss/rsbuild, @teacss/bun, @teacss/postcss, @teacss/inspector) and the teacss command share. You do not install it yourself. The shells depend on it, and npm installs the platform package that matches your machine through optionalDependencies.
Supported platforms
| Rust target | Package | os / cpu / libc | Status | Minimum |
| --- | --- | --- | --- | --- |
| aarch64-apple-darwin | @teacss/engine-darwin-arm64 | darwin / arm64 / - | required | macOS 11.0 |
| x86_64-apple-darwin | @teacss/engine-darwin-x64 | darwin / x64 / - | required | macOS 11.0 |
| x86_64-unknown-linux-gnu | @teacss/engine-linux-x64-gnu | linux / x64 / glibc | required | glibc 2.17 |
| x86_64-unknown-linux-musl | @teacss/engine-linux-x64-musl | linux / x64 / musl | required | - |
| aarch64-unknown-linux-gnu | @teacss/engine-linux-arm64-gnu | linux / arm64 / glibc | required | glibc 2.17 |
| aarch64-unknown-linux-musl | @teacss/engine-linux-arm64-musl | linux / arm64 / musl | optional | - |
| x86_64-pc-windows-msvc | @teacss/engine-win32-x64-msvc | win32 / x64 / - | required | - |
| aarch64-pc-windows-msvc | @teacss/engine-win32-arm64-msvc | win32 / arm64 / - | optional | - |
Every package needs Node.js 26 or later. A required platform blocks a release when it fails to build or test; an optional one is published later if it fails.
A platform outside this matrix has no fallback: there is no wasm package, and the TypeScript engine is the only alternative. To run the Rust engine there, build it yourself from this repository with cargo build -p teacss-napi --release, rename the cdylib in target/release/ to teacss-engine.<os>-<cpu>[-<libc>].node (the name the loader derives for your host, for example teacss-engine.linux-riscv64-gnu.node), and place it in packages/engine/ next to binding.js. The loader tries that file before any platform package.
Configuration
Configuration comes only from the CSS entry (@presets, @source, @shortcut, @safelist, @custom and the role directives such as @primary; see the CSS entry) plus a shell's ShellOptions, a small static object (root, entry, inline, envMode, unmatched, outputToCssLayers, shortcutsLayer, presetOptions, minify) that maps onto LoadProjectFromRootRequest. Build integrations describes each option and the options a shell adds on top. There is no UserConfig, no preset object and no translation layer: a key the request does not know is E_INVALID_ARGUMENT, and the one remaining unsupported case is an @presets name that is not standard, official or icons, which loadProjectFromRoot reports as E_UNSUPPORTED with details.reason preset-not-builtin and details.path @presets[<i>]. A project that needs JavaScript rules, variants or hooks runs on the TypeScript ecosystem (teacss-ts), which this package does not load.
Direct use of the binding
import { Engine, version } from "@teacss/engine/binding";The types are in binding.d.ts. The binding is a tooling-level API and is not part of the stability promise; integrations go through the package root (createProject and the contract types).
Troubleshooting
| Symptom | Cause | Fix |
| --- | --- | --- |
| Failed to load native binding, and the detail lists Cannot find module '@teacss/engine-linux-x64-gnu' | Optional dependencies were skipped at install time (--omit=optional, --no-optional, or a CI cache holding another platform's node_modules) | Run npm ci again without the omit, or install @teacss/engine-<platform> explicitly; pnpm users check supportedArchitectures |
| The same, but on Alpine with the detail trying a -gnu package | musl detection failed: gcompat makes process.report.getReport() report a glibc version, so the loader picked the gnu package | Remove gcompat, or install @teacss/engine-linux-x64-musl explicitly; if that does not help, report the detection case to napi-rs |
| Module did not self-register or a NODE_MODULE_VERSION mismatch | Cannot happen with a Node-API binary; it means the loaded .node is not this package's (for example an Electron with a Node-API version below 9, or an old Bun) | Upgrade the runtime |
| dlopen reports GLIBC_2.xx not found | glibc is older than the 2.17 build baseline | Not supported; build the binding yourself (see Supported platforms) |
| macOS reports "code signature invalid" | The .node was copied from outside npm and carries the quarantine attribute | xattr -d com.apple.quarantine <file>; files installed by npm do not carry it |
| A shell in this repository does not pick up a local build:debug | Its node_modules/@teacss/engine is a registry copy instead of the file:../engine link | npm --prefix packages/<shell> ci and check with ls -l packages/<shell>/node_modules/@teacss/engine that it is a symlink |
Verifying a release
Every GitHub release carries SHA256SUMS over the .node files, the teacss binaries and the npm tarballs:
shasum -a 256 -c SHA256SUMS # Linux: sha256sum -c SHA256SUMSReleases carry no npm provenance or GitHub attestation (v02.11 §1.3).
Development
npm --prefix packages/engine ci
npm --prefix packages/engine run build:debug # teacss-engine.<platform>.node, binding.js, binding.d.ts
npm --prefix packages/engine test
npm --prefix packages/engine run check:types
node -e 'import("./packages/engine/dist/index.js").then(m => console.log(m.version()))'build:debug uses the dev profile and rebuilds incrementally in seconds. npm run build uses the release profile with lto = "fat"; use it only to reproduce the size budget or the import checks locally.
The shells in this repository (packages/{vite,astro,rsbuild,bun,postcss,inspector}) depend on @teacss/engine through file:../engine, so npm --prefix packages/<shell> ci links them to this directory and they use the local build; the loader finds the .node next to binding.js first, so no platform package is needed. After a Rust change, run build:debug again.
