@bldrs-ai/conway 1.379.1191 → 1.381.1195

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 (49) hide show
  1. package/compiled/examples/browser-bundled.cjs +51 -2
  2. package/compiled/examples/cli-bundled.cjs +338 -40
  3. package/compiled/examples/cli-step-bundled.cjs +63 -3
  4. package/compiled/examples/validator-bundled.cjs +51 -2
  5. package/compiled/src/AP214E3_2010/ap214_geometry_extraction.d.ts +12 -0
  6. package/compiled/src/AP214E3_2010/ap214_geometry_extraction.d.ts.map +1 -1
  7. package/compiled/src/AP214E3_2010/ap214_geometry_extraction.js +19 -1
  8. package/compiled/src/cli/cli_progress_renderer.d.ts +28 -14
  9. package/compiled/src/cli/cli_progress_renderer.d.ts.map +1 -1
  10. package/compiled/src/cli/cli_progress_renderer.js +52 -45
  11. package/compiled/src/compat/web-ifc/ifc_api.d.ts +8 -0
  12. package/compiled/src/compat/web-ifc/ifc_api.d.ts.map +1 -1
  13. package/compiled/src/compat/web-ifc/ifc_api_model_passthrough_factory.d.ts +5 -4
  14. package/compiled/src/compat/web-ifc/ifc_api_model_passthrough_factory.d.ts.map +1 -1
  15. package/compiled/src/compat/web-ifc/ifc_api_model_passthrough_factory.js +24 -10
  16. package/compiled/src/compat/web-ifc/ifc_api_proxy_ap214.d.ts +71 -1
  17. package/compiled/src/compat/web-ifc/ifc_api_proxy_ap214.d.ts.map +1 -1
  18. package/compiled/src/compat/web-ifc/ifc_api_proxy_ap214.js +196 -49
  19. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts.map +1 -1
  20. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.js +17 -0
  21. package/compiled/src/compat/web-ifc/index.d.ts +1 -0
  22. package/compiled/src/compat/web-ifc/index.d.ts.map +1 -1
  23. package/compiled/src/compat/web-ifc/index.js +4 -0
  24. package/compiled/src/core/progress_log.d.ts +150 -0
  25. package/compiled/src/core/progress_log.d.ts.map +1 -0
  26. package/compiled/src/core/progress_log.js +293 -0
  27. package/compiled/src/core/progress_log.test.d.ts +2 -0
  28. package/compiled/src/core/progress_log.test.d.ts.map +1 -0
  29. package/compiled/src/core/progress_log.test.js +89 -0
  30. package/compiled/src/ifc/ifc_command_line_main.js +4 -2
  31. package/compiled/src/ifc/ifc_geometry_extraction.d.ts +13 -0
  32. package/compiled/src/ifc/ifc_geometry_extraction.d.ts.map +1 -1
  33. package/compiled/src/ifc/ifc_geometry_extraction.js +20 -1
  34. package/compiled/src/index.d.ts +1 -0
  35. package/compiled/src/index.d.ts.map +1 -1
  36. package/compiled/src/index.js +1 -0
  37. package/compiled/src/loaders/conway_model_loader.d.ts +7 -0
  38. package/compiled/src/loaders/conway_model_loader.d.ts.map +1 -1
  39. package/compiled/src/loaders/conway_model_loader.js +18 -1
  40. package/compiled/src/loaders/loading_utilities.d.ts +13 -1
  41. package/compiled/src/loaders/loading_utilities.d.ts.map +1 -1
  42. package/compiled/src/loaders/loading_utilities.js +44 -0
  43. package/compiled/src/statistics/statistics.d.ts +31 -0
  44. package/compiled/src/statistics/statistics.d.ts.map +1 -1
  45. package/compiled/src/statistics/statistics.js +56 -1
  46. package/compiled/src/version/version.d.ts.map +1 -1
  47. package/compiled/src/version/version.js +1 -1
  48. package/compiled/tsconfig.tsbuildinfo +1 -1
  49. package/package.json +1 -1
@@ -30,7 +30,7 @@ var import_node_process = require("node:process");
30
30
  var readline = __toESM(require("node:readline"), 1);
31
31
 
32
32
  // compiled/src/version/version.js
33
- var versionString = "Conway Web-Ifc Shim v1.379.1191";
33
+ var versionString = "Conway v1.381.1195";
34
34
 
35
35
  // compiled/dependencies/conway-geom/interface/conway_geometry.js
36
36
  var wasmType = "";
