@oasys/oecs 0.5.3 → 0.6.0

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 (510) hide show
  1. package/CHANGELOG.md +1399 -276
  2. package/README.md +327 -169
  3. package/dist/core/ecs/access_check.d.cts +31 -31
  4. package/dist/core/ecs/access_check.d.ts +31 -31
  5. package/dist/core/ecs/access_check.d.ts.map +1 -1
  6. package/dist/core/ecs/archetype.d.cts +273 -205
  7. package/dist/core/ecs/archetype.d.ts +273 -205
  8. package/dist/core/ecs/archetype.d.ts.map +1 -1
  9. package/dist/core/ecs/archetype_closure.d.cts +23 -0
  10. package/dist/core/ecs/archetype_closure.d.ts +23 -0
  11. package/dist/core/ecs/archetype_closure.d.ts.map +1 -0
  12. package/dist/core/ecs/archetype_graph.d.cts +34 -34
  13. package/dist/core/ecs/archetype_graph.d.ts +34 -34
  14. package/dist/core/ecs/archetype_graph.d.ts.map +1 -1
  15. package/dist/core/ecs/archetype_types.d.cts +55 -0
  16. package/dist/core/ecs/archetype_types.d.ts +55 -0
  17. package/dist/core/ecs/archetype_types.d.ts.map +1 -0
  18. package/dist/core/ecs/change_feed.d.cts +53 -0
  19. package/dist/core/ecs/change_feed.d.ts +53 -0
  20. package/dist/core/ecs/change_feed.d.ts.map +1 -0
  21. package/dist/core/ecs/changed_query.d.cts +36 -0
  22. package/dist/core/ecs/changed_query.d.ts +36 -0
  23. package/dist/core/ecs/changed_query.d.ts.map +1 -0
  24. package/dist/core/ecs/chunk_columns.d.cts +49 -0
  25. package/dist/core/ecs/chunk_columns.d.ts +49 -0
  26. package/dist/core/ecs/chunk_columns.d.ts.map +1 -0
  27. package/dist/core/ecs/command_log.d.cts +30 -30
  28. package/dist/core/ecs/command_log.d.ts +30 -30
  29. package/dist/core/ecs/command_log.d.ts.map +1 -1
  30. package/dist/core/ecs/component.d.cts +45 -44
  31. package/dist/core/ecs/component.d.ts +45 -44
  32. package/dist/core/ecs/component.d.ts.map +1 -1
  33. package/dist/core/ecs/component_registry.d.cts +53 -0
  34. package/dist/core/ecs/component_registry.d.ts +53 -0
  35. package/dist/core/ecs/component_registry.d.ts.map +1 -0
  36. package/dist/core/ecs/compute_backend.d.cts +18 -7
  37. package/dist/core/ecs/compute_backend.d.ts +18 -7
  38. package/dist/core/ecs/compute_backend.d.ts.map +1 -1
  39. package/dist/core/ecs/deferred_commands.d.cts +15 -14
  40. package/dist/core/ecs/deferred_commands.d.ts +15 -14
  41. package/dist/core/ecs/deferred_commands.d.ts.map +1 -1
  42. package/dist/core/ecs/dispatch_trace.d.cts +32 -31
  43. package/dist/core/ecs/dispatch_trace.d.ts +32 -31
  44. package/dist/core/ecs/dispatch_trace.d.ts.map +1 -1
  45. package/dist/core/ecs/ecs.d.cts +337 -276
  46. package/dist/core/ecs/ecs.d.ts +337 -276
  47. package/dist/core/ecs/ecs.d.ts.map +1 -1
  48. package/dist/core/ecs/ecs_memory.d.cts +134 -136
  49. package/dist/core/ecs/ecs_memory.d.ts +134 -136
  50. package/dist/core/ecs/ecs_memory.d.ts.map +1 -1
  51. package/dist/core/ecs/ecs_options.d.cts +89 -0
  52. package/dist/core/ecs/ecs_options.d.ts +89 -0
  53. package/dist/core/ecs/ecs_options.d.ts.map +1 -0
  54. package/dist/core/ecs/entity.d.cts +4 -4
  55. package/dist/core/ecs/entity.d.ts +4 -4
  56. package/dist/core/ecs/entity_allocator.d.cts +24 -22
  57. package/dist/core/ecs/entity_allocator.d.ts +24 -22
  58. package/dist/core/ecs/entity_allocator.d.ts.map +1 -1
  59. package/dist/core/ecs/event.d.cts +37 -23
  60. package/dist/core/ecs/event.d.ts +37 -23
  61. package/dist/core/ecs/event.d.ts.map +1 -1
  62. package/dist/core/ecs/facades.d.cts +12 -126
  63. package/dist/core/ecs/facades.d.ts +12 -126
  64. package/dist/core/ecs/facades.d.ts.map +1 -1
  65. package/dist/core/ecs/frame_stepper.d.cts +12 -12
  66. package/dist/core/ecs/frame_stepper.d.ts +12 -12
  67. package/dist/core/ecs/frame_stepper.d.ts.map +1 -1
  68. package/dist/core/ecs/frame_trace.d.cts +34 -34
  69. package/dist/core/ecs/frame_trace.d.ts +34 -34
  70. package/dist/core/ecs/frame_trace.d.ts.map +1 -1
  71. package/dist/core/ecs/host_commands.d.cts +107 -89
  72. package/dist/core/ecs/host_commands.d.ts +107 -89
  73. package/dist/core/ecs/host_commands.d.ts.map +1 -1
  74. package/dist/core/ecs/index.d.cts +22 -12
  75. package/dist/core/ecs/index.d.ts +22 -12
  76. package/dist/core/ecs/index.d.ts.map +1 -1
  77. package/dist/core/ecs/observer.d.cts +41 -122
  78. package/dist/core/ecs/observer.d.ts +41 -122
  79. package/dist/core/ecs/observer.d.ts.map +1 -1
  80. package/dist/core/ecs/phase.d.cts +79 -0
  81. package/dist/core/ecs/phase.d.ts +79 -0
  82. package/dist/core/ecs/phase.d.ts.map +1 -0
  83. package/dist/core/ecs/plugin.d.cts +125 -0
  84. package/dist/core/ecs/plugin.d.ts +125 -0
  85. package/dist/core/ecs/plugin.d.ts.map +1 -0
  86. package/dist/core/ecs/plugin_slots.d.cts +26 -0
  87. package/dist/core/ecs/plugin_slots.d.ts +26 -0
  88. package/dist/core/ecs/plugin_slots.d.ts.map +1 -0
  89. package/dist/core/ecs/query.d.cts +219 -568
  90. package/dist/core/ecs/query.d.ts +219 -568
  91. package/dist/core/ecs/query.d.ts.map +1 -1
  92. package/dist/core/ecs/query_cache.d.cts +130 -0
  93. package/dist/core/ecs/query_cache.d.ts +130 -0
  94. package/dist/core/ecs/query_cache.d.ts.map +1 -0
  95. package/dist/core/ecs/query_registry.d.cts +47 -0
  96. package/dist/core/ecs/query_registry.d.ts +47 -0
  97. package/dist/core/ecs/query_registry.d.ts.map +1 -0
  98. package/dist/core/ecs/query_terms.d.cts +126 -0
  99. package/dist/core/ecs/query_terms.d.ts +126 -0
  100. package/dist/core/ecs/query_terms.d.ts.map +1 -0
  101. package/dist/core/ecs/ref.d.cts +129 -16
  102. package/dist/core/ecs/ref.d.ts +129 -16
  103. package/dist/core/ecs/ref.d.ts.map +1 -1
  104. package/dist/core/ecs/relation.d.cts +105 -186
  105. package/dist/core/ecs/relation.d.ts +105 -186
  106. package/dist/core/ecs/relation.d.ts.map +1 -1
  107. package/dist/core/ecs/resource.d.cts +14 -14
  108. package/dist/core/ecs/resource.d.ts +14 -14
  109. package/dist/core/ecs/resource_registry.d.cts +6 -6
  110. package/dist/core/ecs/resource_registry.d.ts +6 -6
  111. package/dist/core/ecs/resource_registry.d.ts.map +1 -1
  112. package/dist/core/ecs/row_kinds.d.cts +24 -0
  113. package/dist/core/ecs/row_kinds.d.ts +24 -0
  114. package/dist/core/ecs/row_kinds.d.ts.map +1 -0
  115. package/dist/core/ecs/run_condition.d.cts +23 -23
  116. package/dist/core/ecs/run_condition.d.ts +23 -23
  117. package/dist/core/ecs/run_condition.d.ts.map +1 -1
  118. package/dist/core/ecs/schedule.d.cts +98 -114
  119. package/dist/core/ecs/schedule.d.ts +98 -114
  120. package/dist/core/ecs/schedule.d.ts.map +1 -1
  121. package/dist/core/ecs/schedule_plan.d.cts +33 -0
  122. package/dist/core/ecs/schedule_plan.d.ts +33 -0
  123. package/dist/core/ecs/schedule_plan.d.ts.map +1 -0
  124. package/dist/core/ecs/snapshot.d.cts +77 -0
  125. package/dist/core/ecs/snapshot.d.ts +77 -0
  126. package/dist/core/ecs/snapshot.d.ts.map +1 -0
  127. package/dist/core/ecs/snapshot_mount.d.cts +42 -0
  128. package/dist/core/ecs/snapshot_mount.d.ts +42 -0
  129. package/dist/core/ecs/snapshot_mount.d.ts.map +1 -0
  130. package/dist/core/ecs/sparse_store.d.cts +110 -53
  131. package/dist/core/ecs/sparse_store.d.ts +110 -53
  132. package/dist/core/ecs/sparse_store.d.ts.map +1 -1
  133. package/dist/core/ecs/store.d.cts +644 -511
  134. package/dist/core/ecs/store.d.ts +644 -511
  135. package/dist/core/ecs/store.d.ts.map +1 -1
  136. package/dist/core/ecs/store_layout_listener.d.cts +8 -8
  137. package/dist/core/ecs/store_layout_listener.d.ts +8 -8
  138. package/dist/core/ecs/store_types.d.cts +122 -0
  139. package/dist/core/ecs/store_types.d.ts +122 -0
  140. package/dist/core/ecs/store_types.d.ts.map +1 -0
  141. package/dist/core/ecs/system.d.cts +151 -66
  142. package/dist/core/ecs/system.d.ts +151 -66
  143. package/dist/core/ecs/system.d.ts.map +1 -1
  144. package/dist/core/ecs/system_context.d.cts +296 -0
  145. package/dist/core/ecs/system_context.d.ts +296 -0
  146. package/dist/core/ecs/system_context.d.ts.map +1 -0
  147. package/dist/core/ecs/system_set.d.cts +48 -0
  148. package/dist/core/ecs/system_set.d.ts +48 -0
  149. package/dist/core/ecs/system_set.d.ts.map +1 -0
  150. package/dist/core/ecs/utils/arrays.d.cts +15 -1
  151. package/dist/core/ecs/utils/arrays.d.ts +15 -1
  152. package/dist/core/ecs/utils/arrays.d.ts.map +1 -1
  153. package/dist/core/ecs/utils/error.d.cts +87 -4
  154. package/dist/core/ecs/utils/error.d.ts +87 -4
  155. package/dist/core/ecs/utils/error.d.ts.map +1 -1
  156. package/dist/core/ecs/utils/plugin_error.d.cts +10 -0
  157. package/dist/core/ecs/utils/plugin_error.d.ts +10 -0
  158. package/dist/core/ecs/utils/plugin_error.d.ts.map +1 -0
  159. package/dist/core/restore_errors.d.cts +30 -0
  160. package/dist/core/restore_errors.d.ts +30 -0
  161. package/dist/core/restore_errors.d.ts.map +1 -0
  162. package/dist/core/store/action_ring.d.cts +48 -49
  163. package/dist/core/store/action_ring.d.ts +48 -49
  164. package/dist/core/store/action_ring.d.ts.map +1 -1
  165. package/dist/core/store/allocator.d.cts +166 -114
  166. package/dist/core/store/allocator.d.ts +166 -114
  167. package/dist/core/store/allocator.d.ts.map +1 -1
  168. package/dist/core/store/buffer_backed_column.d.cts +21 -22
  169. package/dist/core/store/buffer_backed_column.d.ts +21 -22
  170. package/dist/core/store/buffer_backed_column.d.ts.map +1 -1
  171. package/dist/core/store/column_store.d.cts +138 -100
  172. package/dist/core/store/column_store.d.ts +138 -100
  173. package/dist/core/store/column_store.d.ts.map +1 -1
  174. package/dist/core/store/command_dispatch.d.cts +14 -15
  175. package/dist/core/store/command_dispatch.d.ts +14 -15
  176. package/dist/core/store/command_dispatch.d.ts.map +1 -1
  177. package/dist/core/store/command_ring.d.cts +41 -45
  178. package/dist/core/store/command_ring.d.ts +41 -45
  179. package/dist/core/store/command_ring.d.ts.map +1 -1
  180. package/dist/core/store/descriptor.d.cts +35 -18
  181. package/dist/core/store/descriptor.d.ts +35 -18
  182. package/dist/core/store/descriptor.d.ts.map +1 -1
  183. package/dist/core/store/entity_index.d.cts +34 -35
  184. package/dist/core/store/entity_index.d.ts +34 -35
  185. package/dist/core/store/entity_index.d.ts.map +1 -1
  186. package/dist/core/store/event_ring.d.cts +40 -42
  187. package/dist/core/store/event_ring.d.ts +40 -42
  188. package/dist/core/store/event_ring.d.ts.map +1 -1
  189. package/dist/core/store/extend.d.cts +15 -9
  190. package/dist/core/store/extend.d.ts +15 -9
  191. package/dist/core/store/extend.d.ts.map +1 -1
  192. package/dist/core/store/grow.d.cts +3 -3
  193. package/dist/core/store/grow.d.ts +3 -3
  194. package/dist/core/store/grow.d.ts.map +1 -1
  195. package/dist/core/store/header.d.cts +37 -33
  196. package/dist/core/store/header.d.ts +37 -33
  197. package/dist/core/store/header.d.ts.map +1 -1
  198. package/dist/core/store/index.d.cts +10 -10
  199. package/dist/core/store/index.d.ts +10 -10
  200. package/dist/core/store/index.d.ts.map +1 -1
  201. package/dist/core/store/layout_ops.d.cts +72 -63
  202. package/dist/core/store/layout_ops.d.ts +72 -63
  203. package/dist/core/store/layout_ops.d.ts.map +1 -1
  204. package/dist/core/store/region_table.d.cts +28 -21
  205. package/dist/core/store/region_table.d.ts +28 -21
  206. package/dist/core/store/region_table.d.ts.map +1 -1
  207. package/dist/core/store/snapshot.d.cts +31 -16
  208. package/dist/core/store/snapshot.d.ts +31 -16
  209. package/dist/core/store/snapshot.d.ts.map +1 -1
  210. package/dist/core/store/state_hash.d.cts +14 -14
  211. package/dist/core/store/state_hash.d.ts +14 -14
  212. package/dist/core/store/state_hash.d.ts.map +1 -1
  213. package/dist/core/store/store_regions.d.cts +10 -10
  214. package/dist/core/store/store_regions.d.ts +10 -10
  215. package/dist/core/store/store_regions.d.ts.map +1 -1
  216. package/dist/core/store/vendored_abi/abi.d.cts +27 -2
  217. package/dist/core/store/vendored_abi/abi.d.ts +27 -2
  218. package/dist/core/store/vendored_abi/abi.d.ts.map +1 -1
  219. package/dist/host_commands-B2KMx8O2.cjs +1 -0
  220. package/dist/host_commands-ClVPvhSa.cjs +2 -0
  221. package/dist/host_commands-CwxVQS1z.js +1524 -0
  222. package/dist/host_commands-nJvTy88E.js +1667 -0
  223. package/dist/index.cjs +1 -1
  224. package/dist/index.d.cts +16 -11
  225. package/dist/index.d.ts +16 -11
  226. package/dist/index.d.ts.map +1 -1
  227. package/dist/index.development.cjs +1 -1
  228. package/dist/index.development.js +6709 -5729
  229. package/dist/index.js +5664 -4743
  230. package/dist/internal.cjs +2 -2
  231. package/dist/internal.d.cts +5 -2
  232. package/dist/internal.d.ts +5 -2
  233. package/dist/internal.d.ts.map +1 -1
  234. package/dist/internal.development.cjs +1 -1
  235. package/dist/internal.development.js +70 -20
  236. package/dist/internal.js +138 -83
  237. package/dist/plugins/abi-D3V-QUSf.cjs +1 -0
  238. package/dist/plugins/abi-NP8pNxpd.js +42 -0
  239. package/dist/plugins/arrays-Dr_1hCjL.js +28 -0
  240. package/dist/plugins/arrays-Dt-Joc4i.cjs +1 -0
  241. package/dist/plugins/assertions-gtDVfbnQ.js +6 -0
  242. package/dist/plugins/assertions-z5GQd_bB.cjs +1 -0
  243. package/dist/{extensions → plugins}/editor/editor.d.cts +56 -56
  244. package/dist/{extensions → plugins}/editor/editor.d.ts +56 -56
  245. package/dist/plugins/editor/editor.d.ts.map +1 -0
  246. package/dist/{extensions → plugins}/editor/field_handle.d.cts +13 -13
  247. package/dist/{extensions → plugins}/editor/field_handle.d.ts +13 -13
  248. package/dist/plugins/editor/field_handle.d.ts.map +1 -0
  249. package/dist/plugins/editor/index.d.cts +22 -0
  250. package/dist/plugins/editor/index.d.ts +22 -0
  251. package/dist/plugins/editor/index.d.ts.map +1 -0
  252. package/dist/plugins/editor.cjs +1 -0
  253. package/dist/plugins/editor.d.cts +1 -0
  254. package/dist/plugins/editor.d.ts +1 -0
  255. package/dist/plugins/editor.development.cjs +1 -0
  256. package/dist/{extensions/editor/index.development.js → plugins/editor.development.js} +83 -66
  257. package/dist/{extensions/editor/index.js → plugins/editor.js} +83 -66
  258. package/dist/plugins/events/event_channel.d.cts +13 -0
  259. package/dist/plugins/events/event_channel.d.ts +13 -0
  260. package/dist/plugins/events/event_channel.d.ts.map +1 -0
  261. package/dist/plugins/events/event_registry.d.cts +22 -0
  262. package/dist/plugins/events/event_registry.d.ts +22 -0
  263. package/dist/plugins/events/event_registry.d.ts.map +1 -0
  264. package/dist/plugins/events/facade.d.cts +26 -0
  265. package/dist/plugins/events/facade.d.ts +26 -0
  266. package/dist/plugins/events/facade.d.ts.map +1 -0
  267. package/dist/plugins/events/index.d.cts +10 -0
  268. package/dist/plugins/events/index.d.ts +10 -0
  269. package/dist/plugins/events/index.d.ts.map +1 -0
  270. package/dist/plugins/events.cjs +1 -0
  271. package/dist/plugins/events.d.cts +1 -0
  272. package/dist/plugins/events.d.ts +1 -0
  273. package/dist/plugins/events.development.cjs +1 -0
  274. package/dist/plugins/events.development.js +174 -0
  275. package/dist/plugins/events.js +159 -0
  276. package/dist/plugins/observers/index.d.cts +23 -0
  277. package/dist/plugins/observers/index.d.ts +23 -0
  278. package/dist/plugins/observers/index.d.ts.map +1 -0
  279. package/dist/plugins/observers/observer_registry.d.cts +101 -0
  280. package/dist/plugins/observers/observer_registry.d.ts +101 -0
  281. package/dist/plugins/observers/observer_registry.d.ts.map +1 -0
  282. package/dist/plugins/observers.cjs +1 -0
  283. package/dist/plugins/observers.d.cts +1 -0
  284. package/dist/plugins/observers.d.ts +1 -0
  285. package/dist/plugins/observers.development.cjs +1 -0
  286. package/dist/plugins/observers.development.js +431 -0
  287. package/dist/plugins/observers.js +403 -0
  288. package/dist/plugins/relation_store-BsoegrZh.js +313 -0
  289. package/dist/plugins/relation_store-DQKSnxsm.cjs +1 -0
  290. package/dist/plugins/relation_store-RBhpcE28.cjs +1 -0
  291. package/dist/plugins/relation_store-RqW5Snx6.js +328 -0
  292. package/dist/plugins/relations/builtin_relations.d.cts +48 -0
  293. package/dist/plugins/relations/builtin_relations.d.ts +48 -0
  294. package/dist/plugins/relations/builtin_relations.d.ts.map +1 -0
  295. package/dist/plugins/relations/facade.d.cts +73 -0
  296. package/dist/plugins/relations/facade.d.ts +73 -0
  297. package/dist/plugins/relations/facade.d.ts.map +1 -0
  298. package/dist/plugins/relations/index.d.cts +11 -0
  299. package/dist/plugins/relations/index.d.ts +11 -0
  300. package/dist/plugins/relations/index.d.ts.map +1 -0
  301. package/dist/{core/ecs → plugins/relations}/relation_service.d.cts +93 -105
  302. package/dist/{core/ecs → plugins/relations}/relation_service.d.ts +93 -105
  303. package/dist/plugins/relations/relation_service.d.ts.map +1 -0
  304. package/dist/plugins/relations/relation_store.d.cts +177 -0
  305. package/dist/plugins/relations/relation_store.d.ts +177 -0
  306. package/dist/plugins/relations/relation_store.d.ts.map +1 -0
  307. package/dist/plugins/relations.cjs +1 -0
  308. package/dist/plugins/relations.d.cts +1 -0
  309. package/dist/plugins/relations.d.ts +1 -0
  310. package/dist/plugins/relations.development.cjs +1 -0
  311. package/dist/plugins/relations.development.js +603 -0
  312. package/dist/plugins/relations.js +553 -0
  313. package/dist/plugins/snapshots/index.d.cts +33 -0
  314. package/dist/plugins/snapshots/index.d.ts +33 -0
  315. package/dist/plugins/snapshots/index.d.ts.map +1 -0
  316. package/dist/plugins/snapshots/resume.d.cts +57 -0
  317. package/dist/plugins/snapshots/resume.d.ts +57 -0
  318. package/dist/plugins/snapshots/resume.d.ts.map +1 -0
  319. package/dist/plugins/snapshots/snapshot_service.d.cts +59 -0
  320. package/dist/plugins/snapshots/snapshot_service.d.ts +59 -0
  321. package/dist/plugins/snapshots/snapshot_service.d.ts.map +1 -0
  322. package/dist/plugins/snapshots.cjs +1 -0
  323. package/dist/plugins/snapshots.d.cts +1 -0
  324. package/dist/plugins/snapshots.d.ts +1 -0
  325. package/dist/plugins/snapshots.development.cjs +1 -0
  326. package/dist/plugins/snapshots.development.js +737 -0
  327. package/dist/plugins/snapshots.js +737 -0
  328. package/dist/plugins/solid/index.d.cts +8 -0
  329. package/dist/plugins/solid/index.d.ts +8 -0
  330. package/dist/plugins/solid/index.d.ts.map +1 -0
  331. package/dist/plugins/solid/solid.d.cts +97 -0
  332. package/dist/plugins/solid/solid.d.ts +97 -0
  333. package/dist/plugins/solid/solid.d.ts.map +1 -0
  334. package/dist/plugins/solid.cjs +1 -0
  335. package/dist/plugins/solid.d.cts +1 -0
  336. package/dist/plugins/solid.d.ts +1 -0
  337. package/dist/plugins/solid.development.cjs +1 -0
  338. package/dist/plugins/solid.development.js +319 -0
  339. package/dist/plugins/solid.js +319 -0
  340. package/dist/plugins/workers/index.d.cts +75 -0
  341. package/dist/plugins/workers/index.d.ts +75 -0
  342. package/dist/plugins/workers/index.d.ts.map +1 -0
  343. package/dist/plugins/workers/node_threads.d.cts +25 -0
  344. package/dist/plugins/workers/node_threads.d.ts +25 -0
  345. package/dist/plugins/workers/node_threads.d.ts.map +1 -0
  346. package/dist/plugins/workers/plan.d.cts +61 -0
  347. package/dist/plugins/workers/plan.d.ts +61 -0
  348. package/dist/plugins/workers/plan.d.ts.map +1 -0
  349. package/dist/plugins/workers/pool.d.cts +144 -0
  350. package/dist/plugins/workers/pool.d.ts +144 -0
  351. package/dist/plugins/workers/pool.d.ts.map +1 -0
  352. package/dist/plugins/workers/protocol.d.cts +112 -0
  353. package/dist/plugins/workers/protocol.d.ts +112 -0
  354. package/dist/plugins/workers/protocol.d.ts.map +1 -0
  355. package/dist/plugins/workers/worker_bind.d.cts +64 -0
  356. package/dist/plugins/workers/worker_bind.d.ts +64 -0
  357. package/dist/plugins/workers/worker_bind.d.ts.map +1 -0
  358. package/dist/plugins/workers/worker_loop.d.cts +14 -0
  359. package/dist/plugins/workers/worker_loop.d.ts +14 -0
  360. package/dist/plugins/workers/worker_loop.d.ts.map +1 -0
  361. package/dist/plugins/workers.cjs +1 -0
  362. package/dist/plugins/workers.d.cts +1 -0
  363. package/dist/plugins/workers.d.ts +1 -0
  364. package/dist/plugins/workers.development.cjs +1 -0
  365. package/dist/plugins/workers.development.js +596 -0
  366. package/dist/plugins/workers.js +474 -0
  367. package/dist/primitives.cjs +1 -1
  368. package/dist/primitives.d.cts +4 -4
  369. package/dist/primitives.d.ts +4 -4
  370. package/dist/primitives.development.cjs +1 -1
  371. package/dist/primitives.development.js +66 -22
  372. package/dist/primitives.js +66 -22
  373. package/dist/shared-BKl12xF1.js +132 -0
  374. package/dist/shared-Dk-pACZT.cjs +1 -0
  375. package/dist/shared.cjs +1 -1
  376. package/dist/shared.d.cts +7 -7
  377. package/dist/shared.d.ts +7 -7
  378. package/dist/shared.d.ts.map +1 -1
  379. package/dist/shared.development.cjs +1 -1
  380. package/dist/shared.development.js +4 -3
  381. package/dist/shared.js +4 -3
  382. package/dist/topological_sort-Cc_yXqPT.js +346 -0
  383. package/dist/topological_sort-vp1imU6D.cjs +1 -0
  384. package/dist/type_primitives/assertions.d.cts +12 -16
  385. package/dist/type_primitives/assertions.d.ts +12 -16
  386. package/dist/type_primitives/assertions.d.ts.map +1 -1
  387. package/dist/type_primitives/binary_heap/binary_heap.d.cts +2 -6
  388. package/dist/type_primitives/binary_heap/binary_heap.d.ts +2 -6
  389. package/dist/type_primitives/binary_heap/binary_heap.d.ts.map +1 -1
  390. package/dist/type_primitives/bitset/bitset.d.cts +7 -11
  391. package/dist/type_primitives/bitset/bitset.d.ts +7 -11
  392. package/dist/type_primitives/bitset/bitset.d.ts.map +1 -1
  393. package/dist/type_primitives/brand.d.cts +2 -7
  394. package/dist/type_primitives/brand.d.ts +2 -7
  395. package/dist/type_primitives/brand.d.ts.map +1 -1
  396. package/dist/type_primitives/error.d.cts +1 -2
  397. package/dist/type_primitives/error.d.ts +1 -2
  398. package/dist/type_primitives/error.d.ts.map +1 -1
  399. package/dist/type_primitives/index.d.cts +1 -1
  400. package/dist/type_primitives/index.d.ts +1 -1
  401. package/dist/type_primitives/sparse_map/sparse_map.d.cts +3 -7
  402. package/dist/type_primitives/sparse_map/sparse_map.d.ts +3 -7
  403. package/dist/type_primitives/sparse_map/sparse_map.d.ts.map +1 -1
  404. package/dist/type_primitives/sparse_set/sparse_set.d.cts +2 -6
  405. package/dist/type_primitives/sparse_set/sparse_set.d.ts +2 -6
  406. package/dist/type_primitives/sparse_set/sparse_set.d.ts.map +1 -1
  407. package/dist/type_primitives/topological_sort/topological_sort.d.cts +1 -5
  408. package/dist/type_primitives/topological_sort/topological_sort.d.ts +1 -5
  409. package/dist/type_primitives/topological_sort/topological_sort.d.ts.map +1 -1
  410. package/dist/type_primitives/typed_arrays/typed_arrays.d.cts +18 -17
  411. package/dist/type_primitives/typed_arrays/typed_arrays.d.ts +18 -17
  412. package/dist/type_primitives/typed_arrays/typed_arrays.d.ts.map +1 -1
  413. package/dist/utils/error.d.ts.map +1 -1
  414. package/dist/version.d.cts +4 -4
  415. package/dist/version.d.ts +4 -4
  416. package/dist/worker.cjs +1 -0
  417. package/dist/worker.d.cts +17 -0
  418. package/dist/worker.d.ts +17 -0
  419. package/dist/worker.d.ts.map +1 -0
  420. package/dist/worker.development.cjs +1 -0
  421. package/dist/worker.development.js +253 -0
  422. package/dist/worker.js +253 -0
  423. package/package.json +363 -191
  424. package/dist/core/ecs/builtin_relations.d.cts +0 -43
  425. package/dist/core/ecs/builtin_relations.d.ts +0 -43
  426. package/dist/core/ecs/builtin_relations.d.ts.map +0 -1
  427. package/dist/core/ecs/event_registry.d.cts +0 -22
  428. package/dist/core/ecs/event_registry.d.ts +0 -22
  429. package/dist/core/ecs/event_registry.d.ts.map +0 -1
  430. package/dist/core/ecs/relation_service.d.ts.map +0 -1
  431. package/dist/core/ecs/resume.d.cts +0 -85
  432. package/dist/core/ecs/resume.d.ts +0 -85
  433. package/dist/core/ecs/resume.d.ts.map +0 -1
  434. package/dist/core/ecs/snapshot_service.d.cts +0 -94
  435. package/dist/core/ecs/snapshot_service.d.ts +0 -94
  436. package/dist/core/ecs/snapshot_service.d.ts.map +0 -1
  437. package/dist/extensions/editor/editor.d.ts.map +0 -1
  438. package/dist/extensions/editor/field_handle.d.ts.map +0 -1
  439. package/dist/extensions/editor/index.cjs +0 -1
  440. package/dist/extensions/editor/index.d.cts +0 -21
  441. package/dist/extensions/editor/index.d.ts +0 -21
  442. package/dist/extensions/editor/index.d.ts.map +0 -1
  443. package/dist/extensions/editor/index.development.cjs +0 -1
  444. package/dist/extensions/reactive/ecs_sync.d.cts +0 -214
  445. package/dist/extensions/reactive/ecs_sync.d.ts +0 -214
  446. package/dist/extensions/reactive/ecs_sync.d.ts.map +0 -1
  447. package/dist/extensions/reactive/index.cjs +0 -1
  448. package/dist/extensions/reactive/index.d.cts +0 -23
  449. package/dist/extensions/reactive/index.d.ts +0 -23
  450. package/dist/extensions/reactive/index.d.ts.map +0 -1
  451. package/dist/extensions/reactive/index.development.cjs +0 -1
  452. package/dist/extensions/reactive/index.development.js +0 -215
  453. package/dist/extensions/reactive/index.js +0 -215
  454. package/dist/extensions/solid/index.cjs +0 -1
  455. package/dist/extensions/solid/index.d.cts +0 -6
  456. package/dist/extensions/solid/index.d.ts +0 -6
  457. package/dist/extensions/solid/index.d.ts.map +0 -1
  458. package/dist/extensions/solid/index.development.cjs +0 -1
  459. package/dist/extensions/solid/index.development.js +0 -40
  460. package/dist/extensions/solid/index.js +0 -36
  461. package/dist/extensions/solid/kernel_solid.d.cts +0 -45
  462. package/dist/extensions/solid/kernel_solid.d.ts +0 -45
  463. package/dist/extensions/solid/kernel_solid.d.ts.map +0 -1
  464. package/dist/host_commands-3jyFfWNg.js +0 -2326
  465. package/dist/host_commands-DNf0f6ko.cjs +0 -1
  466. package/dist/internal-C9jjL90H.js +0 -2485
  467. package/dist/internal-RZN14uMw.cjs +0 -2
  468. package/dist/interop-CT-REx0W.cjs +0 -1
  469. package/dist/interop-CcY6ASQc.js +0 -18
  470. package/dist/interop-DqxleBo7.js +0 -18
  471. package/dist/interop-T1HZ-Dpa.cjs +0 -1
  472. package/dist/kernel-Cz2Kxlwl.js +0 -240
  473. package/dist/kernel-DgyrLFjW.js +0 -227
  474. package/dist/kernel-sw7ScKWu.cjs +0 -1
  475. package/dist/kernel-yWV3XnAb.cjs +0 -1
  476. package/dist/reactive/array.d.cts +0 -24
  477. package/dist/reactive/array.d.ts +0 -24
  478. package/dist/reactive/array.d.ts.map +0 -1
  479. package/dist/reactive/index.cjs +0 -1
  480. package/dist/reactive/index.d.cts +0 -11
  481. package/dist/reactive/index.d.ts +0 -11
  482. package/dist/reactive/index.d.ts.map +0 -1
  483. package/dist/reactive/index.development.cjs +0 -1
  484. package/dist/reactive/index.development.js +0 -18
  485. package/dist/reactive/index.js +0 -18
  486. package/dist/reactive/interop.d.cts +0 -19
  487. package/dist/reactive/interop.d.ts +0 -19
  488. package/dist/reactive/interop.d.ts.map +0 -1
  489. package/dist/reactive/kernel.d.cts +0 -73
  490. package/dist/reactive/kernel.d.ts +0 -73
  491. package/dist/reactive/kernel.d.ts.map +0 -1
  492. package/dist/reactive/map.d.cts +0 -16
  493. package/dist/reactive/map.d.ts +0 -16
  494. package/dist/reactive/map.d.ts.map +0 -1
  495. package/dist/reactive/shallow.d.cts +0 -11
  496. package/dist/reactive/shallow.d.ts +0 -11
  497. package/dist/reactive/shallow.d.ts.map +0 -1
  498. package/dist/reactive/struct.d.cts +0 -10
  499. package/dist/reactive/struct.d.ts +0 -10
  500. package/dist/reactive/struct.d.ts.map +0 -1
  501. package/dist/shallow-9S1pY_Iw.js +0 -159
  502. package/dist/shallow-C5YmTbtb.cjs +0 -1
  503. package/dist/shallow-DQ8aG51_.cjs +0 -1
  504. package/dist/shallow-DfnAm9vG.js +0 -150
  505. package/dist/shared-BMXh9hxm.cjs +0 -1
  506. package/dist/shared-DQKK0i-E.js +0 -109
  507. package/dist/topological_sort-BDvEyb9W.cjs +0 -1
  508. package/dist/topological_sort-DK6EjpWa.js +0 -135
  509. package/dist/typed_arrays-BcXcnzB4.js +0 -258
  510. package/dist/typed_arrays-D3NmwtCG.cjs +0 -1
