@bldrs-ai/conway 1.389.1221 → 1.394.1504

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 (382) hide show
  1. package/README.md +36 -22
  2. package/compiled/Dist/ConwayGeomWasmNode.js +0 -0
  3. package/compiled/Dist/ConwayGeomWasmNodeMT.js +0 -0
  4. package/compiled/Dist/ConwayGeomWasmWeb.js +0 -0
  5. package/compiled/Dist/ConwayGeomWasmWebMT.js +1 -1
  6. package/compiled/Dist/ConwayGeomWasmWebMT.wasm +0 -0
  7. package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmNode.js +0 -0
  8. package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmNodeMT.js +0 -0
  9. package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWeb.js +0 -0
  10. package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWebMT.js +1 -1
  11. package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWebMT.wasm +0 -0
  12. package/compiled/dependencies/conway-geom/interface/conway_geometry.d.ts +19 -0
  13. package/compiled/dependencies/conway-geom/interface/conway_geometry.d.ts.map +1 -1
  14. package/compiled/dependencies/conway-geom/interface/conway_geometry.js +17 -0
  15. package/compiled/dependencies/conway-geom/interface/parameters/surface_object.d.ts +6 -0
  16. package/compiled/dependencies/conway-geom/interface/parameters/surface_object.d.ts.map +1 -1
  17. package/compiled/examples/browser-bundled.cjs +1569 -51
  18. package/compiled/examples/cli-bundled.cjs +2790 -436
  19. package/compiled/examples/cli-step-bundled.cjs +1904 -229
  20. package/compiled/examples/validator-bundled.cjs +1569 -51
  21. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_curve.gen.d.ts +2 -2
  22. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_curve.gen.d.ts.map +1 -1
  23. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_curve.gen.js +2 -2
  24. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_surface.gen.d.ts +3 -3
  25. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_surface.gen.d.ts.map +1 -1
  26. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_surface.gen.js +3 -3
  27. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/composite_curve.gen.d.ts +1 -1
  28. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/composite_curve.gen.d.ts.map +1 -1
  29. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/composite_curve.gen.js +1 -1
  30. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_2d.gen.d.ts +1 -1
  31. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_2d.gen.d.ts.map +1 -1
  32. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_2d.gen.js +1 -1
  33. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_3d.gen.d.ts +1 -1
  34. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_3d.gen.d.ts.map +1 -1
  35. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_3d.gen.js +1 -1
  36. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_surface.gen.d.ts +1 -1
  37. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_surface.gen.d.ts.map +1 -1
  38. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_surface.gen.js +1 -1
  39. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/presentation_style_assignment.gen.d.ts.map +1 -1
  40. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/presentation_style_assignment.gen.js +2 -2
  41. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/schema_ap214.gen.js +11 -11
  42. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/shape_aspect.gen.d.ts +1 -1
  43. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/shape_aspect.gen.d.ts.map +1 -1
  44. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/shape_aspect.gen.js +1 -1
  45. package/compiled/src/AP214E3_2010/ap214_command_line_main.js +7 -3
  46. package/compiled/src/AP214E3_2010/ap214_geometry_extraction.d.ts +181 -7
  47. package/compiled/src/AP214E3_2010/ap214_geometry_extraction.d.ts.map +1 -1
  48. package/compiled/src/AP214E3_2010/ap214_geometry_extraction.js +906 -137
  49. package/compiled/src/AP214E3_2010/ap214_geometry_extraction.test.js +10 -2
  50. package/compiled/src/AP214E3_2010/ap214_logical_attribute.test.d.ts +2 -0
  51. package/compiled/src/AP214E3_2010/ap214_logical_attribute.test.d.ts.map +1 -0
  52. package/compiled/src/AP214E3_2010/ap214_logical_attribute.test.js +114 -0
  53. package/compiled/src/AP214E3_2010/ap214_model_geometry.d.ts +6 -0
  54. package/compiled/src/AP214E3_2010/ap214_model_geometry.d.ts.map +1 -1
  55. package/compiled/src/AP214E3_2010/ap214_model_geometry.js +9 -0
  56. package/compiled/src/AP214E3_2010/ap214_pcurve_basis_surfaces.test.d.ts +2 -0
  57. package/compiled/src/AP214E3_2010/ap214_pcurve_basis_surfaces.test.d.ts.map +1 -0
  58. package/compiled/src/AP214E3_2010/ap214_pcurve_basis_surfaces.test.js +233 -0
  59. package/compiled/src/AP214E3_2010/ap214_sphere_vertex_loop.test.d.ts +2 -0
  60. package/compiled/src/AP214E3_2010/ap214_sphere_vertex_loop.test.d.ts.map +1 -0
  61. package/compiled/src/AP214E3_2010/ap214_sphere_vertex_loop.test.js +147 -0
  62. package/compiled/src/AP214E3_2010/ap214_step_model.d.ts +2 -1
  63. package/compiled/src/AP214E3_2010/ap214_step_model.d.ts.map +1 -1
  64. package/compiled/src/AP214E3_2010/ap214_step_model.js +1 -1
  65. package/compiled/src/AP214E3_2010/ap214_typed_select_enum.test.d.ts +2 -0
  66. package/compiled/src/AP214E3_2010/ap214_typed_select_enum.test.d.ts.map +1 -0
  67. package/compiled/src/AP214E3_2010/ap214_typed_select_enum.test.js +65 -0
  68. package/compiled/src/AP214E3_2010/ap214_unit_scale.test.d.ts +2 -0
  69. package/compiled/src/AP214E3_2010/ap214_unit_scale.test.d.ts.map +1 -0
  70. package/compiled/src/AP214E3_2010/ap214_unit_scale.test.js +111 -0
  71. package/compiled/src/compat/web-ifc/ap214_streamed_open.test.d.ts +2 -0
  72. package/compiled/src/compat/web-ifc/ap214_streamed_open.test.d.ts.map +1 -0
  73. package/compiled/src/compat/web-ifc/ap214_streamed_open.test.js +190 -0
  74. package/compiled/src/compat/web-ifc/coordination_export_order.test.d.ts +2 -0
  75. package/compiled/src/compat/web-ifc/coordination_export_order.test.d.ts.map +1 -0
  76. package/compiled/src/compat/web-ifc/coordination_export_order.test.js +110 -0
  77. package/compiled/src/compat/web-ifc/coordination_f64.d.ts +165 -0
  78. package/compiled/src/compat/web-ifc/coordination_f64.d.ts.map +1 -0
  79. package/compiled/src/compat/web-ifc/coordination_f64.js +286 -0
  80. package/compiled/src/compat/web-ifc/coordination_f64.test.d.ts +2 -0
  81. package/compiled/src/compat/web-ifc/coordination_f64.test.d.ts.map +1 -0
  82. package/compiled/src/compat/web-ifc/coordination_f64.test.js +225 -0
  83. package/compiled/src/compat/web-ifc/ifc_api.d.ts +154 -0
  84. package/compiled/src/compat/web-ifc/ifc_api.d.ts.map +1 -1
  85. package/compiled/src/compat/web-ifc/ifc_api.js +211 -3
  86. package/compiled/src/compat/web-ifc/ifc_api_deferred_open.test.d.ts +2 -0
  87. package/compiled/src/compat/web-ifc/ifc_api_deferred_open.test.d.ts.map +1 -0
  88. package/compiled/src/compat/web-ifc/ifc_api_deferred_open.test.js +288 -0
  89. package/compiled/src/compat/web-ifc/ifc_api_model_passthrough.d.ts +39 -0
  90. package/compiled/src/compat/web-ifc/ifc_api_model_passthrough.d.ts.map +1 -1
  91. package/compiled/src/compat/web-ifc/ifc_api_model_passthrough_factory.d.ts +30 -0
  92. package/compiled/src/compat/web-ifc/ifc_api_model_passthrough_factory.d.ts.map +1 -1
  93. package/compiled/src/compat/web-ifc/ifc_api_model_passthrough_factory.js +83 -0
  94. package/compiled/src/compat/web-ifc/ifc_api_preview_channel.test.d.ts +2 -0
  95. package/compiled/src/compat/web-ifc/ifc_api_preview_channel.test.d.ts.map +1 -0
  96. package/compiled/src/compat/web-ifc/ifc_api_preview_channel.test.js +383 -0
  97. package/compiled/src/compat/web-ifc/ifc_api_preview_coordination.test.d.ts +2 -0
  98. package/compiled/src/compat/web-ifc/ifc_api_preview_coordination.test.d.ts.map +1 -0
  99. package/compiled/src/compat/web-ifc/ifc_api_preview_coordination.test.js +124 -0
  100. package/compiled/src/compat/web-ifc/ifc_api_proxy_ap214.d.ts +132 -0
  101. package/compiled/src/compat/web-ifc/ifc_api_proxy_ap214.d.ts.map +1 -1
  102. package/compiled/src/compat/web-ifc/ifc_api_proxy_ap214.js +488 -92
  103. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts +268 -0
  104. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts.map +1 -1
  105. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.js +996 -149
  106. package/compiled/src/compat/web-ifc/ifc_api_streamed_open.test.d.ts +2 -0
  107. package/compiled/src/compat/web-ifc/ifc_api_streamed_open.test.d.ts.map +1 -0
  108. package/compiled/src/compat/web-ifc/ifc_api_streamed_open.test.js +129 -0
  109. package/compiled/src/compat/web-ifc/spatial_imposter.d.ts +134 -0
  110. package/compiled/src/compat/web-ifc/spatial_imposter.d.ts.map +1 -0
  111. package/compiled/src/compat/web-ifc/spatial_imposter.js +933 -0
  112. package/compiled/src/compat/web-ifc/spatial_imposter.test.d.ts +2 -0
  113. package/compiled/src/compat/web-ifc/spatial_imposter.test.d.ts.map +1 -0
  114. package/compiled/src/compat/web-ifc/spatial_imposter.test.js +467 -0
  115. package/compiled/src/compat/web-ifc/store_preview_channel.d.ts +187 -0
  116. package/compiled/src/compat/web-ifc/store_preview_channel.d.ts.map +1 -0
  117. package/compiled/src/compat/web-ifc/store_preview_channel.js +524 -0
  118. package/compiled/src/compat/web-ifc/store_preview_channel.test.d.ts +2 -0
  119. package/compiled/src/compat/web-ifc/store_preview_channel.test.d.ts.map +1 -0
  120. package/compiled/src/compat/web-ifc/store_preview_channel.test.js +234 -0
  121. package/compiled/src/compat/web-ifc/streamed_preview_channel.d.ts +306 -0
  122. package/compiled/src/compat/web-ifc/streamed_preview_channel.d.ts.map +1 -0
  123. package/compiled/src/compat/web-ifc/streamed_preview_channel.js +580 -0
  124. package/compiled/src/compat/web-ifc/web_wasm_directory.test.d.ts +2 -0
  125. package/compiled/src/compat/web-ifc/web_wasm_directory.test.d.ts.map +1 -0
  126. package/compiled/src/compat/web-ifc/web_wasm_directory.test.js +22 -0
  127. package/compiled/src/core/composed_model_skeleton.d.ts +63 -0
  128. package/compiled/src/core/composed_model_skeleton.d.ts.map +1 -0
  129. package/compiled/src/core/composed_model_skeleton.js +66 -0
  130. package/compiled/src/core/composed_model_skeleton.test.d.ts +2 -0
  131. package/compiled/src/core/composed_model_skeleton.test.d.ts.map +1 -0
  132. package/compiled/src/core/composed_model_skeleton.test.js +69 -0
  133. package/compiled/src/core/demand_geometry_queue.d.ts +147 -0
  134. package/compiled/src/core/demand_geometry_queue.d.ts.map +1 -0
  135. package/compiled/src/core/demand_geometry_queue.js +223 -0
  136. package/compiled/src/core/demand_geometry_queue.test.d.ts +2 -0
  137. package/compiled/src/core/demand_geometry_queue.test.d.ts.map +1 -0
  138. package/compiled/src/core/demand_geometry_queue.test.js +133 -0
  139. package/compiled/src/core/demand_residency_pump.d.ts +93 -0
  140. package/compiled/src/core/demand_residency_pump.d.ts.map +1 -0
  141. package/compiled/src/core/demand_residency_pump.js +120 -0
  142. package/compiled/src/core/demand_residency_pump.test.d.ts +2 -0
  143. package/compiled/src/core/demand_residency_pump.test.d.ts.map +1 -0
  144. package/compiled/src/core/demand_residency_pump.test.js +148 -0
  145. package/compiled/src/core/geometry_tile_bindings.d.ts +110 -0
  146. package/compiled/src/core/geometry_tile_bindings.d.ts.map +1 -0
  147. package/compiled/src/core/geometry_tile_bindings.js +76 -0
  148. package/compiled/src/core/geometry_tile_bindings.test.d.ts +2 -0
  149. package/compiled/src/core/geometry_tile_bindings.test.d.ts.map +1 -0
  150. package/compiled/src/core/geometry_tile_bindings.test.js +211 -0
  151. package/compiled/src/core/geometry_tile_pool.d.ts +99 -0
  152. package/compiled/src/core/geometry_tile_pool.d.ts.map +1 -0
  153. package/compiled/src/core/geometry_tile_pool.js +104 -0
  154. package/compiled/src/core/geometry_tile_pool.test.d.ts +2 -0
  155. package/compiled/src/core/geometry_tile_pool.test.d.ts.map +1 -0
  156. package/compiled/src/core/geometry_tile_pool.test.js +180 -0
  157. package/compiled/src/core/mem/chunked_pool.d.ts +116 -0
  158. package/compiled/src/core/mem/chunked_pool.d.ts.map +1 -0
  159. package/compiled/src/core/mem/chunked_pool.js +149 -0
  160. package/compiled/src/core/mem/chunked_pool.test.d.ts +2 -0
  161. package/compiled/src/core/mem/chunked_pool.test.d.ts.map +1 -0
  162. package/compiled/src/core/mem/chunked_pool.test.js +63 -0
  163. package/compiled/src/core/mem/shared_asset_pool.d.ts +82 -0
  164. package/compiled/src/core/mem/shared_asset_pool.d.ts.map +1 -0
  165. package/compiled/src/core/mem/shared_asset_pool.js +113 -0
  166. package/compiled/src/core/mem/shared_asset_pool.test.d.ts +2 -0
  167. package/compiled/src/core/mem/shared_asset_pool.test.d.ts.map +1 -0
  168. package/compiled/src/core/mem/shared_asset_pool.test.js +49 -0
  169. package/compiled/src/core/model_registry.d.ts +87 -0
  170. package/compiled/src/core/model_registry.d.ts.map +1 -0
  171. package/compiled/src/core/model_registry.js +101 -0
  172. package/compiled/src/core/model_registry.test.d.ts +2 -0
  173. package/compiled/src/core/model_registry.test.d.ts.map +1 -0
  174. package/compiled/src/core/model_registry.test.js +60 -0
  175. package/compiled/src/core/model_uri.d.ts +57 -0
  176. package/compiled/src/core/model_uri.d.ts.map +1 -0
  177. package/compiled/src/core/model_uri.js +101 -0
  178. package/compiled/src/core/model_uri.test.d.ts +2 -0
  179. package/compiled/src/core/model_uri.test.d.ts.map +1 -0
  180. package/compiled/src/core/model_uri.test.js +49 -0
  181. package/compiled/src/core/progress.d.ts +16 -2
  182. package/compiled/src/core/progress.d.ts.map +1 -1
  183. package/compiled/src/core/progress.js +31 -5
  184. package/compiled/src/core/progress.test.js +11 -2
  185. package/compiled/src/core/progress_log.d.ts +1 -0
  186. package/compiled/src/core/progress_log.d.ts.map +1 -1
  187. package/compiled/src/core/progress_log.js +7 -2
  188. package/compiled/src/core/progress_log.test.js +21 -0
  189. package/compiled/src/core/shared_byte_budget.d.ts +60 -0
  190. package/compiled/src/core/shared_byte_budget.d.ts.map +1 -0
  191. package/compiled/src/core/shared_byte_budget.js +85 -0
  192. package/compiled/src/core/shared_byte_budget.test.d.ts +2 -0
  193. package/compiled/src/core/shared_byte_budget.test.d.ts.map +1 -0
  194. package/compiled/src/core/shared_byte_budget.test.js +55 -0
  195. package/compiled/src/core/wasm_heap.d.ts +208 -0
  196. package/compiled/src/core/wasm_heap.d.ts.map +1 -0
  197. package/compiled/src/core/wasm_heap.js +417 -0
  198. package/compiled/src/core/wasm_heap.test.d.ts +2 -0
  199. package/compiled/src/core/wasm_heap.test.d.ts.map +1 -0
  200. package/compiled/src/core/wasm_heap.test.js +546 -0
  201. package/compiled/src/demand/index.d.ts +23 -0
  202. package/compiled/src/demand/index.d.ts.map +1 -0
  203. package/compiled/src/demand/index.js +22 -0
  204. package/compiled/src/ifc/ifc4_gen/IfcLogical.gen.d.ts +1 -1
  205. package/compiled/src/ifc/ifc4_gen/IfcLogical.gen.d.ts.map +1 -1
  206. package/compiled/src/ifc/ifc4_gen/IfcLogical.gen.js +1 -1
  207. package/compiled/src/ifc/ifc4_gen/IfcPresentationStyleAssignment.gen.d.ts.map +1 -1
  208. package/compiled/src/ifc/ifc4_gen/IfcPresentationStyleAssignment.gen.js +2 -2
  209. package/compiled/src/ifc/ifc4_gen/IfcRelInterferesElements.gen.d.ts +1 -1
  210. package/compiled/src/ifc/ifc4_gen/IfcRelInterferesElements.gen.d.ts.map +1 -1
  211. package/compiled/src/ifc/ifc4_gen/IfcRelInterferesElements.gen.js +1 -1
  212. package/compiled/src/ifc/ifc4_gen/schema_ifc.gen.js +2 -2
  213. package/compiled/src/ifc/ifc_demand_extraction.test.d.ts +2 -0
  214. package/compiled/src/ifc/ifc_demand_extraction.test.d.ts.map +1 -0
  215. package/compiled/src/ifc/ifc_demand_extraction.test.js +251 -0
  216. package/compiled/src/ifc/ifc_geometry_extraction.d.ts +367 -6
  217. package/compiled/src/ifc/ifc_geometry_extraction.d.ts.map +1 -1
  218. package/compiled/src/ifc/ifc_geometry_extraction.js +1322 -389
  219. package/compiled/src/ifc/ifc_grid_placement.test.d.ts +2 -0
  220. package/compiled/src/ifc/ifc_grid_placement.test.d.ts.map +1 -0
  221. package/compiled/src/ifc/ifc_grid_placement.test.js +261 -0
  222. package/compiled/src/ifc/ifc_model_geometry.d.ts +12 -0
  223. package/compiled/src/ifc/ifc_model_geometry.d.ts.map +1 -1
  224. package/compiled/src/ifc/ifc_model_geometry.js +15 -0
  225. package/compiled/src/ifc/ifc_regression_batch_main.js +210 -12
  226. package/compiled/src/ifc/ifc_spatial_skeleton.d.ts +145 -0
  227. package/compiled/src/ifc/ifc_spatial_skeleton.d.ts.map +1 -0
  228. package/compiled/src/ifc/ifc_spatial_skeleton.js +266 -0
  229. package/compiled/src/ifc/ifc_spatial_skeleton.test.d.ts +2 -0
  230. package/compiled/src/ifc/ifc_spatial_skeleton.test.d.ts.map +1 -0
  231. package/compiled/src/ifc/ifc_spatial_skeleton.test.js +199 -0
  232. package/compiled/src/ifc/ifc_step_model.d.ts +6 -2
  233. package/compiled/src/ifc/ifc_step_model.d.ts.map +1 -1
  234. package/compiled/src/ifc/ifc_step_model.js +6 -4
  235. package/compiled/src/ifc/ifc_step_parser.d.ts +58 -0
  236. package/compiled/src/ifc/ifc_step_parser.d.ts.map +1 -1
  237. package/compiled/src/ifc/ifc_step_parser.js +64 -0
  238. package/compiled/src/ifc/ifc_stream_model.test.d.ts +2 -0
  239. package/compiled/src/ifc/ifc_stream_model.test.d.ts.map +1 -0
  240. package/compiled/src/ifc/ifc_stream_model.test.js +70 -0
  241. package/compiled/src/ifc/ifc_stream_open.d.ts +131 -0
  242. package/compiled/src/ifc/ifc_stream_open.d.ts.map +1 -0
  243. package/compiled/src/ifc/ifc_stream_open.js +116 -0
  244. package/compiled/src/ifc/ifc_stream_open.test.d.ts +2 -0
  245. package/compiled/src/ifc/ifc_stream_open.test.d.ts.map +1 -0
  246. package/compiled/src/ifc/ifc_stream_open.test.js +230 -0
  247. package/compiled/src/ifc/ifc_tile_extractor.d.ts +84 -0
  248. package/compiled/src/ifc/ifc_tile_extractor.d.ts.map +1 -0
  249. package/compiled/src/ifc/ifc_tile_extractor.js +134 -0
  250. package/compiled/src/ifc/ifc_tile_extractor.test.d.ts +2 -0
  251. package/compiled/src/ifc/ifc_tile_extractor.test.d.ts.map +1 -0
  252. package/compiled/src/ifc/ifc_tile_extractor.test.js +118 -0
  253. package/compiled/src/ifc/ifc_typed_select_enum.test.d.ts +2 -0
  254. package/compiled/src/ifc/ifc_typed_select_enum.test.d.ts.map +1 -0
  255. package/compiled/src/ifc/ifc_typed_select_enum.test.js +60 -0
  256. package/compiled/src/index.d.ts +21 -1
  257. package/compiled/src/index.d.ts.map +1 -1
  258. package/compiled/src/index.js +28 -1
  259. package/compiled/src/logging/logger.d.ts +16 -2
  260. package/compiled/src/logging/logger.d.ts.map +1 -1
  261. package/compiled/src/logging/logger.js +34 -7
  262. package/compiled/src/logging/logger.test.js +30 -0
  263. package/compiled/src/mem/index.d.ts +17 -0
  264. package/compiled/src/mem/index.d.ts.map +1 -0
  265. package/compiled/src/mem/index.js +16 -0
  266. package/compiled/src/namespace_surface.test.d.ts +2 -0
  267. package/compiled/src/namespace_surface.test.d.ts.map +1 -0
  268. package/compiled/src/namespace_surface.test.js +43 -0
  269. package/compiled/src/parsing/parsing_buffer.d.ts +23 -0
  270. package/compiled/src/parsing/parsing_buffer.d.ts.map +1 -1
  271. package/compiled/src/parsing/parsing_buffer.js +31 -0
  272. package/compiled/src/scripts/model_report_displacement.test.d.ts +2 -0
  273. package/compiled/src/scripts/model_report_displacement.test.d.ts.map +1 -0
  274. package/compiled/src/scripts/model_report_displacement.test.js +104 -0
  275. package/compiled/src/scripts/render_glb_paths.test.d.ts +2 -0
  276. package/compiled/src/scripts/render_glb_paths.test.d.ts.map +1 -0
  277. package/compiled/src/scripts/render_glb_paths.test.js +115 -0
  278. package/compiled/src/step/indexing/step_type_indexer.d.ts +20 -0
  279. package/compiled/src/step/indexing/step_type_indexer.d.ts.map +1 -1
  280. package/compiled/src/step/indexing/step_type_indexer.js +67 -0
  281. package/compiled/src/step/parsing/byte_source.d.ts +153 -0
  282. package/compiled/src/step/parsing/byte_source.d.ts.map +1 -0
  283. package/compiled/src/step/parsing/byte_source.js +106 -0
  284. package/compiled/src/step/parsing/byte_source.test.d.ts +2 -0
  285. package/compiled/src/step/parsing/byte_source.test.d.ts.map +1 -0
  286. package/compiled/src/step/parsing/byte_source.test.js +47 -0
  287. package/compiled/src/step/parsing/byte_source_node.d.ts +41 -0
  288. package/compiled/src/step/parsing/byte_source_node.d.ts.map +1 -0
  289. package/compiled/src/step/parsing/byte_source_node.js +54 -0
  290. package/compiled/src/step/parsing/columnar_index.d.ts +103 -0
  291. package/compiled/src/step/parsing/columnar_index.d.ts.map +1 -0
  292. package/compiled/src/step/parsing/columnar_index.js +224 -0
  293. package/compiled/src/step/parsing/columnar_index.test.d.ts +2 -0
  294. package/compiled/src/step/parsing/columnar_index.test.d.ts.map +1 -0
  295. package/compiled/src/step/parsing/columnar_index.test.js +155 -0
  296. package/compiled/src/step/parsing/cross_reference_registry.d.ts +95 -0
  297. package/compiled/src/step/parsing/cross_reference_registry.d.ts.map +1 -0
  298. package/compiled/src/step/parsing/cross_reference_registry.js +91 -0
  299. package/compiled/src/step/parsing/cross_reference_registry.test.d.ts +2 -0
  300. package/compiled/src/step/parsing/cross_reference_registry.test.d.ts.map +1 -0
  301. package/compiled/src/step/parsing/cross_reference_registry.test.js +66 -0
  302. package/compiled/src/step/parsing/decode_utf8.d.ts +15 -0
  303. package/compiled/src/step/parsing/decode_utf8.d.ts.map +1 -1
  304. package/compiled/src/step/parsing/decode_utf8.js +28 -0
  305. package/compiled/src/step/parsing/express_ref_scan.d.ts +20 -0
  306. package/compiled/src/step/parsing/express_ref_scan.d.ts.map +1 -0
  307. package/compiled/src/step/parsing/express_ref_scan.js +91 -0
  308. package/compiled/src/step/parsing/express_ref_scan.test.d.ts +2 -0
  309. package/compiled/src/step/parsing/express_ref_scan.test.d.ts.map +1 -0
  310. package/compiled/src/step/parsing/express_ref_scan.test.js +28 -0
  311. package/compiled/src/step/parsing/index_sidecar.d.ts +81 -0
  312. package/compiled/src/step/parsing/index_sidecar.d.ts.map +1 -0
  313. package/compiled/src/step/parsing/index_sidecar.js +283 -0
  314. package/compiled/src/step/parsing/index_sidecar.test.d.ts +2 -0
  315. package/compiled/src/step/parsing/index_sidecar.test.d.ts.map +1 -0
  316. package/compiled/src/step/parsing/index_sidecar.test.js +122 -0
  317. package/compiled/src/step/parsing/inf_recovery_index.test.d.ts +2 -0
  318. package/compiled/src/step/parsing/inf_recovery_index.test.d.ts.map +1 -0
  319. package/compiled/src/step/parsing/inf_recovery_index.test.js +108 -0
  320. package/compiled/src/step/parsing/prefix_type_index.d.ts +124 -0
  321. package/compiled/src/step/parsing/prefix_type_index.d.ts.map +1 -0
  322. package/compiled/src/step/parsing/prefix_type_index.js +207 -0
  323. package/compiled/src/step/parsing/prefix_type_index.test.d.ts +2 -0
  324. package/compiled/src/step/parsing/prefix_type_index.test.d.ts.map +1 -0
  325. package/compiled/src/step/parsing/prefix_type_index.test.js +298 -0
  326. package/compiled/src/step/parsing/range_byte_source.d.ts +69 -0
  327. package/compiled/src/step/parsing/range_byte_source.d.ts.map +1 -0
  328. package/compiled/src/step/parsing/range_byte_source.js +78 -0
  329. package/compiled/src/step/parsing/range_byte_source.test.d.ts +2 -0
  330. package/compiled/src/step/parsing/range_byte_source.test.d.ts.map +1 -0
  331. package/compiled/src/step/parsing/range_byte_source.test.js +70 -0
  332. package/compiled/src/step/parsing/record_event.d.ts +23 -0
  333. package/compiled/src/step/parsing/record_event.d.ts.map +1 -0
  334. package/compiled/src/step/parsing/record_event.js +1 -0
  335. package/compiled/src/step/parsing/record_field_cursor.d.ts +94 -0
  336. package/compiled/src/step/parsing/record_field_cursor.d.ts.map +1 -0
  337. package/compiled/src/step/parsing/record_field_cursor.js +189 -0
  338. package/compiled/src/step/parsing/step_deserialization_functions.d.ts +29 -0
  339. package/compiled/src/step/parsing/step_deserialization_functions.d.ts.map +1 -1
  340. package/compiled/src/step/parsing/step_deserialization_functions.js +45 -0
  341. package/compiled/src/step/parsing/step_deserialization_functions.test.js +59 -1
  342. package/compiled/src/step/parsing/step_parser.d.ts +66 -1
  343. package/compiled/src/step/parsing/step_parser.d.ts.map +1 -1
  344. package/compiled/src/step/parsing/step_parser.js +164 -10
  345. package/compiled/src/step/parsing/step_string_parser.js +8 -8
  346. package/compiled/src/step/parsing/streaming_index_builder.d.ts +141 -0
  347. package/compiled/src/step/parsing/streaming_index_builder.d.ts.map +1 -0
  348. package/compiled/src/step/parsing/streaming_index_builder.js +280 -0
  349. package/compiled/src/step/parsing/streaming_index_builder.test.d.ts +2 -0
  350. package/compiled/src/step/parsing/streaming_index_builder.test.d.ts.map +1 -0
  351. package/compiled/src/step/parsing/streaming_index_builder.test.js +107 -0
  352. package/compiled/src/step/parsing/streaming_index_builder_async.test.d.ts +2 -0
  353. package/compiled/src/step/parsing/streaming_index_builder_async.test.d.ts.map +1 -0
  354. package/compiled/src/step/parsing/streaming_index_builder_async.test.js +109 -0
  355. package/compiled/src/step/parsing/streaming_record_dispatcher.d.ts +71 -0
  356. package/compiled/src/step/parsing/streaming_record_dispatcher.d.ts.map +1 -0
  357. package/compiled/src/step/parsing/streaming_record_dispatcher.js +88 -0
  358. package/compiled/src/step/parsing/streaming_record_dispatcher.test.d.ts +2 -0
  359. package/compiled/src/step/parsing/streaming_record_dispatcher.test.d.ts.map +1 -0
  360. package/compiled/src/step/parsing/streaming_record_dispatcher.test.js +66 -0
  361. package/compiled/src/step/parsing/uint32_sink.d.ts +72 -0
  362. package/compiled/src/step/parsing/uint32_sink.d.ts.map +1 -0
  363. package/compiled/src/step/parsing/uint32_sink.js +180 -0
  364. package/compiled/src/step/parsing/uint32_sink.test.d.ts +2 -0
  365. package/compiled/src/step/parsing/uint32_sink.test.d.ts.map +1 -0
  366. package/compiled/src/step/parsing/uint32_sink.test.js +199 -0
  367. package/compiled/src/step/step_buffer_provider.d.ts +48 -3
  368. package/compiled/src/step/step_buffer_provider.d.ts.map +1 -1
  369. package/compiled/src/step/step_buffer_provider.js +60 -11
  370. package/compiled/src/step/step_buffer_provider.test.js +14 -0
  371. package/compiled/src/step/step_entity_base.d.ts +65 -3
  372. package/compiled/src/step/step_entity_base.d.ts.map +1 -1
  373. package/compiled/src/step/step_entity_base.js +135 -3
  374. package/compiled/src/step/step_model_base.d.ts +221 -8
  375. package/compiled/src/step/step_model_base.d.ts.map +1 -1
  376. package/compiled/src/step/step_model_base.js +542 -7
  377. package/compiled/src/stream/index.d.ts +34 -0
  378. package/compiled/src/stream/index.d.ts.map +1 -0
  379. package/compiled/src/stream/index.js +32 -0
  380. package/compiled/src/version/version.js +1 -1
  381. package/compiled/tsconfig.tsbuildinfo +1 -1
  382. package/package.json +16 -1