@@ -187,6 +187,52 @@ var Statistics = class {
187
187
  setMemoryStatistics(value) {
188
188
  this.memoryStatistics = value;
189
189
  }
190
+ /**
191
+ *
192
+ * @return {number | undefined} - number of products extracted
193
+ */
194
+ getProductCount() {
195
+ return this.productCount;
196
+ }
197
+ /**
198
+ *
199
+ * @param value - number of products extracted
200
+ */
201
+ setProductCount(value) {
202
+ this.productCount = value;
203
+ }
204
+ /**
205
+ *
206
+ * @return {Map<string, number> | undefined} - geometry type breakdown
207
+ * (entity type name -> count of unique geometry definitions extracted)
208
+ */
209
+ getGeometryTypeCounts() {
210
+ return this.geometryTypeCounts;
211
+ }
212
+ /**
213
+ *
214
+ * @param value - geometry type breakdown map
215
+ */
216
+ setGeometryTypeCounts(value) {
217
+ this.geometryTypeCounts = value;
218
+ }
219
+ /**
220
+ * Format the geometry-type breakdown as a compact sorted list, e.g.
221
+ * "IFCEXTRUDEDAREASOLID×3421 IFCFACETEDBREP×212 (+3 more)".
222
+ *
223
+ * @param maxEntries - cap on listed types (rest summarized)
224
+ * @return {string | undefined} the formatted breakdown, if any
225
+ */
226
+ // eslint-disable-next-line no-magic-numbers
227
+ formatGeometryTypeCounts(maxEntries = 12) {
228
+ if (this.geometryTypeCounts === void 0 || this.geometryTypeCounts.size === 0) {
229
+ return void 0;
230
+ }
231
+ const sorted = Array.from(this.geometryTypeCounts.entries()).sort((leftEntry, rightEntry) => rightEntry[1] - leftEntry[1]);
232
+ const shown = sorted.slice(0, maxEntries).map(([name, count]) => `${name}\xD7${count}`).join(" ");
233
+ const remainder = sorted.length - maxEntries;
234
+ return remainder > 0 ? `${shown} (+${remainder} more)` : shown;
235
+ }
190
236
  /**
191
237
  * prints statistics
192
238
  */
@@ -229,7 +275,10 @@ var Statistics = class {
229
275
  } else {
230
276
  versionStr = "Version not defined";
231
277
  }
232
- return `[${dateString}]: Load Status: ${this.loadStatus}, Project Name: ${this.projectName}, Version: ${versionStr}, Conway Version: ${conwayVersionNumber}-${wasmType}, Parse Time: ${this.parseTime} ms, Geometry Time: ${this.geometryTime} ms, Total Time: ${this.totalTime} ms, Geometry Memory: ${this.geometryMemory?.toFixed(3)} MB, Memory Statistics: ${this.memoryStatistics}, Preprocessor Version: ${this.preprocessorVersion}, Originating System: ${this.originatingSystem}`;
278
+ const products = this.productCount !== void 0 ? `Products: ${this.productCount}, ` : "";
279
+ const breakdown = this.formatGeometryTypeCounts();
280
+ const geometryTypes = breakdown !== void 0 ? `, Geometry Types: ${breakdown}` : "";
281
+ return `[${dateString}]: Load Status: ${this.loadStatus}, Project Name: ${this.projectName}, Version: ${versionStr}, Conway Version: ${conwayVersionNumber}-${wasmType}, Parse Time: ${this.parseTime} ms, Geometry Time: ${this.geometryTime} ms, Total Time: ${this.totalTime} ms, Geometry Memory: ${this.geometryMemory?.toFixed(3)} MB, ` + products + `Memory Statistics: ${this.memoryStatistics}, Preprocessor Version: ${this.preprocessorVersion}, Originating System: ${this.originatingSystem}` + geometryTypes;
233
282
  }
234
283
  };
235
284
 
