@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,298 @@
1
+ /* eslint-disable no-magic-numbers */
2
+ // M2 (#393): the type index over the records parsed so far.
3
+ //
4
+ // Two things are pinned here, and they are the two the event-fed
5
+ // IncrementalTypeIndex this replaces got wrong:
6
+ // 1. final membership equals the resident model's type index — the exit
7
+ // criterion "consumers produce output identical to today's end-of-parse
8
+ // construction";
9
+ // 2. complex (multi-mapped) records are attributed to their mapped classes,
10
+ // which is invisible to a consumer reading the record event's typeID
11
+ // (complex records arrive there as 0).
12
+ import * as fs from "fs";
13
+ import { beforeAll, describe, expect, test } from "@jest/globals";
14
+ import ParsingBuffer from "../../parsing/parsing_buffer.js";
15
+ import IfcStepParser from "../../ifc/ifc_step_parser.js";
16
+ import { EntityTypesIfcCount } from "../../ifc/ifc4_gen/entity_types_ifc.gen.js";
17
+ import { IfcRoot, IfcProduct, IfcProject, IfcWall, IfcPropertySet, } from "../../ifc/ifc4_gen/index.js";
18
+ import { MultiIndexSetCursorOr } from "../../indexing/multi_index_set_cursor_or.js";
19
+ import { SingleIndexSetCursor } from "../../indexing/single_index_set_cursor.js";
20
+ import { StepTypeIndexer } from "../indexing/step_type_indexer.js";
21
+ import { BufferByteSource } from "./byte_source.js";
22
+ import { ColumnarIndexSink } from "./columnar_index.js";
23
+ import { PrefixTypeIndex } from "./prefix_type_index.js";
24
+ import { buildIndexStreaming } from "./streaming_index_builder.js";
25
+ import { ParseResult } from "./step_parser.js";
26
+ let bytes;
27
+ let model;
28
+ // The resident parse's top-level entries, in parse order — the independent
29
+ // ground truth the property test below reconstructs prefixes from. It never
30
+ // goes near the streaming path, so it cannot agree with a bug by sharing one.
31
+ let residentEntries;
32
+ beforeAll(() => {
33
+ bytes = new Uint8Array(fs.readFileSync("data/index.ifc"));
34
+ const input = new ParsingBuffer(bytes);
35
+ IfcStepParser.Instance.parseHeader(input);
36
+ model = IfcStepParser.Instance.parseDataToModel(input)[1];
37
+ const groundTruthInput = new ParsingBuffer(bytes);
38
+ IfcStepParser.Instance.parseHeader(groundTruthInput);
39
+ residentEntries = IfcStepParser.Instance.parseDataBlock(groundTruthInput)[0].elements;
40
+ });
41
+ /**
42
+ * The express IDs a correct index would hold over the first `records`
43
+ * top-level records, computed straight from the resident parse.
44
+ *
45
+ * @param records How many records the view covers.
46
+ * @param closure The queried subtype closure, as raw type IDs.
47
+ * @return {Set<number>} The expected express IDs.
48
+ */
49
+ function expectedOverPrefix(records, closure) {
50
+ const wanted = new Set(closure);
51
+ const result = new Set();
52
+ for (let localID = 0; localID < records; ++localID) {
53
+ const entry = residentEntries[localID];
54
+ if (entry === void 0) {
55
+ break;
56
+ }
57
+ if (entry.typeID !== void 0 && wanted.has(entry.typeID)) {
58
+ result.add(entry.expressID);
59
+ continue;
60
+ }
61
+ // Complex records carry their real classes in the multi-mapping.
62
+ for (const mapped of entry.multiMapping ?? []) {
63
+ if (mapped.typeID !== void 0 && wanted.has(mapped.typeID)) {
64
+ result.add(entry.expressID);
65
+ break;
66
+ }
67
+ }
68
+ }
69
+ return result;
70
+ }
71
+ /**
72
+ * Stream index.ifc into a sink, optionally pausing at `stopAfter` records to
73
+ * hand the caller a mid-parse view, and return the index over that sink.
74
+ *
75
+ * @param onRecord Optional per-record hook, so a test can query the index
76
+ * while the parse is still filling the sink behind it.
77
+ * @return {PrefixTypeIndex} The index over the (fully parsed) sink.
78
+ */
79
+ function streamed(onRecord) {
80
+ const sink = new ColumnarIndexSink();
81
+ const index = new PrefixTypeIndex(sink, new StepTypeIndexer(EntityTypesIfcCount));
82
+ const result = buildIndexStreaming(new BufferByteSource(bytes), IfcStepParser.Instance, 4 * 1024, onRecord === void 0 ? void 0 : (localID) => onRecord(index, localID), sink);
83
+ expect(result.result).toBe(ParseResult.COMPLETE);
84
+ return index;
85
+ }
86
+ describe("PrefixTypeIndex", () => {
87
+ test.each([
88
+ ["IfcRoot", IfcRoot],
89
+ ["IfcProduct", IfcProduct],
90
+ ["IfcWall", IfcWall],
91
+ ["IfcPropertySet", IfcPropertySet],
92
+ ])("final membership matches the resident type index for %s", (_name, ctor) => {
93
+ const index = streamed();
94
+ const prefix = new Set(index.expressIDsOfTypes(ctor));
95
+ const resident = new Set(model.expressIDsOfTypes(ctor));
96
+ expect(prefix).toEqual(resident);
97
+ });
98
+ test("a multi-type query unions the subtype closures", () => {
99
+ const index = streamed();
100
+ const prefix = new Set(index.expressIDsOfTypes(IfcWall, IfcPropertySet));
101
+ const resident = new Set(model.expressIDsOfTypes(IfcWall, IfcPropertySet));
102
+ expect(prefix).toEqual(resident);
103
+ });
104
+ test("nothing is built until something is queried", () => {
105
+ const sink = new ColumnarIndexSink();
106
+ const index = new PrefixTypeIndex(sink, new StepTypeIndexer(EntityTypesIfcCount));
107
+ expect(index.generation).toBe(0);
108
+ expect(index.recordCount).toBe(0);
109
+ // The whole point of deriving rather than pushing: a consumer that never
110
+ // asks pays nothing, however long the parse ran.
111
+ buildIndexStreaming(new BufferByteSource(bytes), IfcStepParser.Instance, 4 * 1024, void 0, sink);
112
+ expect(index.generation).toBe(0);
113
+ });
114
+ test("a mid-parse query answers over the prefix, and grows with it", () => {
115
+ // Rebuild on every record so the view tracks the parse exactly; the
116
+ // default growth pacing is about cost, not correctness.
117
+ const sink = new ColumnarIndexSink();
118
+ const index = new PrefixTypeIndex(sink, new StepTypeIndexer(EntityTypesIfcCount), { growthFactor: 1, minimumRecords: 0 });
119
+ const counts = [];
120
+ buildIndexStreaming(new BufferByteSource(bytes), IfcStepParser.Instance, 4 * 1024, (localID) => {
121
+ if (localID === 64 || localID === 128) {
122
+ counts.push([...index.expressIDsOfTypes(IfcRoot)].length);
123
+ }
124
+ }, sink);
125
+ const final = [...index.expressIDsOfTypes(IfcRoot)].length;
126
+ const resident = [...model.expressIDsOfTypes(IfcRoot)].length;
127
+ expect(counts).toHaveLength(2);
128
+ expect(counts[0]).toBeLessThanOrEqual(counts[1]);
129
+ expect(counts[1]).toBeLessThanOrEqual(final);
130
+ expect(final).toBe(resident);
131
+ });
132
+ test("a record is indexed before its own event fires", () => {
133
+ // The event announces record N; a consumer querying the index from that
134
+ // event must see N, not 0..N-1. One record makes the off-by-one total:
135
+ // the only record in the file would be invisible to the only event.
136
+ const source = [
137
+ "ISO-10303-21;",
138
+ "HEADER;",
139
+ "FILE_DESCRIPTION((''),'');",
140
+ "FILE_NAME('','',(''),(''),'','','');",
141
+ "FILE_SCHEMA(('IFC4'));",
142
+ "ENDSEC;",
143
+ "DATA;",
144
+ "#1= IFCPROJECT('p',$,'Only Record',$,$,$,$,$,$);",
145
+ "ENDSEC;",
146
+ "END-ISO-10303-21;",
147
+ "",
148
+ ].join("\n");
149
+ const sink = new ColumnarIndexSink();
150
+ const index = new PrefixTypeIndex(sink, new StepTypeIndexer(EntityTypesIfcCount), { growthFactor: 1, minimumRecords: 0 });
151
+ const seenInEvent = [];
152
+ const result = buildIndexStreaming(new BufferByteSource(new TextEncoder().encode(source)), IfcStepParser.Instance, 4 * 1024, () => {
153
+ seenInEvent.push([...index.expressIDsOfTypes(IfcProject)]);
154
+ }, sink);
155
+ expect(result.result).toBe(ParseResult.COMPLETE);
156
+ expect(seenInEvent).toEqual([[1]]);
157
+ });
158
+ test("an early query on a small file does not freeze the view", () => {
159
+ // index.ifc has fewer records than the default minimumRecords, so it sits
160
+ // entirely in the "rebuild is trivial, stay exact" regime. Querying from
161
+ // the very first event must not pin the view to that one-record prefix
162
+ // for the rest of the parse — least of all after it finishes.
163
+ const sink = new ColumnarIndexSink();
164
+ const index = new PrefixTypeIndex(sink, new StepTypeIndexer(EntityTypesIfcCount));
165
+ let queriedEarly = false;
166
+ buildIndexStreaming(new BufferByteSource(bytes), IfcStepParser.Instance, 4 * 1024, (localID) => {
167
+ if (localID === 0) {
168
+ expect([...index.expressIDsOfTypes(IfcRoot)]).toHaveLength(0);
169
+ queriedEarly = true;
170
+ }
171
+ }, sink);
172
+ expect(queriedEarly).toBe(true);
173
+ expect(sink.topLevelCount).toBeLessThan(1024);
174
+ const final = new Set(index.expressIDsOfTypes(IfcRoot));
175
+ const resident = new Set(model.expressIDsOfTypes(IfcRoot));
176
+ expect(final).toEqual(resident);
177
+ });
178
+ test("a sink reset invalidates the view instead of pacing past it", () => {
179
+ // The streaming builder's grow-and-restart resets the sink. Growth pacing
180
+ // alone would never notice: the count drops, and a restarted parse can
181
+ // finish below the threshold the abandoned pass already built at.
182
+ const sink = new ColumnarIndexSink();
183
+ const index = new PrefixTypeIndex(sink, new StepTypeIndexer(16));
184
+ for (let record = 0; record < 8; ++record) {
185
+ sink.pushTopLevel({ address: record, length: 1, typeID: 5, expressID: record + 1 });
186
+ }
187
+ expect([...index.expressIDsOfTypeIDs(5)]).toHaveLength(8);
188
+ expect(index.generation).toBe(1);
189
+ sink.reset();
190
+ sink.pushTopLevel({ address: 0, length: 1, typeID: 5, expressID: 99 });
191
+ expect([...index.expressIDsOfTypeIDs(5)]).toEqual([99]);
192
+ expect(index.generation).toBe(2);
193
+ });
194
+ // Property sweep: whatever the query cadence and pacing, two invariants must
195
+ // hold at every query, and between them they pin the whole contract —
196
+ // consistency: the view equals a resident parse of exactly the records it
197
+ // claims to cover (`recordCount`), so it is never a mix of prefixes;
198
+ // freshness: `recordCount` is either current, or within `growthFactor`
199
+ // of current, so a view can go stale but can never be abandoned.
200
+ // Each of the mid-parse bugs found in review violated one of these; asserting
201
+ // only the final state (as the first tests here did) passes through all of
202
+ // them, because everything is exact once the parse returns.
203
+ describe.each([
204
+ ["default pacing", { growthFactor: 2, minimumRecords: 1024 }],
205
+ ["paced from the start", { growthFactor: 2, minimumRecords: 0 }],
206
+ ["coarse pacing", { growthFactor: 4, minimumRecords: 8 }],
207
+ ["fine pacing", { growthFactor: 1.25, minimumRecords: 32 }],
208
+ ["never paced", { growthFactor: 1, minimumRecords: 0 }],
209
+ ])("invariants under %s", (_name, options) => {
210
+ test.each([1, 7, 97, 0])("hold when queried every %i records (0 = only at the end)", (cadence) => {
211
+ const closure = IfcRoot.query;
212
+ const sink = new ColumnarIndexSink();
213
+ const index = new PrefixTypeIndex(sink, new StepTypeIndexer(EntityTypesIfcCount), options);
214
+ let queries = 0;
215
+ /** Query once and assert both invariants against the ground truth. */
216
+ const queryAndCheck = () => {
217
+ const parsed = sink.topLevelCount;
218
+ const view = new Set(index.expressIDsOfTypes(IfcRoot));
219
+ ++queries;
220
+ expect(view).toEqual(expectedOverPrefix(index.recordCount, closure));
221
+ const fresh = index.recordCount === parsed ||
222
+ parsed < index.recordCount * options.growthFactor;
223
+ expect(fresh).toBe(true);
224
+ };
225
+ const result = buildIndexStreaming(new BufferByteSource(bytes), IfcStepParser.Instance, 4 * 1024, cadence === 0 ?
226
+ void 0 :
227
+ (localID) => {
228
+ if (localID % cadence === 0) {
229
+ queryAndCheck();
230
+ }
231
+ }, sink);
232
+ expect(result.result).toBe(ParseResult.COMPLETE);
233
+ queryAndCheck();
234
+ expect(queries).toBeGreaterThan(0);
235
+ // And an explicit refresh always lands on the whole file, whatever
236
+ // the pacing left behind.
237
+ index.refresh();
238
+ expect(new Set(index.expressIDsOfTypes(IfcRoot)))
239
+ .toEqual(new Set(model.expressIDsOfTypes(IfcRoot)));
240
+ });
241
+ });
242
+ // Cursors come from LIFO pools, so "was it returned?" is observable by
243
+ // identity: park one in the pool, run a query, and see whether the next
244
+ // allocation hands back the same instance. A query that leaks its cursor
245
+ // leaves the pool empty and the next allocation is a fresh object.
246
+ //
247
+ // Both cursor kinds are covered because which one a query allocates depends
248
+ // on the size of the subtype closure — IfcProject's is a single type
249
+ // (SingleIndexSetCursor), a two-type query is a union
250
+ // (MultiIndexSetCursorOr). Testing only a subtyped query would park a single
251
+ // cursor that the query never touches, and pass no matter what.
252
+ describe.each([
253
+ ["single-type", () => SingleIndexSetCursor.allocate(new Uint32Array(2)), (index) => index.expressIDsOfTypes(IfcProject)],
254
+ ["multi-type", () => MultiIndexSetCursorOr.allocate(new Uint32Array(2)), (index) => index.expressIDsOfTypes(IfcProject, IfcPropertySet)],
255
+ ])("the %s cursor pool", (_name, park, query) => {
256
+ test.each([
257
+ ["a fully consumed query", (ids) => {
258
+ for (const _id of ids) {
259
+ // drain
260
+ }
261
+ }],
262
+ ["a query abandoned partway", (ids) => {
263
+ for (const _id of ids) {
264
+ break;
265
+ }
266
+ }],
267
+ ])("gets its cursor back after %s", (_consumeName, consume) => {
268
+ // The abandoned case is the one that needs try/finally rather than a
269
+ // free() after the loop — a consumer breaking out of a query is
270
+ // ordinary, not exceptional.
271
+ const index = streamed();
272
+ const parked = park();
273
+ parked.free();
274
+ consume(query(index));
275
+ const reused = park();
276
+ reused.free();
277
+ expect(reused).toBe(parked);
278
+ });
279
+ });
280
+ test("complex records are attributed to their mapped classes", () => {
281
+ // Built by hand rather than parsed: the point is precisely the shape the
282
+ // record event cannot express — one address, typeID 0, several mapped
283
+ // classes hanging off it.
284
+ const sink = new ColumnarIndexSink();
285
+ sink.pushTopLevel({ address: 0, length: 10, typeID: 5, expressID: 1 });
286
+ sink.pushTopLevel({
287
+ address: 10,
288
+ length: 20,
289
+ typeID: 0,
290
+ expressID: 2,
291
+ multiMapping: [{ address: 12, length: 5, typeID: 7 }],
292
+ });
293
+ const index = new PrefixTypeIndex(sink, new StepTypeIndexer(16));
294
+ expect([...index.expressIDsOfTypeIDs(5)]).toEqual([1]);
295
+ expect([...index.expressIDsOfTypeIDs(7)]).toEqual([2]);
296
+ expect([...index.types()]).toEqual(expect.arrayContaining([5, 7]));
297
+ });
298
+ });
@@ -0,0 +1,69 @@
1
+ import { StepExternalByteStore } from "../step_buffer_provider.js";
2
+ /**
3
+ * Fetch accounting for a {@link RangeByteSource}: how many range requests were
4
+ * issued and how many bytes actually crossed the wire, versus how many the
5
+ * caller asked for. The gap between `bytesFetched` and `bytesServed` is the
6
+ * over-read imposed by block alignment (a real HTTP-Range / OPFS-block store
7
+ * can only fetch whole blocks); a small gap means the access pattern has good
8
+ * locality — the property an index-first open (M4) leans on.
9
+ */
10
+ export interface RangeFetchStats {
11
+ /** Number of `read` calls that reached the backing store. */
12
+ requestCount: number;
13
+ /** Total bytes actually fetched from the backing store (aligned spans). */
14
+ bytesFetched: number;
15
+ /** Total bytes handed back to callers (the sum of requested lengths). */
16
+ bytesServed: number;
17
+ }
18
+ /**
19
+ * An asynchronous {@link StepExternalByteStore} that models a **range-fetched**
20
+ * source — an HTTP server honouring `Range:` requests, or an OPFS/blob store
21
+ * read block-by-block — so the index-first open path (M4) can be exercised and
22
+ * measured without a network. It wraps a fully-resident buffer (the "server")
23
+ * but never assumes the client holds it: every `read` is counted as a fetch,
24
+ * and with a `blockBytes` grid the fetch is rounded out to whole blocks, so
25
+ * {@link stats} reports the real transfer an aligned store would incur.
26
+ *
27
+ * This is the source a sidecar-driven open pairs with: reconstruct the entity
28
+ * index from the sidecar (no scan), then pull only the byte ranges demand asks
29
+ * for through a source like this — and read back from `stats` how little of the
30
+ * file that touched.
31
+ */
32
+ export declare class RangeByteSource implements StepExternalByteStore {
33
+ private readonly bytes_;
34
+ private readonly blockBytes_;
35
+ private requestCount_;
36
+ private bytesFetched_;
37
+ private bytesServed_;
38
+ /**
39
+ * @param bytes_ The full backing bytes (the notional server-side file). Not
40
+ * copied; treated as read-only.
41
+ * @param blockBytes Optional fetch granularity: reads are rounded out to a
42
+ * multiple of this so `bytesFetched` reflects whole-block transfer. Omit (or
43
+ * pass 0) for exact, unaligned fetches.
44
+ */
45
+ constructor(bytes_: Uint8Array, blockBytes?: number);
46
+ /**
47
+ * Total size of the stored byte sequence.
48
+ *
49
+ * @return {number} The byte length.
50
+ */
51
+ get byteLength(): number;
52
+ /**
53
+ * A snapshot of the fetch counters.
54
+ *
55
+ * @return {RangeFetchStats} The current stats.
56
+ */
57
+ get stats(): RangeFetchStats;
58
+ /**
59
+ * Read a range, accounting for the (block-aligned) fetch it would incur.
60
+ * Returns exactly the requested `length` bytes as a standalone array, even
61
+ * though the underlying fetch may have pulled a wider aligned span.
62
+ *
63
+ * @param offset Absolute offset of the first byte to read.
64
+ * @param length Number of bytes to read.
65
+ * @return {Promise< Uint8Array >} The requested bytes (byteOffset 0).
66
+ */
67
+ read(offset: number, length: number): Promise<Uint8Array>;
68
+ }
69
+ //# sourceMappingURL=range_byte_source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"range_byte_source.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/range_byte_source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAG/D;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAE9B,6DAA6D;IAC7D,YAAY,EAAE,MAAM,CAAA;IAEpB,2EAA2E;IAC3E,YAAY,EAAE,MAAM,CAAA;IAEpB,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAA;CACpB;AAQD;;;;;;;;;;;;;GAaG;AACH,qBAAa,eAAgB,YAAW,qBAAqB;IAkBvD,OAAO,CAAC,QAAQ,CAAC,MAAM;IAhB3B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IAEpC,OAAO,CAAC,aAAa,CAAI;IAEzB,OAAO,CAAC,aAAa,CAAI;IAEzB,OAAO,CAAC,YAAY,CAAI;IAExB;;;;;;OAMG;gBAEkB,MAAM,EAAE,UAAU,EACnC,UAAU,GAAE,MAAU;IAS1B;;;;OAIG;IACH,IAAW,UAAU,IAAI,MAAM,CAE9B;IAED;;;;OAIG;IACH,IAAW,KAAK,IAAI,eAAe,CAMlC;IAED;;;;;;;;OAQG;IACI,IAAI,CAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAI,OAAO,CAAE,UAAU,CAAE;CAkBrE"}
@@ -0,0 +1,78 @@
1
+ // Default block granularity when none is given: reads are unaligned, so
2
+ // `bytesFetched` equals `bytesServed` (each read fetches exactly its range).
3
+ const NO_ALIGNMENT = 1;
4
+ /**
5
+ * An asynchronous {@link StepExternalByteStore} that models a **range-fetched**
6
+ * source — an HTTP server honouring `Range:` requests, or an OPFS/blob store
7
+ * read block-by-block — so the index-first open path (M4) can be exercised and
8
+ * measured without a network. It wraps a fully-resident buffer (the "server")
9
+ * but never assumes the client holds it: every `read` is counted as a fetch,
10
+ * and with a `blockBytes` grid the fetch is rounded out to whole blocks, so
11
+ * {@link stats} reports the real transfer an aligned store would incur.
12
+ *
13
+ * This is the source a sidecar-driven open pairs with: reconstruct the entity
14
+ * index from the sidecar (no scan), then pull only the byte ranges demand asks
15
+ * for through a source like this — and read back from `stats` how little of the
16
+ * file that touched.
17
+ */
18
+ export class RangeByteSource {
19
+ /**
20
+ * @param bytes_ The full backing bytes (the notional server-side file). Not
21
+ * copied; treated as read-only.
22
+ * @param blockBytes Optional fetch granularity: reads are rounded out to a
23
+ * multiple of this so `bytesFetched` reflects whole-block transfer. Omit (or
24
+ * pass 0) for exact, unaligned fetches.
25
+ */
26
+ constructor(bytes_, blockBytes = 0) {
27
+ this.bytes_ = bytes_;
28
+ this.requestCount_ = 0;
29
+ this.bytesFetched_ = 0;
30
+ this.bytesServed_ = 0;
31
+ if (blockBytes < 0) {
32
+ throw new Error(`Invalid blockBytes ${blockBytes}`);
33
+ }
34
+ this.blockBytes_ = blockBytes > 0 ? blockBytes : NO_ALIGNMENT;
35
+ }
36
+ /**
37
+ * Total size of the stored byte sequence.
38
+ *
39
+ * @return {number} The byte length.
40
+ */
41
+ get byteLength() {
42
+ return this.bytes_.byteLength;
43
+ }
44
+ /**
45
+ * A snapshot of the fetch counters.
46
+ *
47
+ * @return {RangeFetchStats} The current stats.
48
+ */
49
+ get stats() {
50
+ return {
51
+ requestCount: this.requestCount_,
52
+ bytesFetched: this.bytesFetched_,
53
+ bytesServed: this.bytesServed_,
54
+ };
55
+ }
56
+ /**
57
+ * Read a range, accounting for the (block-aligned) fetch it would incur.
58
+ * Returns exactly the requested `length` bytes as a standalone array, even
59
+ * though the underlying fetch may have pulled a wider aligned span.
60
+ *
61
+ * @param offset Absolute offset of the first byte to read.
62
+ * @param length Number of bytes to read.
63
+ * @return {Promise< Uint8Array >} The requested bytes (byteOffset 0).
64
+ */
65
+ read(offset, length) {
66
+ const total = this.bytes_.byteLength;
67
+ const start = Math.max(0, Math.min(offset, total));
68
+ const end = Math.max(start, Math.min(offset + length, total));
69
+ // The aligned span a block-granular store would actually transfer.
70
+ const block = this.blockBytes_;
71
+ const fetchStart = start - (start % block);
72
+ const fetchEnd = Math.min(total, Math.ceil(end / block) * block);
73
+ this.requestCount_ += 1;
74
+ this.bytesFetched_ += fetchEnd - fetchStart;
75
+ this.bytesServed_ += end - start;
76
+ return Promise.resolve(this.bytes_.slice(start, end));
77
+ }
78
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=range_byte_source.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"range_byte_source.test.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/range_byte_source.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,70 @@
1
+ /* eslint-disable no-magic-numbers */
2
+ // M4: the range-fetched byte source models an HTTP-Range / block store — it
3
+ // returns exactly the requested bytes while accounting for the (possibly
4
+ // wider, block-aligned) fetch it would really incur. Index-first open reads
5
+ // back from those stats to prove it touched only a fraction of the file.
6
+ import { describe, expect, test } from "@jest/globals";
7
+ import { RangeByteSource } from "./range_byte_source.js";
8
+ /**
9
+ * A deterministic ramp buffer: byte i === i mod 256.
10
+ *
11
+ * @param n Length.
12
+ * @return {Uint8Array} The buffer.
13
+ */
14
+ function ramp(n) {
15
+ const bytes = new Uint8Array(n);
16
+ for (let where = 0; where < n; ++where) {
17
+ bytes[where] = where & 255;
18
+ }
19
+ return bytes;
20
+ }
21
+ describe("RangeByteSource", () => {
22
+ test("returns exactly the requested range", async () => {
23
+ const source = new RangeByteSource(ramp(1000));
24
+ const got = await source.read(100, 16);
25
+ expect(got.byteLength).toBe(16);
26
+ expect(Array.from(got)).toEqual(Array.from({ length: 16 }, (_v, i) => (100 + i) & 255));
27
+ });
28
+ test("unaligned reads fetch exactly what is served", async () => {
29
+ const source = new RangeByteSource(ramp(1000));
30
+ await source.read(10, 20);
31
+ await source.read(500, 4);
32
+ const stats = source.stats;
33
+ expect(stats.requestCount).toBe(2);
34
+ expect(stats.bytesServed).toBe(24);
35
+ expect(stats.bytesFetched).toBe(24);
36
+ });
37
+ test("block alignment over-reads to whole blocks", async () => {
38
+ const source = new RangeByteSource(ramp(10000), 4096);
39
+ // A 10-byte read at offset 100 sits inside the first 4096-byte block.
40
+ await source.read(100, 10);
41
+ expect(source.stats.bytesFetched).toBe(4096);
42
+ expect(source.stats.bytesServed).toBe(10);
43
+ // A read straddling the first/second block boundary pulls two blocks.
44
+ await source.read(4090, 20);
45
+ expect(source.stats.bytesFetched).toBe(4096 + 8192);
46
+ expect(source.stats.bytesServed).toBe(30);
47
+ });
48
+ test("clamps reads at end of source", async () => {
49
+ const source = new RangeByteSource(ramp(100));
50
+ const got = await source.read(90, 50);
51
+ expect(got.byteLength).toBe(10);
52
+ expect(source.stats.bytesServed).toBe(10);
53
+ });
54
+ test("a read fully past the end is empty and fetches nothing", async () => {
55
+ const source = new RangeByteSource(ramp(100));
56
+ const got = await source.read(200, 10);
57
+ expect(got.byteLength).toBe(0);
58
+ expect(source.stats.bytesFetched).toBe(0);
59
+ });
60
+ test("block-aligned fetch never exceeds the source length", async () => {
61
+ const source = new RangeByteSource(ramp(5000), 4096);
62
+ // Last block is partial (5000 = 4096 + 904); fetching into it must clamp.
63
+ await source.read(4990, 10);
64
+ expect(source.stats.bytesFetched).toBe(5000 - 4096);
65
+ expect(source.stats.bytesFetched).toBeLessThanOrEqual(5000);
66
+ });
67
+ test("reports byteLength of the backing source", () => {
68
+ expect(new RangeByteSource(ramp(777)).byteLength).toBe(777);
69
+ });
70
+ });
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The streaming parse's per-record event (M2, issue #393): fired as each
3
+ * top-level record is indexed, before the record's bytes leave the window.
4
+ *
5
+ * The record's raw bytes are handed over as `(buffer, byteOffset, byteLength)`
6
+ * rather than as a `Uint8Array` slice, deliberately: a slice would be a fresh
7
+ * object per record — 9.4 M allocations on a PSB-class file, measured at ~5.7 %
8
+ * of parse wall-clock and ~46 MB of retained heap for handlers that never look
9
+ * at the bytes (the spike in `scripts/m2_consumer_spike.mjs`). With the view
10
+ * un-materialised, a handler that only wants ids pays nothing, and one that
11
+ * wants bytes calls `buffer.subarray( byteOffset, byteOffset + byteLength )`
12
+ * itself.
13
+ *
14
+ * `buffer` is the parse window, so the bytes are valid ONLY for the duration
15
+ * of the call — the window slides and is overwritten as the parse advances.
16
+ * A handler that needs them later must copy.
17
+ *
18
+ * Handlers run synchronously inside the parse loop and must stay cheap
19
+ * (copy ids into compact structures). Anything expensive belongs on the
20
+ * demand queue — see design/new/streaming-federated-loader.md § 2.
21
+ */
22
+ export type RecordEventHandler<TypeIDType> = (localID: number, expressID: number, typeID: TypeIDType | undefined, buffer?: Uint8Array, byteOffset?: number, byteLength?: number) => void;
23
+ //# sourceMappingURL=record_event.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record_event.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/record_event.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,MAAM,kBAAkB,CAAC,UAAU,IAAI,CAC3C,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,UAAU,GAAG,SAAS,EAC9B,MAAM,CAAC,EAAE,UAAU,EACnB,UAAU,CAAC,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,MAAM,KAAM,IAAI,CAAA"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,94 @@
1
+ import StepParser from "./step_parser.js";
2
+ /**
3
+ * Reads individual attributes out of a record's raw bytes, without a model and
4
+ * without materialising an entity (M2, issue #393).
5
+ *
6
+ * This is what makes a parse-path consumer viable at all: the streaming
7
+ * parse's record event hands over the record's attribute list as a window
8
+ * range, and a consumer that wants two strings out of it should not have to
9
+ * wait for the model, page the record back in, and construct an entity to get
10
+ * them. Field positions come from the production tokenizer
11
+ * ({@link StepParser.extractDataEntry}), so a record this reads and a record
12
+ * the model reads agree by construction — including on the awkward cases
13
+ * (quoted commas, nested parens, escaped quotes) a hand-rolled splitter gets
14
+ * wrong.
15
+ *
16
+ * One instance is reused across records: {@link open} clears and refills a
17
+ * single vtable buffer, so a consumer running over millions of records
18
+ * allocates nothing per record. Attribute indices are the same ones the
19
+ * generated accessors use (`extractString( 2, … )` for `IfcRoot.Name`, and so
20
+ * on), read against the *record's own* attribute list — inherited attributes
21
+ * included, since STEP serialises the flattened list.
22
+ */
23
+ export declare class RecordFieldCursor<TypeIDType> {
24
+ private readonly parser_;
25
+ private readonly vtable_;
26
+ private buffer_;
27
+ private indexMark_;
28
+ private fieldCount_;
29
+ private endCursor_;
30
+ /**
31
+ * @param parser_ The schema's parser — used only for its record tokenizer.
32
+ */
33
+ constructor(parser_: StepParser<TypeIDType>);
34
+ /**
35
+ * Point this at one record's attribute list.
36
+ *
37
+ * @param buffer The buffer holding the record (the live parse window, for an
38
+ * event consumer — so everything read here must be read before returning).
39
+ * @param byteOffset Offset of the record's first attribute byte.
40
+ * @param byteLength Length of the attribute list in bytes.
41
+ * @return {number} The number of top-level attributes found; 0 if the record
42
+ * could not be tokenized (a truncated or malformed record — the caller
43
+ * should skip it rather than guess).
44
+ */
45
+ open(buffer: Uint8Array, byteOffset: number, byteLength: number): number;
46
+ /**
47
+ * The byte range of one attribute, as `[start, end)`.
48
+ *
49
+ * @param index The attribute index.
50
+ * @return {[number, number] | undefined} The range, or undefined when the
51
+ * record has no such attribute.
52
+ */
53
+ private range;
54
+ /**
55
+ * Read a string attribute.
56
+ *
57
+ * @param index The attribute index.
58
+ * @return {string | undefined} The decoded string, or undefined when the
59
+ * attribute is absent, `$`, or not a string.
60
+ */
61
+ string(index: number): string | undefined;
62
+ /**
63
+ * Read a single express reference attribute (`#123`).
64
+ *
65
+ * @param index The attribute index.
66
+ * @return {number | undefined} The express ID, or undefined when the
67
+ * attribute is absent or is not a reference.
68
+ */
69
+ reference(index: number): number | undefined;
70
+ /**
71
+ * Visit every express reference in an attribute, which is how a reference
72
+ * list (`(#1,#2,#3)`) is read — the enclosing parens and separators need no
73
+ * interpretation, since a reference is the only thing a `#` can start.
74
+ *
75
+ * @param index The attribute index.
76
+ * @param visit Called with each express ID, in order.
77
+ */
78
+ forEachReference(index: number, visit: (expressID: number) => void): void;
79
+ /**
80
+ * Read the digits of a reference whose `#` sits at `cursor`.
81
+ *
82
+ * @param cursor Offset of the `#`.
83
+ * @param end Exclusive end of the attribute.
84
+ * @return {number | undefined} The express ID, or undefined if `cursor` is
85
+ * not a `#` followed by at least one digit.
86
+ */
87
+ private readReferenceAt;
88
+ /**
89
+ * @param code A byte.
90
+ * @return {boolean} Whether it is an ASCII digit.
91
+ */
92
+ private isDigit;
93
+ }
94
+ //# sourceMappingURL=record_field_cursor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record_field_cursor.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/record_field_cursor.ts"],"names":[],"mappings":"AACA,OAAO,UAAU,MAAM,eAAe,CAAA;AAkBtC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,iBAAiB,CAAC,UAAU;IAe1B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAbrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAElD,OAAO,CAAC,OAAO,CAAiC;IAEhD,OAAO,CAAC,UAAU,CAAI;IAEtB,OAAO,CAAC,WAAW,CAAI;IAEvB,OAAO,CAAC,UAAU,CAAI;IAEtB;;OAEG;gBAC2B,OAAO,EAAE,UAAU,CAAC,UAAU,CAAC;IAE7D;;;;;;;;;;OAUG;IACI,IAAI,CAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAI,MAAM;IAsBjF;;;;;;OAMG;IACH,OAAO,CAAC,KAAK;IAiBb;;;;;;OAMG;IACI,MAAM,CAAE,KAAK,EAAE,MAAM,GAAI,MAAM,GAAG,SAAS;IAUlD;;;;;;OAMG;IACI,SAAS,CAAE,KAAK,EAAE,MAAM,GAAI,MAAM,GAAG,SAAS;IAwBrD;;;;;;;OAOG;IACI,gBAAgB,CAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAE,SAAS,EAAE,MAAM,KAAM,IAAI,GAAI,IAAI;IA8BpF;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;IAoBvB;;;OAGG;IACH,OAAO,CAAC,OAAO;CAGhB"}