package/README.md CHANGED
@@ -1,58 +1,74 @@
1
1
  # oecs
2
2
 
3
- **A full-featured, archetype-based Entity Component System for TypeScript.**
4
-
5
- `@oasys/oecs` is a complete ECS not just storage-and-queries, but the whole toolkit you expect from a
6
- mature engine: observers, relations with wildcards, sparse storage, system sets and run conditions,
7
- entity enable/disable, templates, deterministic hashing with snapshot/restore, a typed host→ECS write
8
- seam, and an optional reactive UI bridge. It is **pure TypeScript and zero-dependency by default** — it
9
- runs over a plain resizable `ArrayBuffer`, so it needs no `SharedArrayBuffer` and no cross-origin
10
- isolation (COOP/COEP). An opt-in shared-memory profile swaps in a `SharedArrayBuffer` for worker offload
11
- or a WASM compute backend; both profiles share one core and agree, byte-for-byte, on `stateHash`.
12
-
13
- - **Fast** — struct-of-arrays column storage grouped by archetype; iteration is a tight loop over typed
14
- arrays with no per-entity object allocation.
15
- - **Type-safe** component handles are callable defs with stable numeric ids at runtime and fully-typed schemas at compile time;
16
- misspelled fields are compile errors.
17
- - **Deterministic** an opt-in mode gives a backing-agnostic `stateHash` plus snapshot/restore and
18
- command-log replay.
19
- - **Complete** the feature surface below is the whole engine, not a starting point.
3
+ **A complete, archetype-based Entity Component System for TypeScript.**
4
+
5
+ `@oasys/oecs` gives you more than storage and queries. It gives you the tools that a mature engine
6
+ has:
7
+
8
+ - observers
9
+ - relations with wildcards
10
+ - sparse storage
11
+ - system sets and run conditions
12
+ - enable and disable for an entity
13
+ - templates
14
+ - deterministic hashing, with snapshot and restore
15
+ - a typed write path from the host into the ECS
16
+ - one system across a pool of workers, with a WASM or a JavaScript kernel
17
+ - an optional Solid plugin, for a UI
18
+
19
+ The package is **pure TypeScript, and it has no dependencies by default**. It runs over one plain
20
+ `ArrayBuffer`. So it does not need a `SharedArrayBuffer`, and it does not need cross-origin
21
+ isolation (COOP and COEP). An optional shared-memory profile uses a `SharedArrayBuffer` instead. Use
22
+ that profile for worker offload, or for a WASM compute backend. The two profiles use one core, and
23
+ they agree byte-for-byte on `stateHash`.
24
+
25
+ - **Data-oriented**. Columns use struct-of-arrays storage, grouped by archetype. Iteration is a
26
+ small loop over typed arrays. The loop allocates no object for each entity.
27
+ - **Type-safe**. A component handle is a callable definition. It has a stable numeric id at run
28
+ time and a full schema type at compile time. A field name with a spelling error is a compile
29
+ error.
30
+ - **Deterministic**. An optional mode gives you a `stateHash` that is independent of the storage
31
+ type. It also gives you snapshot, restore, and replay of a command log.
32
+ - **Complete**. The features below are the full engine. They are not only a start.
20
33
 