@@ -14965,7 +14965,7 @@ ${t5.join("\n")}` : "";
14965
14965
  var import_process = require("process");
14966
14966
 
14967
14967
  // compiled/src/version/version.js
14968
- var versionString = "Conway Web-Ifc Shim v1.379.1191";
14968
+ var versionString = "Conway v1.381.1195";
14969
14969
 
14970
14970
  // compiled/dependencies/conway-geom/interface/conway_geometry.js
14971
14971
  function pThreadsAllowed() {
@@ -15844,6 +15844,52 @@ var Statistics = class {
15844
15844
  setMemoryStatistics(value) {
15845
15845
  this.memoryStatistics = value;
15846
15846
  }
15847
+ /**
15848
+ *
15849
+ * @return {number | undefined} - number of products extracted
15850
+ */
15851
+ getProductCount() {
15852
+ return this.productCount;
15853
+ }
15854
+ /**
15855
+ *
15856
+ * @param value - number of products extracted
15857
+ */
15858
+ setProductCount(value) {
15859
+ this.productCount = value;
15860
+ }
15861
+ /**
15862
+ *
15863
+ * @return {Map<string, number> | undefined} - geometry type breakdown
15864
+ * (entity type name -> count of unique geometry definitions extracted)
15865
+ */
15866
+ getGeometryTypeCounts() {
15867
+ return this.geometryTypeCounts;
15868
+ }
15869
+ /**
15870
+ *
15871
+ * @param value - geometry type breakdown map
15872
+ */
15873
+ setGeometryTypeCounts(value) {
15874
+ this.geometryTypeCounts = value;
15875
+ }
15876
+ /**
15877
+ * Format the geometry-type breakdown as a compact sorted list, e.g.
15878
+ * "IFCEXTRUDEDAREASOLID×3421 IFCFACETEDBREP×212 (+3 more)".
15879
+ *
15880
+ * @param maxEntries - cap on listed types (rest summarized)
15881
+ * @return {string | undefined} the formatted breakdown, if any
15882
+ */
15883
+ // eslint-disable-next-line no-magic-numbers
15884
+ formatGeometryTypeCounts(maxEntries = 12) {
15885
+ if (this.geometryTypeCounts === void 0 || this.geometryTypeCounts.size === 0) {
15886
+ return void 0;
15887
+ }
15888
+ const sorted = Array.from(this.geometryTypeCounts.entries()).sort((leftEntry, rightEntry) => rightEntry[1] - leftEntry[1]);
15889
+ const shown = sorted.slice(0, maxEntries).map(([name, count]) => `${name}\xD7${count}`).join(" ");
15890
+ const remainder = sorted.length - maxEntries;
15891
+ return remainder > 0 ? `${shown} (+${remainder} more)` : shown;
15892
+ }
15847
15893
  /**
15848
15894
  * prints statistics
15849
15895
  */
@@ -15886,7 +15932,10 @@ var Statistics = class {
15886
15932
  } else {
15887
15933
  versionStr = "Version not defined";
15888
15934
  }
15889
- return `[${dateString}]: Load Status: ${this.loadStatus}, Project Name: ${this.projectName}, Version: ${versionStr}, Conway Version: ${conwayVersionNumber}-${wasmType}, Parse Time: ${this.parseTime} ms, Geometry Time: ${this.geometryTime} ms, Total Time: ${this.totalTime} ms, Geometry Memory: ${this.geometryMemory?.toFixed(3)} MB, Memory Statistics: ${this.memoryStatistics}, Preprocessor Version: ${this.preprocessorVersion}, Originating System: ${this.originatingSystem}`;
15935
+ const products = this.productCount !== void 0 ? `Products: ${this.productCount}, ` : "";
15936
+ const breakdown = this.formatGeometryTypeCounts();
15937
+ const geometryTypes = breakdown !== void 0 ? `, Geometry Types: ${breakdown}` : "";
15938
+ return `[${dateString}]: Load Status: ${this.loadStatus}, Project Name: ${this.projectName}, Version: ${versionStr}, Conway Version: ${conwayVersionNumber}-${wasmType}, Parse Time: ${this.parseTime} ms, Geometry Time: ${this.geometryTime} ms, Total Time: ${this.totalTime} ms, Geometry Memory: ${this.geometryMemory?.toFixed(3)} MB, ` + products + `Memory Statistics: ${this.memoryStatistics}, Preprocessor Version: ${this.preprocessorVersion}, Originating System: ${this.originatingSystem}` + geometryTypes;
15890
15939
  }
15891
15940
  };
15892
15941
 
@@ -87125,6 +87174,7 @@ var IfcGeometryExtraction = class _IfcGeometryExtraction {
87125
87174
  this.circleSegments = 12;
87126
87175
  this.pointBuffer = null;
87127
87176
  this.csgMemoization = true;
87177
+ this.geometryTypeCounts = /* @__PURE__ */ new Map();
87128
87178
  this.csgDepth = 0;
87129
87179
  this.freeVectorPolygonalFaces_ = [];
87130
87180
  this.csgMemoization = !this.lowMemoryMode;
@@ -89748,6 +89798,14 @@ var IfcGeometryExtraction = class _IfcGeometryExtraction {
89748
89798
  this.scene.popTransform();
89749
89799
  }
89750
89800
  }
89801
+ /**
89802
+ * Increment the geometry-type breakdown counter for a type name.
89803
+ *
89804
+ * @param name The entity type name.
89805
+ */
89806
+ countGeometryType(name) {
89807
+ this.geometryTypeCounts.set(name, (this.geometryTypeCounts.get(name) ?? 0) + 1);
89808
+ }
89751
89809
  /**
89752
89810
  * Extract a representation item, including its geometry if necessary,
89753
89811
  * adding it to the current scene walk.
@@ -89779,7 +89837,9 @@ var IfcGeometryExtraction = class _IfcGeometryExtraction {
89779
89837
  }
89780
89838
  if (from instanceof IfcMappedItem) {
89781
89839
  return;
89782
- } else if (from instanceof IfcPolygonalFaceSet) {
89840
+ }
89841
+ this.countGeometryType(entity_types_ifc_gen_default[from.type]);
89842
+ if (from instanceof IfcPolygonalFaceSet) {
89783
89843
  const faceSetResult = this.extractPolygonalFaceSet(from, false, isRelVoid);
89784
89844
  if (faceSetResult !== ExtractResult.COMPLETE) {
89785
89845
  logger_default.warning(`Face set express ID: ${from.expressID} extraction incomplete.`);
@@ -91569,77 +91629,284 @@ var GeometryAggregator = class {
91569
91629
  }
91570
91630
  };
91571
91631
 
91572
- // compiled/src/cli/cli_progress_renderer.js
91573
- var PHASE_LABELS = {
91574
- headerParse: "Parsing header",
91575
- dataParse: "Parsing model data",
91576
- geometry: "Extracting geometry",
91577
- sceneBuild: "Building scene",
91578
- serialize: "Writing output"
91632
+ // compiled/src/core/progress_log.js
91633
+ var STAGE_LABELS = {
91634
+ download: "Download",
91635
+ headerParse: "Parsing",
91636
+ dataParse: "Parsing",
91637
+ geometry: "Geometry",
91638
+ sceneBuild: "Scene",
91639
+ serialize: "Writing",
91640
+ convert: "Convert"
91579
91641
  };
91642
+ var BAR_FULL_DOTS = 16;
91580
91643
  var PERCENT = 100;
91581
- var DEFAULT_NON_TTY_INTERVAL_MS = 2e3;
91582
91644
  var MS_PER_SECOND = 1e3;
91645
+ var SECONDS_DECIMALS = 3;
91646
+ var MB_DECIMALS = 6;
91647
+ function stageLabel(phase) {
91648
+ const known = STAGE_LABELS[phase];
91649
+ if (known !== void 0) {
91650
+ return known;
91651
+ }
91652
+ return phase.charAt(0).toUpperCase() + phase.slice(1);
91653
+ }
91654
+ function formatBar(percent) {
91655
+ if (percent === void 0 || !isFinite(percent)) {
91656
+ return "[...]";
91657
+ }
91658
+ const clamped = Math.max(0, Math.min(PERCENT, percent));
91659
+ const dotCount = Math.round(clamped / PERCENT * BAR_FULL_DOTS);
91660
+ return `[0%${".".repeat(dotCount)}${Math.floor(clamped)}%]`;
91661
+ }
91662
+ function formatSeconds(milliseconds) {
91663
+ return `${(milliseconds / MS_PER_SECOND).toFixed(SECONDS_DECIMALS)}s`;
91664
+ }
91665
+ function formatMb(megabytes) {
91666
+ return megabytes.toFixed(MB_DECIMALS);
91667
+ }
91668
+ function formatModelLine(info) {
91669
+ const parts = [];
91670
+ if (info.schema !== void 0 && info.schema !== "") {
91671
+ parts.push(info.schema);
91672
+ }
91673
+ if (info.byteLength !== void 0) {
91674
+ parts.push(`${(info.byteLength / (1024 * 1024)).toFixed(1)} MB`);
91675
+ }
91676
+ if (info.originatingSystem !== void 0 && info.originatingSystem !== "") {
91677
+ const preprocessor = info.preprocessorVersion !== void 0 && info.preprocessorVersion !== "" ? ` (${info.preprocessorVersion})` : "";
91678
+ parts.push(`${info.originatingSystem}${preprocessor}`);
91679
+ } else if (info.preprocessorVersion !== void 0 && info.preprocessorVersion !== "") {
91680
+ parts.push(info.preprocessorVersion);
91681
+ }
91682
+ const name = info.fileName !== void 0 && info.fileName !== "" ? info.fileName : "(unnamed)";
91683
+ const detail = parts.length > 0 ? ` \u2014 ${parts.join(", ")}` : "";
91684
+ return `Model: ${name}${detail}`;
91685
+ }
91686
+ function heapDeltaSuffix(state) {
91687
+ if (state.startHeapMb === void 0 || state.lastHeapMb === void 0) {
91688
+ return "";
91689
+ }
91690
+ const delta = state.lastHeapMb - state.startHeapMb;
91691
+ const sign = delta >= 0 ? "+" : "-";
91692
+ return `, ${sign}${formatMb(Math.abs(delta))} MB heap`;
91693
+ }
91694
+ function formatStageLine(state, final) {
91695
+ const duration = state.lastElapsedMs - state.startElapsedMs;
91696
+ const heap = heapDeltaSuffix(state);
91697
+ const determinate = state.percent !== void 0;
91698
+ if (final && !(determinate && state.percent < PERCENT)) {
91699
+ return `${state.label}: ${formatSeconds(duration)}${heap}`;
91700
+ }
91701
+ const bar = formatBar(determinate ? state.percent : void 0);
91702
+ return `${state.label} ${bar} ${formatSeconds(duration)}${heap}`;
91703
+ }
91704
+ var LoadLogAccumulator = class {
91705
+ constructor() {
91706
+ this.finished_ = [];
91707
+ this.lastElapsedMs_ = 0;
91708
+ }
91709
+ /**
91710
+ * Record the model line (from header info) — kept with the report.
91711
+ *
91712
+ * @param info The model header info.
91713
+ * @return {string} The formatted model line.
91714
+ */
91715
+ setModelInfo(info) {
91716
+ this.modelLine_ = formatModelLine(info);
91717
+ return this.modelLine_;
91718
+ }
91719
+ /**
91720
+ * Feed one progress event; returns the finished stage's line when this
91721
+ * event closed a stage (so callers can mirror it to a console/log once).
91722
+ *
91723
+ * @param event The progress event.
91724
+ * @return {string | undefined} The line for a just-finished stage, if any.
91725
+ */
91726
+ onProgress(event) {
91727
+ const label = stageLabel(event.phase);
91728
+ this.firstElapsedMs_ ??= event.elapsedMs;
91729
+ this.lastElapsedMs_ = event.elapsedMs;
91730
+ if (event.memoryMb !== void 0) {
91731
+ this.firstHeapMb_ ??= event.memoryMb;
91732
+ this.lastHeapMb_ = event.memoryMb;
91733
+ }
91734
+ let closedLine;
91735
+ if (this.current_ === void 0 || this.current_.label !== label) {
91736
+ closedLine = this.closeCurrentStage(event.elapsedMs, event.memoryMb);
91737
+ this.current_ = {
91738
+ label,
91739
+ startElapsedMs: event.elapsedMs,
91740
+ lastElapsedMs: event.elapsedMs,
91741
+ startHeapMb: event.memoryMb,
91742
+ lastHeapMb: event.memoryMb
91743
+ };
91744
+ }
91745
+ const current = this.current_;
91746
+ current.lastElapsedMs = event.elapsedMs;
91747
+ if (event.memoryMb !== void 0) {
91748
+ current.startHeapMb ??= event.memoryMb;
91749
+ current.lastHeapMb = event.memoryMb;
91750
+ }
91751
+ if (event.total !== void 0 && event.total > 0) {
91752
+ current.percent = event.completed / event.total * PERCENT;
91753
+ }
91754
+ return closedLine;
91755
+ }
91756
+ /**
91757
+ * Close any open stage (e.g. at load end) and freeze its line. When an
91758
+ * end point is given, the stage is extended to it first (a stage ends
91759
+ * when the next begins, or when the load finishes).
91760
+ *
91761
+ * @param atElapsedMs Elapsed ms to extend the stage to before freezing.
91762
+ * @param atMemoryMb Heap MB to extend the stage to before freezing.
91763
+ * @return {string | undefined} The closed stage's line, if one was open.
91764
+ */
91765
+ closeCurrentStage(atElapsedMs, atMemoryMb) {
91766
+ if (this.current_ === void 0) {
91767
+ return void 0;
91768
+ }
91769
+ if (atElapsedMs !== void 0) {
91770
+ this.current_.lastElapsedMs = atElapsedMs;
91771
+ this.lastElapsedMs_ = atElapsedMs;
91772
+ }
91773
+ if (atMemoryMb !== void 0) {
91774
+ this.current_.lastHeapMb = atMemoryMb;
91775
+ this.lastHeapMb_ = atMemoryMb;
91776
+ }
91777
+ const line = formatStageLine(this.current_, true);
91778
+ this.finished_.push(line);
91779
+ this.current_ = void 0;
91780
+ return line;
91781
+ }
91782
+ /**
91783
+ * The live line for the running stage, if any.
91784
+ *
91785
+ * @return {string | undefined} The current stage's animated line.
91786
+ */
91787
+ currentLine() {
91788
+ if (this.current_ === void 0) {
91789
+ return void 0;
91790
+ }
91791
+ return formatStageLine(this.current_, false);
91792
+ }
91793
+ /**
91794
+ * Lines for finished stages, in completion order.
91795
+ *
91796
+ * @return {string[]} The frozen stage lines.
91797
+ */
91798
+ finishedLines() {
91799
+ return this.finished_.slice();
91800
+ }
91801
+ /**
91802
+ * The separate before/after Total line: overall wall clock and heap
91803
+ * observation, not a sum of stages.
91804
+ *
91805
+ * @return {string} e.g. "Total: 44.7s, 512 → 1110 MB heap"
91806
+ */
91807
+ totalLine() {
91808
+ const duration = this.lastElapsedMs_ - (this.firstElapsedMs_ ?? 0);
91809
+ let heap = "";
91810
+ if (this.firstHeapMb_ !== void 0 && this.lastHeapMb_ !== void 0) {
91811
+ heap = `, ${formatMb(this.firstHeapMb_)} \u2192 ${formatMb(this.lastHeapMb_)} MB heap`;
91812
+ }
91813
+ return `Total: ${formatSeconds(duration)}${heap}`;
91814
+ }
91815
+ /**
91816
+ * The full report: model line (if known), finished stage lines, then the
91817
+ * Total line. Call closeCurrentStage() first at load end.
91818
+ *
91819
+ * @return {string[]} All report lines.
91820
+ */
91821
+ allLines() {
91822
+ const lines = [];
91823
+ if (this.modelLine_ !== void 0) {
91824
+ lines.push(this.modelLine_);
91825
+ }
91826
+ lines.push(...this.finished_);
91827
+ lines.push(this.totalLine());
91828
+ return lines;
91829
+ }
91830
+ };
91831
+
91832
+ // compiled/src/cli/cli_progress_renderer.js
91833
+ var DEFAULT_NON_TTY_INTERVAL_MS = 2e3;
91583
91834
  var CliProgressRenderer = class {
91584
91835
  /**
91585
91836
  * Construct this against an output stream.
91586
91837
  *
91587
91838
  * @param out The stream to render to (default stderr).
91588
- * @param nonTtyIntervalMs Minimum ms between lines when not a TTY.
91839
+ * @param nonTtyIntervalMs Minimum ms between live lines when not a TTY.
91589
91840
  */
91590
91841
  constructor(out = process.stderr, nonTtyIntervalMs = DEFAULT_NON_TTY_INTERVAL_MS) {
91591
91842
  this.out = out;
91592
91843
  this.nonTtyIntervalMs = nonTtyIntervalMs;
91844
+ this.log = new LoadLogAccumulator();
91593
91845
  this.lastLineLength = 0;
91594
91846
  this.lastPrintTime = 0;
91595
91847
  this.onProgress = (event) => {
91848
+ const closedLine = this.log.onProgress(event);
91849
+ if (closedLine !== void 0) {
91850
+ this.freezeLine(closedLine);
91851
+ }
91852
+ const currentLine = this.log.currentLine();
91853
+ if (currentLine === void 0) {
91854
+ return;
91855
+ }
91596
91856
  const now = Date.now();
91597
- const phaseChanged = event.phase !== this.lastPhase;
91598
- if (!this.out.isTTY && !phaseChanged && now - this.lastPrintTime < this.nonTtyIntervalMs) {
91857
+ if (!this.out.isTTY && now - this.lastPrintTime < this.nonTtyIntervalMs) {
91599
91858
  return;
91600
91859
  }
91601
- this.lastPhase = event.phase;
91602
91860
  this.lastPrintTime = now;
91603
- const line = this.format(event);
91604
91861
  if (this.out.isTTY) {
91605
- const padded = line.padEnd(this.lastLineLength);
91606
- this.lastLineLength = line.length;
91862
+ const padded = currentLine.padEnd(this.lastLineLength);
91863
+ this.lastLineLength = currentLine.length;
91607
91864
  this.out.write(`\r${padded}`);
91608
91865
  } else {
91609
- this.out.write(`${line}
91866
+ this.out.write(`${currentLine}
91610
91867
  `);
