@oasys/oecs 0.4.0 → 0.5.1

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 (273) hide show
  1. package/CHANGELOG.md +636 -0
  2. package/README.md +47 -32
  3. package/dist/core/ecs/access_check.d.cts +77 -0
  4. package/dist/core/ecs/access_check.d.ts +8 -8
  5. package/dist/core/ecs/access_check.d.ts.map +1 -1
  6. package/dist/core/ecs/archetype.d.cts +486 -0
  7. package/dist/core/ecs/archetype.d.ts +25 -13
  8. package/dist/core/ecs/archetype.d.ts.map +1 -1
  9. package/dist/core/ecs/archetype_graph.d.cts +96 -0
  10. package/dist/core/ecs/archetype_graph.d.ts +96 -0
  11. package/dist/core/ecs/archetype_graph.d.ts.map +1 -0
  12. package/dist/core/ecs/builtin_relations.d.cts +43 -0
  13. package/dist/core/ecs/builtin_relations.d.ts +8 -8
  14. package/dist/core/ecs/builtin_relations.d.ts.map +1 -1
  15. package/dist/core/ecs/command_log.d.cts +116 -0
  16. package/dist/core/ecs/command_log.d.ts +13 -10
  17. package/dist/core/ecs/command_log.d.ts.map +1 -1
  18. package/dist/core/ecs/component.d.cts +201 -0
  19. package/dist/core/ecs/component.d.ts +100 -5
  20. package/dist/core/ecs/component.d.ts.map +1 -1
  21. package/dist/core/ecs/compute_backend.d.cts +37 -0
  22. package/dist/core/ecs/compute_backend.d.ts +2 -2
  23. package/dist/core/ecs/debug_names.d.cts +7 -0
  24. package/dist/core/ecs/debug_names.d.ts +7 -0
  25. package/dist/core/ecs/debug_names.d.ts.map +1 -0
  26. package/dist/core/ecs/deferred_commands.d.cts +55 -0
  27. package/dist/core/ecs/deferred_commands.d.ts +55 -0
  28. package/dist/core/ecs/deferred_commands.d.ts.map +1 -0
  29. package/dist/core/ecs/dispatch_trace.d.cts +93 -0
  30. package/dist/core/ecs/dispatch_trace.d.ts +3 -3
  31. package/dist/core/ecs/ecs.d.cts +580 -0
  32. package/dist/core/ecs/ecs.d.ts +340 -293
  33. package/dist/core/ecs/ecs.d.ts.map +1 -1
  34. package/dist/core/ecs/ecs_memory.d.cts +179 -0
  35. package/dist/core/ecs/ecs_memory.d.ts +1 -1
  36. package/dist/core/ecs/entity.d.cts +34 -0
  37. package/dist/core/ecs/entity.d.ts +8 -2
  38. package/dist/core/ecs/entity.d.ts.map +1 -1
  39. package/dist/core/ecs/entity_allocator.d.cts +59 -0
  40. package/dist/core/ecs/entity_allocator.d.ts +59 -0
  41. package/dist/core/ecs/entity_allocator.d.ts.map +1 -0
  42. package/dist/core/ecs/event.d.cts +79 -0
  43. package/dist/core/ecs/event.d.ts +36 -11
  44. package/dist/core/ecs/event.d.ts.map +1 -1
  45. package/dist/core/ecs/event_registry.d.cts +22 -0
  46. package/dist/core/ecs/event_registry.d.ts +22 -0
  47. package/dist/core/ecs/event_registry.d.ts.map +1 -0
  48. package/dist/core/ecs/facades.d.cts +158 -0
  49. package/dist/core/ecs/facades.d.ts +158 -0
  50. package/dist/core/ecs/facades.d.ts.map +1 -0
  51. package/dist/core/ecs/frame_stepper.d.cts +58 -0
  52. package/dist/core/ecs/frame_stepper.d.ts +58 -0
  53. package/dist/core/ecs/frame_stepper.d.ts.map +1 -0
  54. package/dist/core/ecs/frame_trace.d.cts +133 -0
  55. package/dist/core/ecs/frame_trace.d.ts +5 -5
  56. package/dist/core/ecs/frame_trace.d.ts.map +1 -1
  57. package/dist/core/ecs/host_commands.d.cts +284 -0
  58. package/dist/core/ecs/host_commands.d.ts +77 -45
  59. package/dist/core/ecs/host_commands.d.ts.map +1 -1
  60. package/dist/core/ecs/index.d.cts +46 -0
  61. package/dist/core/ecs/index.d.ts +45 -40
  62. package/dist/core/ecs/index.d.ts.map +1 -1
  63. package/dist/core/ecs/observer.d.cts +173 -0
  64. package/dist/core/ecs/observer.d.ts +44 -13
  65. package/dist/core/ecs/observer.d.ts.map +1 -1
  66. package/dist/core/ecs/query.d.cts +734 -0
  67. package/dist/core/ecs/query.d.ts +267 -90
  68. package/dist/core/ecs/query.d.ts.map +1 -1
  69. package/dist/core/ecs/ref.d.cts +31 -0
  70. package/dist/core/ecs/ref.d.ts +3 -3
  71. package/dist/core/ecs/ref.d.ts.map +1 -1
  72. package/dist/core/ecs/relation.d.cts +243 -0
  73. package/dist/core/ecs/relation.d.ts +26 -14
  74. package/dist/core/ecs/relation.d.ts.map +1 -1
  75. package/dist/core/ecs/relation_service.d.cts +235 -0
  76. package/dist/core/ecs/relation_service.d.ts +235 -0
  77. package/dist/core/ecs/relation_service.d.ts.map +1 -0
  78. package/dist/core/ecs/resource.d.cts +53 -0
  79. package/dist/core/ecs/resource.d.ts +25 -5
  80. package/dist/core/ecs/resource.d.ts.map +1 -1
  81. package/dist/core/ecs/resource_registry.d.cts +20 -0
  82. package/dist/core/ecs/resource_registry.d.ts +20 -0
  83. package/dist/core/ecs/resource_registry.d.ts.map +1 -0
  84. package/dist/core/ecs/resume.d.cts +85 -0
  85. package/dist/core/ecs/resume.d.ts +6 -6
  86. package/dist/core/ecs/resume.d.ts.map +1 -1
  87. package/dist/core/ecs/run_condition.d.cts +81 -0
  88. package/dist/core/ecs/run_condition.d.ts +16 -10
  89. package/dist/core/ecs/run_condition.d.ts.map +1 -1
  90. package/dist/core/ecs/schedule.d.cts +142 -0
  91. package/dist/core/ecs/schedule.d.ts +15 -6
  92. package/dist/core/ecs/schedule.d.ts.map +1 -1
  93. package/dist/core/ecs/snapshot_service.d.cts +94 -0
  94. package/dist/core/ecs/snapshot_service.d.ts +94 -0
  95. package/dist/core/ecs/snapshot_service.d.ts.map +1 -0
  96. package/dist/core/ecs/sparse_store.d.cts +110 -0
  97. package/dist/core/ecs/sparse_store.d.ts +5 -2
  98. package/dist/core/ecs/sparse_store.d.ts.map +1 -1
  99. package/dist/core/ecs/store.d.cts +937 -0
  100. package/dist/core/ecs/store.d.ts +144 -356
  101. package/dist/core/ecs/store.d.ts.map +1 -1
  102. package/dist/core/ecs/store_layout_listener.d.cts +23 -0
  103. package/dist/core/ecs/system.d.cts +250 -0
  104. package/dist/core/ecs/system.d.ts +138 -22
  105. package/dist/core/ecs/system.d.ts.map +1 -1
  106. package/dist/{utils/arrays.d.ts → core/ecs/utils/arrays.d.cts} +1 -0
  107. package/dist/core/ecs/utils/error.d.cts +61 -0
  108. package/dist/core/ecs/utils/error.d.ts +12 -2
  109. package/dist/core/ecs/utils/error.d.ts.map +1 -1
  110. package/dist/core/store/action_ring.d.cts +136 -0
  111. package/dist/core/store/allocator.d.cts +238 -0
  112. package/dist/core/store/allocator.d.ts.map +1 -1
  113. package/dist/core/store/buffer_backed_column.d.cts +69 -0
  114. package/dist/core/store/buffer_backed_column.d.ts +2 -2
  115. package/dist/core/store/column_store.d.cts +273 -0
  116. package/dist/core/store/column_store.d.ts +18 -10
  117. package/dist/core/store/column_store.d.ts.map +1 -1
  118. package/dist/core/store/command_dispatch.d.cts +52 -0
  119. package/dist/core/store/command_ring.d.cts +107 -0
  120. package/dist/core/store/descriptor.d.cts +80 -0
  121. package/dist/core/store/descriptor.d.ts +1 -1
  122. package/dist/core/store/descriptor.d.ts.map +1 -1
  123. package/dist/core/store/entity_index.d.cts +108 -0
  124. package/dist/core/store/event_ring.d.cts +95 -0
  125. package/dist/core/store/extend.d.cts +39 -0
  126. package/dist/core/store/extend.d.ts +3 -73
  127. package/dist/core/store/extend.d.ts.map +1 -1
  128. package/dist/core/store/grow.d.cts +34 -0
  129. package/dist/core/store/grow.d.ts +4 -9
  130. package/dist/core/store/grow.d.ts.map +1 -1
  131. package/dist/core/store/header.d.cts +64 -0
  132. package/dist/core/store/header.d.ts +1 -1
  133. package/dist/core/store/header.d.ts.map +1 -1
  134. package/dist/core/store/index.d.cts +17 -0
  135. package/dist/core/store/index.d.ts +16 -15
  136. package/dist/core/store/index.d.ts.map +1 -1
  137. package/dist/core/store/layout_ops.d.cts +152 -0
  138. package/dist/core/store/layout_ops.d.ts +152 -0
  139. package/dist/core/store/layout_ops.d.ts.map +1 -0
  140. package/dist/core/store/region_table.d.cts +74 -0
  141. package/dist/core/store/region_table.d.ts +1 -1
  142. package/dist/core/store/region_table.d.ts.map +1 -1
  143. package/dist/core/store/snapshot.d.cts +43 -0
  144. package/dist/core/store/snapshot.d.ts +2 -2
  145. package/dist/core/store/state_hash.d.cts +38 -0
  146. package/dist/core/store/state_hash.d.ts +1 -1
  147. package/dist/core/store/store_regions.d.cts +38 -0
  148. package/dist/core/store/store_regions.d.ts +1 -1
  149. package/dist/core/store/vendored_abi/abi.d.ts +43 -0
  150. package/dist/core/store/{__generated__ → vendored_abi}/abi.d.ts.map +1 -1
  151. package/dist/dev_flag.d.cts +2 -0
  152. package/dist/dev_flag.d.ts +2 -0
  153. package/dist/dev_flag.d.ts.map +1 -0
  154. package/dist/extensions/editor/editor.d.cts +172 -0
  155. package/dist/extensions/editor/editor.d.ts +65 -42
  156. package/dist/extensions/editor/editor.d.ts.map +1 -1
  157. package/dist/extensions/editor/field_handle.d.cts +40 -0
  158. package/dist/extensions/editor/field_handle.d.ts +10 -5
  159. package/dist/extensions/editor/field_handle.d.ts.map +1 -1
  160. package/dist/extensions/editor/index.cjs +1 -1
  161. package/dist/extensions/editor/index.d.cts +21 -0
  162. package/dist/extensions/editor/index.d.ts +2 -2
  163. package/dist/extensions/editor/index.js +130 -100
  164. package/dist/extensions/reactive/ecs_sync.d.cts +214 -0
  165. package/dist/extensions/reactive/ecs_sync.d.ts +26 -22
  166. package/dist/extensions/reactive/ecs_sync.d.ts.map +1 -1
  167. package/dist/extensions/reactive/index.cjs +1 -1
  168. package/dist/extensions/reactive/index.d.cts +23 -0
  169. package/dist/extensions/reactive/index.d.ts +1 -1
  170. package/dist/extensions/reactive/index.js +106 -116
  171. package/dist/extensions/solid/index.cjs +1 -1
  172. package/dist/extensions/solid/index.d.cts +6 -0
  173. package/dist/extensions/solid/index.d.ts +2 -2
  174. package/dist/extensions/solid/index.js +8 -4
  175. package/dist/extensions/solid/kernel_solid.d.cts +45 -0
  176. package/dist/extensions/solid/kernel_solid.d.ts +6 -3
  177. package/dist/extensions/solid/kernel_solid.d.ts.map +1 -1
  178. package/dist/host_commands-BI8pEmjH.js +2326 -0
  179. package/dist/host_commands-CxhpzMx9.cjs +1 -0
  180. package/dist/index.cjs +1 -2
  181. package/dist/index.d.cts +66 -0
  182. package/dist/index.d.ts +50 -1
  183. package/dist/index.d.ts.map +1 -1
  184. package/dist/index.js +4489 -5898
  185. package/dist/internal.cjs +2 -0
  186. package/dist/internal.d.cts +20 -0
  187. package/dist/internal.d.ts +20 -0
  188. package/dist/internal.d.ts.map +1 -0
  189. package/dist/internal.js +141 -0
  190. package/dist/primitives.cjs +1 -1
  191. package/dist/primitives.d.cts +18 -0
  192. package/dist/primitives.d.ts +6 -6
  193. package/dist/primitives.js +24 -23
  194. package/dist/reactive/array.d.ts +24 -0
  195. package/dist/reactive/array.d.ts.map +1 -0
  196. package/dist/reactive/index.cjs +1 -0
  197. package/dist/reactive/index.d.cts +11 -0
  198. package/dist/reactive/index.d.ts +11 -0
  199. package/dist/reactive/index.d.ts.map +1 -0
  200. package/dist/reactive/index.js +18 -0
  201. package/dist/reactive/interop.d.cts +19 -0
  202. package/dist/{core/reactive → reactive}/interop.d.ts +1 -1
  203. package/dist/reactive/interop.d.ts.map +1 -0
  204. package/dist/reactive/kernel.d.cts +73 -0
  205. package/dist/{core/reactive → reactive}/kernel.d.ts +5 -3
  206. package/dist/reactive/kernel.d.ts.map +1 -0
  207. package/dist/reactive/map.d.ts +16 -0
  208. package/dist/reactive/map.d.ts.map +1 -0
  209. package/dist/reactive/shallow.d.cts +11 -0
  210. package/dist/reactive/shallow.d.ts +11 -0
  211. package/dist/reactive/shallow.d.ts.map +1 -0
  212. package/dist/reactive/struct.d.cts +10 -0
  213. package/dist/{core/reactive → reactive}/struct.d.ts +1 -1
  214. package/dist/reactive/struct.d.ts.map +1 -0
  215. package/dist/shallow-DQ8aG51_.cjs +1 -0
  216. package/dist/shallow-DfnAm9vG.js +150 -0
  217. package/dist/shared-BU1Cd40h.js +103 -0
  218. package/dist/shared-BymrGTyR.cjs +1 -0
  219. package/dist/shared.cjs +1 -1
  220. package/dist/shared.d.cts +22 -0
  221. package/dist/shared.d.ts +2 -2
  222. package/dist/shared.js +1 -1
  223. package/dist/topological_sort-BDvEyb9W.cjs +1 -0
  224. package/dist/topological_sort-DK6EjpWa.js +135 -0
  225. package/dist/type_primitives/assertions.d.cts +32 -0
  226. package/dist/type_primitives/assertions.d.ts +13 -1
  227. package/dist/type_primitives/assertions.d.ts.map +1 -1
  228. package/dist/type_primitives/binary_heap/binary_heap.d.cts +37 -0
  229. package/dist/type_primitives/bitset/bitset.d.cts +54 -0
  230. package/dist/type_primitives/brand.d.cts +23 -0
  231. package/dist/type_primitives/error.d.cts +16 -0
  232. package/dist/type_primitives/error.d.ts +4 -3
  233. package/dist/type_primitives/error.d.ts.map +1 -1
  234. package/dist/type_primitives/index.d.cts +13 -0
  235. package/dist/type_primitives/index.d.ts +9 -9
  236. package/dist/type_primitives/sparse_map/sparse_map.d.cts +30 -0
  237. package/dist/type_primitives/sparse_set/sparse_set.d.cts +28 -0
  238. package/dist/type_primitives/topological_sort/topological_sort.d.cts +29 -0
  239. package/dist/type_primitives/typed_arrays/typed_arrays.d.cts +127 -0
  240. package/dist/typed_arrays-BcXcnzB4.js +258 -0
  241. package/dist/typed_arrays-D3NmwtCG.cjs +1 -0
  242. package/dist/utils/error.d.cts +6 -0
  243. package/dist/version.d.cts +10 -0
  244. package/dist/version.d.ts +10 -0
  245. package/dist/version.d.ts.map +1 -0
  246. package/package.json +102 -19
  247. package/dist/array-CxbPyiHO.cjs +0 -1
  248. package/dist/array-uFR7Q8fU.js +0 -132
  249. package/dist/core/reactive/array.d.ts.map +0 -1
  250. package/dist/core/reactive/index.cjs +0 -1
  251. package/dist/core/reactive/index.d.ts +0 -10
  252. package/dist/core/reactive/index.d.ts.map +0 -1
  253. package/dist/core/reactive/index.js +0 -17
  254. package/dist/core/reactive/interop.d.ts.map +0 -1
  255. package/dist/core/reactive/kernel.d.ts.map +0 -1
  256. package/dist/core/reactive/map.d.ts.map +0 -1
  257. package/dist/core/reactive/struct.d.ts.map +0 -1
  258. package/dist/log/console_sink.d.ts +0 -4
  259. package/dist/log/console_sink.d.ts.map +0 -1
  260. package/dist/log/index.d.ts +0 -3
  261. package/dist/log/index.d.ts.map +0 -1
  262. package/dist/log/logger.d.ts +0 -27
  263. package/dist/log/logger.d.ts.map +0 -1
  264. package/dist/shared-BXSZnxx4.cjs +0 -1
  265. package/dist/shared-C678TAPY.js +0 -99
  266. package/dist/topological_sort-DlRpSrxu.js +0 -391
  267. package/dist/topological_sort-WAT-VHb-.cjs +0 -1
  268. package/dist/utils/arrays.d.ts.map +0 -1
  269. package/dist/utils/constants.d.ts.map +0 -1
  270. /package/dist/{utils/constants.d.ts → core/ecs/utils/constants.d.cts} +0 -0
  271. /package/dist/core/store/{__generated__/abi.d.ts → vendored_abi/abi.d.cts} +0 -0
  272. /package/dist/{core/reactive/array.d.ts → reactive/array.d.cts} +0 -0
  273. /package/dist/{core/reactive/map.d.ts → reactive/map.d.cts} +0 -0
