@ifc-lite/cli 0.21.1 → 0.23.1

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.
Files changed (71) hide show
  1. package/dist/commands/clash.d.ts.map +1 -1
  2. package/dist/commands/clash.js +88 -46
  3. package/dist/commands/clash.js.map +1 -1
  4. package/dist/commands/diagnose-geometry.d.ts.map +1 -1
  5. package/dist/commands/diagnose-geometry.js +28 -22
  6. package/dist/commands/diagnose-geometry.js.map +1 -1
  7. package/dist/commands/diff-content.d.ts +11 -0
  8. package/dist/commands/diff-content.d.ts.map +1 -0
  9. package/dist/commands/diff-content.js +270 -0
  10. package/dist/commands/diff-content.js.map +1 -0
  11. package/dist/commands/diff-engine.d.ts +23 -0
  12. package/dist/commands/diff-engine.d.ts.map +1 -0
  13. package/dist/commands/diff-engine.js +159 -0
  14. package/dist/commands/diff-engine.js.map +1 -0
  15. package/dist/commands/diff-scope.d.ts +77 -0
  16. package/dist/commands/diff-scope.d.ts.map +1 -0
  17. package/dist/commands/diff-scope.js +160 -0
  18. package/dist/commands/diff-scope.js.map +1 -0
  19. package/dist/commands/diff-test-helpers.d.ts +70 -0
  20. package/dist/commands/diff-test-helpers.d.ts.map +1 -0
  21. package/dist/commands/diff-test-helpers.js +203 -0
  22. package/dist/commands/diff-test-helpers.js.map +1 -0
  23. package/dist/commands/diff.d.ts +1 -0
  24. package/dist/commands/diff.d.ts.map +1 -1
  25. package/dist/commands/diff.js +71 -25
  26. package/dist/commands/diff.js.map +1 -1
  27. package/dist/commands/eval.d.ts.map +1 -1
  28. package/dist/commands/eval.js +7 -3
  29. package/dist/commands/eval.js.map +1 -1
  30. package/dist/commands/export.d.ts.map +1 -1
  31. package/dist/commands/export.js +45 -16
  32. package/dist/commands/export.js.map +1 -1
  33. package/dist/commands/extract-entities.d.ts.map +1 -1
  34. package/dist/commands/extract-entities.js +8 -2
  35. package/dist/commands/extract-entities.js.map +1 -1
  36. package/dist/commands/gym/channels.d.ts.map +1 -1
  37. package/dist/commands/gym/channels.js +4 -3
  38. package/dist/commands/gym/channels.js.map +1 -1
  39. package/dist/commands/gym.d.ts.map +1 -1
  40. package/dist/commands/gym.js +77 -62
  41. package/dist/commands/gym.js.map +1 -1
  42. package/dist/commands/layer-push.d.ts.map +1 -1
  43. package/dist/commands/layer-push.js +2 -0
  44. package/dist/commands/layer-push.js.map +1 -1
  45. package/dist/commands/query.d.ts +30 -0
  46. package/dist/commands/query.d.ts.map +1 -1
  47. package/dist/commands/query.js +32 -17
  48. package/dist/commands/query.js.map +1 -1
  49. package/dist/commands/schema.d.ts.map +1 -1
  50. package/dist/commands/schema.js +23 -2
  51. package/dist/commands/schema.js.map +1 -1
  52. package/dist/commands/validate.d.ts.map +1 -1
  53. package/dist/commands/validate.js +36 -5
  54. package/dist/commands/validate.js.map +1 -1
  55. package/dist/hbjson-export.d.ts.map +1 -1
  56. package/dist/hbjson-export.js +27 -24
  57. package/dist/hbjson-export.js.map +1 -1
  58. package/dist/headless-backend.d.ts.map +1 -1
  59. package/dist/headless-backend.js +44 -4
  60. package/dist/headless-backend.js.map +1 -1
  61. package/dist/index.js +6 -13
  62. package/dist/index.js.map +1 -1
  63. package/dist/output.d.ts +8 -0
  64. package/dist/output.d.ts.map +1 -1
  65. package/dist/output.js +21 -0
  66. package/dist/output.js.map +1 -1
  67. package/dist/version.d.ts +14 -0
  68. package/dist/version.d.ts.map +1 -0
  69. package/dist/version.js +38 -0
  70. package/dist/version.js.map +1 -0
  71. package/package.json +20 -19