91611
91868
  }
91612
91869
  };
91613
91870
  }
91614
91871
  /**
91615
- * Finish rendering — terminates the TTY status line so subsequent output
91616
- * (log table, statistics) starts on a fresh line.
91872
+ * Print the early model line (from header info).
91873
+ *
91874
+ * @param info The model header info.
91617
91875
  */
91618
- done() {
91619
- if (this.out.isTTY && this.lastLineLength > 0) {
91620
- this.out.write("\n");
91876
+ onModelInfo(info) {
91877
+ const line = this.log.setModelInfo(info);
91878
+ this.freezeLine(line);
91879
+ }
91880
+ /**
91881
+ * Finish rendering: freeze any running stage's line and print the
91882
+ * separate before/after Total line.
91883
+ *
91884
+ * @param atElapsedMs Optional load-end elapsed ms, so the final stage's
91885
+ * duration covers the time until the load finished (not just until its
91886
+ * last progress event).
91887
+ * @param atMemoryMb Optional load-end heap MB.
91888
+ */
91889
+ done(atElapsedMs, atMemoryMb) {
91890
+ const closedLine = this.log.closeCurrentStage(atElapsedMs, atMemoryMb);
91891
+ if (closedLine !== void 0) {
91892
+ this.freezeLine(closedLine);
91621
91893
  }
91622
- this.lastLineLength = 0;
91623
- this.lastPhase = void 0;
91894
+ this.freezeLine(this.log.totalLine());
91624
91895
  }
91625
91896
  /**
91626
- * Format one event as a status line.
91897
+ * Print a line permanently, replacing any animated line on a TTY.
91627
91898
  *
91628
- * @param event The progress event.
91629
- * @return {string} e.g. "Extracting geometry 42% (3800/9000 products) 12.4s 512MB"
91899
+ * @param line The line to freeze.
91630
91900
  */
91631
- format(event) {
91632
- const label = PHASE_LABELS[event.phase] ?? event.phase;
91633
- const elapsedSeconds = (event.elapsedMs / MS_PER_SECOND).toFixed(1);
91634
- let counts;
91635
- if (event.total !== void 0 && event.total > 0) {
91636
- const percent = Math.floor(event.completed / event.total * PERCENT);
91637
- counts = `${percent}% (${event.completed}/${event.total} ${event.unit})`;
91901
+ freezeLine(line) {
91902
+ if (this.out.isTTY && this.lastLineLength > 0) {
91903
+ this.out.write(`\r${line.padEnd(this.lastLineLength)}
91904
+ `);
91638
91905
  } else {
91639
- counts = `${event.completed} ${event.unit}`;
91906
+ this.out.write(`${line}
91907
+ `);
91640
91908
  }
91641
- const memory = event.memoryMb !== void 0 ? ` ${Math.round(event.memoryMb)}MB` : "";
91642
- return `${label} ${counts} ${elapsedSeconds}s${memory}`;
91909
+ this.lastLineLength = 0;
91643
91910
  }
91644
91911
  };
91645
91912
 
@@ -91669,6 +91936,36 @@ function parseFileHeader(input) {
91669
91936
  }
91670
91937
  return result;
91671
91938
  }
91939
+ var FILE_NAME_NAME = 0;
91940
+ var FILE_NAME_PREPROCESSOR = 5;
91941
+ var FILE_NAME_ORIGINATING_SYSTEM = 6;
91942
+ function extractModelInfo(stepHeader, byteLength) {
91943
+ const info = { byteLength };
91944
+ const schemaRaw = stepHeader.headers.get("FILE_SCHEMA");
91945
+ if (schemaRaw !== void 0) {
91946
+ const match = schemaRaw.match(/'([^']+)'/);
91947
+ info.schema = match !== null ? match[1] : schemaRaw;
91948
+ }
91949
+ let fileNameRaw = stepHeader.headers.get("FILE_NAME");
91950
+ if (fileNameRaw !== void 0) {
91951
+ fileNameRaw = fileNameRaw.substring(1, fileNameRaw.length - 1);
91952
+ const fields = parseFileHeader(fileNameRaw);
91953
+ const unquote = (value) => {
91954
+ if (value === void 0) {
91955
+ return void 0;
91956
+ }
91957
+ const trimmed = value.trim();
91958
+ return trimmed.replace(/^'/, "").replace(/'$/, "");
91959
+ };
91960
+ const name = unquote(fields[FILE_NAME_NAME]);
91961
+ if (name !== void 0 && name !== "") {
91962
+ info.fileName = name;
91963
+ }
91964
+ info.preprocessorVersion = unquote(fields[FILE_NAME_PREPROCESSOR]);
91965
+ info.originatingSystem = unquote(fields[FILE_NAME_ORIGINATING_SYSTEM]);
91966
+ }
91967
+ return info;
91968
+ }
91672
91969
 
91673
91970
  // compiled/src/ifc/ifc_command_line_main.js
91674
91971
  var modelID = 0;
@@ -91825,6 +92122,7 @@ function doWork() {
91825
92122
  tracker?.beginPhase("headerParse", "bytes", indexIfcBuffer.length);
91826
92123
  const [stepHeader, result0] = parser210.parseHeader(bufferInput);
91827
92124
  const headerDataTimeEnd = Date.now();
92125
+ progressRenderer?.onModelInfo(extractModelInfo(stepHeader, indexIfcBuffer.length));
91828
92126
  switch (result0) {
91829
92127
  case ParseResult.COMPLETE:
91830
92128
  break;
@@ -91967,7 +92265,7 @@ function doWork() {
91967
92265
  }
91968
92266
  statistics.setMemoryStatistics(Memory.checkMemoryUsage());
91969
92267
  }
91970
- progressRenderer?.done();
92268
+ progressRenderer?.done(Date.now() - allTimeStart, Memory.usedHeapMb());
91971
92269
  logger_default.displayLogs();
91972
92270
  logger_default.printStatistics(modelID);
91973
92271
  }).help().argv;