package/README.md CHANGED
@@ -12,7 +12,7 @@ or a WASM compute backend; both profiles share one core and agree, byte-for-byte
12
12
 
13
13
  - **Fast** — struct-of-arrays column storage grouped by archetype; iteration is a tight loop over typed
14
14
  arrays with no per-entity object allocation.
15
- - **Type-safe** — components are branded integers at runtime and fully-typed schemas at compile time;
15
+ - **Type-safe** — component handles are callable defs with stable numeric ids at runtime and fully-typed schemas at compile time;
16
16
  misspelled fields are compile errors.
17
17
  - **Deterministic** — an opt-in mode gives a backing-agnostic `stateHash` plus snapshot/restore and
18
18
  command-log replay.
@@ -28,22 +28,25 @@ deno add jsr:@oasys/oecs # JSR (Deno)
28
28
  npx jsr add @oasys/oecs # JSR (npm-compatible)
29
29
  ```
30
30
 
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+.
33
+
31
34
  ## Quick start
32
35
 
33
36
  ```ts
34
37
  import { ECS, SCHEDULE } from "@oasys/oecs";
35
38
 
36
- const world = new ECS(); // pure-TS heap profile — no SharedArrayBuffer needed
39
+ const ecs = new ECS(); // pure-TS heap profile — no SharedArrayBuffer needed
37
40
 