21
34
  ## Installation
22
35
 
23
36
  ```bash
24
- pnpm add @oasys/oecs # npm / pnpm / yarn
37
+ pnpm add @oasys/oecs # npm, pnpm or yarn
25
38
  # or
26
39
  deno add jsr:@oasys/oecs # JSR (Deno)
27
40
  # or
28
41
  npx jsr add @oasys/oecs # JSR (npm-compatible)
29
42
  ```
30
43
 
31
- Requires a runtime with resizable `ArrayBuffer` (the default heap profile grows in place):
32
- Node 20, Deno 1.38, Chrome 111+, Firefox 128+, Safari 16.4+.
44
+ Supported runtimes are Node 20 or later and Deno 1.38 or later. In a browser, use Chrome 111 or
45
+ later, Firefox 128 or later, or Safari 16.4 or later. The default heap profile uses a plain, fixed
46
+ `ArrayBuffer`. The
47
+ optional shared and WASM profiles need a growable `SharedArrayBuffer` or `WebAssembly.Memory`, and
48
+ those requirements set the version limits.
33
49
 
34
50
  ## Quick start
35
51
 
36
52
  ```ts
37
53
  import { ECS, SCHEDULE } from "@oasys/oecs";
38
54
 
39
- const ecs = new ECS(); // pure-TS heap profile no SharedArrayBuffer needed
55
+ const ecs = new ECS(); // the pure-TS heap profile, and no SharedArrayBuffer needed
40
56
 
41
- // Components record syntax (per-field type) or array shorthand (defaults to "f64")
57
+ // Components. The record syntax gives a type to each field. The array shorthand uses "f64".
42
58
  const Pos = ecs.registerComponent({ x: "f64", y: "f64" });
43
59
  const Vel = ecs.registerComponent(["vx", "vy"] as const);
44
60
 
45
- // A query is a live, cached view over matching archetypes build it once, reuse it.
61
+ // A query is a live, cached view of the matching archetypes. Build it once, then use it again.
46
62
  const movers = ecs.query(Pos, Vel);
47
63
 
48
- // Systems declare the components they read/write (checked in dev builds).
64
+ // Systems declare the components that they read and write (checked in development builds).
49
65
  const move = ecs.registerSystem({
50
66
  reads: [Vel],
51
- writes: [Pos], // a declared write implies read of the same component
67
+ writes: [Pos], // a declared write also gives read access to the same component
52
68
  fn: (ctx, dt) => {
53
- movers.eachChunk((cols, count) => {
54
- const { x, y } = cols.mut(Pos); // whole group; stamps Pos's change tick once
55
- const { vx, vy } = cols.read(Vel); // read-only group
69
+ movers.forEachChunk((cols, count) => {
70
+ const { x, y } = cols.mut(Pos); // the full group. Sets the change tick of Pos one time
71
+ const { vx, vy } = cols.read(Vel); // a read-only group
56
72
  for (let i = 0; i < count; i++) {
57
73
  x[i] += vx[i] * dt;
58
74
  y[i] += vy[i] * dt;
@@ -69,163 +85,300 @@ ecs.addComponent(e, Pos, { x: 0, y: 0 });
69
85
  ecs.addComponent(e, Vel, { vx: 100, vy: 50 });
70
86
 
71
87
  ecs.update(1 / 60);
72
- ecs.getField(e, Pos, "x"); // 1.667
88
+ ecs.getField(e, Pos, "x"); // about 1.667
73
89
  ```
