Developer workflows¶
Start with the result you need. The TypeScript SDK and CLI support headless work; geometry and rendering are separate choices.
| Task | Entry point | Runtime |
|---|---|---|
| Query and edit a loaded IFC model | @ifc-lite/sdk/headless → openModel |
Node or browser |
| Parse into a source data store | @ifc-lite/parser → parseModel |
Node or browser |
| Inspect files and automate checks | @ifc-lite/cli → ifc-lite |
Node |
| Extract meshes for your engine | @ifc-lite/geometry → GeometryProcessor |
WASM-capable Node or browser |
| Process through a native service | @ifc-lite/server-client + Rust server |
HTTP client + server |
| Integrate from Rust | ifc-lite-core, ifc-lite-processing |
Native Rust |
| Extract geometry in Python | ifclite-geom |
Python; see the wheel's supported platforms |
The TypeScript reference lists the modular packages. Rust and Python have their own contracts; they do not imply every scripting namespace is available in every runtime.
First useful result¶
Install the SDK and a TypeScript script runner:
Save this as inspect.mts and run npx tsx inspect.mts model.ifc:
import { readFile } from 'node:fs/promises';
import { openModel } from '@ifc-lite/sdk/headless';
const model = await openModel(await readFile(process.argv[2] ?? 'model.ifc'));
try {
if (model.report.completeness !== 'complete') throw new Error('Record coverage is incomplete or unknown');
const doors = model.bim.query().byType('IfcDoor').toArray();
console.log(JSON.stringify(doors.map(door => ({
GlobalId: door.globalId,
Name: door.name,
FireRating: model.bim.property(door.ref, 'Pset_DoorCommon', 'FireRating'),
})), null, 2));
} finally {
model.close();
}
For a terminal workflow:
npx @ifc-lite/cli info model.ifc --json
npx @ifc-lite/cli query model.ifc --type IfcDoor --props --json
Reference model and runnable recipes¶
The independently authored ArchiCAD FZK reference model has five doors. From a source checkout, fetch it through the manifest-backed, hash-verified fixture command and build the examples:
pnpm install
node scripts/fixtures/fetch-fixtures.mjs ara3d/AC20-FZK-Haus.ifc
pnpm exec turbo build --filter=ifc-lite-headless-workflows --concurrency=2
The complete recipe files share one helper that opens the model, requires known complete record coverage, and closes it on success or error.
| Recipe | Run from the repository root | Result |
|---|---|---|
| Extract data | node examples/headless-workflows/dist/extract.mjs tests/models/ara3d/AC20-FZK-Haus.ifc |
JSON containing five doors with exact IFC attribute names |
| Validate IDS | node examples/headless-workflows/dist/validate.mjs tests/models/ara3d/AC20-FZK-Haus.ifc examples/headless-workflows/doors-have-names.ids |
Native report evaluating five door names |
| Edit/export/reopen | node examples/headless-workflows/dist/edit.mjs tests/models/ara3d/AC20-FZK-Haus.ifc /tmp/edited.ifc |
A checked property is verified after reopening the exported file |
| Extract geometry | node examples/headless-workflows/dist/geometry.mjs tests/models/ara3d/AC20-FZK-Haus.ifc /tmp/model.glb |
A GLB assembled from the processor's meshes |
| Run a service | node examples/headless-workflows/dist/server.mjs |
POST /doors, bounded workers and request cancellation |
The IDS recipe exits 1 for a failed specification and 2 when no entities were evaluated. It retains the native report rather than turning an empty evaluation into a success summary. Use your own IDS document to test different requirements.
Geometry needs the runtime artifact. In a source checkout without Rust, run pnpm build:wasm:fetch; a published consumer gets the WASM package through npm. The processor recipe uses the canonical export path and always disposes the processor. To feed meshes directly into another engine, preserve per-mesh origins and the returned coordinate frame; follow the geometry guide and the Three.js integration.
The geometry recipe first parses data to require complete record coverage, closes that session, then initializes the geometry processor. This adds a data-parse pass before mesh processing. Its JSON result includes the scan report; complete record coverage does not imply complete geometry coverage.
A cancellable local service¶
The service recipe accepts IFC bytes at POST /doors and runs each query in an owned Node worker. Disconnect and timeout terminate that worker, including synchronous parsing work. It limits uploads to 16 MiB, concurrent requests to two, and each operation to 30 seconds. These are explicit example budgets; the Rust server provides the native processing deployment path.
node examples/headless-workflows/dist/server.mjs
curl -f -H 'Content-Type: application/octet-stream' --data-binary @tests/models/ara3d/AC20-FZK-Haus.ifc http://127.0.0.1:3001/doors
curl -f http://127.0.0.1:3001/health
/health exposes active request/worker counts. The worker input is an exact transferred allocation, so a pooled Node Buffer cannot expose unrelated bytes. Results and parse refusals are JSON; interrupted requests release their worker before the concurrency slot is reused.
Integration contracts to keep explicit¶
A scan report describes record coverage, independently of IDS/schema conformance and geometry coverage. Treat unknown as unknown. The validated loader refuses invalid envelopes; the tolerant IfcParser.parseColumnar remains available for recovery tooling. See parsing.
Use bim for queries that include pending edits; model.store is the original source snapshot. A reference pairs a session modelId with its local expressId. IFC GlobalId is a different identifier, and the same EXPRESS number in two loaded files identifies different records. Use an explicitly verified source identity when persisting results across sessions. See stable identity.
model.capability(operation) tells you whether a backend method is implemented/configured. It does not guarantee a native runtime or valid input. The session throws structured errors for unsupported operations and backend calls after close. Closing releases preparation caches; source arrays remain alive while your application retains them. See the SDK lifecycle.
File length units, normalized mesh metres, Y-up mesh coordinates and IFC Z-up coordinates are separate contracts. Preserve coordinateInfo and mesh origins when handing geometry to another system. See coordinate handling.
For a failure report, include package/runtime versions, the operation, structured error/scan codes, and a shareable reproducing fixture or its hash. Keep credentials and private model bytes out of reports. See error handling.