Skip to content

Getting started: JavaScript ​

@openbim/ifcx is the WebAssembly build of the Rust crates, for Node 18 and later, bundlers and plain browser pages, with TypeScript declarations.

sh
npm install @openbim/ifcx

The Node snippets on this page are regions of crates/openbim-ifcx-wasm/tests/js/guide.mjs, which the gate runs against the built package, so they work as shown.

Node ​

js
import { readFileSync, writeFileSync } from "node:fs";
import { IfcxFile, compose, exportGlb, fetchImports, validate } from "@openbim/ifcx";
// or: const { IfcxFile, ... } = require("@openbim/ifcx");

Read, validate and write ​

js
const model = readFileSync("model.ifcx"); // a Buffer is a Uint8Array; a string works too
const file = IfcxFile.parse(model);
console.log(file.header.id, file.nodeCount);

const report = file.validate(); // against the file's own schemas
for (const failure of report.failures) {
  console.log(failure.node, failure.attribute, failure.pointer, failure.kind, failure.message);
}

const text = file.write(true); // JSON text: content, key order and numbers as read

Keep the IfcxFile and call write() to save a file: a plain object from toJSON() may reorder integer-like keys and round integers beyond 2^53.

Compose layers and export GLB ​

js
// Layers weakest first: the last layer's opinions win.
const layers = [model, readFileSync("overlay.ifcx")];

const tree = compose(layers); // { path, attributes, children }
console.log(Object.keys(tree.children)); // the root nodes

const { valid, failures } = validate(layers);

const glb = exportGlb(layers); // Uint8Array, binary glTF 2.0
writeFileSync("model.glb", glb);

Imports ​

Without options.imports, imports are not resolved. With it, every imported file must be supplied, keyed by its exact import uri. fetchImports collects them for you:

js
// Fetch every file the layers import, recursively, keyed by import `uri`.
// The WebAssembly module never touches the network; this is plain JS
// over `fetch` (or the loader you pass).
const imports = await fetchImports([main], { baseUrl: "https://example.org/model/", fetch });
const composed = compose([main], { imports });

fetch defaults to the global fetch; pass your own for credentials, a cache, a mirror or local files, such as { fetch: async (url) => readFile(new URL(url)) } in Node.

Browser ​

With a bundler that supports WebAssembly ES module integration (webpack 5 with experiments.asyncWebAssembly), import @openbim/ifcx as in Node. Otherwise, and with Vite, import the web build and call init() once:

html
<script type="importmap">
  { "imports": { "@openbim/ifcx/web": "/node_modules/@openbim/ifcx/web/openbim_ifcx_wasm.js" } }
</script>
<script type="module">
  import init, { IfcxFile, exportGlb, fetchImports, validate } from "@openbim/ifcx/web";

  await init(); // fetches openbim_ifcx_wasm_bg.wasm next to the module
  const url = new URL("models/house.ifcx", location.href);
  const model = new Uint8Array(await (await fetch(url)).arrayBuffer());

  // Fetch what the model imports, relative to its own URL, then use it.
  const imports = await fetchImports(model, { baseUrl: url });
  const report = validate(model, { imports });
  const glb = exportGlb(model, { imports }); // e.g. for three.js's GLTFLoader.parse
  console.log(IfcxFile.parse(model).header.id, report.valid, glb.length);
</script>

The package's own check loads this build in headless Chrome on every change. The viewer is a complete example: Vite, the web build, three.js, picking by the IFCX path each glTF node carries; its source is demo/.

Errors ​

Every failure throws an Error with name === "IfcxError" and a stable code: read, write, layer, compose, invalid-argument, glb or fetch. The reference lists the whole API, generated from the binding's declarations.

Released under the MIT licence. No buildingSMART files or texts are published here.