74
90
 
75
91
  ## Features
76
92
 
77
- **Storage & data model**
78
-
79
- - **Archetype SoA storage** over a backing-neutral `ColumnStore` — entities with the same component set
80
- share contiguous typed-array columns; cache-friendly loops, no per-entity object allocation.
81
- - **Phantom-typed components** `registerComponent({ x: "f64", y: "f64" })` returns a callable
82
- `ComponentDef` with a stable numeric `.id` at runtime and a fully-typed schema at compile time.
83
- Record syntax for per-field types, array shorthand for uniform `f64`, and `registerTag()` for
84
- data-free markers. Field types: `f32 f64 i8 i16 i32 u8 u16 u32`.
85
- - **Two storage profiles, one core** pure-TS heap (`ArrayBuffer`) by default; opt-in
86
- `SharedArrayBuffer` for workers / WASM. Same code path, same `stateHash`, sized through a single
87
- `memory` surface (entity budget, byte cap, or pinned capacity).
93
+ **Storage and the data model**
94
+
95
+ - **Archetype storage in struct-of-arrays form**, above a storage-neutral `ColumnStore`. Entities
96
+ with the same set of components share adjacent typed-array columns. Loops use the cache well, and
97
+ they allocate no object for each entity.
98
+ - **Components with phantom types**. `registerComponent({ x: "f64", y: "f64" })` gives you a
99
+ callable `ComponentDef`. The definition has a stable numeric `.id` at run time and a full schema
100
+ type at compile time. Use the record syntax for different types in each field. Use the array
101
+ shorthand when all fields are `f64`. Use `registerTag()` for markers that hold no data. The field
102
+ types are `f32 f64 i8 i16 i32 u8 u16 u32`.
103
+ - **Two storage profiles, one core**. The default is a pure-TS heap (`ArrayBuffer`). A
104
+ `SharedArrayBuffer` for workers or WASM is optional. The code path is the same, and the
105
+ `stateHash` is the same. One `memory` option sets the size (a number of entities, a byte limit,
106
+ or a fixed capacity). Size and storage are separate fields, so any pair of them is legal. The shared
107
+ allocators are `growableSabAllocator`, `fixedSabAllocator` and `wasmMemoryAllocator`, from
108
+ `@oasys/oecs/shared`. `fixedSabAllocator(maxBytes)` reserves one buffer that never grows, and it
109
+ keeps the fast write path on JavaScriptCore. A custom allocator implements `InPlaceBufferAllocator`,
110
+ a type export of the root and of `@oasys/oecs/shared`.
88
111
 