@@ -0,0 +1,224 @@
1
+ /** Type sentinel for "no concrete type" in the typeID column. */
2
+ export const COLUMN_UNDEFINED_TYPE = -1;
3
+ // Records per growth segment. 64 K rows × 16 B ≈ 1 MB per segment — growth
4
+ // never copies previously written rows, and finalize concatenates one column
5
+ // at a time so the transient overhead is one column's segments, not 2× the
6
+ // index.
7
+ // eslint-disable-next-line no-magic-numbers
8
+ const SEGMENT_ROWS = 64 * 1024;
9
+ /**
10
+ * A {@link StepIndexSink} that encodes top-level records straight into
11
+ * chunked-segment typed-array columns, so the parse holds **no per-record
12
+ * objects** for the (overwhelmingly common) simple records. Records with
13
+ * children keep their object form — inline entities are unfolded into the
14
+ * inline column range at {@link finalize}, and multi-mapping holders are
15
+ * retained for the model's `complexEntries`, matching the object path's
16
+ * behaviour entry-for-entry.
17
+ *
18
+ * `reset` supports the streaming builder's rare grow-and-restart: columns
19
+ * rewind to empty without reallocating the first segment.
20
+ */
21
+ export class ColumnarIndexSink {
22
+ constructor() {
23
+ this.segments_ = [];
24
+ this.count_ = 0;
25
+ /** Entries with inlineEntities and/or multiMapping, keyed by localID. */
26
+ this.retained_ = new Map();
27
+ this.expressIdsSorted_ = true;
28
+ this.previousExpressID_ = 0;
29
+ }
30
+ /**
31
+ * @return {number} Top-level records pushed so far.
32
+ */
33
+ get topLevelCount() {
34
+ return this.count_;
35
+ }
36
+ /**
37
+ * Encode one completed top-level record into the columns. The entry object
38
+ * is not kept unless it carries children (inline entities / multi-mapping).
39
+ *
40
+ * @param entry The completed top-level index entry.
41
+ */
42
+ pushTopLevel(entry) {
43
+ const localID = this.count_++;
44
+ const segmentIndex = Math.floor(localID / SEGMENT_ROWS);
45
+ const row = localID % SEGMENT_ROWS;
46
+ if (segmentIndex === this.segments_.length) {
47
+ this.segments_.push({
48
+ address: new Uint32Array(SEGMENT_ROWS),
49
+ length: new Uint32Array(SEGMENT_ROWS),
50
+ typeID: new Int32Array(SEGMENT_ROWS),
51
+ expressID: new Uint32Array(SEGMENT_ROWS),
52
+ });
53
+ }
54
+ const segment = this.segments_[segmentIndex];
55
+ segment.address[row] = entry.address;
56
+ segment.length[row] = entry.length;
57
+ segment.typeID[row] =
58
+ entry.typeID === void 0 ? COLUMN_UNDEFINED_TYPE : entry.typeID;
59
+ segment.expressID[row] = entry.expressID;
60
+ if (entry.expressID < this.previousExpressID_) {
61
+ this.expressIdsSorted_ = false;
62
+ }
63
+ this.previousExpressID_ = entry.expressID;
64
+ if (entry.inlineEntities !== void 0 || entry.multiMapping !== void 0) {
65
+ this.retained_.set(localID, entry);
66
+ }
67
+ }
68
+ /**
69
+ * Rewind to empty (the streaming builder's grow-and-restart). The first
70
+ * segment is kept for reuse.
71
+ */
72
+ reset() {
73
+ this.segments_.length = Math.min(this.segments_.length, 1);
74
+ this.count_ = 0;
75
+ this.retained_.clear();
76
+ this.expressIdsSorted_ = true;
77
+ this.previousExpressID_ = 0;
78
+ }
79
+ /**
80
+ * Snapshot the columns pushed SO FAR into a self-contained prefix index,
81
+ * without disturbing the sink — the parse can keep pushing afterwards and
82
+ * a later snapshot/finalize sees the full data. Safe to call between the
83
+ * cooperative parse's yields (the parser only suspends at top-level
84
+ * record boundaries, where the sink is consistent). Top-level localIDs
85
+ * are stable across snapshots (dense parse order), so consumers can carry
86
+ * per-localID cursors from one snapshot to the next; inline-range
87
+ * localIDs are NOT stable (the inline tail re-packs after the growing
88
+ * top-level range) and must not be carried across snapshots.
89
+ *
90
+ * @return {StepIndexColumns} A prefix columnar index over the records
91
+ * pushed so far.
92
+ */
93
+ snapshot() {
94
+ return this.assemble_();
95
+ }
96
+ /**
97
+ * Assemble the final columns: concatenate the top-level segments (one
98
+ * column at a time, bounding transient overhead to a single column's
99
+ * segments) and unfold retained inline entities into the inline range in
100
+ * the model's exact unfold order.
101
+ *
102
+ * @return {StepIndexColumns} The finished columnar index.
103
+ */
104
+ finalize() {
105
+ return this.assemble_();
106
+ }
107
+ /**
108
+ * Shared assembly behind {@link snapshot} and {@link finalize} — pure
109
+ * over the sink's current state.
110
+ *
111
+ * @return {StepIndexColumns} The assembled columnar index.
112
+ */
113
+ assemble_() {
114
+ const topLevel = this.count_;
115
+ // Unfold inline entities exactly as StepModelBase does over the object
116
+ // array: scan in localID order appending children, then keep scanning
117
+ // the appended region (children of children follow all first-level
118
+ // children). Only retained entries can contribute — simple records have
119
+ // no children by construction.
120
+ const unfolded = [];
121
+ for (const entry of this.retained_.values()) {
122
+ if (entry.inlineEntities !== void 0) {
123
+ unfolded.push(...entry.inlineEntities);
124
+ }
125
+ }
126
+ for (let where = 0; where < unfolded.length; ++where) {
127
+ const inlineEntities = unfolded[where].inlineEntities;
128
+ if (inlineEntities !== void 0) {
129
+ unfolded.push(...inlineEntities);
130
+ }
131
+ }
132
+ const count = topLevel + unfolded.length;
133
+ const address = concatColumn(this.segments_, 'address', topLevel, count);
134
+ const length = concatColumn(this.segments_, 'length', topLevel, count);
135
+ const typeID = new Int32Array(count);
136
+ for (let segment = 0; segment * SEGMENT_ROWS < topLevel; ++segment) {
137
+ const rows = Math.min(SEGMENT_ROWS, topLevel - segment * SEGMENT_ROWS);
138
+ typeID.set(this.segments_[segment].typeID.subarray(0, rows), segment * SEGMENT_ROWS);
139
+ }
140
+ const expressID = concatColumn(this.segments_, 'expressID', topLevel, topLevel);
141
+ for (let where = 0; where < unfolded.length; ++where) {
142
+ const entry = unfolded[where];
143
+ const row = topLevel + where;
144
+ address[row] = entry.address;
145
+ length[row] = entry.length;
146
+ typeID[row] =
147
+ entry.typeID === void 0 ? COLUMN_UNDEFINED_TYPE : entry.typeID;
148
+ }
149
+ let complexEntries;
150
+ for (const [localID, entry] of this.retained_) {
151
+ if (entry.multiMapping !== void 0) {
152
+ (complexEntries ??= new Map()).set(localID, cloneIndexEntry(entry));
153
+ }
154
+ }
155
+ return {
156
+ address,
157
+ length,
158
+ typeID,
159
+ expressID,
160
+ count,
161
+ firstInlineElement: topLevel,
162
+ complexEntries,
163
+ expressIdsSorted: this.expressIdsSorted_,
164
+ };
165
+ }
166
+ }
167
+ /**
168
+ * Clone an index entry (and its multiMapping sub-entries, which models
169
+ * also stamp) down to the persistent index fields.
170
+ *
171
+ * Models materialise complex entries by writing lazy parse state —
172
+ * vtable views, buffer references, entity instances — onto the entry
173
+ * objects IN PLACE (see StepModelBase.invalidate, which clears exactly
174
+ * those fields). Handing every snapshot/finalize the same retained
175
+ * object therefore let one model poison every other model built over
176
+ * the same sink: a throwaway prefix model (parse-time preview channel)
177
+ * stamped its own vtable views, and the durable model's short-circuit
178
+ * (`vtableIndex !== undefined`) then read stale views — "Value in STEP
179
+ * was incorrectly typed" on AP214's complex-instance transforms.
180
+ * Cloning per assembly keeps each model's lazy state private.
181
+ * `inlineEntities` stays shared: inline records are unfolded into
182
+ * column scalars above and their objects are never stamped.
183
+ *
184
+ * @param entry The retained entry to clone.
185
+ * @return {StepIndexEntryBase} A fresh holder with persistent fields only.
186
+ */
187
+ function cloneIndexEntry(entry) {
188
+ const clone = {
189
+ address: entry.address,
190
+ length: entry.length,
191
+ };
192
+ if (entry.typeID !== void 0) {
193
+ clone.typeID = entry.typeID;
194
+ }
195
+ if (entry.expressID !== void 0) {
196
+ clone.expressID = entry.expressID;
197
+ }
198
+ if (entry.inlineEntities !== void 0) {
199
+ clone.inlineEntities = entry.inlineEntities;
200
+ }
201
+ if (entry.multiMapping !== void 0) {
202
+ clone.multiMapping = entry.multiMapping.map(cloneIndexEntry);
203
+ }
204
+ return clone;
205
+ }
206
+ /**
207
+ * Concatenate one Uint32 column's segments into a final array of
208
+ * `finalLength`, copying `rows` valid rows.
209
+ *
210
+ * @param segments The growth segments.
211
+ * @param column Which column to concatenate.
212
+ * @param rows Valid rows across the segments.
213
+ * @param finalLength Length of the final array (≥ rows; the tail is for
214
+ * inline rows filled by the caller).
215
+ * @return {Uint32Array} The concatenated column.
216
+ */
217
+ function concatColumn(segments, column, rows, finalLength) {
218
+ const result = new Uint32Array(finalLength);
219
+ for (let segment = 0; segment * SEGMENT_ROWS < rows; ++segment) {
220
+ const valid = Math.min(SEGMENT_ROWS, rows - segment * SEGMENT_ROWS);
221
+ result.set(segments[segment][column].subarray(0, valid), segment * SEGMENT_ROWS);
222
+ }
223
+ return result;
224
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=columnar_index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"columnar_index.test.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/columnar_index.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,155 @@
1
+ /* eslint-disable no-magic-numbers, @typescript-eslint/no-explicit-any */
2
+ // M7: the columnar (no-object-phase) index build must produce a model
3
+ // indistinguishable from the object-path build — identical SoA columns,
4
+ // identical lookup behaviour, identical type index — including on AP214
5
+ // fixtures with inline entities and multi-mappings, the paths the object
6
+ // walk handles specially.
7
+ import * as fs from "fs";
8
+ import { describe, expect, test } from "@jest/globals";
9
+ import ParsingBuffer from "../../parsing/parsing_buffer.js";
10
+ import IfcStepParser from "../../ifc/ifc_step_parser.js";
11
+ import IfcStepModel from "../../ifc/ifc_step_model.js";
12
+ import AP214StepParser from "../../AP214E3_2010/ap214_step_parser.js";
13
+ import AP214StepModel from "../../AP214E3_2010/ap214_step_model.js";
14
+ import { BufferByteSource } from "./byte_source.js";
15
+ import { buildColumnarIndexStreaming } from "./streaming_index_builder.js";
16
+ import { ColumnarIndexSink } from "./columnar_index.js";
17
+ import { ParseResult } from "./step_parser.js";
18
+ import { IfcProduct, IfcRoot } from "../../ifc/ifc4_gen/index.js";
19
+ /**
20
+ * Parse a file resident via the object path and return buffer + elements.
21
+ *
22
+ * @param path The file to parse.
23
+ * @param parser The parser instance for its schema.
24
+ * @return {object} `{ bytes, elements }`.
25
+ */
26
+ function objectParse(path, parser) {
27
+ const bytes = new Uint8Array(fs.readFileSync(path));
28
+ const input = new ParsingBuffer(bytes);
29
+ parser.parseHeader(input);
30
+ const [index, result] = parser.parseDataBlock(input);
31
+ expect(result).toBe(ParseResult.COMPLETE);
32
+ return { bytes, elements: index.elements };
33
+ }
34
+ /**
35
+ * Assert two models have byte-identical internal columns and equal type
36
+ * indexes across every type either contains.
37
+ *
38
+ * @param a First model.
39
+ * @param b Second model.
40
+ */
41
+ function expectModelParity(a, b) {
42
+ expect(a.count_).toBe(b.count_);
43
+ expect(a.firstInlineElement_).toBe(b.firstInlineElement_);
44
+ expect(Array.from(a.address_)).toEqual(Array.from(b.address_));
45
+ expect(Array.from(a.length_)).toEqual(Array.from(b.length_));
46
+ expect(Array.from(a.typeID_)).toEqual(Array.from(b.typeID_));
47
+ expect(Array.from(a.expressID_)).toEqual(Array.from(b.expressID_));
48
+ const typesA = new Set(a.typeIndex.types());
49
+ const typesB = new Set(b.typeIndex.types());
50
+ expect(typesA).toEqual(typesB);
51
+ for (const type of typesA) {
52
+ expect(b.typeIndex.count(type)).toBe(a.typeIndex.count(type));
53
+ }
54
+ }
55
+ describe("columnar index build (M7)", () => {
56
+ test("IFC: columnar streamed model matches the object-path model", () => {
57
+ const path = "data/index.ifc";
58
+ const { bytes, elements } = objectParse(path, IfcStepParser.Instance);
59
+ const objectModel = new IfcStepModel(bytes, elements);
60
+ const { columns, result } = buildColumnarIndexStreaming(new BufferByteSource(bytes), IfcStepParser.Instance, 4 * 1024);
61
+ expect(result).toBe(ParseResult.COMPLETE);
62
+ const columnarModel = new IfcStepModel(bytes, columns);
63
+ expectModelParity(objectModel, columnarModel);
64
+ // Behavioural spot checks through the public surface.
65
+ const roots = new Set(objectModel.expressIDsOfTypes(IfcRoot));
66
+ expect(new Set(columnarModel.expressIDsOfTypes(IfcRoot))).toEqual(roots);
67
+ expect(new Set(columnarModel.expressIDsOfTypes(IfcProduct)))
68
+ .toEqual(new Set(objectModel.expressIDsOfTypes(IfcProduct)));
69
+ for (const expressID of roots) {
70
+ expect(columnarModel.getElementByExpressID(expressID)?.expressID)
71
+ .toBe(objectModel.getElementByExpressID(expressID)?.expressID);
72
+ }
73
+ });
74
+ test.each([
75
+ ["as1-oc-214.stp"],
76
+ ["ap214-mapped-item-test.step"],
77
+ ["ap214-multibody-part.step"],
78
+ ])("AP214 (inline/multi-mapping): parity on %s", (name) => {
79
+ const path = `data/${name}`;
80
+ const { bytes, elements } = objectParse(path, AP214StepParser.Instance);
81
+ const objectModel = new AP214StepModel(bytes, elements);
82
+ const { columns, result } = buildColumnarIndexStreaming(new BufferByteSource(bytes), AP214StepParser.Instance, 4 * 1024);
83
+ expect(result).toBe(ParseResult.COMPLETE);
84
+ const columnarModel = new AP214StepModel(bytes, columns);
85
+ // Inline entities must actually be present for these fixtures to prove
86
+ // the unfold path (guard against a silently trivial test).
87
+ if (name !== "as1-oc-214.stp") {
88
+ expect(columnarModel.count_).toBeGreaterThan(columnarModel.firstInlineElement_);
89
+ }
90
+ expectModelParity(objectModel, columnarModel);
91
+ });
92
+ test("the sink drops simple records but retains complex ones", () => {
93
+ const sink = new ColumnarIndexSink();
94
+ sink.pushTopLevel({ address: 0, length: 10, typeID: 5, expressID: 1 });
95
+ sink.pushTopLevel({
96
+ address: 10,
97
+ length: 20,
98
+ typeID: 0,
99
+ expressID: 2,
100
+ multiMapping: [{ address: 12, length: 5, typeID: 7 }],
101
+ });
102
+ const columns = sink.finalize();
103
+ expect(columns.firstInlineElement).toBe(2);
104
+ expect(columns.count).toBe(2);
105
+ expect(columns.complexEntries?.size).toBe(1);
106
+ expect(columns.complexEntries?.get(1)?.multiMapping?.[0].typeID).toBe(7);
107
+ expect(Array.from(columns.typeID)).toEqual([5, 0]);
108
+ });
109
+ test("inline entities unfold in the model object-walk order", () => {
110
+ const sink = new ColumnarIndexSink();
111
+ // Two parents with children; first parent's child itself has a child.
112
+ // Object-path order: parents (0,1), then first-level children in parent
113
+ // order (2 = p0c, 3 = p1c), then second-level (4 = p0c's child).
114
+ sink.pushTopLevel({
115
+ address: 0,
116
+ length: 10,
117
+ typeID: 1,
118
+ expressID: 1,
119
+ inlineEntities: [{
120
+ address: 2,
121
+ length: 3,
122
+ typeID: 10,
123
+ inlineEntities: [{ address: 3, length: 1, typeID: 20 }],
124
+ }],
125
+ });
126
+ sink.pushTopLevel({
127
+ address: 10,
128
+ length: 10,
129
+ typeID: 2,
130
+ expressID: 2,
131
+ inlineEntities: [{ address: 12, length: 3, typeID: 11 }],
132
+ });
133
+ const columns = sink.finalize();
134
+ expect(columns.firstInlineElement).toBe(2);
135
+ expect(columns.count).toBe(5);
136
+ expect(Array.from(columns.typeID)).toEqual([1, 2, 10, 11, 20]);
137
+ expect(Array.from(columns.address)).toEqual([0, 10, 2, 12, 3]);
138
+ });
139
+ test("reset rewinds for the grow-and-restart", () => {
140
+ const sink = new ColumnarIndexSink();
141
+ sink.pushTopLevel({ address: 0, length: 1, typeID: 1, expressID: 9 });
142
+ sink.reset();
143
+ sink.pushTopLevel({ address: 5, length: 2, typeID: 3, expressID: 1 });
144
+ const columns = sink.finalize();
145
+ expect(columns.count).toBe(1);
146
+ expect(Array.from(columns.address)).toEqual([5]);
147
+ expect(columns.expressIdsSorted).toBe(true);
148
+ });
149
+ test("detects unsorted express IDs", () => {
150
+ const sink = new ColumnarIndexSink();
151
+ sink.pushTopLevel({ address: 0, length: 1, typeID: 1, expressID: 10 });
152
+ sink.pushTopLevel({ address: 1, length: 1, typeID: 1, expressID: 5 });
153
+ expect(sink.finalize().expressIdsSorted).toBe(false);
154
+ });
155
+ });
@@ -0,0 +1,95 @@
1
+ import { EntityAddress } from "../../core/model_uri.js";
2
+ import { RecordHandler } from "./streaming_record_dispatcher.js";
3
+ /**
4
+ * Reads the `Location` string of a cross-reference entity by express ID.
5
+ * Implemented over the finished (or partially materialised) model — a thin
6
+ * seam so the registry's link resolution is testable without a full model.
7
+ * `IfcExternalReference.Location` is the canonical field; STEP AP242's external
8
+ * references expose their location the same way.
9
+ */
10
+ export interface ReferenceLocationReader {
11
+ /**
12
+ * @param expressID The cross-reference entity's express ID.
13
+ * @return {string | null | undefined} Its `Location`, or null/undefined when
14
+ * absent.
15
+ */
16
+ locationOf(expressID: number): string | null | undefined;
17
+ }
18
+ /**
19
+ * An outbound federation link discovered from a cross-reference: the
20
+ * referencing entity in this model, the raw location it declared, and — once
21
+ * resolved against the model's own URI — the absolute URI (and, if the
22
+ * location carried a `#expressID` fragment, the entity address) it points at.
23
+ */
24
+ export interface CrossReferenceLink {
25
+ /** Express ID of the referencing entity in the source model. */
26
+ fromExpressID: number;
27
+ /** The raw `Location` string as authored in the file. */
28
+ location: string;
29
+ /** The location resolved to an absolute URI against the source model URI. */
30
+ targetURI: string;
31
+ /** The target entity address, when the location carried a `#expressID`. */
32
+ targetEntity?: EntityAddress;
33
+ }
34
+ /**
35
+ * Collects a model's **outbound cross-model references** during the streaming
36
+ * parse and, once locations are readable, resolves them into navigable
37
+ * federation links (M5 / design S3).
38
+ *
39
+ * The links come from IFC's own reference entities — `IfcExternalReference`
40
+ * and its subtypes (`IfcDocumentReference`, `IfcClassificationReference`,
41
+ * `IfcLibraryReference`) — and, for STEP AP242, its external references. Two
42
+ * phases, matching M2's "identify while parsing, resolve on demand":
43
+ *
44
+ * 1. **Identify** — subscribe {@link handler} to a
45
+ * {@link StreamingRecordDispatcher} for the reference types
46
+ * (`dispatcher.on([IfcExternalReference], reg.handler)`); it records the
47
+ * express ID of every such record as it streams past. Cheap and idempotent
48
+ * (a `Set`), so the rare grow-restart is harmless.
49
+ * 2. **Resolve** — after parse, {@link resolve} reads each reference's
50
+ * `Location` via a {@link ReferenceLocationReader} and resolves it against
51
+ * the source model URI, yielding {@link CrossReferenceLink}s the UI renders
52
+ * as links. Visiting one opens the target model in the `ModelRegistry`.
53
+ *
54
+ * The location read is deferred because the event stream carries only
55
+ * `(localID, expressID, typeID)` — not attribute strings; pulling `Location`
56
+ * needs the entity's fields, which is a model read, not a parse event.
57
+ */
58
+ export declare class CrossReferenceRegistry<TypeIDType extends number> {
59
+ private readonly sourceURI_;
60
+ private readonly fromExpressIDs_;
61
+ /**
62
+ * @param sourceURI_ The URI of the model these references were found in —
63
+ * the base for resolving relative locations.
64
+ */
65
+ constructor(sourceURI_: string);
66
+ /**
67
+ * Record one cross-reference entity. Bind to a dispatcher subscription
68
+ * filtered to the reference types; every record it is handed is taken to be
69
+ * a cross-reference (the dispatcher does the type filtering).
70
+ *
71
+ * @param localID Unused (kept for the RecordHandler shape).
72
+ * @param expressID The reference entity's express ID.
73
+ * @param typeID Unused (the dispatcher already matched the type set).
74
+ */
75
+ readonly handler: RecordHandler<TypeIDType>;
76
+ /**
77
+ * @return {number} The number of cross-references collected.
78
+ */
79
+ get count(): number;
80
+ /**
81
+ * @return {IterableIterator<number>} The express IDs of the collected
82
+ * reference entities.
83
+ */
84
+ expressIDs(): IterableIterator<number>;
85
+ /**
86
+ * Resolve the collected references into navigable links by reading each
87
+ * one's `Location` and resolving it against the source model URI. References
88
+ * whose location is absent (null / empty) are skipped — they carry no link.
89
+ *
90
+ * @param reader Reads the `Location` of an express ID.
91
+ * @return {CrossReferenceLink[]} The resolved outbound links.
92
+ */
93
+ resolve(reader: ReferenceLocationReader): CrossReferenceLink[];
94
+ }
95
+ //# sourceMappingURL=cross_reference_registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross_reference_registry.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/cross_reference_registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAoB,MAAM,sBAAsB,CAAA;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAG7D;;;;;;GAMG;AACH,MAAM,WAAW,uBAAuB;IAEtC;;;;OAIG;IACH,UAAU,CAAE,SAAS,EAAE,MAAM,GAAI,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;CAC3D;AAGD;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IAEjC,gEAAgE;IAChE,aAAa,EAAE,MAAM,CAAA;IAErB,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAA;IAEhB,6EAA6E;IAC7E,SAAS,EAAE,MAAM,CAAA;IAEjB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,aAAa,CAAA;CAC7B;AAOD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,sBAAsB,CAAC,UAAU,SAAS,MAAM;IAQ9C,OAAO,CAAC,QAAQ,CAAC,UAAU;IANxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAoB;IAEpD;;;OAGG;gBAC2B,UAAU,EAAE,MAAM;IAEhD;;;;;;;;OAQG;IACH,SAAgB,OAAO,EAAE,aAAa,CAAC,UAAU,CAAC,CAG/C;IAEH;;OAEG;IACH,IAAW,KAAK,IAAI,MAAM,CAEzB;IAED;;;OAGG;IACI,UAAU,IAAI,gBAAgB,CAAC,MAAM,CAAC;IAI7C;;;;;;;OAOG;IACI,OAAO,CAAE,MAAM,EAAE,uBAAuB,GAAI,kBAAkB,EAAE;CA8BxE"}
@@ -0,0 +1,91 @@
1
+ import { resolveReference } from "../../core/model_uri.js";
2
+ const FRAGMENT = "#";
3
+ const RADIX = 10;
4
+ /**
5
+ * Collects a model's **outbound cross-model references** during the streaming
6
+ * parse and, once locations are readable, resolves them into navigable
7
+ * federation links (M5 / design S3).
8
+ *
9
+ * The links come from IFC's own reference entities — `IfcExternalReference`
10
+ * and its subtypes (`IfcDocumentReference`, `IfcClassificationReference`,
11
+ * `IfcLibraryReference`) — and, for STEP AP242, its external references. Two
12
+ * phases, matching M2's "identify while parsing, resolve on demand":
13
+ *
14
+ * 1. **Identify** — subscribe {@link handler} to a
15
+ * {@link StreamingRecordDispatcher} for the reference types
16
+ * (`dispatcher.on([IfcExternalReference], reg.handler)`); it records the
17
+ * express ID of every such record as it streams past. Cheap and idempotent
18
+ * (a `Set`), so the rare grow-restart is harmless.
19
+ * 2. **Resolve** — after parse, {@link resolve} reads each reference's
20
+ * `Location` via a {@link ReferenceLocationReader} and resolves it against
21
+ * the source model URI, yielding {@link CrossReferenceLink}s the UI renders
22
+ * as links. Visiting one opens the target model in the `ModelRegistry`.
23
+ *
24
+ * The location read is deferred because the event stream carries only
25
+ * `(localID, expressID, typeID)` — not attribute strings; pulling `Location`
26
+ * needs the entity's fields, which is a model read, not a parse event.
27
+ */
28
+ export class CrossReferenceRegistry {
29
+ /**
30
+ * @param sourceURI_ The URI of the model these references were found in —
31
+ * the base for resolving relative locations.
32
+ */
33
+ constructor(sourceURI_) {
34
+ this.sourceURI_ = sourceURI_;
35
+ this.fromExpressIDs_ = new Set();
36
+ /**
37
+ * Record one cross-reference entity. Bind to a dispatcher subscription
38
+ * filtered to the reference types; every record it is handed is taken to be
39
+ * a cross-reference (the dispatcher does the type filtering).
40
+ *
41
+ * @param localID Unused (kept for the RecordHandler shape).
42
+ * @param expressID The reference entity's express ID.
43
+ * @param typeID Unused (the dispatcher already matched the type set).
44
+ */
45
+ this.handler = (localID, expressID, typeID) => {
46
+ this.fromExpressIDs_.add(expressID);
47
+ };
48
+ }
49
+ /**
50
+ * @return {number} The number of cross-references collected.
51
+ */
52
+ get count() {
53
+ return this.fromExpressIDs_.size;
54
+ }
55
+ /**
56
+ * @return {IterableIterator<number>} The express IDs of the collected
57
+ * reference entities.
58
+ */
59
+ expressIDs() {
60
+ return this.fromExpressIDs_.keys();
61
+ }
62
+ /**
63
+ * Resolve the collected references into navigable links by reading each
64
+ * one's `Location` and resolving it against the source model URI. References
65
+ * whose location is absent (null / empty) are skipped — they carry no link.
66
+ *
67
+ * @param reader Reads the `Location` of an express ID.
68
+ * @return {CrossReferenceLink[]} The resolved outbound links.
69
+ */
70
+ resolve(reader) {
71
+ const links = [];
72
+ for (const fromExpressID of this.fromExpressIDs_) {
73
+ const location = reader.locationOf(fromExpressID);
74
+ if (location === null || location === void 0 || location.length === 0) {
75
+ continue;
76
+ }
77
+ const resolved = resolveReference(this.sourceURI_, location);
78
+ const link = { fromExpressID, location, targetURI: resolved };
79
+ // A location may itself address a specific entity (model.ifc#42).
80
+ const hash = resolved.lastIndexOf(FRAGMENT);
81
+ if (hash >= 0 && /^\d+$/.test(resolved.slice(hash + 1))) {
82
+ link.targetEntity = {
83
+ modelURI: resolved.slice(0, hash),
84
+ expressID: parseInt(resolved.slice(hash + 1), RADIX),
85
+ };
86
+ }
87
+ links.push(link);
88
+ }
89
+ return links;
90
+ }
91
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cross_reference_registry.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross_reference_registry.test.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/cross_reference_registry.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,66 @@
1
+ /* eslint-disable no-magic-numbers */
2
+ // M5: outbound cross-model references are collected during the parse (by type,
3
+ // via the dispatcher) and resolved to navigable federation links against the
4
+ // source model URI once their Location strings are readable.
5
+ import { describe, expect, test } from "@jest/globals";
6
+ import { CrossReferenceRegistry, } from "./cross_reference_registry.js";
7
+ import { StreamingRecordDispatcher } from "./streaming_record_dispatcher.js";
8
+ import { IfcExternalReference } from "../../ifc/ifc4_gen/index.js";
9
+ /**
10
+ * A mock reader over a fixed express-ID → Location map.
11
+ *
12
+ * @param locations The express-ID → Location map.
13
+ * @return {ReferenceLocationReader} The reader.
14
+ */
15
+ function reader(locations) {
16
+ return { locationOf: (expressID) => locations[expressID] };
17
+ }
18
+ describe("CrossReferenceRegistry", () => {
19
+ test("collects references handed to its handler and resolves them", () => {
20
+ const registry = new CrossReferenceRegistry("https://ex.com/site/plan.ifc");
21
+ // Simulate the dispatcher delivering three reference records.
22
+ registry.handler(0, 100, 1);
23
+ registry.handler(1, 200, 1);
24
+ registry.handler(2, 300, 1);
25
+ expect(registry.count).toBe(3);
26
+ const links = registry.resolve(reader({
27
+ 100: "../shared/grid.ifc",
28
+ 200: "https://other.org/lib.ifc",
29
+ 300: "wing-A.ifc#4022",
30
+ }));
31
+ const byFrom = new Map(links.map((l) => [l.fromExpressID, l]));
32
+ expect(byFrom.get(100)?.targetURI).toBe("https://ex.com/shared/grid.ifc");
33
+ expect(byFrom.get(200)?.targetURI).toBe("https://other.org/lib.ifc");
34
+ // A location with a #expressID resolves to a full entity address.
35
+ const wing = byFrom.get(300);
36
+ expect(wing?.targetURI).toBe("https://ex.com/site/wing-A.ifc#4022");
37
+ expect(wing?.targetEntity).toEqual({
38
+ modelURI: "https://ex.com/site/wing-A.ifc",
39
+ expressID: 4022,
40
+ });
41
+ });
42
+ test("skips references with no location", () => {
43
+ const registry = new CrossReferenceRegistry("base.ifc");
44
+ registry.handler(0, 1, 1);
45
+ registry.handler(1, 2, 1);
46
+ const links = registry.resolve(reader({ 1: null, 2: "" }));
47
+ expect(links).toEqual([]);
48
+ });
49
+ test("is idempotent under the streaming grow-restart (dedupes express IDs)", () => {
50
+ const registry = new CrossReferenceRegistry("base.ifc");
51
+ registry.handler(0, 42, 1);
52
+ registry.handler(0, 42, 1); // re-fire from localID 0 after a restart
53
+ expect(registry.count).toBe(1);
54
+ });
55
+ test("wires to the dispatcher, collecting only the reference types", () => {
56
+ const registry = new CrossReferenceRegistry("base.ifc");
57
+ const dispatcher = new StreamingRecordDispatcher();
58
+ dispatcher.on([IfcExternalReference], registry.handler);
59
+ // One record of a matching (subtype-closure) type, one outside it.
60
+ const matching = IfcExternalReference.query[0];
61
+ const nonMatching = 10000000; // not in the reference closure
62
+ dispatcher.onRecordIndexed(0, 500, matching);
63
+ dispatcher.onRecordIndexed(1, 600, nonMatching);
64
+ expect([...registry.expressIDs()]).toEqual([500]);
65
+ });
66
+ });
@@ -27,6 +27,21 @@
27
27
  * @return The decoded string.
28
28
  */
29
29
  export declare function decodeUtf8(view: Uint8Array): string;
30
+ /**
31
+ * Decode the raw byte run of a STEP string literal.
32
+ *
33
+ * ISO 10303-21 says raw (non-\X\-escaped) bytes are ISO 8859-1, but modern
34
+ * exporters routinely write UTF-8 (and some, like Onshape's ST-Developer,
35
+ * write outright invalid sequences). The lenient default decoder mapped every
36
+ * non-UTF-8 byte to U+FFFD, so a spec-conformant latin-1 'Küche' surfaced as
37
+ * 'K�che' in product names and titles. Decode as strict UTF-8 first (the
38
+ * common modern case, and unambiguous when it validates), and fall back to
39
+ * exact ISO 8859-1 (byte = code point, which cannot fail) when it doesn't.
40
+ *
41
+ * @param view The bytes of the string literal's raw run.
42
+ * @return The decoded string.
43
+ */
44
+ export declare function decodeStepString(view: Uint8Array): string;
30
45
  /**
31
46
  * Install a global, idempotent `TextDecoder.prototype.decode` shim that copies a
32
47
  * view out of a resizable/growable buffer before decoding. This covers decodes