@@ -0,0 +1,203 @@
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
+ /** Shared STEP fixtures for the `diff --by-content` test suites (issue #1891). */
5
+ /** A 22-character IFC GlobalId from a short mnemonic. */
6
+ export function guid(mnemonic) {
7
+ return (mnemonic + '0'.repeat(22)).slice(0, 22);
8
+ }
9
+ /** A minimal but real model: project, units, context, storey, two named walls
10
+ * with a spatial containment relation. `wallA`/`wallB` are the GlobalIds, so a
11
+ * "re-export" is the same call with different ones. */
12
+ export function model(wallA, wallB) {
13
+ return `ISO-10303-21;
14
+ HEADER;
15
+ FILE_DESCRIPTION((''),'2;1');
16
+ FILE_NAME('m','2026',(''),(''),'','','');
17
+ FILE_SCHEMA(('IFC4'));
18
+ ENDSEC;
19
+ DATA;
20
+ #1= IFCPROJECT('${guid('PROJ')}',$,'Proj',$,$,$,$,(#20),#30);
21
+ #20= IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-5,#21,$);
22
+ #21= IFCAXIS2PLACEMENT3D(#22,$,$);
23
+ #22= IFCCARTESIANPOINT((0.,0.,0.));
24
+ #30= IFCUNITASSIGNMENT((#31));
25
+ #31= IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
26
+ #40= IFCLOCALPLACEMENT($,#21);
27
+ #41= IFCBUILDINGSTOREY('${guid('STOR')}',$,'L01',$,$,#40,$,$,.ELEMENT.,0.);
28
+ #50= IFCLOCALPLACEMENT(#40,#21);
29
+ #60= IFCRECTANGLEPROFILEDEF(.AREA.,$,#21,2.,0.2);
30
+ #61= IFCEXTRUDEDAREASOLID(#60,#21,#62,3.);
31
+ #62= IFCDIRECTION((0.,0.,1.));
32
+ #63= IFCSHAPEREPRESENTATION(#20,'Body','SweptSolid',(#61));
33
+ #64= IFCPRODUCTDEFINITIONSHAPE($,$,(#63));
34
+ #70= IFCWALL('${wallA}',$,'Wall A',$,$,#50,#64,'tagA',$);
35
+ #71= IFCWALL('${wallB}',$,'Wall B',$,$,#50,#64,'tagB',$);
36
+ #80= IFCRELCONTAINEDINSPATIALSTRUCTURE('${guid('RELC')}',$,$,$,(#70,#71),#41);
37
+ ENDSEC;
38
+ END-ISO-10303-21;
39
+ `;
40
+ }
41
+ /**
42
+ * One entity from each `IfcRoot` branch, plus classes that are not `IfcRoot` at
43
+ * all and classes no schema registry knows.
44
+ *
45
+ * - `IfcTask` / `IfcActor` are `IfcObjectDefinition`s the columnar parser does
46
+ * not put in its `EntityTable` (they are not `IfcProduct` subtypes), so their
47
+ * GlobalId has to come from the STEP record.
48
+ * - `IfcRelDefinesByProperties` is an `IfcRelationship` and `IfcPropertySet` is
49
+ * an `IfcPropertyDefinition`: both carry GlobalIds, both stay out.
50
+ * - `IfcMaterial` has no GlobalId at all — its first attribute is a Name, which
51
+ * the parser's positional extraction stores in the table's GlobalId column.
52
+ * - `IfcVendorTask`, `IfcVendorWallType` and `IfcRelVendorLink` are in no schema
53
+ * registry. The parser's two name-based branches (`…TYPE`, `IFCREL…`) still
54
+ * take the last two into its table.
55
+ */
56
+ export function scheduleModel(taskGuid) {
57
+ return `ISO-10303-21;
58
+ HEADER;
59
+ FILE_DESCRIPTION((''),'2;1');
60
+ FILE_NAME('m','2026',(''),(''),'','','');
61
+ FILE_SCHEMA(('IFC4'));
62
+ ENDSEC;
63
+ DATA;
64
+ #1= IFCPROJECT('${guid('PROJ')}',$,'Proj',$,$,$,$,(#20),#30);
65
+ #20= IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-5,#21,$);
66
+ #21= IFCAXIS2PLACEMENT3D(#22,$,$);
67
+ #22= IFCCARTESIANPOINT((0.,0.,0.));
68
+ #30= IFCUNITASSIGNMENT((#31));
69
+ #31= IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
70
+ #40= IFCLOCALPLACEMENT($,#21);
71
+ #41= IFCBUILDINGSTOREY('${guid('STOR')}',$,'L01',$,$,#40,$,$,.ELEMENT.,0.);
72
+ #70= IFCWALL('${guid('WALL')}',$,'Wall A',$,$,#40,$,'tagA',$);
73
+ #80= IFCMATERIAL('brick',$,$);
74
+ #81= IFCPROPERTYSET('${guid('PSET')}',$,'Pset_X',$,(#82));
75
+ #82= IFCPROPERTYSINGLEVALUE('P',$,IFCLABEL('v'),$);
76
+ #83= IFCRELDEFINESBYPROPERTIES('${guid('RELP')}',$,$,$,(#70),#81);
77
+ #90= IFCTASK('${taskGuid}',$,'Pour slab',$,$,$,$,'ID1',$,.F.,$,$,.CONSTRUCTION.);
78
+ #91= IFCACTOR('${guid('ACTR')}',$,'Site manager',$,$,#92,$);
79
+ #92= IFCPERSON($,'Doe','Jane',$,$,$,$,$);
80
+ #96= IFCRELCONTAINEDINSPATIALSTRUCTURE('${guid('RELC')}',$,$,$,(#70),#41);
81
+ #97= IFCVENDORTASK('${guid('VEND')}',$,'Custom',$);
82
+ #98= IFCVENDORWALLTYPE('${guid('VTYP')}',$,'Custom type',$,$,$,$,$,$,$);
83
+ #99= IFCRELVENDORLINK('${guid('VREL')}',$,$,$,(#70),#41);
84
+ ENDSEC;
85
+ END-ISO-10303-21;
86
+ `;
87
+ }
88
+ /**
89
+ * An IFC2X3 file whose objects are classes IFC4 dropped, so the parser's IFC4
90
+ * codegen pin knows none of them.
91
+ *
92
+ * - `IfcMove` (an `IfcTask` subtype) and `IfcSpaceProgram` (an `IfcControl`)
93
+ * are `IfcObjectDefinition`s with real GlobalIds in slot 0, and are not
94
+ * `IfcProduct`s, so the `EntityTable` does not hold them.
95
+ * - `IfcSymbolStyle` is a *resource*: no GlobalId at all, a Name in slot 0. Its
96
+ * class name ends in `STYLE`, which is one of the parser's two name-based
97
+ * branches, so the table does hold it — with `hatch` in the GlobalId column.
98
+ * - `IfcGasTerminalType` is a real `IfcTypeObject`, reached through the other
99
+ * name-based branch (`…TYPE`).
100
+ *
101
+ * Deciding membership from the IFC4 pin alone gets all three wrong at once.
102
+ */
103
+ export function legacyScheduleModel(moveGuid) {
104
+ return `ISO-10303-21;
105
+ HEADER;
106
+ FILE_DESCRIPTION((''),'2;1');
107
+ FILE_NAME('m','2026',(''),(''),'','','');
108
+ FILE_SCHEMA(('IFC2X3'));
109
+ ENDSEC;
110
+ DATA;
111
+ #1= IFCPROJECT('${guid('PROJ')}',$,'Proj',$,$,$,$,(#20),#30);
112
+ #20= IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-5,#21,$);
113
+ #21= IFCAXIS2PLACEMENT3D(#22,$,$);
114
+ #22= IFCCARTESIANPOINT((0.,0.,0.));
115
+ #30= IFCUNITASSIGNMENT((#31));
116
+ #31= IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
117
+ #40= IFCLOCALPLACEMENT($,#21);
118
+ #41= IFCBUILDINGSTOREY('${guid('STOR')}',$,'L01',$,$,#40,$,$,.ELEMENT.,0.);
119
+ #70= IFCWALLSTANDARDCASE('${guid('WALL')}',$,'Wall A',$,$,#40,$,'tagA');
120
+ #90= IFCMOVE('${moveGuid}',$,'Move A',$,$,'ID1',$,$,.F.,$,#41,#41,$);
121
+ #91= IFCSPACEPROGRAM('${guid('SPGM')}',$,'Program A',$,$,'SP1',$,$,$,$);
122
+ #92= IFCSYMBOLSTYLE('hatch',#93);
123
+ #93= IFCDEFINEDSYMBOL($,$);
124
+ #94= IFCGASTERMINALTYPE('${guid('GTTY')}',$,'GT',$,$,$,$,$,$,.GASAPPLIANCE.);
125
+ #96= IFCRELCONTAINEDINSPATIALSTRUCTURE('${guid('RELC')}',$,$,$,(#70),#41);
126
+ ENDSEC;
127
+ END-ISO-10303-21;
128
+ `;
129
+ }
130
+ /**
131
+ * The `Tag` scoping fixture (issue #2021), in both directions at once.
132
+ *
133
+ * Two `IfcWallType`s that agree on everything the fingerprint hashed before
134
+ * `Tag` did — same Name, same ElementType, same PredefinedType, no properties —
135
+ * and differ only in `Tag`. That is Duplex's eight `'800 mm'`
136
+ * `IfcFurnitureType`s reduced to two, and a type object has no geometry hash,
137
+ * so before #2021 nothing could separate them.
138
+ *
139
+ * Two `IfcWall`s built the same way, differing only in `Tag`. An occurrence's
140
+ * `Tag` is the authoring tool's element id rather than design content, so it
141
+ * must stay OUT of the hash — these two must keep hashing identically.
142
+ */
143
+ export function typeTagModel() {
144
+ return `ISO-10303-21;
145
+ HEADER;
146
+ FILE_DESCRIPTION((''),'2;1');
147
+ FILE_NAME('m','2026',(''),(''),'','','');
148
+ FILE_SCHEMA(('IFC4'));
149
+ ENDSEC;
150
+ DATA;
151
+ #1= IFCPROJECT('${guid('PROJ')}',$,'Proj',$,$,$,$,(#20),#30);
152
+ #20= IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-5,#21,$);
153
+ #21= IFCAXIS2PLACEMENT3D(#22,$,$);
154
+ #22= IFCCARTESIANPOINT((0.,0.,0.));
155
+ #30= IFCUNITASSIGNMENT((#31));
156
+ #31= IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
157
+ #40= IFCLOCALPLACEMENT($,#21);
158
+ #41= IFCBUILDINGSTOREY('${guid('STOR')}',$,'L01',$,$,#40,$,$,.ELEMENT.,0.);
159
+ #50= IFCWALLTYPE('${guid('TYPA')}',$,'800 mm',$,$,$,$,'157200','800 mm',.STANDARD.);
160
+ #51= IFCWALLTYPE('${guid('TYPB')}',$,'800 mm',$,$,$,$,'157607','800 mm',.STANDARD.);
161
+ #70= IFCWALL('${guid('WALA')}',$,'Wall',$,$,#40,$,'tagA',.STANDARD.);
162
+ #71= IFCWALL('${guid('WALB')}',$,'Wall',$,$,#40,$,'tagB',.STANDARD.);
163
+ #80= IFCRELCONTAINEDINSPATIALSTRUCTURE('${guid('RELC')}',$,$,$,(#70,#71),#41);
164
+ ENDSEC;
165
+ END-ISO-10303-21;
166
+ `;
167
+ }
168
+ /**
169
+ * The same `Tag` question on a class the IFC4 codegen pin does not carry.
170
+ *
171
+ * `IfcRailType` is IFC4X3-only. Its inheritance chain resolves across the
172
+ * bundled schemas, so it is correctly in scope and correctly an `IfcTypeObject`
173
+ * — but its *attribute names* do not resolve through the pinned registry
174
+ * (`getAttributeNames('IfcRailType')` is empty, `getAttributeNamesAcrossSchemas`
175
+ * gives all ten with `Tag` at index 7). A `Tag` lookup that goes through the pin
176
+ * therefore finds nothing and silently no-ops on exactly the infrastructure
177
+ * classes IFC4X3 exists for, while passing every test written against IFC2X3 and
178
+ * IFC4. Same pinned-registry family as #2001/#2003.
179
+ */
180
+ export function railTypeModel() {
181
+ return `ISO-10303-21;
182
+ HEADER;
183
+ FILE_DESCRIPTION((''),'2;1');
184
+ FILE_NAME('m','2026',(''),(''),'','','');
185
+ FILE_SCHEMA(('IFC4X3'));
186
+ ENDSEC;
187
+ DATA;
188
+ #1= IFCPROJECT('${guid('PROJ')}',$,'Proj',$,$,$,$,(#20),#30);
189
+ #20= IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-5,#21,$);
190
+ #21= IFCAXIS2PLACEMENT3D(#22,$,$);
191
+ #22= IFCCARTESIANPOINT((0.,0.,0.));
192
+ #30= IFCUNITASSIGNMENT((#31));
193
+ #31= IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
194
+ #50= IFCRAILTYPE('${guid('RALA')}',$,'60E1',$,$,$,$,'157200','60E1',.RACKRAIL.);
195
+ #51= IFCRAILTYPE('${guid('RALB')}',$,'60E1',$,$,$,$,'157607','60E1',.RACKRAIL.);
196
+ ENDSEC;
197
+ END-ISO-10303-21;
198
+ `;
199
+ }
200
+ export const BASE_MODEL = model(guid('OLDA'), guid('OLDB'));
201
+ /** Same building, re-exported: the two walls carry brand-new GlobalIds. */
202
+ export const HEAD_MODEL = model(guid('NEWA'), guid('NEWB'));
203
+ //# sourceMappingURL=diff-test-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-test-helpers.js","sourceRoot":"","sources":["../../src/commands/diff-test-helpers.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D,kFAAkF;AAElF,yDAAyD;AACzD,MAAM,UAAU,IAAI,CAAC,QAAgB;IACnC,OAAO,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClD,CAAC;AAED;;wDAEwD;AACxD,MAAM,UAAU,KAAK,CAAC,KAAa,EAAE,KAAa;IAChD,OAAO;;;;;;;kBAOS,IAAI,CAAC,MAAM,CAAC;;;;;;;0BAOJ,IAAI,CAAC,MAAM,CAAC;;;;;;;gBAOtB,KAAK;gBACL,KAAK;0CACqB,IAAI,CAAC,MAAM,CAAC;;;CAGrD,CAAC;AACF,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,OAAO;;;;;;;kBAOS,IAAI,CAAC,MAAM,CAAC;;;;;;;0BAOJ,IAAI,CAAC,MAAM,CAAC;gBACtB,IAAI,CAAC,MAAM,CAAC;;uBAEL,IAAI,CAAC,MAAM,CAAC;;kCAED,IAAI,CAAC,MAAM,CAAC;gBAC9B,QAAQ;iBACP,IAAI,CAAC,MAAM,CAAC;;0CAEa,IAAI,CAAC,MAAM,CAAC;sBAChC,IAAI,CAAC,MAAM,CAAC;0BACR,IAAI,CAAC,MAAM,CAAC;yBACb,IAAI,CAAC,MAAM,CAAC;;;CAGpC,CAAC;AACF,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IAClD,OAAO;;;;;;;kBAOS,IAAI,CAAC,MAAM,CAAC;;;;;;;0BAOJ,IAAI,CAAC,MAAM,CAAC;4BACV,IAAI,CAAC,MAAM,CAAC;gBACxB,QAAQ;wBACA,IAAI,CAAC,MAAM,CAAC;;;2BAGT,IAAI,CAAC,MAAM,CAAC;0CACG,IAAI,CAAC,MAAM,CAAC;;;CAGrD,CAAC;AACF,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO;;;;;;;kBAOS,IAAI,CAAC,MAAM,CAAC;;;;;;;0BAOJ,IAAI,CAAC,MAAM,CAAC;oBAClB,IAAI,CAAC,MAAM,CAAC;oBACZ,IAAI,CAAC,MAAM,CAAC;gBAChB,IAAI,CAAC,MAAM,CAAC;gBACZ,IAAI,CAAC,MAAM,CAAC;0CACc,IAAI,CAAC,MAAM,CAAC;;;CAGrD,CAAC;AACF,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO;;;;;;;kBAOS,IAAI,CAAC,MAAM,CAAC;;;;;;oBAMV,IAAI,CAAC,MAAM,CAAC;oBACZ,IAAI,CAAC,MAAM,CAAC;;;CAG/B,CAAC;AACF,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;AAC5D,2EAA2E;AAC3E,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC"}
@@ -1,2 +1,3 @@
1
+ export declare function diffPositionals(args: string[]): string[];
1
2
  export declare function diffCommand(args: string[]): Promise<void>;