89
112
  **Queries**
90
113
 
91
- - **Live, cached queries** `ecs.query(Pos, Vel)` refined with `.and()` / `.without()` / `.anyOf()`;
92
- new matching archetypes are pushed in automatically.
93
- - **Two iteration verbs** `forEach(arch => )` for read-only archetype iteration, `eachChunk((cols, count) => …)`
94
- for the mutable hot path (`cols.mut` / `cols.read` resolve a whole component's columns at once).
95
- - **Change detection** per-`(archetype, component)` change ticks; `query.changed(Pos)` visits only
96
- archetypes written since the system's threshold tick.
97
- - **Relation & hierarchy queries** `(R, *)` / `(*, T)` wildcards, `forEachRelatedTo`, and
98
- `query.hierarchy(rel, depth)`. **Sparse queries** via `query.withSparse(...)`; disabled entities are
99
- skipped unless you opt in with `query.includeDisabled()`.
100
-
101
- **Systems & scheduling**
102
-
103
- - **Declarative systems** — plain functions in a `SystemConfig` declaring `reads` / `writes`, enforced by
104
- a dev-mode access checker (tree-shaken in production). Bare `(ctx, dt)` and `(q, ctx, dt)` +
105
- query-builder overloads exist for no-access glue; lifecycle hooks `onAdded` / `onRemoved` / `dispose`;
106
- `exclusive: true` for full-world setup/teardown.
107
- - **Topological scheduler** seven phases (`PRE_STARTUP` → `STARTUP` → `POST_STARTUP`, `FIXED_UPDATE`,
108
- `PRE_UPDATE` → `UPDATE` → `POST_UPDATE`); per-phase Kahn sort by `before` / `after`, with insertion
109
- order as a deterministic tiebreaker. Always-on cycle detection.
110
- - **Fixed timestep** accumulator loop with configurable `fixedTimestep` and spiral-of-death protection.
111
- - **System sets & run conditions** `systemSet(...)` + `configureSet(...)`; `runIfResourceEq`,
112
- `runEveryNTicks`, `runIfAnyMatch`, and custom `RunCondition`s.
114
+ - **Live, cached queries**. Write `ecs.query(Pos, Vel)`, then make it more exact with `.and()`,
115
+ `.not()`, or `.or()`. The store adds new matching archetypes to the query automatically.
116
+ - **A nested expression**. `q.where(or(and(Pos, Vel), Frozen))` says what no chain says. The free
117
+ `and`, `or` and `not` build it. Each operand is an `ArchetypeExpr`, a definition or a term. A
118
+ plugin supplies its own `ArchetypeTerm` on the same footing.
119
+ - **Two iteration verbs**. Use `forEach(arch => …)` to read archetypes. Use
120
+ `forEachChunk((cols, count) => …)` for the high-frequency loop that writes. In that loop, `cols.mut`
121
+ and `cols.read` give you all the columns of one component at the same time.
122
+ - **Change detection**. Each `(archetype, component)` pair has a change tick.
123
+ `query.changed(Pos)` visits only the archetypes that changed at or after the threshold tick of
124
+ the system.
125
+ - **Queries for relations and hierarchies**. Use the wildcards `(R, *)` and `(*, T)`, plus
126
+ `forEachRelatedTo` and `query.hierarchy(rel, depth)`. For **sparse queries**, use
127
+ `query.andSparse(...)`. Queries skip disabled entities. To include them, use
128
+ `query.includeDisabled()`.
129
+
130
+ **Systems and the schedule**
131
+
132
+ - **Systems that declare their access**. A system is a plain function in a `SystemConfig` that
133
+ declares `reads` and `writes`. A development-mode access checker holds you to that declaration,
134
+ and the build tool removes that checker from a production build. There are also `(ctx, dt)` and
135
+ `(q, ctx, dt)`
136
+ forms with a query builder, for connection code that touches no data. The lifecycle hooks are
137
+ `onAdded`, `onRemoved`, and `dispose`. Set `exclusive: true` for full-world setup or teardown.
138
+ - **A topological scheduler**. There are seven built-in phases: `PRE_STARTUP`, `STARTUP`,
139
+ `POST_STARTUP`, `FIXED_UPDATE`, `PRE_UPDATE`, `UPDATE`, and `POST_UPDATE`. Each phase does a Kahn
140
+ sort on the `before` and `after` constraints. Insertion order breaks a tie, which keeps the result
141
+ deterministic. Cycle detection is always active.
142
+ - **An open phase set**. `ecs.addPhase(name, { loop, before, after })` adds one more slot to a loop
143
+ and gives back a `Phase` handle. A plugin owns its own slot that way. `PhaseConfig` is the config.
144
+ `PhaseLoop` is one of `"startup"`, `"fixed"` and `"update"`. `SchedulePhase` is either
145
+ spelling: a `SCHEDULE` member or a handle. `addSystems` takes either. The engine sorts each loop's
146
+ phases the same way, and it throws `UNKNOWN_PHASE` or `CIRCULAR_PHASE_DEPENDENCY` on a mistake. A
147
+ frame trace event carries a `PhaseName`.
148
+ - **A fixed timestep**. An accumulator loop uses the `fixedTimestep` value that you set. A limit
149
+ protects against the spiral of death.
150
+ - **System sets and run conditions**. Use `systemSet(...)` with `configureSet(...)`. The supplied
151
+ conditions are `runIfResourceEq`, `runEveryNTicks`, and `runIfAnyMatch`. You can also write your
152
+ own `RunCondition`.
113
153
 
114
154
  **Structural changes**
115
155
 
116
- - **Deferred inside systems, immediate on the host** `ctx.commands` (a Bevy-`Commands`-style
117
- facade) buffers add / remove / despawn / enable / disable until the phase flush, so iterators
118
- stay valid (`commands.spawn` returns the id immediately; its component attaches are deferred). Every host-side mutation (`ecs.addComponent` / `removeComponent` /
119
- `despawn` / `disable` / `enable`) applies immediately.
120
- - **Entity enable/disable** `disable` / `enable` / `isDisabled`; disabled rows sit in a partitioned
121
- tail and are skipped by default queries.
122
- - **Templates & bundles** `ecs.template(Pos({ x, y }), …)` blueprints consumed by `spawn` /
123
- `spawnMany` for zero-transition spawns; the same callable-bundle varargs drive `spawnBundle(...)`
124
- and `addComponents(...)`.
125
-
126
- **Reactivity & relationships**
127
-
128
- - **Observers** `ecs.observe(...)` for `onAdd` / `onRemove` / `onSet` / `onEnable` / `onDisable`,
129
- structural or per-entity.
130
- - **Relations** `(relation, target)` pairs with `ChildOf` / `IsA` presets, exclusive / multi arities,
131
- bidirectional queries (`targetOf` / `sourcesOf` / `ancestorsOf` / `rootOf` / `cascadeOf`), and
132
- configurable on-delete cleanup (`delete` / `clear` / `orphan`). Stored sparsely — no archetype
133
- transition, no identity bit.
134
- - **Sparse storage** `registerSparseComponent` / `registerSparseTag`, `addSparse` / `removeSparse` for
135
- churny or rare data that shouldn't cause archetype transitions.
136
- - **Resources** typed global singletons via `resourceKey<T>`. **Events** — fire-and-forget SoA channels
137
- via `eventKey<F>` / `signalKey`, cleared at the end of each `update`.
138
- - **Cached refs** — `ctx.ref(def, e)` (mutable, bumps the change tick) / `ctx.refRead(def, e)`
139
- (read-only): resolve archetype + row + column once, then `pos.x += vel.vx * dt`.
140
-
141
- **Determinism, persistence & integration**
142
-
143
- - **Determinism** (opt-in) `new ECS({ deterministic: true })`, then `ecs.snapshots.stateHash()` (an FNV-1a-style
144
- 32-bit digest over live dense bytes, sparse stores, and multi-relation target sets), `ecs.snapshots.capture()` /
145
- `ecs.snapshots.restore(...)`, plus sparse variants. Backing-agnostic: a heap world and a shared world with identical history produce
146
- identical hashes.
147
- - **Host ECS write seam** `installHostCommandSeam(ecs)` applies typed `HostCommand`s off-schedule
148
- via a blessed `exclusive` system, with record/replay (`HostCommandRecorder`, `replayCommandLog`) and a
149
- cross-thread ring transport.
150
- - **Reactive UI seam** (optional) a zero-dep signals kernel (`@oasys/oecs/reactive`), an ECS→reactive
151
- bridge that publishes only dirty entities/columns (`@oasys/oecs/reactive-sync`), and a SolidJS adapter
152
- (`@oasys/oecs/solid`).
153
- - **Editor layer** undo/redo + field handles over the write seam (`@oasys/oecs/editor`).
154
- - **Frame tracing** `ecs.setTrace(sink)` + `FrameTraceRecorder` for a structured per-frame event
155
- stream (dev-gated).
156
- - **Compute backend seam** — `ecs.attachBackend(...)` to run a system body on a compiled backend (WASM,
157
- ) instead of its TS closure.
156
+ - **Deferred in a system, immediate on the host**. `ctx.commands` is a facade in the style of the
157
+ Bevy `Commands` type. It holds add, remove, despawn, enable, and disable operations until the
158
+ flush at the end of the phase. The flush keeps iterators correct. `commands.spawn` gives you the id
159
+ immediately, but it attaches the components later. Each mutation on the host
160
+ (`ecs.addComponent`, `ecs.removeComponent`, `ecs.despawn`, `ecs.disable`, and `ecs.enable`)
161
+ applies immediately.
162
+ - **Enable and disable for an entity**. Use `disable`, `enable`, and `isDisabled`. Disabled rows
163
+ stay in a partition at the end of the archetype, and queries skip them by default.
164
+ - **Templates and bundles**. `ecs.template(Pos({ x, y }), …)` makes a blueprint. `spawn` and
165
+ `spawnMany` use that blueprint to create entities with no archetype transition. The same callable
166
+ bundles are the arguments to `spawnBundle(...)` and `addComponents(...)`.
167
+
168
+ **Reactions and relationships**
169
+
170
+ - **Observers** (the `observers()` plugin). `ecs.observe(...)` registers `onAdd`, `onRemove`,
171
+ `onSet`, `onEnable`, and `onDisable` callbacks, for a structure or for one entity. A sparse
172
+ component takes the entity-level `onSet`.
173
+ - **Change detection at the row grain**. `ecs.trackRows(def)` keeps a change tick for each row.
174
+ A chunk loop records a row with one store into `cols.ticks(def)`. A reader compares
175
+ `cols.ticksRead(def)` with `cols.since` inside `changed(def).forEachChunk`.
176
+ `ctx.sparseChanged(def, e)` asks the same of a sparse component.
177
+ - **Relations** (the `relations()` plugin). A relation is a `(relation, target)` pair. The
178
+ presets are `ChildOf` and `IsA`.
179
+ A relation is exclusive or multi. Queries go in both directions (`targetOf`, `sourcesOf`,
180
+ `ancestorsOf`, `rootOf`, and `cascadeOf`). The cleanup policy for a deleted target is
181
+ `delete`, `clear`, or `orphan`. Relations use sparse storage. So they cause no archetype
182
+ transition, and they use no identity bit.
183
+ - **Sparse storage**. Use `registerSparseComponent` and `registerSparseTag`, then `addSparse` and
184
+ `removeSparse`. A sparse component keeps its data in columns indexed by entity, so a read by id
185
+ is one load. `sparseCursor(def)` with `sparseCursorRead(def)` is the fastest read by id that the
186
+ engine has. Sparse storage is correct for data that a system reads by id, that changes
187
+ frequently, or that is rare. It causes no archetype transition.
188
+ - **Resources**. A resource is a typed global value, keyed with `resourceKey<T>`. It needs no
189
+ plugin. **Events** (the `events()` plugin) are send-and-forget channels in
190
+ struct-of-arrays form, keyed with `eventKey<F>` or `signalKey`. The ECS clears the events at the
191
+ end of each `update`.
192
+ - **Cached refs**. `ctx.ref(def, e)` gives you a writable ref, and it sets the change tick.
193
+ `ctx.refRead(def, e)` gives you a read-only ref. A ref finds the archetype, the row, and the
194
+ columns one time. Then you can write `pos.x += vel.vx * dt`.
195
+ - **Cursors**. `ctx.cursor(def)` gives you an accessor that you can use again for a different
196
+ entity. `ctx.cursorRead(def)` gives you the read-only form. The same two functions are on `ecs`.
197
+ You make a cursor one time. Then each `at(entity)` call moves it to a different entity. Use a
198
+ cursor when you read or write many entities from a list of ids. The loop then makes no ref for
199
+ each entity, and the cursor finds the position of each field one time. Each `at` call finds the
200
+ archetype and the row again. Thus a structural change between two `at` calls cannot make a
201
+ cursor read a different entity.
202
+
203
+ **Determinism, storage of state, and integration**
204
+
205
+ - **Determinism** (optional). Construct the ECS with
206
+ `ECS.create({ deterministic: true, plugins: [snapshots()] })`. Then use
207
+ `ecs.snapshots.stateHash()`. It gives a 32-bit digest in FNV-1a style. The digest covers the live
208
+ dense bytes, the sparse stores, and the target sets of multi relations. The hash is independent of
209
+ the storage type. A heap ECS and a shared ECS with the same history give the same hash.
210
+ `ecs.snapshots.capture()`, `ecs.snapshots.restore(...)`, and the equivalent functions for sparse
211
+ data need the `snapshots()` plugin beside the flag. A restore that does not match the world throws
212
+ `ECSRestoreError`. That is an `ECSError` with the code `SNAPSHOT_RESTORE_FAILED`. The restore
213
+ leaves the world unchanged.
214
+ - **A write path from the host into the ECS**. `installHostCommandSeam(ecs)` applies typed
215
+ `HostCommand` values from outside the schedule, through one approved `exclusive` system. It
216
+ supports record and replay (`HostCommandRecorder` and `replayCommandLog`), and a ring transport
217
+ between threads.
218
+ - **A UI connection** (optional). A Solid app installs the `solid()` plugin from
219
+ `@oasys/oecs/solid`. It projects ECS state into Solid signals, straight off the change feed, and
220
+ a row is one signal. It is the one path into a UI, and this release ships no other framework
221
+ path.
222
+ - **An editor layer**. It adds undo, redo, and field handles above the host write path
223
+ (`@oasys/oecs/editor`).
224
+ - **Frame traces**. `ecs.setTrace(sink)` with `FrameTraceRecorder` gives you a structured stream
225
+ of the events in each frame. It is available in development builds only.
226
+ - **A compute backend connection**. `ecs.attachBackend(...)` runs the body of a system on a
227
+ compiled backend, such as WASM, instead of its TypeScript closure. A backend body receives the
228
+ phase `dt` and the frame tick, because neither is in the store bytes.
229
+ - **Parallel systems** (the `workers()` plugin). `world.workers.attach({ count })` starts a pool of
230
+ workers on the package's own entry, `@oasys/oecs/worker`. A bundled app passes `workerUrl` instead, because a bundler
231
+ leaves that entry out of its graph. A system that carries a `parallel` config names a kernel a worker
232
+ can load. The kernel is a compiled `WebAssembly.Module` export, or an export of a JavaScript
233
+ module URL. The config also names the columns the kernel receives, in order. The schedule hands
234
+ the pass to the pool, parks the host, and joins before the phase flush. So no structural change
235
+ can overlap the workers. Every
236
+ worker computes its own row range, so the result is deterministic. Below `parallel.minRows`, and
237
+ with no pool, the system runs its own `fn`. In a browser the world lives inside a worker, because
238
+ a main thread cannot park. Blink, Gecko and WebKit all run the pool from there. A `wasm` kernel
239
+ follows a module contract that holds for any toolchain. The contract asks for one memory import
240
+ and one exported function. It also asks for an exported `__stack_pointer` when the body uses a
241
+ stack. Every worker instantiates the module over one memory. So the pool gives each instance its
242
+ own shadow stack, and `stackBytes` says how big one is. `joinTimeoutMs` bounds the wait for a
243
+ join. The suite runs kernels built by Zig, Rust, C and AssemblyScript beside one emitted with no
244
+ toolchain.
245
+ - **A store that starts anywhere in its memory**. `memory.storeBase` places the header at a byte
246
+ offset you choose, and the store writes nothing below it. `storeBaseAbove(exports, extraBytes)`
247
+ reads that offset from a module's `__heap_base`, so a WASM-backed world never lands on the
248
+ addresses the module owns.
158
249
 
159
250
  **Reference**
160
251
 
161
- - **Typed errors** an `ECSError` taxonomy with a `category` enum and an `isEcsError` guard, all exported.
162
- - **Reusable primitives** (`@oasys/oecs/primitives`) `BitSet`, `SparseSet`, `SparseMap`,
163
- `GrowableTypedArray`, `BinaryHeap`, and `topologicalSort`, usable standalone.
252
+ - **Typed errors**. There is an `ECSError` taxonomy with a `category` enum and an `isEcsError`
253
+ guard. The package exports all of them.
254
+ - **Primitives that you can use again** (`@oasys/oecs/primitives`). `BitSet`, `SparseSet`,
255
+ `SparseMap`, `GrowableTypedArray`, `BinaryHeap`, and `topologicalSort` also operate alone.
164
256
 
165
257
  ## Entry points
166
258
 
167
- The core is `@oasys/oecs`; everything else is opt-in and costs nothing until imported.
259
+ The core is `@oasys/oecs`. Each other entry point is optional, and it costs nothing until you
260
+ import it.
261
+
262
+ Six subsystems are **plugins**: relations, events, snapshots, observers, workers and solid. A world
263
+ installs the ones it uses, and carries no code for the rest.
264
+
265
+ ```ts
266
+ import { ECS } from "@oasys/oecs";
267
+ import { relations } from "@oasys/oecs/relations";
268
+ import { observers } from "@oasys/oecs/observers";
269
+
270
+ const world = ECS.create({ plugins: [relations(), observers()] });
271
+ world.relations.register(); // ok
272
+ world.events.emit(Damaged, { amount: 1 }); // compile error, events is not installed
273
+ ```
274
+
275
+ `ECS.create` returns the world intersected with the facades its plugins contribute. Thus reaching
276
+ for a plugin you did not install is a compile error, and not a fault at run time. `new ECS()`
277
+ still builds a world, and that world holds none of them. A bundler cannot remove a class method. So
278
+ these live behind an import you make, and not behind a member you always carry.
279
+
280
+ To write a plugin of your own, import the types `Plugin`, `PluginHost` and `PluginsOf`
281
+ from `@oasys/oecs`. `Plugin<X>` is what a factory such as `relations()` returns, and what a
282
+ plugin list holds. Its `install` takes a `PluginHost` and returns `X`, the surface the world
283
+ gains. `PluginsOf` is the surface a plugin list adds to the world. `ChangeFeed` is the store's
284
+ record of what changed, and `ObservationFlags`, `DrainResult` and `StructuralObserverEvents` are
285
+ what crosses it.
286
+
287
+ `PluginHost` carries nine members, and every one is open to any plugin. `store`, `world`,
288
+ `changes`, `context` and `memory` are the state a plugin reads. `onSettle`, `onPrewarm`,
289
+ `onDispose` and `installRoute` are the four hook points. Each is named for what it hooks, and never
290
+ for the plugin that ships it. A plugin that wants a slot of its own in the frame adds a phase with
291
+ `host.world.addPhase`. A plugin that runs a system body itself takes `installRoute`, and gives back
292
+ a `SystemRoutePlanner`. It holds the `RouteControl` that comes back, and hands the schedule a
293
+ `RouteDispatch`. `PluginMemory` is `host.memory`, which names the backing, its source and the store
294
+ base.
295
+
296
+ The [plugins](./docs/api/plugins.md) page documents every host member and the route seam. It also
297
+ documents the rules `ECS.create` checks, and the change feed a plugin drains. It is the one full
298
+ text. The API index
299
+ and the migration guide point at it.
168
300
 
169
301
  | Import | What it is |
170
302
  | --- | --- |
171
- | `@oasys/oecs` | the ECS pure-TS heap profile by default (production build; dev guards stripped) |
172
- | `@oasys/oecs/dev` | the same ECS with the dev guards **on** for a direct guards-on import; see [Dev vs prod](#dev-vs-prod) |
173
- | `@oasys/oecs/shared` | opt-in `SharedArrayBuffer` allocators for worker offload / a WASM backend (needs COOP/COEP) |
174
- | `@oasys/oecs/reactive` | zero-dependency reactive kernel (`signal`/`computed`/`effect`, reactive collections) |
175
- | `@oasys/oecs/reactive-sync` | ECS→reactive bridge publishes only dirty entities/columns |
176
- | `@oasys/oecs/editor` | undo/redo + field-handle layer over the host-write seam |
177
- | `@oasys/oecs/solid` | SolidJS adapter (`solid-js` is an **optional** peer dependency) |
178
- | `@oasys/oecs/primitives` | the standalone data structures oecs is built on |
179
- | `@oasys/oecs/internal` | unstable internals (codecs, ABI constants, access checker) **no semver guarantees** |
180
-
181
- ## Dev vs prod
182
-
183
- A compile-time `__DEV__` flag gates every runtime check bounds and liveness checks, duplicate-system
184
- detection, registration validation, and the system access checker (`reads`/`writes`). These are
185
- **tree-shaken out of production builds**, so treat "throws in dev" as a development tripwire, not a
186
- production guarantee. The scheduler's cycle detection and constructor-option validation (timestep,
187
- memory options, relation cardinality) are always active.
188
-
189
- **Production is the default on both channels; you opt *into* the guards.** On **npm**, `@oasys/oecs`
190
- is the stripped production build dev-mode bundlers (`vite dev`, `webpack --mode development`) pick
191
- the guards-on build automatically via the `development` export condition, or import `@oasys/oecs/dev`
192
- for it directly. On **JSR/Deno** (raw source, no bundler) the default is also production
193
- (`__DEV__ = false`); set `globalThis.__DEV__ = true` before the first import to turn the guards on
194
- while developing. Full details including the browser/CDN and manual-override paths are in the
195
- [**Development guards & production builds**](docs/PRODUCTION.md) guide.
303
+ | `@oasys/oecs` | the ECS, the pure-TS heap profile by default (a production build, with the development guards removed) |
304
+ | `@oasys/oecs/dev` | the same ECS with the development guards on, on npm alone. Import this to get the guards directly. See [Development and production](#dev-vs-prod) |
305
+ | `@oasys/oecs/shared` | the optional `SharedArrayBuffer` allocators, `growableSabAllocator`, `fixedSabAllocator` and `wasmMemoryAllocator`, for worker offload or a WASM backend (this needs COOP and COEP) |
306
+ | `@oasys/oecs/relations` | the relations plugin, `(relation, target)` pairs, wildcards and hierarchy traversal |
307
+ | `@oasys/oecs/events` | the events plugin, host-side channels and signals, and `ctx.emit` |
308
+ | `@oasys/oecs/snapshots` | the snapshots plugin, `capture` and `restore` for a live world |
309
+ | `@oasys/oecs/observers` | the observers plugin, `ecs.observe` for `onAdd`, `onRemove` and `onSet` |
310
+ | `@oasys/oecs/workers` | the workers plugin, `ecs.workers`, one pool of workers for the `parallel` systems |
311
+ | `@oasys/oecs/editor` | undo, redo, and field handles above the host write path |
312
+ | `@oasys/oecs/solid` | the solid plugin, `solid()`, ECS state into Solid signals off the change feed (`solid-js` is an **optional** peer dependency) |
313
+ | `@oasys/oecs/worker` | the engine's worker entry, which `world.workers.attach` starts. A bundled app imports it for its URL alone, and passes that as `workerUrl`. `@oasys/oecs/worker/dev` is the guarded build on npm |
314
+ | `@oasys/oecs/primitives` | the data structures that oecs is built from, which also operate alone |
315
+ | `@oasys/oecs/internal` | unstable internal parts (codecs, ABI constants, the access checker). There are no semver guarantees |
316
+
317
+ <a id="dev-vs-prod"></a>
318
+
319
+ ## Development and production
320
+
321
+ A compile-time flag, `__DEV__`, controls each run-time check. The checks include bounds and
322
+ liveness checks. They also include detection of a system that you added two times. They include
323
+ validation at registration, and the system access checker for `reads` and `writes`. The build tool
324
+ **removes these checks from a production build**. So, when the documentation says that an operation
325
+ "throws in development", that behavior is a development aid. It is not a production guarantee. Two
326
+ checks stay active in each build. One is cycle detection in the scheduler. The other is validation
327
+ of the constructor options (the timestep, the memory options, and the cardinality of a relation).
328
+
329
+ **Production is the default on both channels. You must turn the guards on.** On **npm**,
330
+ `@oasys/oecs` is the production build, with the guards removed. A bundler in development mode
331
+ (`vite dev` or `webpack --mode development`) selects the build with the guards automatically,
332
+ through the `development` export condition. As an alternative, import `@oasys/oecs/dev` directly.
333
+ Each optional entry point has the same subpath: `@oasys/oecs/relations/dev`,
334
+ `@oasys/oecs/events/dev`, `@oasys/oecs/snapshots/dev`, `@oasys/oecs/observers/dev`, `@oasys/oecs/workers/dev`,
335
+ `@oasys/oecs/editor/dev` and `@oasys/oecs/solid/dev`. Take the
336
+ plugin from the same channel as the world. A plugin binds to the core build it was made
337
+ against.
338
+ On **JSR and Deno** there is no bundler, because the package is raw source. The default is also
339
+ production (`__DEV__ = false`). To turn the guards on while you develop, set
340
+ `globalThis.__DEV__ = true` before the first import. For the full details, which include the
341
+ browser, CDN, and manual paths, read the
342
+ [**Development guards and production builds**](docs/PRODUCTION.md) guide.
196
343
 
197
344
  ## Documentation
198
345
 
199
- - **New to oecs?** Start with the [Getting Started](docs/GETTING_STARTED.md) tutorial, then
200
- [Best Practices](docs/BEST_PRACTICES.md) and the [Architecture](docs/ARCHITECTURE.md) overview.
201
- - **Using optional extensions?** See the [Extensions guide](docs/EXTENSIONS.md) for reactive UI,
202
- editor, Solid, shared-memory, and primitives usage.
203
- - **Upgrading from 0.4?** See the [Migration guide (0.4 → 0.5)](docs/MIGRATION-0.4-to-0.5.md) and the
204
- [CHANGELOG](CHANGELOG.md).
205
- - **Upgrading from 0.3?** See the [Migration guide (0.3 → 0.4)](docs/MIGRATION-0.3-to-0.4.md).
206
- - **Full API reference** start at the [reference index](docs/api/index.md):
207
- [components](docs/api/components.md) ·
208
- [entities](docs/api/entities.md) ·
209
- [queries](docs/api/queries.md) ·
210
- [systems](docs/api/systems.md) ·
211
- [schedule](docs/api/schedule.md) ·
212
- [resources](docs/api/resources.md) ·
213
- [events](docs/api/events.md) ·
214
- [refs](docs/api/refs.md) ·
215
- [change detection](docs/api/change-detection.md) ·
216
- [observers](docs/api/observers.md) ·
217
- [relations](docs/api/relations.md) ·
218
- [sparse storage](docs/api/sparse-storage.md) ·
219
- [determinism](docs/api/determinism.md) ·
220
- [memory](docs/api/memory.md) ·
221
- [WASM backends](docs/api/wasm.md) ·
222
- [parallelism](docs/api/parallel.md) ·
223
- [host-write seam](docs/api/host-write-seam.md) ·
224
- [reactive](docs/api/reactive.md) ·
225
- [editor](docs/api/editor.md) ·
226
- [tracing](docs/api/tracing.md) ·
227
- [primitives](docs/api/primitives.md) ·
228
- [errors](docs/api/errors.md)
346
+ - **If oecs is new to you**, start with the [Getting started](docs/GETTING_STARTED.md) tutorial.
347
+ Then read [Best practices](docs/BEST_PRACTICES.md) and the
348
+ [Architecture](docs/ARCHITECTURE.md) overview.
349
+ - **If you use the optional entry points**, read the
350
+ [Integration guide](docs/INTEGRATION.md) for Solid, the editor, shared memory, and the
351
+ primitives.
352
+ - **If you upgrade from 0.5**, read the
353
+ [Migration guide (0.5 to 0.6)](docs/MIGRATION-0.5-to-0.6.md) and the [CHANGELOG](CHANGELOG.md).
354
+ - **If you upgrade from 0.4**, read the
355
+ [Migration guide (0.4 to 0.5)](docs/MIGRATION-0.4-to-0.5.md).
356
+ - **If you upgrade from 0.3**, read the
357
+ [Migration guide (0.3 to 0.4)](docs/MIGRATION-0.3-to-0.4.md).
358
+ - **The full API reference.** Start at the [reference index](docs/api/index.md). The pages are:
359
+ - [components](docs/api/components.md)
360
+ - [entities](docs/api/entities.md)
361
+ - [queries](docs/api/queries.md)
362
+ - [systems](docs/api/systems.md)
363
+ - [schedule](docs/api/schedule.md)
364
+ - [resources](docs/api/resources.md)
365
+ - [events](docs/api/events.md)
366
+ - [refs](docs/api/refs.md)
367
+ - [change detection](docs/api/change-detection.md)
368
+ - [observers](docs/api/observers.md)
369
+ - [relations](docs/api/relations.md)
370
+ - [sparse storage](docs/api/sparse-storage.md)
371
+ - [determinism](docs/api/determinism.md)
372
+ - [memory](docs/api/memory.md)
373
+ - [WASM backends](docs/api/wasm.md)
374
+ - [parallel execution](docs/api/parallel.md), the worker pool and the `parallel` system form
375
+ - [the host write path](docs/api/host-write-seam.md)
376
+ - [solid](docs/api/solid.md)
377
+ - [editor](docs/api/editor.md)
378
+ - [traces](docs/api/tracing.md)
379
+ - [primitives](docs/api/primitives.md)
380
+ - [errors](docs/api/errors.md)
381
+ - [plugins](docs/api/plugins.md)
229
382
 
230
383
  ## Development
231
384
 
@@ -235,18 +388,23 @@ pnpm test # vitest
235
388
  pnpm bench # vitest bench
236
389
  pnpm build # vite library build (multi-entry → dist/)
237
390
  pnpm exec tsc --noEmit # type check
391
+ pnpm fmt # oxfmt, write
392
+ pnpm lint # oxlint
393
+ pnpm verify # format, lint, types, tests, build
238
394
  ```
239
395
 
396
+ `pnpm verify` is the gate the publish workflow runs. Run it before a tag.
397
+
240
398
  ## Acknowledgements
241
399
 
242
- oecs stands on the shoulders of the ECS community. Special thanks to:
400
+ oecs is built on the work of the ECS community. We thank:
243
401
 
244
402
  - **[Bevy](https://bevyengine.org)**, **[Flecs](https://github.com/SanderMertens/flecs)**, and
245
- **[bitECS](https://github.com/NateTheGreatt/bitECS)** a constant source of inspiration; their
246
- designs shaped how oecs approaches archetypes, relations, scheduling, and change detection.
247
- - **[@clinuxrulz](https://github.com/clinuxrulz)** for his amazing showcase and invaluable input on
248
- the ECS.
403
+ **[bitECS](https://github.com/NateTheGreatt/bitECS)**, a continuous source of ideas. Their
404
+ designs gave shape to the archetypes, relations, schedule, and change detection in oecs.
405
+ - **[@clinuxrulz](https://github.com/clinuxrulz)**, for an excellent demonstration and for very
406
+ valuable comments on the ECS.
249
407
 
250
408
  ## License
251
409
 
252
- [MIT](LICENSE)
410
+ [MIT](license)