@@ -15912,7 +15912,7 @@ var ParsingBuffer = class {
15912
15912
  };
15913
15913
 
15914
15914
  // compiled/src/version/version.js
15915
- var versionString = "Conway Web-Ifc Shim v1.379.1191";
15915
+ var versionString = "Conway v1.381.1195";
15916
15916
 
15917
15917
  // compiled/dependencies/conway-geom/interface/conway_geometry.js
15918
15918
  function pThreadsAllowed() {
@@ -16791,6 +16791,52 @@ var Statistics = class {
16791
16791
  setMemoryStatistics(value) {
16792
16792
  this.memoryStatistics = value;
16793
16793
  }
16794
+ /**
16795
+ *
16796
+ * @return {number | undefined} - number of products extracted
16797
+ */
16798
+ getProductCount() {
16799
+ return this.productCount;
16800
+ }
16801
+ /**
16802
+ *
16803
+ * @param value - number of products extracted
16804
+ */
16805
+ setProductCount(value) {
16806
+ this.productCount = value;
16807
+ }
16808
+ /**
16809
+ *
16810
+ * @return {Map<string, number> | undefined} - geometry type breakdown
16811
+ * (entity type name -> count of unique geometry definitions extracted)
16812
+ */
16813
+ getGeometryTypeCounts() {
16814
+ return this.geometryTypeCounts;
16815
+ }
16816
+ /**
16817
+ *
16818
+ * @param value - geometry type breakdown map
16819
+ */
16820
+ setGeometryTypeCounts(value) {
16821
+ this.geometryTypeCounts = value;
16822
+ }
16823
+ /**
16824
+ * Format the geometry-type breakdown as a compact sorted list, e.g.
16825
+ * "IFCEXTRUDEDAREASOLID×3421 IFCFACETEDBREP×212 (+3 more)".
16826
+ *
16827
+ * @param maxEntries - cap on listed types (rest summarized)
16828
+ * @return {string | undefined} the formatted breakdown, if any
16829
+ */
16830
+ // eslint-disable-next-line no-magic-numbers
16831
+ formatGeometryTypeCounts(maxEntries = 12) {
16832
+ if (this.geometryTypeCounts === void 0 || this.geometryTypeCounts.size === 0) {
16833
+ return void 0;
16834
+ }
16835
+ const sorted = Array.from(this.geometryTypeCounts.entries()).sort((leftEntry, rightEntry) => rightEntry[1] - leftEntry[1]);
16836
+ const shown = sorted.slice(0, maxEntries).map(([name, count]) => `${name}\xD7${count}`).join(" ");
16837
+ const remainder = sorted.length - maxEntries;
16838
+ return remainder > 0 ? `${shown} (+${remainder} more)` : shown;
16839
+ }
16794
16840
  /**
16795
16841
  * prints statistics
16796
16842
  */
@@ -16833,7 +16879,10 @@ var Statistics = class {
16833
16879
  } else {
16834
16880
  versionStr = "Version not defined";
16835
16881
  }
16836
- return `[${dateString}]: Load Status: ${this.loadStatus}, Project Name: ${this.projectName}, Version: ${versionStr}, Conway Version: ${conwayVersionNumber}-${wasmType}, Parse Time: ${this.parseTime} ms, Geometry Time: ${this.geometryTime} ms, Total Time: ${this.totalTime} ms, Geometry Memory: ${this.geometryMemory?.toFixed(3)} MB, Memory Statistics: ${this.memoryStatistics}, Preprocessor Version: ${this.preprocessorVersion}, Originating System: ${this.originatingSystem}`;
16882
+ const products = this.productCount !== void 0 ? `Products: ${this.productCount}, ` : "";
16883
+ const breakdown = this.formatGeometryTypeCounts();
16884
+ const geometryTypes = breakdown !== void 0 ? `, Geometry Types: ${breakdown}` : "";
16885
+ return `[${dateString}]: Load Status: ${this.loadStatus}, Project Name: ${this.projectName}, Version: ${versionStr}, Conway Version: ${conwayVersionNumber}-${wasmType}, Parse Time: ${this.parseTime} ms, Geometry Time: ${this.geometryTime} ms, Total Time: ${this.totalTime} ms, Geometry Memory: ${this.geometryMemory?.toFixed(3)} MB, ` + products + `Memory Statistics: ${this.memoryStatistics}, Preprocessor Version: ${this.preprocessorVersion}, Originating System: ${this.originatingSystem}` + geometryTypes;
16837
16886
  }
16838
16887
  };
