Hello, world!¶
Opening an IFC file¶
After Installation, initialize the runtime and load the schema for your sample model. This example uses an IFC4 file. In Node.js, read the file as bytes:
import { readFile, writeFile } from 'node:fs/promises';
import * as ifcopenshell from 'ifcopenshell';
const runtime = await ifcopenshell.init();
await runtime.loadPlugin('schema', 'ifc4');
const bytes = await readFile('model.ifc');
const model = ifcopenshell.open(bytes, 'model.ifc');
In the browser, obtain the same bytes from an uploaded File or an HTTP
response. For example, replace the readFile call with:
const response = await fetch('/models/model.ifc');
if (!response.ok) throw new Error(`Failed to load IFC: ${response.status}`);
const bytes = new Uint8Array(await response.arrayBuffer());
open() accepts a Uint8Array or ArrayBuffer, rather than a filesystem
path. Load the file’s schema plugin before calling it.
Finding and inspecting entities¶
The examples below assume model is still open. Inspect its schema and
retrieve an entity by STEP id:
console.log(model.schema());
const entity = model.byId(1);
{
if (entity) console.log(entity.id(), entity.isA());
}
Query walls, check their IFC class, and read attributes by name or position:
const walls = model.byType('IfcWall');
{
console.log('Number of walls:', walls.length);
const wall = walls[0];
if (wall) {
console.log(wall.isA());
console.log(wall.isA('IfcElement'));
console.log(wall.get(0)); // GlobalId
console.log(wall.get('Name'));
}
}
model.byGuid(globalId) retrieves an entity by GlobalId. Missing id or
GlobalId lookups raise an error. model.byType(typeName) includes subtypes;
model.byTypeExclSubtypes(typeName) selects only the exact IFC class.
Type queries return ordinary JavaScript arrays.
Editing and saving¶
Use set() to change attributes. Serialize the IFC-SPF text with toString()
and write it using your application’s filesystem or download mechanism:
const walls = model.byType('IfcWall');
{
if (walls[0]) walls[0].set('Name', 'My new wall name');
await writeFile('updated.ifc', model.toString(), 'utf8');
}
In a browser, new Blob([model.toString()], { type: 'text/plain' }) produces a
downloadable IFC file. Release the model after all queries and edits are done:
model.dispose();
Creating a new file¶
An empty IFC file can also be constructed after loading its schema plugin:
const model = new ifcopenshell.File('IFC4');
try {
const wall = model.create('IfcWall', { Name: 'Example wall' });
{
wall.set('GlobalId', '0YvctVUKr0kugbFTf53O9L');
console.log(wall.id(), wall.get('Name'));
console.log(model.toString());
}
} finally {
model.dispose();
}
This demonstrates entity creation. A complete exchange model also needs the appropriate project, units, contexts, and relationships. Use a distinct valid IFC GlobalId for each root entity in your application.
Object lifetime¶
The model owns its IFC data. Only File and geometry Iterator objects
implement Disposable. Dispose them when finished to invoke their native
C++ destructors. Entity references and other binding wrappers use GC cleanup;
query results are ordinary JavaScript arrays. Keep the model alive while
accessing its entities. model.remove() removes IFC data from the file.
TypeScript projects can use using declarations for automatic disposal:
using model = new ifcopenshell.File('IFC4');
const wall = model.create('IfcWall', { Name: 'Example wall' });
console.log(wall.get('Name'));
The compiler transforms these declarations into cleanup calls. When writing
JavaScript for runtimes without using support, use try / finally.