@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,280 @@
1
+ import ParsingBuffer from "../../parsing/parsing_buffer.js";
2
+ import { ColumnarIndexSink } from "./columnar_index.js";
3
+ import { ParseResult, } from "./step_parser.js";
4
+ /**
5
+ * Build the entity index by streaming a `ByteSource` through a fixed-size
6
+ * moving window, instead of parsing one resident buffer. The parse loop is
7
+ * byte-for-byte the resident one (`StepParser.parseDataBlockStreamed` drives
8
+ * the same generator); this coordinator only owns the window: it fills it,
9
+ * parses the header from the first fill, then slides the window forward at
10
+ * top-level record boundaries as the parser advances.
11
+ *
12
+ * Because the parser records file-absolute addresses and its rewind stack is
13
+ * empty at every top-level boundary, sliding there is transparent: the
14
+ * unconsumed tail is copied to the front, fresh bytes are appended, and the
15
+ * buffer is rebased so `address` keeps its file-absolute value. Peak JS heap
16
+ * for the index build is therefore `window + index columns`, independent of
17
+ * file size.
18
+ *
19
+ * The window slides only once the cursor passes `pool / 2`, bounding the
20
+ * memmove frequency; a record up to `pool / 2` bytes always fits after a
21
+ * slide. If a single record exceeds that (never on the current corpus, whose
22
+ * largest STEP record is ~25 KB), the whole parse restarts from the
23
+ * beginning with the window doubled, and repeats until every record fits —
24
+ * correctness over the pathological case, at the cost of a re-scan. (M1's
25
+ * production path will instead grow in place / restart from the last
26
+ * boundary; from-scratch keeps the spike simple.)
27
+ *
28
+ * @param source The byte source.
29
+ * @param parser The STEP parser (typed to the schema).
30
+ * @param pool Target window size in bytes.
31
+ * @param onRecordIndexed Optional per-record event, invoked live as each
32
+ * top-level record is indexed with its (localID, expressID, typeID) — the
33
+ * seam for incremental semantic consumers (M2). localIDs are dense and
34
+ * assigned in parse order from 0. On the rare grow-and-restart (a single
35
+ * record larger than the window — never on real files, whose largest STEP
36
+ * record is ~25 KB), the parse re-runs from the start and records re-fire
37
+ * from localID 0; consumers must therefore be idempotent by localID /
38
+ * expressID (the standard consumers — type index keyed by localID, roots
39
+ * registry keyed by expressID — are). Must be synchronous and cheap;
40
+ * expensive work belongs on a demand queue, not the parse path.
41
+ * @return {StreamingIndexResult} The index, header, result and diagnostics.
42
+ */
43
+ export function buildIndexStreaming(source, parser, pool, onRecordIndexed, sink) {
44
+ const fileSize = source.byteLength;
45
+ // Grow-and-restart loop: the body runs a full streamed parse at the current
46
+ // window size. It only re-runs if a single record couldn't fit the window
47
+ // (false end-of-file before true EOF), doubling the window each time.
48
+ let windowBytes = Math.max(pool, MIN_WINDOW);
49
+ for (;;) {
50
+ const window = new Uint8Array(windowBytes);
51
+ let windowStartFile = 0;
52
+ let windowLen = source.read(0, windowBytes, window, 0);
53
+ let bytesRead = windowLen;
54
+ const input = new ParsingBuffer(window, 0, windowLen);
55
+ const [header, headerResult] = parser.parseHeader(input);
56
+ if (headerResult !== ParseResult.COMPLETE) {
57
+ // Header didn't complete in the first window: either malformed, or a
58
+ // header larger than the pool. Report it as-is — the resident parse
59
+ // would surface the same header result.
60
+ return {
61
+ header,
62
+ elements: [],
63
+ result: headerResult,
64
+ stats: { pool, windowBytes, slides: 0, maxRecordLen: 0, bytesRead },
65
+ };
66
+ }
67
+ // Slide once the cursor is past half the window; a record up to this much
68
+ // headroom always fits without a false EOF.
69
+ const slideThreshold = windowBytes >> 1;
70
+ let slides = 0;
71
+ let maxRecordLen = 0;
72
+ let prevBoundaryFile = windowStartFile + input.cursor;
73
+ const onRecordBoundary = (buffer) => {
74
+ const cursor = buffer.cursor;
75
+ const recordFileStart = windowStartFile + cursor;
76
+ const recordLen = recordFileStart - prevBoundaryFile;
77
+ if (recordLen > maxRecordLen) {
78
+ maxRecordLen = recordLen;
79
+ }
80
+ prevBoundaryFile = recordFileStart;
81
+ // Window already spans to EOF — nothing left to slide in.
82
+ if (windowStartFile + windowLen >= fileSize) {
83
+ return;
84
+ }
85
+ // Enough headroom remains; defer the slide to bound memmove frequency.
86
+ if (cursor < slideThreshold) {
87
+ return;
88
+ }
89
+ // Slide: move the unconsumed tail to the front, refill behind it.
90
+ const tail = windowLen - cursor;
91
+ window.copyWithin(0, cursor, windowLen);
92
+ const want = windowBytes - tail;
93
+ const got = source.read(windowStartFile + windowLen, want, window, tail);
94
+ bytesRead += got;
95
+ windowLen = tail + got;
96
+ windowStartFile = recordFileStart;
97
+ buffer.rebaseWindow(window, 0, windowLen, windowStartFile);
98
+ ++slides;
99
+ };
100
+ const [index, result] = parser.parseDataBlockStreamed(input, onRecordBoundary, onRecordIndexed, void 0, sink);
101
+ // A parse that stopped short of true EOF, with the window not spanning to
102
+ // EOF, means a single record overflowed the window: grow and retry.
103
+ const stoppedShort = result !== ParseResult.COMPLETE;
104
+ const notAtEof = windowStartFile + windowLen < fileSize;
105
+ if (stoppedShort && notAtEof) {
106
+ windowBytes *= 2;
107
+ sink?.reset();
108
+ continue;
109
+ }
110
+ // Capture the final record's length (no boundary fires after the last).
111
+ const lastRecordLen = (windowStartFile + input.cursor) - prevBoundaryFile;
112
+ if (lastRecordLen > maxRecordLen) {
113
+ maxRecordLen = lastRecordLen;
114
+ }
115
+ return {
116
+ header,
117
+ elements: index.elements,
118
+ result,
119
+ stats: { pool, windowBytes, slides, maxRecordLen, bytesRead },
120
+ };
121
+ }
122
+ }
123
+ // Floor on the window so a pathologically tiny pool still holds the header
124
+ // and a record with slide headroom. Tests drive pools down to this to force
125
+ // many slides on a small fixture; the pool sweep uses ≥ 128 KB anyway.
126
+ // eslint-disable-next-line no-magic-numbers
127
+ const MIN_WINDOW = 4 * 1024;
128
+ /**
129
+ * Fill `into` from either a sync or async byte source. A sync `read`
130
+ * resolves immediately; this is what lets the cooperative builder
131
+ * parse from an OPFS `File.slice()` store without a worker.
132
+ *
133
+ * @param source Sync or async positioned source.
134
+ * @param offset Absolute source offset.
135
+ * @param length Maximum bytes to copy.
136
+ * @param into Destination buffer.
137
+ * @param intoOffset Offset within `into`.
138
+ * @return {Promise<number>} Bytes copied.
139
+ */
140
+ async function readSource(source, offset, length, into, intoOffset) {
141
+ return await source.read(offset, length, into, intoOffset);
142
+ }
143
+ /**
144
+ * Cooperative twin of {@link buildIndexStreaming}: identical parse, window
145
+ * and grow-and-restart behaviour (mirrored the same way the parser mirrors
146
+ * parseDataBlock/parseDataBlockAsync), but the parse periodically yields to
147
+ * the event loop so browsers repaint progress UI mid-parse instead of
148
+ * flagging the tab as stalled (issue #301 §2 for the streamed path).
149
+ *
150
+ * @param source The byte source.
151
+ * @param parser The STEP parser (typed to the schema).
152
+ * @param pool Target window size in bytes.
153
+ * @param onRecordIndexed Optional per-record event (see buildIndexStreaming).
154
+ * @param sink Optional index sink (columnar builds).
155
+ * @param onProgress Optional progress callback with the ABSOLUTE source byte
156
+ * cursor (unlike the parser's window-relative cursor), so callers can report
157
+ * `cursor / source.byteLength` directly.
158
+ * @param yieldIntervalMs Minimum ms between event-loop yields.
159
+ * @return {Promise<StreamingIndexResult>} The index, header, result and
160
+ * diagnostics.
161
+ */
162
+ export async function buildIndexStreamingAsync(source, parser, pool, onRecordIndexed, sink, onProgress, yieldIntervalMs) {
163
+ const fileSize = source.byteLength;
164
+ let windowBytes = Math.max(pool, MIN_WINDOW);
165
+ for (;;) {
166
+ const window = new Uint8Array(windowBytes);
167
+ let windowStartFile = 0;
168
+ let windowLen = await readSource(source, 0, windowBytes, window, 0);
169
+ let bytesRead = windowLen;
170
+ const input = new ParsingBuffer(window, 0, windowLen);
171
+ const [header, headerResult] = parser.parseHeader(input);
172
+ if (headerResult !== ParseResult.COMPLETE) {
173
+ return {
174
+ header,
175
+ elements: [],
176
+ result: headerResult,
177
+ stats: { pool, windowBytes, slides: 0, maxRecordLen: 0, bytesRead },
178
+ };
179
+ }
180
+ const slideThreshold = windowBytes >> 1;
181
+ let slides = 0;
182
+ let maxRecordLen = 0;
183
+ let prevBoundaryFile = windowStartFile + input.cursor;
184
+ const onRecordBoundary = (buffer) => {
185
+ const cursor = buffer.cursor;
186
+ const recordFileStart = windowStartFile + cursor;
187
+ const recordLen = recordFileStart - prevBoundaryFile;
188
+ if (recordLen > maxRecordLen) {
189
+ maxRecordLen = recordLen;
190
+ }
191
+ prevBoundaryFile = recordFileStart;
192
+ if (windowStartFile + windowLen >= fileSize) {
193
+ return;
194
+ }
195
+ if (cursor < slideThreshold) {
196
+ return;
197
+ }
198
+ const tail = windowLen - cursor;
199
+ window.copyWithin(0, cursor, windowLen);
200
+ const want = windowBytes - tail;
201
+ const fillAt = windowStartFile + windowLen;
202
+ // Only return a Promise when this boundary actually slides —
203
+ // an `async` callback would force an await at every record
204
+ // (millions of hops on a PSB-class file).
205
+ return readSource(source, fillAt, want, window, tail).then((got) => {
206
+ bytesRead += got;
207
+ windowLen = tail + got;
208
+ windowStartFile = recordFileStart;
209
+ buffer.rebaseWindow(window, 0, windowLen, windowStartFile);
210
+ ++slides;
211
+ });
212
+ };
213
+ // Translate the parser's window-relative cursor to an absolute source
214
+ // cursor (windowStartFile advances as the window slides).
215
+ const progressTick = onProgress !== void 0 ?
216
+ (cursor) => onProgress(windowStartFile + cursor) : void 0;
217
+ const [index, result] = await parser.parseDataBlockStreamedAsync(input, onRecordBoundary, onRecordIndexed, progressTick, sink, yieldIntervalMs);
218
+ const stoppedShort = result !== ParseResult.COMPLETE;
219
+ const notAtEof = windowStartFile + windowLen < fileSize;
220
+ if (stoppedShort && notAtEof) {
221
+ windowBytes *= 2;
222
+ sink?.reset();
223
+ continue;
224
+ }
225
+ const lastRecordLen = (windowStartFile + input.cursor) - prevBoundaryFile;
226
+ if (lastRecordLen > maxRecordLen) {
227
+ maxRecordLen = lastRecordLen;
228
+ }
229
+ return {
230
+ header,
231
+ elements: index.elements,
232
+ result,
233
+ stats: { pool, windowBytes, slides, maxRecordLen, bytesRead },
234
+ };
235
+ }
236
+ }
237
+ /**
238
+ * Build the entity index by streaming, **directly into typed-array columns**
239
+ * (M7): identical parse and window behaviour to {@link buildIndexStreaming},
240
+ * but completed records are encoded straight into a {@link ColumnarIndexSink}
241
+ * so the per-record object index never materialises. Peak JS heap for the
242
+ * index build becomes `window + columns` — the object phase (the dominant
243
+ * heap cost on large models) is gone.
244
+ *
245
+ * @param source The byte source.
246
+ * @param parser The STEP parser (typed to the schema).
247
+ * @param pool Target window size in bytes.
248
+ * @param onRecordIndexed Optional per-record event (see buildIndexStreaming).
249
+ * @param sink Optional caller-owned sink. Pass one to hold the *live* columns
250
+ * while the parse runs — that is what a prefix-derived consumer
251
+ * ({@link import('./prefix_type_index').PrefixTypeIndex}) reads. Omit it and
252
+ * the columns only exist once this returns.
253
+ * @return {StreamingColumnarIndexResult} Columns, header, result, stats.
254
+ */
255
+ export function buildColumnarIndexStreaming(source, parser, pool, onRecordIndexed, sink = new ColumnarIndexSink()) {
256
+ const { header, result, stats } = buildIndexStreaming(source, parser, pool, onRecordIndexed, sink);
257
+ return { header, columns: sink.finalize(), result, stats };
258
+ }
259
+ /**
260
+ * Cooperative twin of {@link buildColumnarIndexStreaming}: identical
261
+ * columnar build, but the parse periodically yields to the event loop (see
262
+ * {@link buildIndexStreamingAsync}) and reports absolute byte-cursor
263
+ * progress — the browser-facing variant for large models.
264
+ *
265
+ * @param source The byte source.
266
+ * @param parser The STEP parser (typed to the schema).
267
+ * @param pool Target window size in bytes.
268
+ * @param onRecordIndexed Optional per-record event (see buildIndexStreaming).
269
+ * @param onProgress Optional absolute byte-cursor progress callback.
270
+ * @param yieldIntervalMs Minimum ms between event-loop yields.
271
+ * @param sink Optional caller-owned sink (see
272
+ * {@link buildColumnarIndexStreaming}) — the seam for reading the columns
273
+ * while the parse is still running.
274
+ * @return {Promise<StreamingColumnarIndexResult>} Columns, header, result,
275
+ * stats.
276
+ */
277
+ export async function buildColumnarIndexStreamingAsync(source, parser, pool, onRecordIndexed, onProgress, yieldIntervalMs, sink = new ColumnarIndexSink()) {
278
+ const { header, result, stats } = await buildIndexStreamingAsync(source, parser, pool, onRecordIndexed, sink, onProgress, yieldIntervalMs);
279
+ return { header, columns: sink.finalize(), result, stats };
280
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=streaming_index_builder.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming_index_builder.test.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/streaming_index_builder.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,107 @@
1
+ /* eslint-disable no-magic-numbers */
2
+ // M0 spike: streaming index build must be byte-identical to the resident
3
+ // parse. The parser reads file-absolute addresses and only rewinds within a
4
+ // single top-level record, so feeding it from a moving window that slides at
5
+ // record boundaries must produce the exact same index columns — at every
6
+ // pool size, including one small enough to force many slides + straddles.
7
+ import * as fs from "fs";
8
+ import { beforeAll, 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 { BufferByteSource } from "./byte_source.js";
12
+ import { buildIndexStreaming } from "./streaming_index_builder.js";
13
+ import { ParseResult } from "./step_parser.js";
14
+ /**
15
+ * Flatten the index (top-level records + their inline / multi-mapping
16
+ * children) into a stable, comparable column dump: every field the streaming
17
+ * parse must reproduce identically.
18
+ *
19
+ * @param elements The index elements.
20
+ * @return {object[]} A flat list of column tuples in traversal order.
21
+ */
22
+ function columns(elements) {
23
+ const out = [];
24
+ const visit = (e) => {
25
+ out.push({
26
+ address: e.address,
27
+ length: e.length,
28
+ typeID: e.typeID,
29
+ expressID: e.expressID ?? null,
30
+ });
31
+ for (const child of e.inlineEntities ?? []) {
32
+ visit(child);
33
+ }
34
+ for (const child of e.multiMapping ?? []) {
35
+ visit(child);
36
+ }
37
+ };
38
+ for (const e of elements) {
39
+ visit(e);
40
+ }
41
+ return out;
42
+ }
43
+ let bytes;
44
+ let residentColumns;
45
+ let residentCount;
46
+ beforeAll(() => {
47
+ bytes = new Uint8Array(fs.readFileSync("data/index.ifc"));
48
+ const input = new ParsingBuffer(bytes);
49
+ IfcStepParser.Instance.parseHeader(input);
50
+ const [index, result] = IfcStepParser.Instance.parseDataBlock(input);
51
+ expect(result).toBe(ParseResult.COMPLETE);
52
+ residentColumns = columns(index.elements);
53
+ residentCount = index.elements.length;
54
+ });
55
+ describe("buildIndexStreaming", () => {
56
+ // A tiny pool relative to the 18 KB fixture forces repeated slides and at
57
+ // least one record straddling a window boundary; a large one takes the
58
+ // whole file in a single window (no slide). Both must match the resident
59
+ // parse exactly.
60
+ const POOLS = [4 * 1024, 8 * 1024, 16 * 1024, 128 * 1024];
61
+ test.each(POOLS)("produces the resident index at pool=%d bytes", (pool) => {
62
+ const source = new BufferByteSource(bytes);
63
+ const result = buildIndexStreaming(source, IfcStepParser.Instance, pool);
64
+ expect(result.result).toBe(ParseResult.COMPLETE);
65
+ expect(result.elements.length).toBe(residentCount);
66
+ expect(columns(result.elements)).toEqual(residentColumns);
67
+ });
68
+ test("the small pool actually slides the window (straddle exercised)", () => {
69
+ const source = new BufferByteSource(bytes);
70
+ const result = buildIndexStreaming(source, IfcStepParser.Instance, 4 * 1024);
71
+ // 18 KB fixture through a 4 KB window must slide several times.
72
+ expect(result.stats.slides).toBeGreaterThan(1);
73
+ // Physical window never grew past the pool (no record exceeds it).
74
+ expect(result.stats.windowBytes).toBe(4 * 1024);
75
+ // Every byte read once (no growth re-reads) — bounded to file size.
76
+ expect(result.stats.bytesRead).toBe(bytes.length);
77
+ });
78
+ test("the large pool takes the whole file in one window (no slide)", () => {
79
+ const source = new BufferByteSource(bytes);
80
+ const result = buildIndexStreaming(source, IfcStepParser.Instance, 128 * 1024);
81
+ expect(result.stats.slides).toBe(0);
82
+ expect(result.stats.maxRecordLen).toBeGreaterThan(0);
83
+ });
84
+ test("grows the window and restarts when a single record exceeds the pool", () => {
85
+ // Synthetic file with one record far larger than a tiny pool — the
86
+ // corpus never hits this (largest STEP record ~25 KB), so exercise the
87
+ // grow-and-restart safety valve directly. A long text literal makes one
88
+ // record ~12 KB; a 4 KB pool must grow past it and still index it.
89
+ const bigValue = "X".repeat(12000);
90
+ const text = "ISO-10303-21;\nHEADER;\nENDSEC;\nDATA;\n" +
91
+ "#1=IFCWALL('a');\n" +
92
+ `#2=IFCPROPERTYSINGLEVALUE('${bigValue}');\n` +
93
+ "#3=IFCWALL('c');\nENDSEC;\n";
94
+ const synthetic = new TextEncoder().encode(text);
95
+ const resident = new ParsingBuffer(synthetic);
96
+ IfcStepParser.Instance.parseHeader(resident);
97
+ const [residentIndex, residentResult] = IfcStepParser.Instance.parseDataBlock(resident);
98
+ expect(residentResult).toBe(ParseResult.COMPLETE);
99
+ const streamed = buildIndexStreaming(new BufferByteSource(synthetic), IfcStepParser.Instance, 4 * 1024);
100
+ expect(streamed.result).toBe(ParseResult.COMPLETE);
101
+ // Window grew past the 4 KB pool to fit the ~12 KB record.
102
+ expect(streamed.stats.windowBytes).toBeGreaterThan(4 * 1024);
103
+ expect(streamed.stats.maxRecordLen).toBeGreaterThan(12000);
104
+ // ...and the index is still byte-identical to the resident parse.
105
+ expect(columns(streamed.elements)).toEqual(columns(residentIndex.elements));
106
+ });
107
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=streaming_index_builder_async.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming_index_builder_async.test.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/streaming_index_builder_async.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,109 @@
1
+ /* eslint-disable no-magic-numbers */
2
+ // The cooperative streamed columnar build must be byte-identical to the
3
+ // synchronous build (same columns, same window mechanics) AND actually
4
+ // yield to the event loop mid-parse — the repaint/no-stall property
5
+ // (#301 §2) the streamed open path relies on. The parse generator only
6
+ // suspends every PARSE_PROGRESS_ELEMENT_MASK+1 (4096) records, so the
7
+ // yield/progress assertions use a synthesized >4096-record model; the
8
+ // column-parity assertions use the real fixture.
9
+ import fs from "fs";
10
+ import { describe, expect, test } from "@jest/globals";
11
+ import IfcStepParser from "../../ifc/ifc_step_parser.js";
12
+ import { BufferByteSource, StoreByteSource } from "./byte_source.js";
13
+ import { InMemoryStepByteStore } from "../step_buffer_provider.js";
14
+ import { buildColumnarIndexStreaming, buildColumnarIndexStreamingAsync, } from "./streaming_index_builder.js";
15
+ import { ParseResult } from "./step_parser.js";
16
+ const POOL = 8 * 1024; // small window → forces slides on both inputs
17
+ /**
18
+ * Synthesize a valid IFC4 file with `recordCount` simple records — enough
19
+ * to cross the parser's progress-suspension mask several times.
20
+ *
21
+ * @param recordCount Number of data records.
22
+ * @return {Uint8Array} The encoded file.
23
+ */
24
+ function syntheticIfc(recordCount) {
25
+ const parts = [
26
+ "ISO-10303-21;\nHEADER;\n" +
27
+ "FILE_DESCRIPTION((''),'2;1');\n" +
28
+ "FILE_NAME('','',(''),(''),'','','');\n" +
29
+ "FILE_SCHEMA(('IFC4'));\nENDSEC;\nDATA;\n",
30
+ ];
31
+ for (let where = 1; where <= recordCount; ++where) {
32
+ parts.push(`#${where}=IFCCARTESIANPOINT((${where}.,0.,0.));\n`);
33
+ }
34
+ parts.push("ENDSEC;\nEND-ISO-10303-21;\n");
35
+ return new TextEncoder().encode(parts.join(""));
36
+ }
37
+ describe("buildColumnarIndexStreamingAsync", () => {
38
+ test("produces identical columns to the sync build (real fixture)", async () => {
39
+ const bytes = new Uint8Array(fs.readFileSync("data/index.ifc"));
40
+ const parser = IfcStepParser.Instance;
41
+ const sync = buildColumnarIndexStreaming(new BufferByteSource(bytes), parser, POOL);
42
+ const cooperative = await buildColumnarIndexStreamingAsync(new BufferByteSource(bytes), parser, POOL, void 0, void 0, 0);
43
+ expect(sync.result).toBe(ParseResult.COMPLETE);
44
+ expect(cooperative.result).toBe(ParseResult.COMPLETE);
45
+ const a = sync.columns;
46
+ const b = cooperative.columns;
47
+ expect(b.count).toBe(a.count);
48
+ expect(b.firstInlineElement).toBe(a.firstInlineElement);
49
+ expect(Array.from(b.address)).toEqual(Array.from(a.address));
50
+ expect(Array.from(b.length)).toEqual(Array.from(a.length));
51
+ expect(Array.from(b.typeID)).toEqual(Array.from(a.typeID));
52
+ expect(Array.from(b.expressID)).toEqual(Array.from(a.expressID));
53
+ // Same window mechanics (slides prove the moving window really moved).
54
+ expect(cooperative.stats.slides).toBe(sync.stats.slides);
55
+ expect(cooperative.stats.slides).toBeGreaterThan(0);
56
+ }, 60000);
57
+ test("StoreByteSource fills produce the same columns as a buffer source", async () => {
58
+ const bytes = new Uint8Array(fs.readFileSync("data/index.ifc"));
59
+ const parser = IfcStepParser.Instance;
60
+ const fromBuffer = await buildColumnarIndexStreamingAsync(new BufferByteSource(bytes), parser, POOL, void 0, void 0, 0);
61
+ const fromStore = await buildColumnarIndexStreamingAsync(new StoreByteSource(new InMemoryStepByteStore(bytes)), parser, POOL, void 0, void 0, 0);
62
+ expect(fromStore.result).toBe(ParseResult.COMPLETE);
63
+ expect(Array.from(fromStore.columns.address))
64
+ .toEqual(Array.from(fromBuffer.columns.address));
65
+ expect(Array.from(fromStore.columns.expressID))
66
+ .toEqual(Array.from(fromBuffer.columns.expressID));
67
+ }, 60000);
68
+ test("yields to the event loop and reports absolute progress mid-parse", async () => {
69
+ const bytes = syntheticIfc(10000);
70
+ const parser = IfcStepParser.Instance;
71
+ // Count macrotask turns that run while the build is in flight — with a
72
+ // zero yield interval the parse must give the event loop real turns.
73
+ let turns = 0;
74
+ let pumping = true;
75
+ const pump = () => {
76
+ if (!pumping) {
77
+ return;
78
+ }
79
+ ++turns;
80
+ setTimeout(pump, 0);
81
+ };
82
+ setTimeout(pump, 0);
83
+ const progressCursors = [];
84
+ const cooperative = await buildColumnarIndexStreamingAsync(new BufferByteSource(bytes), parser, POOL, void 0, (cursor) => progressCursors.push(cursor), 0);
85
+ pumping = false;
86
+ expect(cooperative.result).toBe(ParseResult.COMPLETE);
87
+ expect(cooperative.columns.count).toBe(10000);
88
+ expect(turns).toBeGreaterThan(0);
89
+ // Progress reports absolute source cursors: monotonically
90
+ // non-decreasing, bounded by the file size, and past the first window —
91
+ // the window-relative → absolute translation must hold across slides.
92
+ expect(progressCursors.length).toBeGreaterThan(1);
93
+ for (let where = 1; where < progressCursors.length; ++where) {
94
+ expect(progressCursors[where])
95
+ .toBeGreaterThanOrEqual(progressCursors[where - 1]);
96
+ }
97
+ expect(progressCursors[progressCursors.length - 1])
98
+ .toBeLessThanOrEqual(bytes.byteLength);
99
+ expect(progressCursors[progressCursors.length - 1])
100
+ .toBeGreaterThan(POOL);
101
+ // And the synthetic build matches its own sync twin exactly.
102
+ const sync = buildColumnarIndexStreaming(new BufferByteSource(bytes), parser, POOL);
103
+ expect(Array.from(cooperative.columns.address))
104
+ .toEqual(Array.from(sync.columns.address));
105
+ expect(Array.from(cooperative.columns.expressID))
106
+ .toEqual(Array.from(sync.columns.expressID));
107
+ expect(cooperative.stats.slides).toBe(sync.stats.slides);
108
+ }, 60000);
109
+ });
@@ -0,0 +1,71 @@
1
+ import { StepEntityConstructorAbstract } from "../step_entity_constructor.js";
2
+ import { RecordEventHandler } from "./record_event.js";
3
+ /**
4
+ * A per-record event handler: a record's dense `localID` (assigned in parse
5
+ * order from 0), its `expressID`, its `typeID` (0 for external-mapping
6
+ * records), and the record's raw bytes as an un-materialised
7
+ * `(buffer, byteOffset, byteLength)` view over the live parse window.
8
+ * See {@link RecordEventHandler} — in particular, the bytes are only valid
9
+ * for the duration of the call.
10
+ */
11
+ export type RecordHandler<TypeIDType> = RecordEventHandler<TypeIDType>;
12
+ /**
13
+ * Routes the streaming parse's per-record events (M2) to consumers that
14
+ * subscribe by **type set**. A subscription's type set is the subtype closure
15
+ * of the entity constructors it names — the same `query` closure the type
16
+ * index and `expressIDsOfTypes` use (conway #383) — so `on([IfcRoot], …)`
17
+ * matches every product, relationship, property set and quantity, and any
18
+ * future IfcRoot subtype, with no whitelist to maintain.
19
+ *
20
+ * Feed `dispatcher.onRecordIndexed` to `buildIndexStreaming` /
21
+ * `parseDataBlockStreamed`. Handlers run synchronously in the parse path, so
22
+ * they must be cheap (copy ids into a compact structure); anything expensive
23
+ * belongs on a demand queue, not here.
24
+ *
25
+ * Because subscriptions match on the raw parse `typeID`, external-mapping /
26
+ * complex records (typeID 0) are only delivered via `onAnyRecord`. Resolving
27
+ * their concrete types is not this class's job and never was: the columns
28
+ * carry the multi-mapping, so
29
+ * {@link import('./prefix_type_index').PrefixTypeIndex} attributes them
30
+ * correctly without the event stream. For the overwhelming majority of records
31
+ * (simple, one type each) type-set delivery is exact.
32
+ */
33
+ export declare class StreamingRecordDispatcher<TypeIDType extends number> {
34
+ /**
35
+ * Concrete type → the handlers subscribed to it, unioned across
36
+ * subscriptions. Dispatch is one lookup per record no matter how many
37
+ * consumers are attached: the per-record cost of a subscription is the only
38
+ * cost this class has at 9.4 M records, so it must not scale with the
39
+ * subscriber count (issue #393).
40
+ */
41
+ private readonly byType;
42
+ private readonly any;
43
+ /**
44
+ * Subscribe to records of the given entity types (including their
45
+ * subtypes).
46
+ *
47
+ * @param types The entity constructors whose subtype closures to match.
48
+ * @param handler Called for each matching record.
49
+ */
50
+ on(types: StepEntityConstructorAbstract<TypeIDType>[], handler: RecordHandler<TypeIDType>): void;
51
+ /**
52
+ * Subscribe to every record regardless of type (the firehose — including
53
+ * external-mapping records).
54
+ *
55
+ * @param handler Called for every record.
56
+ */
57
+ onAnyRecord(handler: RecordHandler<TypeIDType>): void;
58
+ /**
59
+ * The per-record callback to hand to the streaming parse. Dispatches each
60
+ * record to the matching subscribers. Bound so it can be passed directly.
61
+ *
62
+ * @param localID The record's dense local ID.
63
+ * @param expressID The record's express ID.
64
+ * @param typeID The record's type ID (0 for external-mapping records).
65
+ * @param buffer The live parse window holding the record's bytes.
66
+ * @param byteOffset Offset of the record's first byte within `buffer`.
67
+ * @param byteLength Length of the record in bytes.
68
+ */
69
+ readonly onRecordIndexed: RecordHandler<TypeIDType>;
70
+ }
71
+ //# sourceMappingURL=streaming_record_dispatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming_record_dispatcher.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/streaming_record_dispatcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAA;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAGnD;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,CAAC,UAAU,IAAI,kBAAkB,CAAC,UAAU,CAAC,CAAA;AAGtE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,yBAAyB,CAAC,UAAU,SAAS,MAAM;IAE9D;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqD;IAE5E,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkC;IAEtD;;;;;;OAMG;IACI,EAAE,CACL,KAAK,EAAE,6BAA6B,CAAC,UAAU,CAAC,EAAE,EAClD,OAAO,EAAE,aAAa,CAAC,UAAU,CAAC,GAAI,IAAI;IAkB9C;;;;;OAKG;IACI,WAAW,CAAE,OAAO,EAAE,aAAa,CAAC,UAAU,CAAC,GAAI,IAAI;IAI9D;;;;;;;;;;OAUG;IACH,SAAgB,eAAe,EAAE,aAAa,CAAC,UAAU,CAAC,CAsBvD;CACJ"}