@ifc-lite/cli 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +373 -0
- package/dist/commands/bcf.d.ts +2 -0
- package/dist/commands/bcf.d.ts.map +1 -0
- package/dist/commands/bcf.js +78 -0
- package/dist/commands/bcf.js.map +1 -0
- package/dist/commands/bsdd.d.ts +2 -0
- package/dist/commands/bsdd.d.ts.map +1 -0
- package/dist/commands/bsdd.js +73 -0
- package/dist/commands/bsdd.js.map +1 -0
- package/dist/commands/convert.d.ts +2 -0
- package/dist/commands/convert.d.ts.map +1 -0
- package/dist/commands/convert.js +49 -0
- package/dist/commands/convert.js.map +1 -0
- package/dist/commands/create.d.ts +2 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/create.js +430 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/diff.d.ts +2 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +106 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/eval.d.ts +2 -0
- package/dist/commands/eval.d.ts.map +1 -0
- package/dist/commands/eval.js +47 -0
- package/dist/commands/eval.js.map +1 -0
- package/dist/commands/export.d.ts +2 -0
- package/dist/commands/export.d.ts.map +1 -0
- package/dist/commands/export.js +62 -0
- package/dist/commands/export.js.map +1 -0
- package/dist/commands/ids.d.ts +2 -0
- package/dist/commands/ids.d.ts.map +1 -0
- package/dist/commands/ids.js +187 -0
- package/dist/commands/ids.js.map +1 -0
- package/dist/commands/info.d.ts +2 -0
- package/dist/commands/info.d.ts.map +1 -0
- package/dist/commands/info.js +77 -0
- package/dist/commands/info.js.map +1 -0
- package/dist/commands/merge.d.ts +2 -0
- package/dist/commands/merge.d.ts.map +1 -0
- package/dist/commands/merge.js +60 -0
- package/dist/commands/merge.js.map +1 -0
- package/dist/commands/props.d.ts +2 -0
- package/dist/commands/props.d.ts.map +1 -0
- package/dist/commands/props.js +40 -0
- package/dist/commands/props.js.map +1 -0
- package/dist/commands/query.d.ts +2 -0
- package/dist/commands/query.d.ts.map +1 -0
- package/dist/commands/query.js +124 -0
- package/dist/commands/query.js.map +1 -0
- package/dist/commands/run.d.ts +2 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +43 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/schema.d.ts +2 -0
- package/dist/commands/schema.d.ts.map +1 -0
- package/dist/commands/schema.js +107 -0
- package/dist/commands/schema.js.map +1 -0
- package/dist/commands/validate.d.ts +2 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +111 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/headless-backend.d.ts +36 -0
- package/dist/headless-backend.d.ts.map +1 -0
- package/dist/headless-backend.js +441 -0
- package/dist/headless-backend.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +174 -0
- package/dist/index.js.map +1 -0
- package/dist/loader.d.ts +15 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +46 -0
- package/dist/loader.js.map +1 -0
- package/dist/output.d.ts +30 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +90 -0
- package/dist/output.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"AAuBA,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB9D"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/**
|
|
5
|
+
* ifc-lite run <script.js> <file.ifc>
|
|
6
|
+
*
|
|
7
|
+
* Execute a JavaScript file against the BIM SDK.
|
|
8
|
+
* The `bim` object is available globally in the script.
|
|
9
|
+
*
|
|
10
|
+
* Example script:
|
|
11
|
+
* const walls = bim.query().byType('IfcWall').toArray();
|
|
12
|
+
* console.log(`Found ${walls.length} walls`);
|
|
13
|
+
* for (const wall of walls) {
|
|
14
|
+
* const props = bim.properties(wall.ref);
|
|
15
|
+
* console.log(wall.name, props.length, 'property sets');
|
|
16
|
+
* }
|
|
17
|
+
*/
|
|
18
|
+
import { readFile } from 'node:fs/promises';
|
|
19
|
+
import { createHeadlessContext } from '../loader.js';
|
|
20
|
+
import { fatal } from '../output.js';
|
|
21
|
+
export async function runCommand(args) {
|
|
22
|
+
const positional = args.filter(a => !a.startsWith('-'));
|
|
23
|
+
if (positional.length < 2)
|
|
24
|
+
fatal('Usage: ifc-lite run <script.js> <file.ifc>');
|
|
25
|
+
const [scriptPath, filePath] = positional;
|
|
26
|
+
const scriptContent = await readFile(scriptPath, 'utf-8');
|
|
27
|
+
const { bim } = await createHeadlessContext(filePath);
|
|
28
|
+
// Execute script with bim context available
|
|
29
|
+
const wrappedScript = `
|
|
30
|
+
"use strict";
|
|
31
|
+
return (async function(bim, console) {
|
|
32
|
+
${scriptContent}
|
|
33
|
+
})(bim, console);
|
|
34
|
+
`;
|
|
35
|
+
try {
|
|
36
|
+
const fn = new Function('bim', 'console', wrappedScript);
|
|
37
|
+
await fn(bim, console);
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
fatal(`Script error: ${err.message}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAErC,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAc;IAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IACxD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAE/E,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,GAAG,UAAU,CAAC;IAE1C,MAAM,aAAa,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC1D,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAEtD,4CAA4C;IAC5C,MAAM,aAAa,GAAG;;;QAGhB,aAAa;;GAElB,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;QACzD,MAAM,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACzB,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,KAAK,CAAC,iBAAiB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACxC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/commands/schema.ts"],"names":[],"mappings":"AAaA,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgCjE"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/**
|
|
5
|
+
* ifc-lite schema
|
|
6
|
+
*
|
|
7
|
+
* Dump the complete SDK API schema as JSON.
|
|
8
|
+
* Useful for LLM tools to discover available commands and methods.
|
|
9
|
+
*/
|
|
10
|
+
import { printJson, hasFlag } from '../output.js';
|
|
11
|
+
export async function schemaCommand(args) {
|
|
12
|
+
const compact = hasFlag(args, '--compact');
|
|
13
|
+
// Dynamically import the bridge schema to get tool definitions
|
|
14
|
+
let schemas;
|
|
15
|
+
try {
|
|
16
|
+
const mod = await import('@ifc-lite/sandbox/schema');
|
|
17
|
+
schemas = mod.NAMESPACE_SCHEMAS;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
// Fallback: provide a static schema summary
|
|
21
|
+
schemas = getStaticSchema();
|
|
22
|
+
}
|
|
23
|
+
const output = schemas.map(ns => ({
|
|
24
|
+
namespace: ns.name,
|
|
25
|
+
description: ns.doc,
|
|
26
|
+
methods: ns.methods.map((m) => {
|
|
27
|
+
const entry = {
|
|
28
|
+
name: m.name,
|
|
29
|
+
description: m.doc,
|
|
30
|
+
};
|
|
31
|
+
if (!compact) {
|
|
32
|
+
if (m.paramNames)
|
|
33
|
+
entry.params = m.paramNames;
|
|
34
|
+
if (m.tsReturn)
|
|
35
|
+
entry.returns = m.tsReturn;
|
|
36
|
+
if (m.llmSemantics?.useWhen)
|
|
37
|
+
entry.useWhen = m.llmSemantics.useWhen;
|
|
38
|
+
if (m.llmSemantics?.taskTags)
|
|
39
|
+
entry.taskTags = m.llmSemantics.taskTags;
|
|
40
|
+
}
|
|
41
|
+
return entry;
|
|
42
|
+
}),
|
|
43
|
+
}));
|
|
44
|
+
printJson(output);
|
|
45
|
+
}
|
|
46
|
+
function getStaticSchema() {
|
|
47
|
+
return [
|
|
48
|
+
{
|
|
49
|
+
name: 'model', doc: 'Model operations',
|
|
50
|
+
methods: [
|
|
51
|
+
{ name: 'list', doc: 'List loaded models' },
|
|
52
|
+
{ name: 'active', doc: 'Get active model' },
|
|
53
|
+
{ name: 'activeId', doc: 'Get active model ID' },
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'query', doc: 'Query entities',
|
|
58
|
+
methods: [
|
|
59
|
+
{ name: 'all', doc: 'Get all entities' },
|
|
60
|
+
{ name: 'byType', doc: 'Filter by IFC type', paramNames: ['...types'] },
|
|
61
|
+
{ name: 'entity', doc: 'Get single entity', paramNames: ['modelId', 'expressId'] },
|
|
62
|
+
{ name: 'attributes', doc: 'Entity IFC attributes', paramNames: ['entity'] },
|
|
63
|
+
{ name: 'properties', doc: 'Property sets', paramNames: ['entity'] },
|
|
64
|
+
{ name: 'quantities', doc: 'Quantity sets', paramNames: ['entity'] },
|
|
65
|
+
{ name: 'classifications', doc: 'Classification references', paramNames: ['entity'] },
|
|
66
|
+
{ name: 'materials', doc: 'Material assignments', paramNames: ['entity'] },
|
|
67
|
+
{ name: 'typeProperties', doc: 'Type-level properties', paramNames: ['entity'] },
|
|
68
|
+
{ name: 'documents', doc: 'Linked documents', paramNames: ['entity'] },
|
|
69
|
+
{ name: 'relationships', doc: 'Structural relationships', paramNames: ['entity'] },
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: 'export', doc: 'Multi-format export',
|
|
74
|
+
methods: [
|
|
75
|
+
{ name: 'csv', doc: 'Export to CSV', paramNames: ['entities', 'options'] },
|
|
76
|
+
{ name: 'json', doc: 'Export to JSON', paramNames: ['entities', 'columns'] },
|
|
77
|
+
{ name: 'ifc', doc: 'Export to IFC STEP', paramNames: ['entities', 'options'] },
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: 'ids', doc: 'IDS validation',
|
|
82
|
+
methods: [
|
|
83
|
+
{ name: 'parse', doc: 'Parse IDS XML document', paramNames: ['xmlContent'] },
|
|
84
|
+
{ name: 'validate', doc: 'Validate against IFC model', paramNames: ['idsDocument', 'options'] },
|
|
85
|
+
{ name: 'summarize', doc: 'Summarize validation report', paramNames: ['report'] },
|
|
86
|
+
],
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: 'bcf', doc: 'BCF collaboration',
|
|
90
|
+
methods: [
|
|
91
|
+
{ name: 'createProject', doc: 'Create BCF project', paramNames: ['options'] },
|
|
92
|
+
{ name: 'createTopic', doc: 'Create topic/issue', paramNames: ['options'] },
|
|
93
|
+
{ name: 'createComment', doc: 'Create comment', paramNames: ['options'] },
|
|
94
|
+
{ name: 'read', doc: 'Read BCF file', paramNames: ['data'] },
|
|
95
|
+
{ name: 'write', doc: 'Write BCF file', paramNames: ['project'] },
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: 'create', doc: 'IFC creation',
|
|
100
|
+
methods: [
|
|
101
|
+
{ name: 'project', doc: 'Create new IFC project', paramNames: ['params'] },
|
|
102
|
+
{ name: 'building', doc: 'Create project with one storey', paramNames: ['params'] },
|
|
103
|
+
],
|
|
104
|
+
},
|
|
105
|
+
];
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/commands/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAyBA,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAiGnE"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/**
|
|
5
|
+
* ifc-lite validate <file.ifc> [--json]
|
|
6
|
+
*
|
|
7
|
+
* Perform structural validation checks on an IFC file:
|
|
8
|
+
* - Schema version detection
|
|
9
|
+
* - Required entity presence (IfcProject, IfcSite, IfcBuilding)
|
|
10
|
+
* - Spatial structure completeness
|
|
11
|
+
* - Orphan entity detection
|
|
12
|
+
* - GlobalId uniqueness
|
|
13
|
+
*/
|
|
14
|
+
import { loadIfcFile } from '../loader.js';
|
|
15
|
+
import { hasFlag, fatal, printJson } from '../output.js';
|
|
16
|
+
import { EntityNode } from '@ifc-lite/query';
|
|
17
|
+
export async function validateCommand(args) {
|
|
18
|
+
const filePath = args.find(a => !a.startsWith('-'));
|
|
19
|
+
if (!filePath)
|
|
20
|
+
fatal('Usage: ifc-lite validate <file.ifc> [--json]');
|
|
21
|
+
const jsonOutput = hasFlag(args, '--json');
|
|
22
|
+
const store = await loadIfcFile(filePath);
|
|
23
|
+
const issues = [];
|
|
24
|
+
// 1. Check required spatial entities
|
|
25
|
+
const requiredTypes = ['IFCPROJECT', 'IFCSITE', 'IFCBUILDING'];
|
|
26
|
+
for (const reqType of requiredTypes) {
|
|
27
|
+
const ids = store.entityIndex.byType.get(reqType) ?? [];
|
|
28
|
+
if (ids.length === 0) {
|
|
29
|
+
issues.push({ severity: 'error', rule: 'required-entity', message: `Missing required entity: ${reqType}` });
|
|
30
|
+
}
|
|
31
|
+
else if (ids.length > 1 && reqType === 'IFCPROJECT') {
|
|
32
|
+
issues.push({ severity: 'error', rule: 'single-project', message: `Multiple IfcProject entities found (${ids.length})` });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// 2. Check storeys
|
|
36
|
+
const storeyIds = store.entityIndex.byType.get('IFCBUILDINGSTOREY') ?? [];
|
|
37
|
+
if (storeyIds.length === 0) {
|
|
38
|
+
issues.push({ severity: 'warning', rule: 'has-storeys', message: 'No IfcBuildingStorey entities found' });
|
|
39
|
+
}
|
|
40
|
+
// 3. Check GlobalId uniqueness
|
|
41
|
+
const globalIds = new Map();
|
|
42
|
+
for (const [, ids] of store.entityIndex.byType) {
|
|
43
|
+
for (const id of ids) {
|
|
44
|
+
const node = new EntityNode(store, id);
|
|
45
|
+
const gid = node.globalId;
|
|
46
|
+
if (gid) {
|
|
47
|
+
const existing = globalIds.get(gid);
|
|
48
|
+
if (existing) {
|
|
49
|
+
existing.push(id);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
globalIds.set(gid, [id]);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const duplicateGlobalIds = [...globalIds.entries()].filter(([, ids]) => ids.length > 1);
|
|
58
|
+
if (duplicateGlobalIds.length > 0) {
|
|
59
|
+
issues.push({
|
|
60
|
+
severity: 'error',
|
|
61
|
+
rule: 'unique-globalid',
|
|
62
|
+
message: `${duplicateGlobalIds.length} duplicate GlobalId(s) found`,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
// 4. Check for unnamed elements
|
|
66
|
+
const productTypes = ['IFCWALL', 'IFCSLAB', 'IFCCOLUMN', 'IFCBEAM', 'IFCDOOR', 'IFCWINDOW',
|
|
67
|
+
'IFCSTAIR', 'IFCROOF', 'IFCSPACE', 'IFCRAILING', 'IFCMEMBER', 'IFCPLATE', 'IFCFOOTING'];
|
|
68
|
+
let unnamedCount = 0;
|
|
69
|
+
for (const pt of productTypes) {
|
|
70
|
+
const ids = store.entityIndex.byType.get(pt) ?? [];
|
|
71
|
+
for (const id of ids) {
|
|
72
|
+
const node = new EntityNode(store, id);
|
|
73
|
+
if (!node.name || node.name === '' || node.name === '$')
|
|
74
|
+
unnamedCount++;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (unnamedCount > 0) {
|
|
78
|
+
issues.push({ severity: 'info', rule: 'named-elements', message: `${unnamedCount} building elements have no Name` });
|
|
79
|
+
}
|
|
80
|
+
// 5. Schema version
|
|
81
|
+
if (!store.schemaVersion) {
|
|
82
|
+
issues.push({ severity: 'warning', rule: 'schema-version', message: 'Could not determine IFC schema version' });
|
|
83
|
+
}
|
|
84
|
+
const summary = {
|
|
85
|
+
file: filePath,
|
|
86
|
+
schema: store.schemaVersion,
|
|
87
|
+
entityCount: store.entityCount,
|
|
88
|
+
valid: issues.filter(i => i.severity === 'error').length === 0,
|
|
89
|
+
errors: issues.filter(i => i.severity === 'error').length,
|
|
90
|
+
warnings: issues.filter(i => i.severity === 'warning').length,
|
|
91
|
+
info: issues.filter(i => i.severity === 'info').length,
|
|
92
|
+
issues,
|
|
93
|
+
};
|
|
94
|
+
if (jsonOutput) {
|
|
95
|
+
printJson(summary);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
const status = summary.valid ? 'VALID' : 'INVALID';
|
|
99
|
+
process.stdout.write(`\n ${status}: ${filePath}\n`);
|
|
100
|
+
process.stdout.write(` Schema: ${store.schemaVersion ?? 'unknown'}\n`);
|
|
101
|
+
process.stdout.write(` Entities: ${store.entityCount}\n\n`);
|
|
102
|
+
for (const issue of issues) {
|
|
103
|
+
const icon = issue.severity === 'error' ? 'ERR' : issue.severity === 'warning' ? 'WRN' : 'INF';
|
|
104
|
+
process.stdout.write(` [${icon}] ${issue.rule}: ${issue.message}\n`);
|
|
105
|
+
}
|
|
106
|
+
process.stdout.write(`\n ${summary.errors} error(s), ${summary.warnings} warning(s), ${summary.info} info\n\n`);
|
|
107
|
+
}
|
|
108
|
+
if (!summary.valid)
|
|
109
|
+
process.exitCode = 1;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HeadlessBackend — BimBackend implementation for CLI (no renderer).
|
|
3
|
+
*
|
|
4
|
+
* Wraps an IfcDataStore parsed from an IFC file and exposes it through
|
|
5
|
+
* the standard BimBackend interface. Viewer-specific operations (colorize,
|
|
6
|
+
* flyTo, etc.) are no-ops.
|
|
7
|
+
*/
|
|
8
|
+
import type { BimBackend, BimEventType, ModelBackendMethods, QueryBackendMethods, SelectionBackendMethods, VisibilityBackendMethods, ViewerBackendMethods, MutateBackendMethods, SpatialBackendMethods, ExportBackendMethods, LensBackendMethods, FilesBackendMethods } from '@ifc-lite/sdk';
|
|
9
|
+
import type { IfcDataStore } from '@ifc-lite/parser';
|
|
10
|
+
export declare class HeadlessBackend implements BimBackend {
|
|
11
|
+
readonly model: ModelBackendMethods;
|
|
12
|
+
readonly query: QueryBackendMethods;
|
|
13
|
+
readonly selection: SelectionBackendMethods;
|
|
14
|
+
readonly visibility: VisibilityBackendMethods;
|
|
15
|
+
readonly viewer: ViewerBackendMethods;
|
|
16
|
+
readonly mutate: MutateBackendMethods;
|
|
17
|
+
readonly spatial: SpatialBackendMethods;
|
|
18
|
+
readonly export: ExportBackendMethods;
|
|
19
|
+
readonly lens: LensBackendMethods;
|
|
20
|
+
readonly files: FilesBackendMethods;
|
|
21
|
+
private store;
|
|
22
|
+
private modelName;
|
|
23
|
+
constructor(store: IfcDataStore, modelName: string);
|
|
24
|
+
subscribe(_event: BimEventType, _handler: (data: unknown) => void): () => void;
|
|
25
|
+
private createModelAdapter;
|
|
26
|
+
private createQueryAdapter;
|
|
27
|
+
private createSelectionAdapter;
|
|
28
|
+
private createVisibilityAdapter;
|
|
29
|
+
private createViewerAdapter;
|
|
30
|
+
private createMutateAdapter;
|
|
31
|
+
private createSpatialAdapter;
|
|
32
|
+
private createExportAdapter;
|
|
33
|
+
private createLensAdapter;
|
|
34
|
+
private createFilesAdapter;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=headless-backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headless-backend.d.ts","sourceRoot":"","sources":["../src/headless-backend.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,EACvB,wBAAwB,EACxB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EAapB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAwErD,qBAAa,eAAgB,YAAW,UAAU;IAChD,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,uBAAuB,CAAC;IAC5C,QAAQ,CAAC,UAAU,EAAE,wBAAwB,CAAC;IAC9C,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,qBAAqB,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAC;IAEpC,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,SAAS,CAAS;gBAEd,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM;IAelD,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI;IAI9E,OAAO,CAAC,kBAAkB;IAmB1B,OAAO,CAAC,kBAAkB;IA+J1B,OAAO,CAAC,sBAAsB;IAQ9B,OAAO,CAAC,uBAAuB;IAS/B,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,mBAAmB;IAY3B,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,mBAAmB;IAoG3B,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,kBAAkB;CAQ3B"}
|