2
3
  //# sourceMappingURL=diff.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"AAgBA,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAqG/D"}
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"AAmCA,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAWxD;AAYD,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA8G/D"}
@@ -6,18 +6,75 @@
6
6
  *
7
7
  * Compare two IFC files and report differences in entity counts,
8
8
  * types, and optionally property values.
9
+ *
10
+ * `--by-entity` adds a GlobalId-level added/removed/common count over the
11
+ * entities `diff-scope.ts` decides are comparable, which is the same set
12
+ * `--by-content` fingerprints — one answer about which entities a diff is
13
+ * about, for both modes of the command.
14
+ *
15
+ * `--by-content` switches to the `@ifc-lite/diff` engine with content-keyed
16
+ * matching and the identity-map sidecar (issue #1891) — see `diff-content.ts`.
9
17
  */
10
18
  import { loadIfcFile } from '../loader.js';
11
- import { hasFlag, fatal, printJson, formatTable } from '../output.js';
12
- import { EntityNode } from '@ifc-lite/query';
19
+ import { hasFlag, getFlag, fatal, printJson, formatTable } from '../output.js';
13
20
  import { IFC_ENTITY_NAMES } from '@ifc-lite/data';
21
+ import { contentDiffCommand } from './diff-content.js';
22
+ import { comparableGlobalIds } from './diff-scope.js';
23
+ const USAGE = 'Usage: ifc-lite diff <file1.ifc> <file2.ifc> [--json] [--by-entity]\n' +
24
+ ' [--by-content] [--identity-out <map.json>] [--identity-in <map.json>]';
25
+ /** Flags that consume the following argument, so it is never mistaken for a
26
+ * positional file path. Deliberately only the flags this command owns: the
27
+ * shared `args.filter(a => !a.startsWith('-'))` idiom would have swallowed
28
+ * `--identity-out map.json` as a third file. */
29
+ const VALUE_FLAGS = new Set(['--identity-out', '--identity-in']);
30
+ export function diffPositionals(args) {
31
+ const positional = [];
32
+ for (let i = 0; i < args.length; i++) {
33
+ const arg = args[i];
34
+ if (arg.startsWith('-')) {
35
+ if (VALUE_FLAGS.has(arg))
36
+ i++;
37
+ continue;
38
+ }
39
+ positional.push(arg);
40
+ }
41
+ return positional;
42
+ }
43
+ /** Read a path-valued flag, rejecting a missing value or one that is obviously
44
+ * the next flag — `--identity-out --json` would otherwise write a file called
45
+ * `--json`. */
46
+ function identityPath(args, flag) {
47
+ if (!hasFlag(args, flag))
48
+ return undefined;
49
+ const value = getFlag(args, flag);
50
+ if (value === undefined || value.startsWith('-'))
51
+ fatal(`${flag} requires a file path`);
52
+ return value;
53
+ }
14
54
  export async function diffCommand(args) {
15
- const positional = args.filter(a => !a.startsWith('-'));
16
- if (positional.length < 2)
17
- fatal('Usage: ifc-lite diff <file1.ifc> <file2.ifc> [--json] [--by-type] [--by-entity]');
55
+ const positional = diffPositionals(args);
56
+ // Exactly two, not "at least two". A third path is never a diff the command
57
+ // can do, and silently dropping it is how `diff a.ifc b.ifc c.ifc` comes back
58
+ // with a confident answer about the wrong pair of files.
59
+ if (positional.length !== 2)
60
+ fatal(USAGE);
18
61
  const [file1, file2] = positional;
19
62
  const jsonOutput = hasFlag(args, '--json');
20
63
  const byEntity = hasFlag(args, '--by-entity');
64
+ // The identity-map flags only mean anything on the engine path, so they imply
65
+ // it rather than being silently ignored next to the type-count diff.
66
+ const identityOut = identityPath(args, '--identity-out');
67
+ const identityIn = identityPath(args, '--identity-in');
68
+ if (hasFlag(args, '--by-content') || identityOut !== undefined || identityIn !== undefined) {
69
+ await contentDiffCommand({
70
+ basePath: file1,
71
+ headPath: file2,
72
+ identityIn,
73
+ identityOut,
74
+ json: jsonOutput,
75
+ });
76
+ return;
77
+ }
21
78
  process.stderr.write(`Loading files...\n`);
22
79
  const store1 = await loadIfcFile(file1);
23
80
  const store2 = await loadIfcFile(file2);
@@ -42,27 +99,16 @@ export async function diffCommand(args) {
42
99
  }
43
100
  }
44
101
  typeDiffs.sort((a, b) => Math.abs(b.delta) - Math.abs(a.delta));
45
- // Entity-level comparison by GlobalId
102
+ // Entity-level comparison by GlobalId, over the entities `diff-scope.ts`
103
+ // says are comparable at all. Asking every row of the entity index for a
104
+ // GlobalId instead — which is what this did — answered with a *Name* for
105
+ // every resource entity whose STEP record starts with one, so two materials
106
+ // sharing a name were compared as one entity, and it counted relationships
107
+ // and property sets whose identity belongs to the things they connect.
46
108
  let entityDiff;
47
109
  if (byEntity) {
48
- const globalIds1 = new Set();
49
- const globalIds2 = new Set();
50
- for (const [, ids] of store1.entityIndex.byType) {
51
- for (const id of ids) {
52
- const node = new EntityNode(store1, id);
53
- const gid = node.globalId;
54
- if (gid)
55
- globalIds1.add(gid);
56
- }
57
- }
58
- for (const [, ids] of store2.entityIndex.byType) {
59
- for (const id of ids) {
60
- const node = new EntityNode(store2, id);
61
- const gid = node.globalId;
62
- if (gid)
63
- globalIds2.add(gid);
64
- }
65
- }
110
+ const globalIds1 = comparableGlobalIds(store1);
111
+ const globalIds2 = comparableGlobalIds(store2);
66
112
  const added = [...globalIds2].filter(g => !globalIds1.has(g));
67
113
  const removed = [...globalIds1].filter(g => !globalIds2.has(g));
68
114
  const common = [...globalIds1].filter(g => globalIds2.has(g)).length;
@@ -98,7 +144,7 @@ export async function diffCommand(args) {
98
144
  process.stdout.write(` No type differences.\n`);
99
145
  }
100
146
  if (entityDiff) {
101
- process.stdout.write(`\n Entity comparison (by GlobalId):\n`);
147
+ process.stdout.write(`\n Entity comparison (by GlobalId, every IfcObjectDefinition):\n`);
102
148
  process.stdout.write(` Common: ${entityDiff.common}\n`);
103
149
  process.stdout.write(` Added: ${entityDiff.added.length}\n`);
104
150
  process.stdout.write(` Removed: ${entityDiff.removed.length}\n`);
@@ -1 +1 @@
1
- {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"eval.d.ts","sourceRoot":"","sources":["../../src/commands/eval.ts"],"names":[],"mappings":"AA2BA,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA6G/D"}
1
+ {"version":3,"file":"eval.d.ts","sourceRoot":"","sources":["../../src/commands/eval.ts"],"names":[],"mappings":"AA2BA,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAiH/D"}
@@ -16,7 +16,7 @@
16
16
  * ifc-lite eval model.ifc "bim.query().byType('IfcDoor').toArray().map(d => d.name)"
17
17
  */
18
18
  import { createHeadlessContext, createStreamingContext } from '../loader.js';
19
- import { printJson, fatal, hasFlag, getFlag, validateViewerPort } from '../output.js';
19
+ import { printJson, fatal, hasFlag, getFlag, validateViewerPort, validateLimit } from '../output.js';
20
20
  /** Known flags that take a value argument */
21
21
  const EVAL_VALUE_FLAGS = new Set(['--type', '--limit', '--viewer']);
22
22
  /** Known boolean flags (no value) */
@@ -72,8 +72,12 @@ export async function evalCommand(args) {
72
72
  return 'Ifc' + trimmed;
73
73
  });
74
74
  let entities = bim.query().byType(...types).toArray();
75
- if (limitStr)
76
- entities = entities.slice(0, parseInt(limitStr, 10));
75
+ // Validated, not parseInt'd: a non-numeric --limit yields NaN and
76
+ // slice(0, NaN) returns [], so a typo silently evaluated nothing and
77
+ // reported success. Same guard as export --limit.
78
+ const evalLimit = validateLimit(limitStr);
79
+ if (evalLimit !== undefined)
80
+ entities = entities.slice(0, evalLimit);
77
81
  const results = [];
78
82
  const evalFn = buildEvalFunction(expression, ['bim', 'ref', 'entity']);
79
83
  for (const entity of entities) {
@@ -1 +1 @@
1
- {"version":3,"file":"eval.js","sourceRoot":"","sources":["../../src/commands/eval.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"eval.js","sourceRoot":"","sources":["../../src/commands/eval.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAErG,6CAA6C;AAC7C,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;AACpE,qCAAqC;AACrC,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;AAE/C,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAc;IAC9C,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAC1C,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,kBAAkB,CAAC,aAAa,CAAC,CAAC;IAErD,gEAAgE;IAChE,4EAA4E;IAC5E,0EAA0E;IAC1E,oEAAoE;IACpE,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,aAAa,GAAG,IAAI,CAAC;YACrB,SAAS;QACX,CAAC;QACD,oDAAoD;QACpD,IAAI,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9B,CAAC,EAAE,CAAC,CAAC,kBAAkB;YACvB,SAAS;QACX,CAAC;QACD,IAAI,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC1C,wDAAwD;QACxD,IAAI,CAAC,aAAa,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QACpD,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACrB,wEAAwE;QACxE,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,aAAa,GAAG,IAAI,CAAC;IACpD,CAAC;IAED,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,gDAAgD,CAAC,CAAC;IAEnF,MAAM,CAAC,QAAQ,EAAE,GAAG,SAAS,CAAC,GAAG,UAAU,CAAC;IAC5C,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEvC,wEAAwE;IACxE,uDAAuD;IACvD,MAAM,EAAE,GAAG,EAAE,GAAG,UAAU;QACxB,CAAC,CAAC,MAAM,sBAAsB,CAAC,QAAQ,EAAE,UAAU,CAAC;QACpD,CAAC,CAAC,MAAM,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAE1C,yFAAyF;IACzF,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;YAC1C,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YACzB,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC;gBAAE,OAAO,OAAO,CAAC;YACxG,OAAO,KAAK,GAAG,OAAO,CAAC;QACzB,CAAC,CAAC,CAAC;QACH,IAAI,QAAQ,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;QACtD,kEAAkE;QAClE,qEAAqE;QACrE,kDAAkD;QAClD,MAAM,SAAS,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,SAAS,KAAK,SAAS;YAAE,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;QAErE,MAAM,OAAO,GAAU,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,iBAAiB,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;QAEvE,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;YAC9B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;gBAC/C,MAAM,QAAQ,GAAG,MAAM,YAAY,OAAO,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;gBACnE,OAAO,CAAC,IAAI,CAAC;oBACX,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ;oBACzB,MAAM,EAAE,QAAQ,IAAI,IAAI;iBACzB,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,OAAO,CAAC,IAAI,CAAC;oBACX,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ;oBACzB,KAAK,EAAE,GAAG,CAAC,OAAO;iBACnB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,IAAI,UAAU,EAAE,CAAC;YACf,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QACzB,CAAC;aAAM,CAAC;YACN,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;gBACxB,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;gBAClE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,QAAQ,KAAK,GAAG,IAAI,CAAC,CAAC;YAC5D,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,OAAO,CAAC,MAAM,uBAAuB,CAAC,CAAC;QACnE,CAAC;QACD,OAAO;IACT,CAAC;IAED,wEAAwE;IACxE,MAAM,MAAM,GAAG,iBAAiB,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEtD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAE3B,uBAAuB;QACvB,MAAM,QAAQ,GAAG,MAAM,YAAY,OAAO,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;QAEnE,IAAI,UAAU,EAAE,CAAC;YACf,SAAS,CAAC,EAAE,MAAM,EAAE,QAAQ,IAAI,IAAI,EAAE,CAAC,CAAC;QAC1C,CAAC;aAAM,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YACvD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACjC,CAAC;aAAM,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACxC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,KAAK,CAAC,qBAAqB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,iBAAiB,CAAC,UAAkB,EAAE,UAAoB;IACjE,MAAM,WAAW,GAAG,gFAAgF,CAAC,IAAI,CAAC,UAAU,CAAC;WAChH,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAE9B,IAAI,IAAY,CAAC;IACjB,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC5E,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC/C,MAAM,iBAAiB,GAAG,6EAA6E,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnH,IAAI,CAAC,iBAAiB,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChD,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,WAAW,IAAI,GAAG,CAAC;QACzD,CAAC;aAAM,IAAI,iBAAiB,IAAI,6BAA6B,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACzE,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;YAC7D,IAAI,QAAQ,EAAE,CAAC;gBACb,UAAU,CAAC,IAAI,CAAC,UAAU,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;QACD,IAAI,GAAG,yBAAyB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;IAC/D,CAAC;SAAM,CAAC;QACN,IAAI,GAAG,WAAW,UAAU,GAAG,CAAC;IAClC,CAAC;IAED,OAAO,IAAI,QAAQ,CAAC,GAAG,UAAU,EAAE;;MAE/B,IAAI;GACP,CAAC,CAAC;AACL,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IACzD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC5D,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../src/commands/export.ts"],"names":[],"mappings":"AA+JA,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAyOjE"}
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../src/commands/export.ts"],"names":[],"mappings":"AAuKA,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA2PjE"}
@@ -13,7 +13,7 @@ import { basename } from 'node:path';
13
13
  import { GeometryProcessor, isNoRenderGeometryError } from '@ifc-lite/geometry';
14
14
  import { countGlbMeshes } from '@ifc-lite/export';
15
15
  import { createHeadlessContext } from '../loader.js';
16
- import { getFlag, hasFlag, fatal, writeOutput } from '../output.js';
16
+ import { getFlag, hasFlag, fatal, writeOutput, validateLimit } from '../output.js';
17
17
  import { logger } from '../logger.js';
18
18
  import { formatGeometryReport, NO_DIAGNOSTICS_LINE } from '../geometry-report.js';
19
19
  /**
@@ -121,10 +121,19 @@ function columnValueToCsv(value) {
121
121
  /**
122
122
  * Resolve the raw IFC bytes (parsed store source, or re-read from disk) plus a
123
123
  * one-shot wasm GeometryProcessor for the Rust-backed exporters (OBJ / glTF / JSON-LD).
124
+ *
125
+ * Every Rust exporter below takes the WHOLE file, so the source is genuinely
126
+ * materialised here (#2183). It is handed back rather than scoped through a
127
+ * callback because the caller is one `switch` arm of a single CLI invocation
128
+ * that also runs the optional diagnostics pass over the same bytes; the buffer
129
+ * dies with the command.
124
130
  */
125
131
  async function rustExportContext(store, filePath) {
126
- let bytes = store.source;
127
- if (!bytes || bytes.byteLength === 0) {
132
+ let bytes;
133
+ if (store.source.byteLength > 0) {
134
+ bytes = store.source.materialize();
135
+ }
136
+ else {
128
137
  const buf = await readFile(filePath);
129
138
  bytes = new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
130
139
  }
@@ -154,26 +163,32 @@ export async function exportCommand(args) {
154
163
  const limit = getFlag(args, '--limit');
155
164
  const propFilter = getFlag(args, '--where');
156
165
  const storeyFilter = getFlag(args, '--storey');
166
+ // IFCX and USD are whole-model, geometry-backed exports: they never honor the
167
+ // entity-isolation filters, so an invalid/zero-match filter must NOT abort the
168
+ // export — skip filter processing entirely and just note it below.
169
+ const wholeModelFormat = format === 'ifcx' || format === 'usd';
170
+ const filterRequested = !!(type || propFilter || storeyFilter || limit);
157
171
  if (!filePath)
158
- fatal('Usage: ifc-lite export <file.ifc> --format csv|json|ifc|obj|gltf|glb|jsonld|step|ifcx|hbjson [--type IfcWall] [--columns Name,Type,GlobalId] [--where PsetName.Prop=Value] [--storey Name] [--name Model] [--out file]');
172
+ fatal('Usage: ifc-lite export <file.ifc> --format csv|json|ifc|obj|gltf|glb|jsonld|step|ifcx|usd|hbjson [--type IfcWall] [--columns Name,Type,GlobalId] [--where PsetName.Prop=Value] [--storey Name] [--name Model] [--out file]');
159
173
  // B9/F6: Auto-prefix Ifc
160
174
  if (type) {
161
175
  type = normalizeTypeName(type);
162
176
  }
163
177
  const { bim, store } = await createHeadlessContext(filePath);
164
- // Build entity query
178
+ // Build entity query. Whole-model formats (ifcx/usd) skip all filtering so a bad or
179
+ // zero-match filter can't abort the export.
165
180
  let q = bim.query();
166
- if (type) {
181
+ if (type && !wholeModelFormat) {
167
182
  q = q.byType(...type.split(','));
168
183
  }
169
- if (propFilter) {
184
+ if (propFilter && !wholeModelFormat) {
170
185
  const parsed = parseWhereFilter(propFilter);
171
186
  q = q.where(parsed.psetName, parsed.propName, parsed.operator, parsed.value);
172
187
  }
173
188
  // Don't apply limit to the query yet — storey filtering must happen first
174
189
  let entities = q.toArray();
175
190
  // B4: --storey filter (applied before limit so --limit restricts storey-filtered results)
176
- if (storeyFilter) {
191
+ if (storeyFilter && !wholeModelFormat) {
177
192
  const storeys = bim.storeys();
178
193
  const matchedStorey = storeys.find((s) => s.name === storeyFilter ||
179
194
  s.name.toLowerCase().includes(storeyFilter.toLowerCase()) ||
@@ -186,9 +201,13 @@ export async function exportCommand(args) {
186
201
  const storeyIds = new Set(contained.map((e) => e.ref.expressId));
187
202
  entities = entities.filter((e) => storeyIds.has(e.ref.expressId));
188
203
  }
189
- // Apply limit after storey filtering
190
- if (limit) {
191
- entities = entities.slice(0, parseInt(limit, 10));
204
+ // Apply limit after storey filtering. A non-numeric/negative --limit used
205
+ // to fall through to Array.prototype.slice(0, NaN), which silently returns
206
+ // an empty array — a typo'd flag turned into a zero-row export reported as
207
+ // success. validateLimit() rejects that loudly instead.
208
+ const parsedLimit = validateLimit(limit);
209
+ if (parsedLimit !== undefined) {
210
+ entities = entities.slice(0, parsedLimit);
192
211
  }
193
212
  const refs = entities.map((e) => e.ref);
194
213
  const columns = columnsStr
@@ -252,8 +271,11 @@ export async function exportCommand(args) {
252
271
  case 'glb':
253
272
  case 'jsonld':
254
273
  case 'ifcx':
274
+ case 'usd':
255
275
  case 'step': {
256
- const filterActive = !!(type || propFilter || storeyFilter || limit);
276
+ // Whole-model formats (ifcx/usd) never isolate, so filters were skipped above and
277
+ // must not gate the export here — only the isolating formats treat a filter as active.
278
+ const filterActive = !wholeModelFormat && filterRequested;
257
279
  const isolated = filterActive
258
280
  ? new Uint32Array(refs.map((r) => r.expressId))
259
281
  : new Uint32Array();
@@ -263,9 +285,9 @@ export async function exportCommand(args) {
263
285
  if (filterActive && isolated.length === 0) {
264
286
  fatal('Filter matched 0 entities — nothing to export. Check --type/--storey/--where/--limit.');
265
287
  }
266
- // IFCX is a whole-model USD-style graph; it does not honor the isolation set.
267
- if (filterActive && format === 'ifcx') {
268
- process.stderr.write('Note: --type/--storey/--where/--limit do not apply to IFCX; exporting the whole model.\n');
288
+ // IFCX / USD are whole-model exports; a requested filter is ignored, not an error.
289
+ if (filterRequested && wholeModelFormat) {
290
+ process.stderr.write(`Note: --type/--storey/--where/--limit do not apply to ${format.toUpperCase()}; exporting the whole model.\n`);
269
291
  }
270
292
  // --profile: attribute wall-time between the per-invocation wasm
271
293
  // bootstrap (GeometryProcessor init) and the export itself - the
@@ -284,6 +306,13 @@ export async function exportCommand(args) {
284
306
  fatal('IFCX export failed (geometry pipeline not initialized)');
285
307
  await writeOutput(out, outPath);
286
308
  }
309
+ else if (format === 'usd') {
310
+ // OpenUSD (.usda ASCII) — whole-model Z-up USD stage (geometry-backed).
311
+ const out = gp.exportUsd(bytes);
312
+ if (out == null)
313
+ fatal('USD export failed (geometry pipeline not initialized)');
314
+ await writeOutput(out, outPath);
315
+ }
287
316
  else if (format === 'step') {
288
317
  // Rust faithful re-serialization (+ reference-closed subset when filtered).
289
318
  const schema = getFlag(args, '--schema') ?? '';
@@ -373,7 +402,7 @@ export async function exportCommand(args) {
373
402
  break;
374
403
  }
375
404
  default:
376
- fatal(`Unknown format: ${format}. Supported: csv, json, ifc, obj, gltf, glb, jsonld, step, ifcx, hbjson`);
405
+ fatal(`Unknown format: ${format}. Supported: csv, json, ifc, obj, gltf, glb, jsonld, step, ifcx, usd, hbjson`);
377
406
  }
378
407
  }
379
408
  //# sourceMappingURL=export.js.map