38
41
  // Components — record syntax (per-field type) or array shorthand (defaults to "f64")
39
- const Pos = world.registerComponent({ x: "f64", y: "f64" });
40
- const Vel = world.registerComponent(["vx", "vy"] as const);
42
+ const Pos = ecs.registerComponent({ x: "f64", y: "f64" });
43
+ const Vel = ecs.registerComponent(["vx", "vy"] as const);
41
44
 
42
45
  // A query is a live, cached view over matching archetypes — build it once, reuse it.
43
- const movers = world.query(Pos, Vel);
46
+ const movers = ecs.query(Pos, Vel);
44
47
 
45
48
  // Systems declare the components they read/write (checked in dev builds).
46
- const move = world.registerSystem({
49
+ const move = ecs.registerSystem({
47
50
  reads: [Vel],
48
51
  writes: [Pos], // a declared write implies read of the same component
49
52
  fn: (ctx, dt) => {
@@ -58,15 +61,15 @@ const move = world.registerSystem({
58
61
  },
59
62
  });
60
63
 
61
- world.addSystems(SCHEDULE.UPDATE, move);
62
- world.startup();
64
+ ecs.addSystems(SCHEDULE.UPDATE, move);
65
+ ecs.startup();
63
66
 
64
- const e = world.createEntity();
65
- world.addComponent(e, Pos, { x: 0, y: 0 });
66
- world.addComponent(e, Vel, { vx: 100, vy: 50 });
67
+ const e = ecs.spawn();
68
+ ecs.addComponent(e, Pos, { x: 0, y: 0 });
69
+ ecs.addComponent(e, Vel, { vx: 100, vy: 50 });
67
70
 
68
- world.update(1 / 60);
69
- world.getField(e, Pos, "x"); // ≈ 1.667
71
+ ecs.update(1 / 60);
72
+ ecs.getField(e, Pos, "x"); // ≈ 1.667
70
73
  ```
71
74
 
72
75
  ## Features
@@ -75,16 +78,17 @@ world.getField(e, Pos, "x"); // ≈ 1.667
75
78
 
76
79
  - **Archetype SoA storage** over a backing-neutral `ColumnStore` — entities with the same component set
77
80
  share contiguous typed-array columns; cache-friendly loops, no per-entity object allocation.
78
- - **Phantom-typed components** — `registerComponent({ x: "f64", y: "f64" })` is a branded integer at
79
- runtime and a fully-typed schema at compile time. Record syntax for per-field types, array shorthand
80
- for uniform `f64`, and `registerTag()` for data-free markers. Field types: `f32 f64 i8 i16 i32 u8 u16 u32`.
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`.
81
85
  - **Two storage profiles, one core** — pure-TS heap (`ArrayBuffer`) by default; opt-in
82
86
  `SharedArrayBuffer` for workers / WASM. Same code path, same `stateHash`, sized through a single
83
87
  `memory` surface (entity budget, byte cap, or pinned capacity).
84
88
 
85
89
  **Queries**
86
90
 
87
- - **Live, cached queries** — `world.query(Pos, Vel)` refined with `.and()` / `.without()` / `.anyOf()`;
91
+ - **Live, cached queries** — `ecs.query(Pos, Vel)` refined with `.and()` / `.without()` / `.anyOf()`;
88
92
  new matching archetypes are pushed in automatically.
89
93
  - **Two iteration verbs** — `forEach(arch => …)` for read-only archetype iteration, `eachChunk((cols, count) => …)`
90
94
  for the mutable hot path (`cols.mut` / `cols.read` resolve a whole component's columns at once).
@@ -98,7 +102,7 @@ world.getField(e, Pos, "x"); // ≈ 1.667
98
102
 
99
103
  - **Declarative systems** — plain functions in a `SystemConfig` declaring `reads` / `writes`, enforced by
100
104
  a dev-mode access checker (tree-shaken in production). Bare `(ctx, dt)` and `(q, ctx, dt)` +
101
- query-builder overloads exist for access-free glue; lifecycle hooks `onAdded` / `onRemoved` / `dispose`;
105
+ query-builder overloads exist for no-access glue; lifecycle hooks `onAdded` / `onRemoved` / `dispose`;
102
106
  `exclusive: true` for full-world setup/teardown.
103
107
  - **Topological scheduler** — seven phases (`PRE_STARTUP` → `STARTUP` → `POST_STARTUP`, `FIXED_UPDATE`,
104
108
  `PRE_UPDATE` → `UPDATE` → `POST_UPDATE`); per-phase Kahn sort by `before` / `after`, with insertion
@@ -109,17 +113,19 @@ world.getField(e, Pos, "x"); // ≈ 1.667
109
113
 
110
114
  **Structural changes**
111
115
 
112
- - **Deferred by default** — `ctx.commands` (a Bevy-`Commands`-style facade) buffers
113
- spawn / add / remove / despawn / enable / disable until the phase flush, so iterators stay valid.
114
- `world.addComponent` etc. are the immediate counterparts.
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.
115
120
  - **Entity enable/disable** — `disable` / `enable` / `isDisabled`; disabled rows sit in a partitioned
116
121
  tail and are skipped by default queries.
117
- - **Templates & bundles** — `world.template([...])` blueprints consumed by `createEntity` /
118
- `createEntities` for zero-transition spawns; `bundle(...)` + `spawnBundle(...)`.
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(...)`.
119
125
 
120
126
  **Reactivity & relationships**
121
127
 
122
- - **Observers** — `world.observe(...)` for `onAdd` / `onRemove` / `onSet` / `onEnable` / `onDisable`,
128
+ - **Observers** — `ecs.observe(...)` for `onAdd` / `onRemove` / `onSet` / `onEnable` / `onDisable`,
123
129
  structural or per-entity.
124
130
  - **Relations** — `(relation, target)` pairs with `ChildOf` / `IsA` presets, exclusive / multi arities,
125
131
  bidirectional queries (`targetOf` / `sourcesOf` / `ancestorsOf` / `rootOf` / `cascadeOf`), and
@@ -134,19 +140,20 @@ world.getField(e, Pos, "x"); // ≈ 1.667
134
140
 
135
141
  **Determinism, persistence & integration**
136
142
 
137
- - **Determinism** (opt-in) — `new ECS({ deterministic: true })`, then `world.stateHash()` (FNV-1a over
138
- live column bytes), `snapshot()` / `restoreInto(...)`, plus sparse variants. Backing-agnostic: a heap
139
- world and a shared world with identical history produce identical hashes.
140
- - **Host → ECS write seam** — `installHostCommandSeam(world)` applies typed `HostCommand`s off-schedule
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
141
148
  via a blessed `exclusive` system, with record/replay (`HostCommandRecorder`, `replayCommandLog`) and a
142
149
  cross-thread ring transport.
143
150
  - **Reactive UI seam** (optional) — a zero-dep signals kernel (`@oasys/oecs/reactive`), an ECS→reactive
144
151
  bridge that publishes only dirty entities/columns (`@oasys/oecs/reactive-sync`), and a SolidJS adapter
145
152
  (`@oasys/oecs/solid`).
146
153
  - **Editor layer** — undo/redo + field handles over the write seam (`@oasys/oecs/editor`).
147
- - **Frame tracing** — `world.setTrace(sink)` + `FrameTraceRecorder` for a structured per-frame event
154
+ - **Frame tracing** — `ecs.setTrace(sink)` + `FrameTraceRecorder` for a structured per-frame event
148
155
  stream (dev-gated).
149
- - **Compute backend seam** — `world.attachBackend(...)` to run a system body on a compiled backend (WASM,
156
+ - **Compute backend seam** — `ecs.attachBackend(...)` to run a system body on a compiled backend (WASM,
150
157
  …) instead of its TS closure.
151
158
 
152
159
  **Reference**
@@ -168,20 +175,26 @@ The core is `@oasys/oecs`; everything else is opt-in and costs nothing until imp
168
175
  | `@oasys/oecs/editor` | undo/redo + field-handle layer over the host-write seam |
169
176
  | `@oasys/oecs/solid` | SolidJS adapter (`solid-js` is an **optional** peer dependency) |
170
177
  | `@oasys/oecs/primitives` | the standalone data structures oecs is built on |
178
+ | `@oasys/oecs/internal` | unstable internals (codecs, ABI constants, access checker) — **no semver guarantees** |
171
179
 
172
180
  ## Dev vs prod
173
181
 
174
182
  A compile-time `__DEV__` flag gates every runtime check — bounds and liveness checks, duplicate-system
175
183
  detection, registration validation, and the system access checker (`reads`/`writes`). These are
176
184
  **tree-shaken out of production builds**, so treat "throws in dev" as a development tripwire, not a
177
- production guarantee. The scheduler's cycle detection is the one check that is always active.
185
+ production guarantee. (Raw-source consumers JSR/Deno get `__DEV__ = true` by default; set
186
+ `globalThis.__DEV__ = false` to opt out.) The scheduler's cycle detection and constructor-option
187
+ validation (timestep, memory options, relation cardinality) are always active.
178
188
 
179
189
  ## Documentation
180
190
 
181
191
  - **New to oecs?** Start with the [Getting Started](docs/GETTING_STARTED.md) tutorial, then
182
192
  [Best Practices](docs/BEST_PRACTICES.md) and the [Architecture](docs/ARCHITECTURE.md) overview.
183
- - **Upgrading from 0.3?** See the [Migration guide (0.3 → 0.4)](docs/MIGRATION-0.3-to-0.4.md) and the
193
+ - **Using optional extensions?** See the [Extensions guide](docs/EXTENSIONS.md) for reactive UI,
194
+ editor, Solid, shared-memory, and primitives usage.
195
+ - **Upgrading from 0.4?** See the [Migration guide (0.4 → 0.5)](docs/MIGRATION-0.4-to-0.5.md) and the
184
196
  [CHANGELOG](CHANGELOG.md).
197
+ - **Upgrading from 0.3?** See the [Migration guide (0.3 → 0.4)](docs/MIGRATION-0.3-to-0.4.md).
185
198
  - **Full API reference** — start at the [reference index](docs/api/index.md):
186
199
  [components](docs/api/components.md) ·
187
200
  [entities](docs/api/entities.md) ·
@@ -197,6 +210,8 @@ production guarantee. The scheduler's cycle detection is the one check that is a
197
210
  [sparse storage](docs/api/sparse-storage.md) ·
198
211
  [determinism](docs/api/determinism.md) ·
199
212
  [memory](docs/api/memory.md) ·
213
+ [WASM backends](docs/api/wasm.md) ·
214
+ [parallelism](docs/api/parallel.md) ·
200
215
  [host-write seam](docs/api/host-write-seam.md) ·
201
216
  [reactive](docs/api/reactive.md) ·
202
217
  [editor](docs/api/editor.md) ·
@@ -0,0 +1,77 @@
1
+ import { ComponentDef, ComponentHandle } from './component.cjs';
2
+ import { SparseComponentDef } from './sparse_store.cjs';
3
+ import { RelationDef } from './relation.cjs';
4
+ import { ResourceKey } from './resource.cjs';
5
+ import { SystemDescriptor } from './system.cjs';
6
+ interface AccessSets {
7
+ reads: Set<number>;
8
+ writes: Set<number>;
9
+ addAllowed: Set<number>;
10
+ removeAllowed: Set<number>;
11
+ hasDespawns: boolean;
12
+ resourceReads: Set<symbol>;
13
+ resourceWrites: Set<symbol>;
14
+ sparseReads: Set<number>;
15
+ sparseWrites: Set<number>;
16
+ relationReads: Set<number>;
17
+ relationWrites: Set<number>;
18
+ }
19
+ declare function setsFor(desc: SystemDescriptor): AccessSets;
20
+ /** The reads-only access surface a run condition declares (#576). A condition
21
+ * can only `reads` components (via a captured query) and `resourceReads`; every
22
+ * mutation set is empty by construction, so the same `check_*` machinery rejects
23
+ * any write/structural/resource-write a misbehaving predicate attempts. */
24
+ interface ConditionAccess {
25
+ readonly name: string;
26
+ readonly reads?: readonly ComponentDef[];
27
+ readonly resourceReads?: readonly ResourceKey<any>[];
28
+ }
29
+ declare class AccessCheck {
30
+ private active;
31
+ private sets;
32
+ private activeName;
33
+ private exclusive;
34
+ enter(desc: SystemDescriptor): void;
35
+ /** Open a reads-only span for a run condition (#576). No descriptor — a
36
+ * condition can gate a whole SystemSet, so it isn't attributable to one
37
+ * system — just its declared reads/resource_reads and a name for diagnostics.
38
+ * Paired with `leave()`. */
39
+ enterCondition(cond: ConditionAccess): void;
40
+ leave(): void;
41
+ isActive(): boolean;
42
+ /** Current system descriptor, if any. Null during a run-condition span. */
43
+ current(): SystemDescriptor | null;
44
+ checkRead(def: ComponentHandle): void;
45
+ checkWrite(def: ComponentHandle): void;
46
+ checkAdd(def: ComponentHandle): void;
47
+ checkRemove(def: ComponentHandle): void;
48
+ checkDestroy(): void;
49
+ checkResourceRead(key: ResourceKey<any>): void;
50
+ checkResourceWrite(key: ResourceKey<any>): void;
51
+ checkSparseRead(def: SparseComponentDef): void;
52
+ checkSparseWrite(def: SparseComponentDef): void;
53
+ checkRelationRead(def: RelationDef): void;
54
+ checkRelationWrite(def: RelationDef): void;
55
+ /** A `(*, T)` wildcard (`Query.forEachRelatedTo`, #579) reads every
56
+ * relation's reverse index, so it can't name a specific relation — it is
57
+ * authorised by the `ANY_RELATION` sentinel in `relationReads`. Honoured here
58
+ * exactly like a per-relation read, just keyed on the reserved sentinel id
59
+ * (which computeSets folds into `relationReads` like any other entry). */
60
+ checkRelationReadAny(): void;
61
+ private optionalScopes;
62
+ enterOptionalScope(optional: readonly number[]): void;
63
+ leaveOptionalScope(): void;
64
+ checkOptionalFetch(def: ComponentHandle): void;
65
+ private failComponent;
66
+ private failSparse;
67
+ private failRelation;
68
+ private failResource;
69
+ }
70
+ export declare const accessCheck: AccessCheck;
71
+ /** @internal — test seam for unit tests that need a fresh tracker. */
72
+ export declare const _accessCheckInternals: {
73
+ create: () => AccessCheck;
74
+ setsFor: typeof setsFor;
75
+ };
76
+ export {};
77
+ //# sourceMappingURL=access_check.d.ts.map
@@ -1,8 +1,8 @@
1
- import { ComponentDef, ComponentHandle } from './component';
2
- import { SparseComponentDef } from './sparse_store';
3
- import { RelationDef } from './relation';
4
- import { ResourceKey } from './resource';
5
- import { SystemDescriptor } from './system';
1
+ import { ComponentDef, ComponentHandle } from './component.js';
2
+ import { SparseComponentDef } from './sparse_store.js';
3
+ import { RelationDef } from './relation.js';
4
+ import { ResourceKey } from './resource.js';
5
+ import { SystemDescriptor } from './system.js';
6
6
  interface AccessSets {
7
7
  reads: Set<number>;
8
8
  writes: Set<number>;
@@ -24,7 +24,7 @@ declare function setsFor(desc: SystemDescriptor): AccessSets;
24
24
  interface ConditionAccess {
25
25
  readonly name: string;
26
26
  readonly reads?: readonly ComponentDef[];
27
- readonly resourceReads?: readonly ResourceKey<unknown>[];
27
+ readonly resourceReads?: readonly ResourceKey<any>[];
28
28
  }
29
29
  declare class AccessCheck {
30
30
  private active;
@@ -46,8 +46,8 @@ declare class AccessCheck {
46
46
  checkAdd(def: ComponentHandle): void;
47
47
  checkRemove(def: ComponentHandle): void;
48
48
  checkDestroy(): void;
49
- checkResourceRead(key: ResourceKey<unknown>): void;
50
- checkResourceWrite(key: ResourceKey<unknown>): void;
49
+ checkResourceRead(key: ResourceKey<any>): void;
50
+ checkResourceWrite(key: ResourceKey<any>): void;
51
51
  checkSparseRead(def: SparseComponentDef): void;
52
52
  checkSparseWrite(def: SparseComponentDef): void;
53
53
  checkRelationRead(def: RelationDef): void;
@@ -1 +1 @@
1
- {"version":3,"file":"access_check.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/access_check.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"access_check.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/access_check.ts"],"names":[],"mappings":"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"}