16839
16888
 
@@ -81151,6 +81200,7 @@ var AP214GeometryExtraction = class _AP214GeometryExtraction {
81151
81200
  this.csgMemoization = true;
81152
81201
  this.csgDepth = 0;
81153
81202
  this.freeVectorPolygonalFaces_ = [];
81203
+ this.geometryTypeCounts = /* @__PURE__ */ new Map();
81154
81204
  this.csgMemoization = !this.lowMemoryMode;
81155
81205
  this.materials = model.materials;
81156
81206
  this.scene = new AP214SceneBuilder(model, conwayModel, this.materials);
@@ -82655,6 +82705,14 @@ var AP214GeometryExtraction = class _AP214GeometryExtraction {
82655
82705
  this.scene.popTransform();
82656
82706
  }
82657
82707
  }
82708
+ /**
82709
+ * Increment the geometry-type breakdown counter for a type name.
82710
+ *
82711
+ * @param name The entity type name.
82712
+ */
82713
+ countGeometryType(name) {
82714
+ this.geometryTypeCounts.set(name, (this.geometryTypeCounts.get(name) ?? 0) + 1);
82715
+ }
82658
82716
  /**
82659
82717
  * Extract a representation item, including its geometry if necessary,
82660
82718
  * adding it to the current scene walk.
@@ -82681,7 +82739,9 @@ var AP214GeometryExtraction = class _AP214GeometryExtraction {
82681
82739
  }
82682
82740
  if (from instanceof mapped_item) {
82683
82741
  return;
82684
- } else if (from instanceof boolean_result) {
82742
+ }
82743
+ this.countGeometryType(entity_types_ap214_gen_default[from.type]);
82744
+ if (from instanceof boolean_result) {
82685
82745
  this.extractBooleanResult(from);
82686
82746
  } else if (from instanceof extruded_area_solid) {
82687
82747
  this.extractExtrudedAreaSolid(from, false);