@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,122 @@
1
+ /* eslint-disable no-magic-numbers */
2
+ // M4: the index sidecar must serialise a model's parse index and deserialise
3
+ // it back byte-identically, so an index-first open reconstructs the entity
4
+ // index without re-scanning the source — and it must refuse to be trusted when
5
+ // the source it was built from no longer matches (hash / length handshake).
6
+ import * as fs from "fs";
7
+ import { describe, expect, test } from "@jest/globals";
8
+ import ParsingBuffer from "../../parsing/parsing_buffer.js";
9
+ import IfcStepParser from "../../ifc/ifc_step_parser.js";
10
+ import { deserializeIndexSidecar, deserializeIndexSidecarToColumns, hashSource, serializeIndexSidecar, serializeIndexSidecarFromColumns, sidecarMatchesSource, } from "./index_sidecar.js";
11
+ import { BufferByteSource } from "./byte_source.js";
12
+ import { buildColumnarIndexStreaming } from "./streaming_index_builder.js";
13
+ /**
14
+ * Parse index.ifc resident and return its top-level element index plus the
15
+ * source bytes it was built from.
16
+ *
17
+ * @return {object} `{ bytes, elements }`.
18
+ */
19
+ function residentIndex() {
20
+ const bytes = new Uint8Array(fs.readFileSync("data/index.ifc"));
21
+ const input = new ParsingBuffer(bytes);
22
+ IfcStepParser.Instance.parseHeader(input);
23
+ const [index,] = IfcStepParser.Instance.parseDataBlock(input);
24
+ return { bytes, elements: index.elements };
25
+ }
26
+ describe("index sidecar", () => {
27
+ test("round-trips the top-level index byte-identically", () => {
28
+ const { bytes, elements } = residentIndex();
29
+ const hash = hashSource(bytes);
30
+ const blob = serializeIndexSidecar(elements, bytes.byteLength, hash);
31
+ const decoded = deserializeIndexSidecar(blob);
32
+ expect(decoded.sourceByteLength).toBe(bytes.byteLength);
33
+ expect(decoded.sourceHash).toBe(hash);
34
+ expect(decoded.elements.length).toBe(elements.length);
35
+ for (let where = 0; where < elements.length; ++where) {
36
+ const original = elements[where];
37
+ const restored = decoded.elements[where];
38
+ expect(restored.address).toBe(original.address);
39
+ expect(restored.length).toBe(original.length);
40
+ expect(restored.expressID).toBe(original.expressID);
41
+ // typeID round-trips including the undefined case (stored as -1).
42
+ expect(restored.typeID).toBe(original.typeID);
43
+ }
44
+ });
45
+ test("accepts a sidecar whose hash and length match the source", () => {
46
+ const { bytes, elements } = residentIndex();
47
+ const hash = hashSource(bytes);
48
+ const decoded = deserializeIndexSidecar(serializeIndexSidecar(elements, bytes.byteLength, hash));
49
+ expect(sidecarMatchesSource(decoded, bytes.byteLength, hash)).toBe(true);
50
+ });
51
+ test("rejects a sidecar when the source bytes changed (hash mismatch)", () => {
52
+ const { bytes, elements } = residentIndex();
53
+ const hash = hashSource(bytes);
54
+ const decoded = deserializeIndexSidecar(serializeIndexSidecar(elements, bytes.byteLength, hash));
55
+ // Same length, one byte flipped → different hash → must not be trusted.
56
+ const mutated = bytes.slice();
57
+ mutated[Math.floor(mutated.length / 2)] ^= 255;
58
+ expect(sidecarMatchesSource(decoded, mutated.byteLength, hashSource(mutated)))
59
+ .toBe(false);
60
+ });
61
+ test("rejects a sidecar when the source length changed", () => {
62
+ const { bytes, elements } = residentIndex();
63
+ const hash = hashSource(bytes);
64
+ const decoded = deserializeIndexSidecar(serializeIndexSidecar(elements, bytes.byteLength, hash));
65
+ expect(sidecarMatchesSource(decoded, bytes.byteLength + 1, hash))
66
+ .toBe(false);
67
+ });
68
+ test("hashSource is deterministic and sensitive to content", () => {
69
+ const a = new Uint8Array([1, 2, 3, 4, 5]);
70
+ const b = new Uint8Array([1, 2, 3, 4, 5]);
71
+ const c = new Uint8Array([1, 2, 3, 4, 6]);
72
+ expect(hashSource(a)).toBe(hashSource(b));
73
+ expect(hashSource(a)).not.toBe(hashSource(c));
74
+ });
75
+ test("preserves undefined typeID through the -1 sentinel", () => {
76
+ const elements = [
77
+ { address: 0, length: 10, typeID: 7, expressID: 1 },
78
+ { address: 10, length: 20, typeID: void 0, expressID: 2 },
79
+ { address: 30, length: 5, typeID: 0, expressID: 3 },
80
+ ];
81
+ const decoded = deserializeIndexSidecar(serializeIndexSidecar(elements, 35, 0));
82
+ expect(decoded.elements[0].typeID).toBe(7);
83
+ expect(decoded.elements[1].typeID).toBe(void 0);
84
+ expect(decoded.elements[2].typeID).toBe(0);
85
+ });
86
+ test("throws on a blob with bad magic", () => {
87
+ const garbage = new Uint8Array(32);
88
+ expect(() => deserializeIndexSidecar(garbage)).toThrow(/magic/);
89
+ });
90
+ test("round-trips an empty index", () => {
91
+ const decoded = deserializeIndexSidecar(serializeIndexSidecar([], 0, 0));
92
+ expect(decoded.elements.length).toBe(0);
93
+ });
94
+ test("columns-form serialize is byte-identical to the object-form blob (M7)", () => {
95
+ const { bytes, elements } = residentIndex();
96
+ const hash = hashSource(bytes);
97
+ const { columns } = buildColumnarIndexStreaming(new BufferByteSource(bytes),
98
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
99
+ IfcStepParser.Instance, 4096);
100
+ const fromObjects = serializeIndexSidecar(elements, bytes.byteLength, hash);
101
+ const fromColumns = serializeIndexSidecarFromColumns(columns, bytes.byteLength, hash);
102
+ expect(fromColumns).toEqual(fromObjects);
103
+ });
104
+ test("deserializes straight to columns for the index-first open (M7)", () => {
105
+ const { bytes, elements } = residentIndex();
106
+ const hash = hashSource(bytes);
107
+ const blob = serializeIndexSidecar(elements, bytes.byteLength, hash);
108
+ const restored = deserializeIndexSidecarToColumns(blob);
109
+ expect(restored.sourceByteLength).toBe(bytes.byteLength);
110
+ expect(restored.sourceHash).toBe(hash);
111
+ expect(restored.columns.count).toBe(elements.length);
112
+ expect(restored.columns.firstInlineElement).toBe(elements.length);
113
+ expect(restored.columns.expressIdsSorted).toBe(true);
114
+ for (let where = 0; where < elements.length; ++where) {
115
+ expect(restored.columns.address[where]).toBe(elements[where].address);
116
+ expect(restored.columns.length[where]).toBe(elements[where].length);
117
+ expect(restored.columns.expressID[where]).toBe(elements[where].expressID);
118
+ expect(restored.columns.typeID[where])
119
+ .toBe(elements[where].typeID ?? -1);
120
+ }
121
+ });
122
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=inf_recovery_index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inf_recovery_index.test.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/inf_recovery_index.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,108 @@
1
+ // `INF` where a real belongs is not valid ISO 10303-21, but exporters emit it
2
+ // for unbounded quantities and the parser recovers from it. The recovery used
3
+ // to stamp the offending record's express ID over every top-level entry
4
+ // indexed so far in the block, which corrupted every lookup that followed.
5
+ //
6
+ // It stayed hidden only because no public corpus model reaches this recovery.
7
+ // Not because a failed parse is harmless: the stamping ran before the rollback
8
+ // and the INF check, so any top-level inline-instance failure poisoned the
9
+ // index, and parseDataToModel builds a model from those elements whatever the
10
+ // ParseResult. A private model reaches it - `IFCQUANTITYLENGTH(...,INF,$)`
11
+ // from a Swiss architectural export - where it cost 3,116 entities and
12
+ // produced 630 relationship failures all reporting the same express ID.
13
+ // See bldrs-ai/conway#412, #481, #482.
14
+ //
15
+ // Parser-only, so no geometry wasm is initialized here.
16
+ import { describe, expect, test } from "@jest/globals";
17
+ import IfcStepParser from "../../ifc/ifc_step_parser.js";
18
+ import ParsingBuffer from "../../parsing/parsing_buffer.js";
19
+ import { ParseResult } from "./step_parser.js";
20
+ const parser = IfcStepParser.Instance;
21
+ // The middle record carries the bare INF. The records around it are ordinary,
22
+ // and they are the ones the stamping loop used to overwrite - the bug is not
23
+ // in how the INF record itself is read, it is in what reading it does to
24
+ // everything already indexed.
25
+ // The express IDs under test, kept in one place so the assertions read as
26
+ // "the IDs written in the source", which is exactly what the bug destroyed.
27
+ const BEFORE_ID = 11;
28
+ const INF_ID = 22;
29
+ const AFTER_ID = 33;
30
+ const EXPECTED_IDS = [BEFORE_ID, INF_ID, AFTER_ID];
31
+ // One template, one substitution point. Derived with String.replace on a
32
+ // whitespace-exact literal, the controls below would silently become copies of
33
+ // the INF case the moment anyone reflowed the source - replace() returns its
34
+ // input unchanged when the token is absent - and "indexes the same as the
35
+ // equivalent record with a real" would degrade to expect(x).toEqual(x), which
36
+ // passes even with the bug reinstated.
37
+ const VALUE_SLOT = "<<VALUE>>";
38
+ const TEMPLATE = [
39
+ `#${BEFORE_ID}= IFCQUANTITYLENGTH('before',$,$,1.5,$);`,
40
+ `#${INF_ID}= IFCQUANTITYLENGTH('unbounded',$,$,${VALUE_SLOT},$);`,
41
+ `#${AFTER_ID}= IFCQUANTITYLENGTH('after',$,$,2.5,$);`,
42
+ ].join("\n");
43
+ /**
44
+ * Build the fixture with a given value in the middle record's 4th attribute.
45
+ *
46
+ * @param value The value text to substitute.
47
+ * @return {string} The fixture source.
48
+ */
49
+ function withValue(value) {
50
+ if (!TEMPLATE.includes(VALUE_SLOT)) {
51
+ throw new Error("fixture template lost its substitution slot");
52
+ }
53
+ return TEMPLATE.replace(VALUE_SLOT, value);
54
+ }
55
+ // Leading whitespace preserved from the real export, since it is what puts an
56
+ // identifier-like token where an attribute is expected.
57
+ const WITH_INF = withValue(" INF");
58
+ // The control: whatever the index looks like with an ordinary real is what the
59
+ // INF version has to match.
60
+ const WITHOUT_INF = withValue("3.5");
61
+ // The same export writes `-INF` for the opposite bound. Also a CONTROL, not a
62
+ // second case of the bug: a leading '-' is dispatched as a number, so it never
63
+ // reaches the inline-instance recovery and was never affected. Kept so that
64
+ // stays visible - the defect is specific to the bare identifier-like form, and
65
+ // anyone reading INF handling should not assume both directions went through
66
+ // it.
67
+ const WITH_NEGATIVE_INF = withValue(" -INF");
68
+ /**
69
+ * Parse a data block and return each top-level entry's express ID, in order.
70
+ *
71
+ * @param source The STEP text to parse.
72
+ * @return {number[]} Express IDs as indexed.
73
+ */
74
+ function indexedExpressIDs(source) {
75
+ const input = new ParsingBuffer(new TextEncoder().encode(source));
76
+ const [index, result] = parser.parseDataBlock(input);
77
+ // INCOMPLETE is the expected result for a bare run of records with no
78
+ // ENDSEC; terminator - what matters here is that it is not a syntax error.
79
+ expect([ParseResult.COMPLETE, ParseResult.INCOMPLETE]).toContain(result);
80
+ return index.elements.map((element) => element.expressID);
81
+ }
82
+ describe("a bare INF attribute", () => {
83
+ test("does not stamp its express ID over the records before it", () => {
84
+ expect(indexedExpressIDs(WITH_INF)).toEqual(EXPECTED_IDS);
85
+ });
86
+ test("indexes the same as the equivalent record with a real", () => {
87
+ expect(indexedExpressIDs(WITH_INF))
88
+ .toEqual(indexedExpressIDs(WITHOUT_INF));
89
+ });
90
+ // Passes with or without the fix, by design - see WITH_NEGATIVE_INF above.
91
+ test("negative INF is dispatched as a number and never took this path", () => {
92
+ expect(indexedExpressIDs(WITH_NEGATIVE_INF)).toEqual(EXPECTED_IDS);
93
+ });
94
+ // The whole file has to remain resolvable, not just the index array: a
95
+ // corrupted express ID column makes getElementByExpressID hand back the
96
+ // wrong record, which is how this surfaced as relationship failures rather
97
+ // than as a parse error.
98
+ test("every record is still reachable by its own express ID", () => {
99
+ const [result, model] = parser.parseDataToModel(new ParsingBuffer(new TextEncoder().encode(WITH_INF)));
100
+ expect([ParseResult.COMPLETE, ParseResult.INCOMPLETE]).toContain(result);
101
+ expect(model).not.toBeUndefined();
102
+ for (const expressID of EXPECTED_IDS) {
103
+ const element = model?.getElementByExpressID(expressID);
104
+ expect(element).not.toBeUndefined();
105
+ expect(element?.expressID).toBe(expressID);
106
+ }
107
+ });
108
+ });
@@ -0,0 +1,124 @@
1
+ import { StepTypeIndexer } from "../indexing/step_type_indexer.js";
2
+ import { StepEntityConstructorAbstract } from "../step_entity_constructor.js";
3
+ import { ColumnarIndexSink } from "./columnar_index.js";
4
+ /**
5
+ * A type index over the records parsed **so far** (M2, issue #393): the same
6
+ * membership the finished model exposes as `typeIndex`, available while the
7
+ * streaming parse is still running.
8
+ *
9
+ * It is a *derivation over the columnar index*, not a consumer of the
10
+ * per-record event stream — deliberately, and this is the M2 design decision
11
+ * that the 2026-08-18 spike settled (`scripts/m2_consumer_spike.mjs`; issue
12
+ * #393 for the tables). Pushing every record into per-type `Set`s cost +88 %
13
+ * of parse wall-clock and +254 MB on PSB (9.4 M records) and *still* produced
14
+ * the wrong answer — 83 concrete types against the production indexer's 95,
15
+ * because complex records arrive on the event stream as `typeID 0` with their
16
+ * mapped classes stripped. Rebuilding from a prefix snapshot through
17
+ * {@link StepTypeIndexer.createFromColumns} instead costs 121 ms on the same
18
+ * file, sees the complex entries' mapped subtypes, and is membership-identical
19
+ * to the finished model's index by construction — it is literally the same
20
+ * indexer call the model makes.
21
+ *
22
+ * The consequence for callers is that incrementality is a **cadence knob**
23
+ * rather than an architecture. Nothing happens per record; a rebuild happens
24
+ * when someone asks for a view that is more than `growthFactor` stale (14
25
+ * rebuilds over a PSB parse at the default 2.0, +7.2 % if you query
26
+ * continuously, ~0 if you query rarely). Callers that want a specific moment —
27
+ * a preview generation, a progress tick — call {@link refresh} themselves.
28
+ *
29
+ * Two regimes, and the boundary matters: at or below `minimumRecords` a
30
+ * rebuild is trivial, so every query with new records behind it rebuilds and
31
+ * the view is exact; above it, growth pacing applies and a query may see a
32
+ * view up to `growthFactor` stale. The staleness a caller can observe is
33
+ * therefore bounded by the growth factor — never by whatever prefix happened
34
+ * to be current the first time it asked.
35
+ *
36
+ * Queries are only ever answered from a built index, so a caller that has
37
+ * never queried has paid nothing.
38
+ */
39
+ export declare class PrefixTypeIndex<TypeIDType extends number> {
40
+ private readonly sink_;
41
+ private readonly indexer_;
42
+ private index_;
43
+ private columns_;
44
+ private builtAtRecords_;
45
+ private generation_;
46
+ private readonly growthFactor_;
47
+ private readonly minimumRecords_;
48
+ /**
49
+ * @param sink_ The sink the streaming parse is filling. Held live: each
50
+ * rebuild takes a fresh {@link ColumnarIndexSink.snapshot} of it.
51
+ * @param indexer_ The schema's type indexer — the same instance kind the
52
+ * model builds its own `typeIndex` with, which is what makes the two
53
+ * membership-identical.
54
+ * @param options Rebuild pacing.
55
+ * @param options.growthFactor How much the record count must grow past the
56
+ * last build before a query rebuilds (default 2.0).
57
+ * @param options.minimumRecords The record count below which growth pacing
58
+ * is skipped — small parses just rebuild.
59
+ */
60
+ constructor(sink_: ColumnarIndexSink<TypeIDType>, indexer_: StepTypeIndexer<TypeIDType>, options?: {
61
+ growthFactor?: number;
62
+ minimumRecords?: number;
63
+ });
64
+ /**
65
+ * How many rebuilds have happened. A caller pacing its own UI can use this
66
+ * to tell a genuinely new view from a repeat query.
67
+ *
68
+ * @return {number} The generation counter, 0 before the first build.
69
+ */
70
+ get generation(): number;
71
+ /**
72
+ * The record count the current view was built at (0 if never built) — not
73
+ * the parse's current count, which is `sink.count`.
74
+ *
75
+ * @return {number} Records covered by the current view.
76
+ */
77
+ get recordCount(): number;
78
+ /**
79
+ * Rebuild the view over everything parsed so far, unconditionally. This is
80
+ * the expensive call — O(records) — and it is the caller's choice of when.
81
+ */
82
+ refresh(): void;
83
+ /**
84
+ * Rebuild only if the parse has moved far enough past the current view (or
85
+ * there is no view yet). Every query goes through this.
86
+ */
87
+ private ensureFresh;
88
+ /**
89
+ * The distinct types present in the current view, including the mapped
90
+ * classes of complex entries.
91
+ *
92
+ * @return {IterableIterator<TypeIDType>} The types.
93
+ */
94
+ types(): IterableIterator<TypeIDType>;
95
+ /**
96
+ * Express IDs of every record of the given types (subtype closures unioned
97
+ * via the generated `query`, conway #383) among the records parsed so far.
98
+ *
99
+ * @param types The entity constructors to query.
100
+ * @return {IterableIterator<number>} Matching express IDs, in parse order.
101
+ * @yields {number} Each matching express ID.
102
+ */
103
+ expressIDsOfTypes(...types: StepEntityConstructorAbstract<TypeIDType>[]): IterableIterator<number>;
104
+ /**
105
+ * Express IDs of records whose concrete (or mapped) type is one of the
106
+ * given raw type IDs — no subtype expansion. The closure-expanding
107
+ * {@link expressIDsOfTypes} is the caller-facing form; this is for callers
108
+ * that already hold type IDs.
109
+ *
110
+ * @param typeIDs The raw type IDs to union.
111
+ * @return {IterableIterator<number>} Matching express IDs, in parse order.
112
+ * @yields {number} Each matching express ID.
113
+ */
114
+ expressIDsOfTypeIDs(...typeIDs: TypeIDType[]): IterableIterator<number>;
115
+ /**
116
+ * Upper-bound count of records of the given types in the current view (see
117
+ * {@link MultiIndexSet.count} for why it is an upper bound).
118
+ *
119
+ * @param types The entity constructors to count.
120
+ * @return {number} The count.
121
+ */
122
+ count(...types: StepEntityConstructorAbstract<TypeIDType>[]): number;
123
+ }
124
+ //# sourceMappingURL=prefix_type_index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefix_type_index.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/prefix_type_index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAA;AAC1E,OAAO,EAAE,iBAAiB,EAAoB,MAAM,kBAAkB,CAAA;AAUtE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,qBAAa,eAAe,CAAC,UAAU,SAAS,MAAM;IA2BlD,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IA1B3B,OAAO,CAAC,MAAM,CAAgD;IAE9D,OAAO,CAAC,QAAQ,CAAmD;IAEnE,OAAO,CAAC,eAAe,CAAI;IAE3B,OAAO,CAAC,WAAW,CAAI;IAEvB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAQ;IAEtC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAQ;IAExC;;;;;;;;;;;OAWG;gBAEgB,KAAK,EAAE,iBAAiB,CAAC,UAAU,CAAC,EACpC,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,EACtD,OAAO,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE;IAM9D;;;;;OAKG;IACH,IAAW,UAAU,IAAI,MAAM,CAE9B;IAED;;;;;OAKG;IACH,IAAW,WAAW,IAAI,MAAM,CAE/B;IAED;;;OAGG;IACI,OAAO,IAAI,IAAI;IAOtB;;;OAGG;IACH,OAAO,CAAC,WAAW;IAqCnB;;;;;OAKG;IACI,KAAK,IAAI,gBAAgB,CAAC,UAAU,CAAC;IAM5C;;;;;;;OAOG;IACK,iBAAiB,CACrB,GAAG,KAAK,EAAE,6BAA6B,CAAC,UAAU,CAAC,EAAE,GACrD,gBAAgB,CAAC,MAAM,CAAC;IAS5B;;;;;;;;;OASG;IACK,mBAAmB,CAAE,GAAG,OAAO,EAAE,UAAU,EAAE,GAAI,gBAAgB,CAAC,MAAM,CAAC;IAuCjF;;;;;;OAMG;IACI,KAAK,CAAE,GAAG,KAAK,EAAE,6BAA6B,CAAC,UAAU,CAAC,EAAE,GAAI,MAAM;CAS9E"}
@@ -0,0 +1,207 @@
1
+ import { extractOneHotLow } from "../../indexing/bit_operations.js";
2
+ /** Default record growth between automatic rebuilds — see the class docs. */
3
+ const DEFAULT_GROWTH_FACTOR = 2;
4
+ /** Below this many records a rebuild is cheap enough not to bother pacing. */
5
+ const DEFAULT_MINIMUM_RECORDS = 1024;
6
+ /**
7
+ * A type index over the records parsed **so far** (M2, issue #393): the same
8
+ * membership the finished model exposes as `typeIndex`, available while the
9
+ * streaming parse is still running.
10
+ *
11
+ * It is a *derivation over the columnar index*, not a consumer of the
12
+ * per-record event stream — deliberately, and this is the M2 design decision
13
+ * that the 2026-08-18 spike settled (`scripts/m2_consumer_spike.mjs`; issue
14
+ * #393 for the tables). Pushing every record into per-type `Set`s cost +88 %
15
+ * of parse wall-clock and +254 MB on PSB (9.4 M records) and *still* produced
16
+ * the wrong answer — 83 concrete types against the production indexer's 95,
17
+ * because complex records arrive on the event stream as `typeID 0` with their
18
+ * mapped classes stripped. Rebuilding from a prefix snapshot through
19
+ * {@link StepTypeIndexer.createFromColumns} instead costs 121 ms on the same
20
+ * file, sees the complex entries' mapped subtypes, and is membership-identical
21
+ * to the finished model's index by construction — it is literally the same
22
+ * indexer call the model makes.
23
+ *
24
+ * The consequence for callers is that incrementality is a **cadence knob**
25
+ * rather than an architecture. Nothing happens per record; a rebuild happens
26
+ * when someone asks for a view that is more than `growthFactor` stale (14
27
+ * rebuilds over a PSB parse at the default 2.0, +7.2 % if you query
28
+ * continuously, ~0 if you query rarely). Callers that want a specific moment —
29
+ * a preview generation, a progress tick — call {@link refresh} themselves.
30
+ *
31
+ * Two regimes, and the boundary matters: at or below `minimumRecords` a
32
+ * rebuild is trivial, so every query with new records behind it rebuilds and
33
+ * the view is exact; above it, growth pacing applies and a query may see a
34
+ * view up to `growthFactor` stale. The staleness a caller can observe is
35
+ * therefore bounded by the growth factor — never by whatever prefix happened
36
+ * to be current the first time it asked.
37
+ *
38
+ * Queries are only ever answered from a built index, so a caller that has
39
+ * never queried has paid nothing.
40
+ */
41
+ export class PrefixTypeIndex {
42
+ /**
43
+ * @param sink_ The sink the streaming parse is filling. Held live: each
44
+ * rebuild takes a fresh {@link ColumnarIndexSink.snapshot} of it.
45
+ * @param indexer_ The schema's type indexer — the same instance kind the
46
+ * model builds its own `typeIndex` with, which is what makes the two
47
+ * membership-identical.
48
+ * @param options Rebuild pacing.
49
+ * @param options.growthFactor How much the record count must grow past the
50
+ * last build before a query rebuilds (default 2.0).
51
+ * @param options.minimumRecords The record count below which growth pacing
52
+ * is skipped — small parses just rebuild.
53
+ */
54
+ constructor(sink_, indexer_, options) {
55
+ this.sink_ = sink_;
56
+ this.indexer_ = indexer_;
57
+ this.index_ = void 0;
58
+ this.columns_ = void 0;
59
+ this.builtAtRecords_ = 0;
60
+ this.generation_ = 0;
61
+ this.growthFactor_ = options?.growthFactor ?? DEFAULT_GROWTH_FACTOR;
62
+ this.minimumRecords_ = options?.minimumRecords ?? DEFAULT_MINIMUM_RECORDS;
63
+ }
64
+ /**
65
+ * How many rebuilds have happened. A caller pacing its own UI can use this
66
+ * to tell a genuinely new view from a repeat query.
67
+ *
68
+ * @return {number} The generation counter, 0 before the first build.
69
+ */
70
+ get generation() {
71
+ return this.generation_;
72
+ }
73
+ /**
74
+ * The record count the current view was built at (0 if never built) — not
75
+ * the parse's current count, which is `sink.count`.
76
+ *
77
+ * @return {number} Records covered by the current view.
78
+ */
79
+ get recordCount() {
80
+ return this.builtAtRecords_;
81
+ }
82
+ /**
83
+ * Rebuild the view over everything parsed so far, unconditionally. This is
84
+ * the expensive call — O(records) — and it is the caller's choice of when.
85
+ */
86
+ refresh() {
87
+ this.columns_ = this.sink_.snapshot();
88
+ this.index_ = this.indexer_.createFromColumns(this.columns_);
89
+ this.builtAtRecords_ = this.sink_.topLevelCount;
90
+ ++this.generation_;
91
+ }
92
+ /**
93
+ * Rebuild only if the parse has moved far enough past the current view (or
94
+ * there is no view yet). Every query goes through this.
95
+ */
96
+ ensureFresh() {
97
+ const parsed = this.sink_.topLevelCount;
98
+ if (this.index_ === void 0) {
99
+ this.refresh();
100
+ return;
101
+ }
102
+ // A count that went BACKWARDS means the sink was reset — the streaming
103
+ // builder's grow-and-restart. The current view then describes records the
104
+ // restarted parse has not reached again, and growth pacing would never
105
+ // catch it (the new parse may finish below the old threshold), so it is
106
+ // rebuilt immediately rather than paced.
107
+ if (parsed < this.builtAtRecords_) {
108
+ this.refresh();
109
+ return;
110
+ }
111
+ if (parsed === this.builtAtRecords_) {
112
+ return;
113
+ }
114
+ // Below the minimum a rebuild is trivial, so the view is kept exact:
115
+ // pacing here would buy nothing, and — because the threshold is absolute
116
+ // rather than relative to the last build — it would freeze a small file's
117
+ // view at whatever prefix happened to be current when it was first
118
+ // queried, permanently, including after the parse finishes.
119
+ if (parsed <= this.minimumRecords_) {
120
+ this.refresh();
121
+ return;
122
+ }
123
+ if (parsed >= this.builtAtRecords_ * this.growthFactor_) {
124
+ this.refresh();
125
+ }
126
+ }
127
+ /**
128
+ * The distinct types present in the current view, including the mapped
129
+ * classes of complex entries.
130
+ *
131
+ * @return {IterableIterator<TypeIDType>} The types.
132
+ */
133
+ types() {
134
+ this.ensureFresh();
135
+ return this.index_.types();
136
+ }
137
+ /**
138
+ * Express IDs of every record of the given types (subtype closures unioned
139
+ * via the generated `query`, conway #383) among the records parsed so far.
140
+ *
141
+ * @param types The entity constructors to query.
142
+ * @return {IterableIterator<number>} Matching express IDs, in parse order.
143
+ * @yields {number} Each matching express ID.
144
+ */
145
+ *expressIDsOfTypes(...types) {
146
+ const distinct = types.length === 1 ?
147
+ types[0].query :
148
+ new Set(types.flatMap((type) => type.query));
149
+ yield* this.expressIDsOfTypeIDs(...distinct);
150
+ }
151
+ /**
152
+ * Express IDs of records whose concrete (or mapped) type is one of the
153
+ * given raw type IDs — no subtype expansion. The closure-expanding
154
+ * {@link expressIDsOfTypes} is the caller-facing form; this is for callers
155
+ * that already hold type IDs.
156
+ *
157
+ * @param typeIDs The raw type IDs to union.
158
+ * @return {IterableIterator<number>} Matching express IDs, in parse order.
159
+ * @yields {number} Each matching express ID.
160
+ */
161
+ *expressIDsOfTypeIDs(...typeIDs) {
162
+ this.ensureFresh();
163
+ const columns = this.columns_;
164
+ const expressIDs = columns.expressID;
165
+ const firstInlineElement = columns.firstInlineElement;
166
+ const cursor = this.index_.cursor(...typeIDs);
167
+ // Cursors are pooled, and a generator can be abandoned mid-iteration (a
168
+ // `break`, a `find`), so the release has to survive early exit — hence
169
+ // try/finally rather than a free() after the loop. Mirrors
170
+ // StepModelBase.expressIDsOfTypes, which this is the prefix twin of; a
171
+ // live consumer querying every generation would otherwise churn a cursor
172
+ // per query for the pool's whole lifetime.
173
+ try {
174
+ while (cursor.step()) {
175
+ const high = cursor.high;
176
+ let low = cursor.low;
177
+ while (low !== 0) {
178
+ const lowestOneHot = extractOneHotLow(low);
179
+ low ^= (1 << lowestOneHot);
180
+ const localID = high | lowestOneHot;
181
+ // Inline entities carry no express ID — the same guard the model's
182
+ // expressIDsOfTypes applies over its own columns.
183
+ if (localID < firstInlineElement) {
184
+ yield expressIDs[localID];
185
+ }
186
+ }
187
+ }
188
+ }
189
+ finally {
190
+ cursor.free();
191
+ }
192
+ }
193
+ /**
194
+ * Upper-bound count of records of the given types in the current view (see
195
+ * {@link MultiIndexSet.count} for why it is an upper bound).
196
+ *
197
+ * @param types The entity constructors to count.
198
+ * @return {number} The count.
199
+ */
200
+ count(...types) {
201
+ this.ensureFresh();
202
+ const distinct = types.length === 1 ?
203
+ types[0].query :
204
+ [...new Set(types.flatMap((type) => type.query))];
205
+ return this.index_.count(...distinct);
206
+ }
207
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=prefix_type_index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefix_type_index.test.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/prefix_type_index.test.ts"],"names":[],"mappings":""}