npm.io
1.14.17 • Published 3d ago

@ifc-lite/query

Licence
MPL-2.0
Version
1.14.17
Deps
4
Size
146 kB
Vulns
0
Weekly
0
Stars
340

@ifc-lite/query

Query system for IFClite. Fluent type-safe filtering of an IfcDataStore, plus full SQL via DuckDB-WASM. Filters by IFC type, property values, and relationships across multi-model federations.

Installation

npm install @ifc-lite/query

Fluent queries

import { IfcQuery } from '@ifc-lite/query';

const query = new IfcQuery(store); // store from `parseColumnar()`

// All external load-bearing walls
const walls = query
  .ofType('IfcWall', 'IfcWallStandardCase')
  .whereProperty('Pset_WallCommon', 'IsExternal', '=', true)
  .whereProperty('Pset_WallCommon', 'LoadBearing', '=', true)
  .execute();

console.log(`${walls.length} external load-bearing walls`);

for (const wall of walls) {
  console.log(wall.name, wall.globalId);
  console.log(wall.properties); // lazily-loaded psets
}

Convenience methods for the common building elements:

query.walls().execute();
query.doors().execute();
query.windows().execute();
query.slabs().execute();
query.columns().execute();
query.beams().execute();
query.spaces().execute();

Comparison operators

query
  .ofType('IfcWall')
  .whereProperty('Qto_WallBaseQuantities', 'NetVolume', '>', 5.0)
  .whereProperty('Pset_WallCommon', 'FireRating', 'startsWith', 'REI')
  .execute();

Supported: =, !=, >, <, >=, <=, contains, startsWith. The first argument names either a property set (Pset_*) or a quantity set (Qto_*).

Comparisons are same-type only — '60' does not match 60 — and a null on either side never matches, including with !=. A filter matches when any property of that name, in any set of that name, satisfies it.

On a STEP (.ifc) model the property sets are resolved lazily from the source buffer rather than from a pre-built index, so whereProperty does work per candidate entity. Narrow with ofType(...) / onStorey(...) before filtering: query.all().whereProperty(...) resolves every entity in the model and on a large one costs many times the type-scoped form. A cache-restored .ifc model behaves the same way: the cache stores the property table as it was built, and a STEP parse leaves it empty. What decides the path is the store rather than the file format — a query answers from the property index whenever the store carries table rows. Both paths return the same entities.

Graph traversal

const wall = query.entity(12345);

// Walk the spatial structure
console.log(wall.storey()?.name);    // 'Ground Floor'
console.log(wall.building()?.name);  // 'Office Tower'

// Containment + composition
const openings = wall.contains(); // openings hosted by the wall
const aggregates = wall.decomposes();

SQL via DuckDB-WASM

const result = await query.sql(`
  SELECT e.type, COUNT(*) AS count, AVG(q.value) AS avg_volume
  FROM entities e
  JOIN quantities q ON q.entity_id = e.express_id
  WHERE q.quantity_name = 'NetVolume'
  GROUP BY e.type
  ORDER BY count DESC
  LIMIT 10
`);

console.table(result.rows);

Tables exposed: entities, properties, quantities, relationships. Useful when you'd rather write SQL than chain method calls.

DuckDB is loaded lazily on the first sql() call and is not bundled (it would add ~4 MB). To use the SQL API, install it alongside:

npm install @duckdb/duckdb-wasm

The fluent query API works without it.

API

See the Querying Guide and API Reference.

License

MPL-2.0

Keywords