@forgeax/engine-ecs 0.1.2

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 (374) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +272 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/__fixtures__/field-shape-fixture.d.ts +16 -0
  5. package/dist/__fixtures__/field-shape-fixture.d.ts.map +1 -0
  6. package/dist/__tests__/__fixtures__/inspect-scripts.snapshot.d.ts +3 -0
  7. package/dist/__tests__/__fixtures__/inspect-scripts.snapshot.d.ts.map +1 -0
  8. package/dist/__tests__/archetype.unit.test.d.ts +2 -0
  9. package/dist/__tests__/archetype.unit.test.d.ts.map +1 -0
  10. package/dist/__tests__/array-handle-element.test-d.d.ts +2 -0
  11. package/dist/__tests__/array-handle-element.test-d.d.ts.map +1 -0
  12. package/dist/__tests__/buffer-array-vocab.test-d.d.ts +2 -0
  13. package/dist/__tests__/buffer-array-vocab.test-d.d.ts.map +1 -0
  14. package/dist/__tests__/buffer-field-input-widen.unit.test.d.ts +2 -0
  15. package/dist/__tests__/buffer-field-input-widen.unit.test.d.ts.map +1 -0
  16. package/dist/__tests__/buffer-pool.test-d.d.ts +2 -0
  17. package/dist/__tests__/buffer-pool.test-d.d.ts.map +1 -0
  18. package/dist/__tests__/change-detection.unit.test.d.ts +2 -0
  19. package/dist/__tests__/change-detection.unit.test.d.ts.map +1 -0
  20. package/dist/__tests__/command-buffer.test.d.ts +2 -0
  21. package/dist/__tests__/command-buffer.test.d.ts.map +1 -0
  22. package/dist/__tests__/commands-deferred.unit.test.d.ts +2 -0
  23. package/dist/__tests__/commands-deferred.unit.test.d.ts.map +1 -0
  24. package/dist/__tests__/component-catalog.test.d.ts +2 -0
  25. package/dist/__tests__/component-catalog.test.d.ts.map +1 -0
  26. package/dist/__tests__/component-definition-identity.unit.test.d.ts +2 -0
  27. package/dist/__tests__/component-definition-identity.unit.test.d.ts.map +1 -0
  28. package/dist/__tests__/component-schema.test-d.d.ts +2 -0
  29. package/dist/__tests__/component-schema.test-d.d.ts.map +1 -0
  30. package/dist/__tests__/component-schema.test.d.ts +2 -0
  31. package/dist/__tests__/component-schema.test.d.ts.map +1 -0
  32. package/dist/__tests__/define-component-options.test-d.d.ts +2 -0
  33. package/dist/__tests__/define-component-options.test-d.d.ts.map +1 -0
  34. package/dist/__tests__/deprecated-vocab-rejection.unit.test.d.ts +2 -0
  35. package/dist/__tests__/deprecated-vocab-rejection.unit.test.d.ts.map +1 -0
  36. package/dist/__tests__/despawn-all.unit.test.d.ts +2 -0
  37. package/dist/__tests__/despawn-all.unit.test.d.ts.map +1 -0
  38. package/dist/__tests__/ecs-core-reduction.characterization.test.d.ts +2 -0
  39. package/dist/__tests__/ecs-core-reduction.characterization.test.d.ts.map +1 -0
  40. package/dist/__tests__/ecs-core-reduction.perf.test.d.ts +2 -0
  41. package/dist/__tests__/ecs-core-reduction.perf.test.d.ts.map +1 -0
  42. package/dist/__tests__/ecs-error-code-31.test-d.d.ts +2 -0
  43. package/dist/__tests__/ecs-error-code-31.test-d.d.ts.map +1 -0
  44. package/dist/__tests__/entity-disabling.unit.test.d.ts +2 -0
  45. package/dist/__tests__/entity-disabling.unit.test.d.ts.map +1 -0
  46. package/dist/__tests__/entity-handle-codec-parity.unit.test.d.ts +2 -0
  47. package/dist/__tests__/entity-handle-codec-parity.unit.test.d.ts.map +1 -0
  48. package/dist/__tests__/errors.unit.test.d.ts +2 -0
  49. package/dist/__tests__/errors.unit.test.d.ts.map +1 -0
  50. package/dist/__tests__/execution-conflict-boundary.unit.test.d.ts +2 -0
  51. package/dist/__tests__/execution-conflict-boundary.unit.test.d.ts.map +1 -0
  52. package/dist/__tests__/execution-shared-storage.unit.test.d.ts +2 -0
  53. package/dist/__tests__/execution-shared-storage.unit.test.d.ts.map +1 -0
  54. package/dist/__tests__/externalization-portable-value.unit.test.d.ts +2 -0
  55. package/dist/__tests__/externalization-portable-value.unit.test.d.ts.map +1 -0
  56. package/dist/__tests__/externalization-projection.unit.test.d.ts +2 -0
  57. package/dist/__tests__/externalization-projection.unit.test.d.ts.map +1 -0
  58. package/dist/__tests__/externalization-root-surface.unit.test.d.ts +2 -0
  59. package/dist/__tests__/externalization-root-surface.unit.test.d.ts.map +1 -0
  60. package/dist/__tests__/field-enum-labels-reflection.test.d.ts +2 -0
  61. package/dist/__tests__/field-enum-labels-reflection.test.d.ts.map +1 -0
  62. package/dist/__tests__/field-shape-fixture.test.d.ts +2 -0
  63. package/dist/__tests__/field-shape-fixture.test.d.ts.map +1 -0
  64. package/dist/__tests__/field-transient-reflection.test.d.ts +2 -0
  65. package/dist/__tests__/field-transient-reflection.test.d.ts.map +1 -0
  66. package/dist/__tests__/field-value-type.test-d.d.ts +2 -0
  67. package/dist/__tests__/field-value-type.test-d.d.ts.map +1 -0
  68. package/dist/__tests__/fixed-update.unit.test.d.ts +2 -0
  69. package/dist/__tests__/fixed-update.unit.test.d.ts.map +1 -0
  70. package/dist/__tests__/handle.test-d.d.ts +2 -0
  71. package/dist/__tests__/handle.test-d.d.ts.map +1 -0
  72. package/dist/__tests__/hierarchy.unit.test.d.ts +2 -0
  73. package/dist/__tests__/hierarchy.unit.test.d.ts.map +1 -0
  74. package/dist/__tests__/managed-array-vocab.test-d.d.ts +2 -0
  75. package/dist/__tests__/managed-array-vocab.test-d.d.ts.map +1 -0
  76. package/dist/__tests__/minimal-example.test-d.d.ts +2 -0
  77. package/dist/__tests__/minimal-example.test-d.d.ts.map +1 -0
  78. package/dist/__tests__/name-read-types.test-d.d.ts +2 -0
  79. package/dist/__tests__/name-read-types.test-d.d.ts.map +1 -0
  80. package/dist/__tests__/plugin-service.test.d.ts +2 -0
  81. package/dist/__tests__/plugin-service.test.d.ts.map +1 -0
  82. package/dist/__tests__/query-combinations.unit.test.d.ts +2 -0
  83. package/dist/__tests__/query-combinations.unit.test.d.ts.map +1 -0
  84. package/dist/__tests__/query-light-extract-flat-column-ratio.perf.test.d.ts +2 -0
  85. package/dist/__tests__/query-light-extract-flat-column-ratio.perf.test.d.ts.map +1 -0
  86. package/dist/__tests__/query-storage-trends.perf.test.d.ts +2 -0
  87. package/dist/__tests__/query-storage-trends.perf.test.d.ts.map +1 -0
  88. package/dist/__tests__/query-trs-flat-column-ratio.perf.test.d.ts +2 -0
  89. package/dist/__tests__/query-trs-flat-column-ratio.perf.test.d.ts.map +1 -0
  90. package/dist/__tests__/query.unit.test.d.ts +2 -0
  91. package/dist/__tests__/query.unit.test.d.ts.map +1 -0
  92. package/dist/__tests__/relationship-index.perf.test.d.ts +2 -0
  93. package/dist/__tests__/relationship-index.perf.test.d.ts.map +1 -0
  94. package/dist/__tests__/relationship-index.test.d.ts +2 -0
  95. package/dist/__tests__/relationship-index.test.d.ts.map +1 -0
  96. package/dist/__tests__/scalar-field-type-owner.test-d.d.ts +2 -0
  97. package/dist/__tests__/scalar-field-type-owner.test-d.d.ts.map +1 -0
  98. package/dist/__tests__/schedule-determinism.unit.test.d.ts +2 -0
  99. package/dist/__tests__/schedule-determinism.unit.test.d.ts.map +1 -0
  100. package/dist/__tests__/schedule-inspection.unit.test.d.ts +2 -0
  101. package/dist/__tests__/schedule-inspection.unit.test.d.ts.map +1 -0
  102. package/dist/__tests__/schedule-scope-error.unit.test.d.ts +2 -0
  103. package/dist/__tests__/schedule-scope-error.unit.test.d.ts.map +1 -0
  104. package/dist/__tests__/schedule-token.unit.test.d.ts +2 -0
  105. package/dist/__tests__/schedule-token.unit.test.d.ts.map +1 -0
  106. package/dist/__tests__/schema-vocab.test-d.d.ts +2 -0
  107. package/dist/__tests__/schema-vocab.test-d.d.ts.map +1 -0
  108. package/dist/__tests__/serialization.unit.test.d.ts +2 -0
  109. package/dist/__tests__/serialization.unit.test.d.ts.map +1 -0
  110. package/dist/__tests__/shared-kernel-eligibility.test-d.d.ts +2 -0
  111. package/dist/__tests__/shared-kernel-eligibility.test-d.d.ts.map +1 -0
  112. package/dist/__tests__/shared-kernel-eligibility.unit.test.d.ts +2 -0
  113. package/dist/__tests__/shared-kernel-eligibility.unit.test.d.ts.map +1 -0
  114. package/dist/__tests__/shared-ref-store.unit.test.d.ts +2 -0
  115. package/dist/__tests__/shared-ref-store.unit.test.d.ts.map +1 -0
  116. package/dist/__tests__/sparse-tag.unit.test.d.ts +2 -0
  117. package/dist/__tests__/sparse-tag.unit.test.d.ts.map +1 -0
  118. package/dist/__tests__/spawn-field-error.test-d.d.ts +2 -0
  119. package/dist/__tests__/spawn-field-error.test-d.d.ts.map +1 -0
  120. package/dist/__tests__/stale-error.test-d.d.ts +2 -0
  121. package/dist/__tests__/stale-error.test-d.d.ts.map +1 -0
  122. package/dist/__tests__/string-view-symmetry.test-d.d.ts +2 -0
  123. package/dist/__tests__/string-view-symmetry.test-d.d.ts.map +1 -0
  124. package/dist/__tests__/string-vocab.test-d.d.ts +2 -0
  125. package/dist/__tests__/string-vocab.test-d.d.ts.map +1 -0
  126. package/dist/__tests__/structure-epoch-boundaries.unit.test.d.ts +2 -0
  127. package/dist/__tests__/structure-epoch-boundaries.unit.test.d.ts.map +1 -0
  128. package/dist/__tests__/structure-epoch.unit.test.d.ts +2 -0
  129. package/dist/__tests__/structure-epoch.unit.test.d.ts.map +1 -0
  130. package/dist/__tests__/table-archetype-mapping.unit.test.d.ts +2 -0
  131. package/dist/__tests__/table-archetype-mapping.unit.test.d.ts.map +1 -0
  132. package/dist/__tests__/time.unit.test.d.ts +2 -0
  133. package/dist/__tests__/time.unit.test.d.ts.map +1 -0
  134. package/dist/__tests__/types.test-d.d.ts +2 -0
  135. package/dist/__tests__/types.test-d.d.ts.map +1 -0
  136. package/dist/__tests__/unique-ref-store.unit.test.d.ts +2 -0
  137. package/dist/__tests__/unique-ref-store.unit.test.d.ts.map +1 -0
  138. package/dist/__tests__/utils/handle-numeric.d.ts +14 -0
  139. package/dist/__tests__/utils/handle-numeric.d.ts.map +1 -0
  140. package/dist/__tests__/validation-root-surface.unit.test.d.ts +2 -0
  141. package/dist/__tests__/validation-root-surface.unit.test.d.ts.map +1 -0
  142. package/dist/__tests__/visibility-atomic-write.unit.test.d.ts +2 -0
  143. package/dist/__tests__/visibility-atomic-write.unit.test.d.ts.map +1 -0
  144. package/dist/__tests__/world-change-journal.unit.test.d.ts +2 -0
  145. package/dist/__tests__/world-change-journal.unit.test.d.ts.map +1 -0
  146. package/dist/__tests__/world-characterization.unit.test.d.ts +2 -0
  147. package/dist/__tests__/world-characterization.unit.test.d.ts.map +1 -0
  148. package/dist/__tests__/world-consumer-inference.test-d.d.ts +2 -0
  149. package/dist/__tests__/world-consumer-inference.test-d.d.ts.map +1 -0
  150. package/dist/__tests__/world-health.contract.test.d.ts +2 -0
  151. package/dist/__tests__/world-health.contract.test.d.ts.map +1 -0
  152. package/dist/__tests__/world-inspection.test.d.ts +2 -0
  153. package/dist/__tests__/world-inspection.test.d.ts.map +1 -0
  154. package/dist/__tests__/world-internal-identity.unit.test.d.ts +2 -0
  155. package/dist/__tests__/world-internal-identity.unit.test.d.ts.map +1 -0
  156. package/dist/__tests__/world-managed-roundtrip.unit.test.d.ts +2 -0
  157. package/dist/__tests__/world-managed-roundtrip.unit.test.d.ts.map +1 -0
  158. package/dist/__tests__/world-scheduling.m4.test.d.ts +2 -0
  159. package/dist/__tests__/world-scheduling.m4.test.d.ts.map +1 -0
  160. package/dist/__tests__/world-unique-roundtrip.unit.test.d.ts +2 -0
  161. package/dist/__tests__/world-unique-roundtrip.unit.test.d.ts.map +1 -0
  162. package/dist/__tests__/world.test-d.d.ts +2 -0
  163. package/dist/__tests__/world.test-d.d.ts.map +1 -0
  164. package/dist/buffer-pool.d.ts +109 -0
  165. package/dist/buffer-pool.d.ts.map +1 -0
  166. package/dist/commands.d.ts +93 -0
  167. package/dist/commands.d.ts.map +1 -0
  168. package/dist/component-default-fallback.d.ts +88 -0
  169. package/dist/component-default-fallback.d.ts.map +1 -0
  170. package/dist/component-schema.d.ts +34 -0
  171. package/dist/component-schema.d.ts.map +1 -0
  172. package/dist/component-value-validate.d.ts +29 -0
  173. package/dist/component-value-validate.d.ts.map +1 -0
  174. package/dist/component.d.ts +581 -0
  175. package/dist/component.d.ts.map +1 -0
  176. package/dist/entity-handle.d.ts +68 -0
  177. package/dist/entity-handle.d.ts.map +1 -0
  178. package/dist/entity.d.ts +86 -0
  179. package/dist/entity.d.ts.map +1 -0
  180. package/dist/errors/query-and-component-errors.d.ts +132 -0
  181. package/dist/errors/query-and-component-errors.d.ts.map +1 -0
  182. package/dist/errors/relationship-errors.d.ts +112 -0
  183. package/dist/errors/relationship-errors.d.ts.map +1 -0
  184. package/dist/errors/sprite-and-shared-errors.d.ts +107 -0
  185. package/dist/errors/sprite-and-shared-errors.d.ts.map +1 -0
  186. package/dist/errors/validation-errors.d.ts +214 -0
  187. package/dist/errors/validation-errors.d.ts.map +1 -0
  188. package/dist/errors.d.ts +756 -0
  189. package/dist/errors.d.ts.map +1 -0
  190. package/dist/execution/shared-kernel.d.ts +106 -0
  191. package/dist/execution/shared-kernel.d.ts.map +1 -0
  192. package/dist/externalization/index.d.ts +31 -0
  193. package/dist/externalization/index.d.ts.map +1 -0
  194. package/dist/externalization/index.mjs +298 -0
  195. package/dist/externalization/index.mjs.map +1 -0
  196. package/dist/index.d.ts +261 -0
  197. package/dist/index.d.ts.map +1 -0
  198. package/dist/index.mjs +7354 -0
  199. package/dist/index.mjs.map +1 -0
  200. package/dist/internal.mjs +479 -0
  201. package/dist/internal.mjs.map +1 -0
  202. package/dist/plugin-service.d.ts +11 -0
  203. package/dist/plugin-service.d.ts.map +1 -0
  204. package/dist/projection/index.d.ts +50 -0
  205. package/dist/projection/index.d.ts.map +1 -0
  206. package/dist/projection/index.mjs +517 -0
  207. package/dist/projection/index.mjs.map +1 -0
  208. package/dist/query/query.d.ts +58 -0
  209. package/dist/query/query.d.ts.map +1 -0
  210. package/dist/relationship-index.d.ts +81 -0
  211. package/dist/relationship-index.d.ts.map +1 -0
  212. package/dist/resource.d.ts +70 -0
  213. package/dist/resource.d.ts.map +1 -0
  214. package/dist/schedule-token.d.ts +16 -0
  215. package/dist/schedule-token.d.ts.map +1 -0
  216. package/dist/schedule.d.ts +271 -0
  217. package/dist/schedule.d.ts.map +1 -0
  218. package/dist/shared-ref-store.d.ts +144 -0
  219. package/dist/shared-ref-store.d.ts.map +1 -0
  220. package/dist/shared.d.ts +3 -0
  221. package/dist/shared.d.ts.map +1 -0
  222. package/dist/shared.mjs +364 -0
  223. package/dist/shared.mjs.map +1 -0
  224. package/dist/storage/archetype-graph.d.ts +54 -0
  225. package/dist/storage/archetype-graph.d.ts.map +1 -0
  226. package/dist/storage/archetype.d.ts +23 -0
  227. package/dist/storage/archetype.d.ts.map +1 -0
  228. package/dist/storage/change-detection.d.ts +40 -0
  229. package/dist/storage/change-detection.d.ts.map +1 -0
  230. package/dist/storage/column.d.ts +111 -0
  231. package/dist/storage/column.d.ts.map +1 -0
  232. package/dist/storage/table.d.ts +29 -0
  233. package/dist/storage/table.d.ts.map +1 -0
  234. package/dist/time.d.ts +57 -0
  235. package/dist/time.d.ts.map +1 -0
  236. package/dist/unique-ref-store.d.ts +105 -0
  237. package/dist/unique-ref-store.d.ts.map +1 -0
  238. package/dist/world-change-journal.d.ts +34 -0
  239. package/dist/world-change-journal.d.ts.map +1 -0
  240. package/dist/world-component-access.d.ts +264 -0
  241. package/dist/world-component-access.d.ts.map +1 -0
  242. package/dist/world-component-storage.d.ts +282 -0
  243. package/dist/world-component-storage.d.ts.map +1 -0
  244. package/dist/world-core.d.ts +39 -0
  245. package/dist/world-core.d.ts.map +1 -0
  246. package/dist/world-entity-lifecycle.d.ts +30 -0
  247. package/dist/world-entity-lifecycle.d.ts.map +1 -0
  248. package/dist/world-internal.d.ts +14 -0
  249. package/dist/world-internal.d.ts.map +1 -0
  250. package/dist/world-scheduling.d.ts +30 -0
  251. package/dist/world-scheduling.d.ts.map +1 -0
  252. package/dist/world.d.ts +620 -0
  253. package/dist/world.d.ts.map +1 -0
  254. package/package.json +77 -0
  255. package/src/__fixtures__/field-shape-fixture.ts +30 -0
  256. package/src/__tests__/__fixtures__/inspect-scripts.snapshot.ts +2 -0
  257. package/src/__tests__/archetype.unit.test.ts +1837 -0
  258. package/src/__tests__/array-handle-element.test-d.ts +34 -0
  259. package/src/__tests__/buffer-array-vocab.test-d.ts +53 -0
  260. package/src/__tests__/buffer-field-input-widen.unit.test.ts +99 -0
  261. package/src/__tests__/buffer-pool.test-d.ts +32 -0
  262. package/src/__tests__/change-detection.unit.test.ts +86 -0
  263. package/src/__tests__/command-buffer.test.ts +179 -0
  264. package/src/__tests__/commands-deferred.unit.test.ts +68 -0
  265. package/src/__tests__/component-catalog.test.ts +59 -0
  266. package/src/__tests__/component-definition-identity.unit.test.ts +24 -0
  267. package/src/__tests__/component-schema.test-d.ts +119 -0
  268. package/src/__tests__/component-schema.test.ts +55 -0
  269. package/src/__tests__/define-component-options.test-d.ts +35 -0
  270. package/src/__tests__/deprecated-vocab-rejection.unit.test.ts +59 -0
  271. package/src/__tests__/despawn-all.unit.test.ts +17 -0
  272. package/src/__tests__/ecs-core-reduction.characterization.test.ts +130 -0
  273. package/src/__tests__/ecs-core-reduction.perf.test.ts +260 -0
  274. package/src/__tests__/ecs-error-code-31.test-d.ts +42 -0
  275. package/src/__tests__/entity-disabling.unit.test.ts +37 -0
  276. package/src/__tests__/entity-handle-codec-parity.unit.test.ts +126 -0
  277. package/src/__tests__/errors.unit.test.ts +1452 -0
  278. package/src/__tests__/execution-conflict-boundary.unit.test.ts +123 -0
  279. package/src/__tests__/execution-shared-storage.unit.test.ts +40 -0
  280. package/src/__tests__/externalization-portable-value.unit.test.ts +275 -0
  281. package/src/__tests__/externalization-projection.unit.test.ts +325 -0
  282. package/src/__tests__/externalization-root-surface.unit.test.ts +33 -0
  283. package/src/__tests__/field-enum-labels-reflection.test.ts +66 -0
  284. package/src/__tests__/field-shape-fixture.test.ts +61 -0
  285. package/src/__tests__/field-transient-reflection.test.ts +59 -0
  286. package/src/__tests__/field-value-type.test-d.ts +57 -0
  287. package/src/__tests__/fixed-update.unit.test.ts +78 -0
  288. package/src/__tests__/handle.test-d.ts +86 -0
  289. package/src/__tests__/hierarchy.unit.test.ts +2534 -0
  290. package/src/__tests__/managed-array-vocab.test-d.ts +137 -0
  291. package/src/__tests__/minimal-example.test-d.ts +42 -0
  292. package/src/__tests__/name-read-types.test-d.ts +72 -0
  293. package/src/__tests__/plugin-service.test.ts +13 -0
  294. package/src/__tests__/query-combinations.unit.test.ts +42 -0
  295. package/src/__tests__/query-light-extract-flat-column-ratio.perf.test.ts +252 -0
  296. package/src/__tests__/query-storage-trends.perf.test.ts +104 -0
  297. package/src/__tests__/query-trs-flat-column-ratio.perf.test.ts +194 -0
  298. package/src/__tests__/query.unit.test.ts +196 -0
  299. package/src/__tests__/relationship-index.perf.test.ts +126 -0
  300. package/src/__tests__/relationship-index.test.ts +70 -0
  301. package/src/__tests__/scalar-field-type-owner.test-d.ts +71 -0
  302. package/src/__tests__/schedule-determinism.unit.test.ts +36 -0
  303. package/src/__tests__/schedule-inspection.unit.test.ts +81 -0
  304. package/src/__tests__/schedule-scope-error.unit.test.ts +63 -0
  305. package/src/__tests__/schedule-token.unit.test.ts +54 -0
  306. package/src/__tests__/schema-vocab.test-d.ts +103 -0
  307. package/src/__tests__/serialization.unit.test.ts +2740 -0
  308. package/src/__tests__/shared-kernel-eligibility.test-d.ts +18 -0
  309. package/src/__tests__/shared-kernel-eligibility.unit.test.ts +78 -0
  310. package/src/__tests__/shared-ref-store.unit.test.ts +646 -0
  311. package/src/__tests__/sparse-tag.unit.test.ts +201 -0
  312. package/src/__tests__/spawn-field-error.test-d.ts +41 -0
  313. package/src/__tests__/stale-error.test-d.ts +207 -0
  314. package/src/__tests__/string-view-symmetry.test-d.ts +26 -0
  315. package/src/__tests__/string-vocab.test-d.ts +49 -0
  316. package/src/__tests__/structure-epoch-boundaries.unit.test.ts +39 -0
  317. package/src/__tests__/structure-epoch.unit.test.ts +48 -0
  318. package/src/__tests__/table-archetype-mapping.unit.test.ts +78 -0
  319. package/src/__tests__/time.unit.test.ts +79 -0
  320. package/src/__tests__/types.test-d.ts +38 -0
  321. package/src/__tests__/unique-ref-store.unit.test.ts +348 -0
  322. package/src/__tests__/utils/handle-numeric.ts +30 -0
  323. package/src/__tests__/validation-root-surface.unit.test.ts +15 -0
  324. package/src/__tests__/visibility-atomic-write.unit.test.ts +82 -0
  325. package/src/__tests__/world-change-journal.unit.test.ts +97 -0
  326. package/src/__tests__/world-characterization.unit.test.ts +408 -0
  327. package/src/__tests__/world-consumer-inference.test-d.ts +16 -0
  328. package/src/__tests__/world-health.contract.test.ts +87 -0
  329. package/src/__tests__/world-inspection.test.ts +37 -0
  330. package/src/__tests__/world-internal-identity.unit.test.ts +17 -0
  331. package/src/__tests__/world-managed-roundtrip.unit.test.ts +98 -0
  332. package/src/__tests__/world-scheduling.m4.test.ts +52 -0
  333. package/src/__tests__/world-unique-roundtrip.unit.test.ts +357 -0
  334. package/src/__tests__/world.test-d.ts +156 -0
  335. package/src/buffer-pool.ts +357 -0
  336. package/src/commands.ts +644 -0
  337. package/src/component-default-fallback.ts +236 -0
  338. package/src/component-schema.ts +92 -0
  339. package/src/component-value-validate.ts +135 -0
  340. package/src/component.ts +1268 -0
  341. package/src/entity-handle.ts +104 -0
  342. package/src/entity.ts +140 -0
  343. package/src/errors/query-and-component-errors.ts +200 -0
  344. package/src/errors/relationship-errors.ts +198 -0
  345. package/src/errors/sprite-and-shared-errors.ts +231 -0
  346. package/src/errors/validation-errors.ts +418 -0
  347. package/src/errors.ts +1453 -0
  348. package/src/execution/shared-kernel.ts +392 -0
  349. package/src/externalization/index.ts +170 -0
  350. package/src/index.ts +414 -0
  351. package/src/plugin-service.ts +35 -0
  352. package/src/projection/index.ts +142 -0
  353. package/src/query/query.ts +606 -0
  354. package/src/relationship-index.ts +175 -0
  355. package/src/resource.ts +106 -0
  356. package/src/schedule-token.ts +40 -0
  357. package/src/schedule.ts +846 -0
  358. package/src/shared-ref-store.ts +418 -0
  359. package/src/shared.ts +23 -0
  360. package/src/storage/archetype-graph.ts +166 -0
  361. package/src/storage/archetype.ts +78 -0
  362. package/src/storage/change-detection.ts +231 -0
  363. package/src/storage/column.ts +247 -0
  364. package/src/storage/table.ts +153 -0
  365. package/src/time.ts +122 -0
  366. package/src/unique-ref-store.ts +278 -0
  367. package/src/world-change-journal.ts +84 -0
  368. package/src/world-component-access.ts +1412 -0
  369. package/src/world-component-storage.ts +1178 -0
  370. package/src/world-core.ts +74 -0
  371. package/src/world-entity-lifecycle.ts +539 -0
  372. package/src/world-internal.ts +75 -0
  373. package/src/world-scheduling.ts +499 -0
  374. package/src/world.ts +1397 -0
@@ -0,0 +1,97 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { componentId, defineComponent } from '../component';
3
+ import { encodeEntity } from '../entity-handle';
4
+ import { createWorldProjection } from '../projection';
5
+ import { World } from '../world';
6
+ import { WorldChangeJournal, type WorldChangeRecord } from '../world-change-journal';
7
+ import { worldInternal } from '../world-internal';
8
+
9
+ describe('WorldChangeJournal', () => {
10
+ it('returns only records after the supplied cursor', () => {
11
+ const journal = new WorldChangeJournal(4);
12
+ const cursor = journal.cursor();
13
+ const first = encodeEntity(7, 0);
14
+ const second = encodeEntity(9, 0);
15
+
16
+ journal.append({ kind: 'component-changed', entity: first, componentId: 3 });
17
+ journal.append({ kind: 'entity-removed', entity: second });
18
+
19
+ expect(journal.readAfter(cursor)).toEqual({
20
+ status: 'ok',
21
+ cursor: 2,
22
+ records: [
23
+ { sequence: 1, kind: 'component-changed', entity: first, componentId: 3 },
24
+ { sequence: 2, kind: 'entity-removed', entity: second },
25
+ ],
26
+ });
27
+ expect(journal.readAfter(2)).toEqual({ status: 'ok', cursor: 2, records: [] });
28
+ });
29
+
30
+ it('reports overflow instead of returning an incomplete delta', () => {
31
+ const journal = new WorldChangeJournal(2);
32
+ const cursor = journal.cursor();
33
+ const first = encodeEntity(1, 0);
34
+ const second = encodeEntity(2, 0);
35
+ const third = encodeEntity(3, 0);
36
+
37
+ journal.append({ kind: 'component-changed', entity: first, componentId: 1 });
38
+ journal.append({ kind: 'component-changed', entity: second, componentId: 1 });
39
+ journal.append({ kind: 'component-changed', entity: third, componentId: 1 });
40
+
41
+ expect(journal.readAfter(cursor)).toEqual({
42
+ status: 'overflow',
43
+ cursor: 3,
44
+ oldestAvailable: 2,
45
+ });
46
+ });
47
+ });
48
+
49
+ describe('World mutation journal', () => {
50
+ it('projects narrow component evidence without exposing journal records', () => {
51
+ const Value = defineComponent('ProjectionValue', { value: 'u32' });
52
+ const world = new World();
53
+ const projection = createWorldProjection(world, { components: [Value] });
54
+ const entity = world.spawn({ component: Value, data: { value: 1 } }).unwrap();
55
+
56
+ const result = projection.poll();
57
+ expect(result.status).toBe('delta');
58
+ if (result.status !== 'delta') return;
59
+ expect(result.changes).toEqual([
60
+ { entity, kind: 'component-added', component: Value, componentId: componentId(Value) },
61
+ ]);
62
+ expect(result.changes[0]).not.toHaveProperty('sequence');
63
+ expect(result.changes[0]).not.toHaveProperty('table');
64
+ expect(result.changes[0]).not.toHaveProperty('column');
65
+ });
66
+
67
+ it('publishes component lifecycle and entity removal as ordered evidence', () => {
68
+ const Marker = defineComponent('WorldJournalMarker', { value: 'f32' });
69
+ const Extra = defineComponent('WorldJournalExtra', { value: 'u32' });
70
+ const world = new World();
71
+ const cursor = world[worldInternal].getChangeCursor();
72
+
73
+ const entity = world.spawn({ component: Marker, data: { value: 1 } }).unwrap();
74
+ world.set(entity, Marker, { value: 2 }).unwrap();
75
+ world.addComponent(entity, { component: Extra, data: { value: 3 } }).unwrap();
76
+ world.removeComponent(entity, Extra).unwrap();
77
+ world.despawn(entity).unwrap();
78
+
79
+ const result = world[worldInternal].readChangesSince(cursor);
80
+ expect(result.status).toBe('ok');
81
+ if (result.status !== 'ok') return;
82
+ expect(
83
+ result.records.map((record: WorldChangeRecord) => ({
84
+ kind: record.kind,
85
+ entity: record.entity,
86
+ componentId: record.componentId,
87
+ })),
88
+ ).toEqual([
89
+ { kind: 'component-added', entity, componentId: 0 },
90
+ { kind: 'component-added', entity, componentId: componentId(Marker) },
91
+ { kind: 'component-changed', entity, componentId: componentId(Marker) },
92
+ { kind: 'component-added', entity, componentId: componentId(Extra) },
93
+ { kind: 'component-removed', entity, componentId: componentId(Extra) },
94
+ { kind: 'entity-removed', entity, componentId: undefined },
95
+ ]);
96
+ });
97
+ });
@@ -0,0 +1,408 @@
1
+ import { Update } from '../schedule-token';
2
+ // M1 w1: World facade characterization tests.
3
+ //
4
+ // These tests lock all public World method behaviors so the M1 extraction
5
+ // (w2-w5) can proceed with a behavioral baseline. Every test must pass
6
+ // identically before and after the refactor.
7
+ //
8
+ // Coverage: spawn, despawn, get, set, addComponent, removeComponent, update,
9
+ // resources, inspection, addSystem, and addSystems.
10
+
11
+ import { describe, expect, it } from 'vitest';
12
+ import { defineComponent } from '../component';
13
+ import { Entity } from '../entity';
14
+ import type { EntityHandle } from '../entity-handle';
15
+ import { defineSystemSet } from '../schedule';
16
+ import { World } from '../world';
17
+
18
+ // ── shared test components ──
19
+
20
+ const Position = defineComponent('W1Position', { x: 'f32', y: 'f32' });
21
+ const Velocity = defineComponent('W1Velocity', { vx: 'f32', vy: 'f32' });
22
+
23
+ // ──────────────────────────────────────────────────────────────────────
24
+ // spawn
25
+ // ──────────────────────────────────────────────────────────────────────
26
+
27
+ describe('M1 w1: spawn characterization', () => {
28
+ it('spawns a single-component entity', () => {
29
+ const w = new World();
30
+ const r = w.spawn({ component: Position, data: { x: 1, y: 2 } });
31
+ expect(r.ok).toBe(true);
32
+ const e = r.unwrap();
33
+ const pos = w.get(e, Position).unwrap();
34
+ expect(pos.x).toBe(1);
35
+ expect(pos.y).toBe(2);
36
+ });
37
+
38
+ it('spawns a multi-component entity', () => {
39
+ const w = new World();
40
+ const r = w.spawn(
41
+ { component: Position, data: { x: 0, y: 0 } },
42
+ { component: Velocity, data: { vx: 1, vy: 2 } },
43
+ );
44
+ expect(r.ok).toBe(true);
45
+ const e = r.unwrap();
46
+ const pos = w.get(e, Position).unwrap();
47
+ const vel = w.get(e, Velocity).unwrap();
48
+ expect(pos.x).toBe(0);
49
+ expect(vel.vx).toBe(1);
50
+ });
51
+
52
+ it('spawn applies defaults for missing fields', () => {
53
+ const w = new World();
54
+ const r = w.spawn({ component: Position, data: {} });
55
+ expect(r.ok).toBe(true);
56
+ const e = r.unwrap();
57
+ const pos = w.get(e, Position).unwrap();
58
+ expect(pos.x).toBe(0);
59
+ expect(pos.y).toBe(0);
60
+ });
61
+
62
+ it('spawn returns unique entity handles', () => {
63
+ const w = new World();
64
+ const e1 = w.spawn({ component: Position, data: { x: 0, y: 0 } }).unwrap();
65
+ const e2 = w.spawn({ component: Position, data: { x: 0, y: 0 } }).unwrap();
66
+ expect(e1).not.toBe(e2);
67
+ });
68
+ });
69
+
70
+ // ──────────────────────────────────────────────────────────────────────
71
+ // despawn
72
+ // ──────────────────────────────────────────────────────────────────────
73
+
74
+ describe('M1 w1: despawn characterization', () => {
75
+ it('despawns an entity and makes get return stale-entity', () => {
76
+ const w = new World();
77
+ const e = w.spawn({ component: Position, data: { x: 0, y: 0 } }).unwrap();
78
+ const r = w.despawn(e);
79
+ expect(r.ok).toBe(true);
80
+ const gr = w.get(e, Position);
81
+ expect(gr.ok).toBe(false);
82
+ if (!gr.ok) expect(gr.error.code).toBe('stale-entity');
83
+ });
84
+
85
+ it('despawn is idempotent on stale handles', () => {
86
+ const w = new World();
87
+ const e = w.spawn({ component: Position, data: { x: 0, y: 0 } }).unwrap();
88
+ w.despawn(e).unwrap();
89
+ const r = w.despawn(e);
90
+ expect(r.ok).toBe(true);
91
+ });
92
+ });
93
+
94
+ // ──────────────────────────────────────────────────────────────────────
95
+ // get
96
+ // ──────────────────────────────────────────────────────────────────────
97
+
98
+ describe('M1 w1: get characterization', () => {
99
+ it('get returns component data for a live entity', () => {
100
+ const w = new World();
101
+ const e = w.spawn({ component: Position, data: { x: 3, y: 4 } }).unwrap();
102
+ const r = w.get(e, Position);
103
+ expect(r.ok).toBe(true);
104
+ expect(r.unwrap().x).toBe(3);
105
+ expect(r.unwrap().y).toBe(4);
106
+ });
107
+
108
+ it('get returns component-not-present for missing component', () => {
109
+ const w = new World();
110
+ const e = w.spawn({ component: Position, data: { x: 0, y: 0 } }).unwrap();
111
+ const r = w.get(e, Velocity);
112
+ expect(r.ok).toBe(false);
113
+ if (!r.ok) expect(r.error.code).toBe('component-not-present');
114
+ });
115
+
116
+ it('get returns stale-entity for dead entity', () => {
117
+ const w = new World();
118
+ const e = w.spawn({ component: Position, data: { x: 0, y: 0 } }).unwrap();
119
+ w.despawn(e).unwrap();
120
+ const r = w.get(e, Position);
121
+ expect(r.ok).toBe(false);
122
+ if (!r.ok) expect(r.error.code).toBe('stale-entity');
123
+ });
124
+
125
+ it('get returns the Entity self-handle', () => {
126
+ const w = new World();
127
+ const e = w.spawn({ component: Position, data: { x: 0, y: 0 } }).unwrap();
128
+ const ent = w.get(e, Entity).unwrap();
129
+ expect(ent.self).toBe(e);
130
+ });
131
+ });
132
+
133
+ // ──────────────────────────────────────────────────────────────────────
134
+ // set
135
+ // ──────────────────────────────────────────────────────────────────────
136
+
137
+ describe('M1 w1: set characterization', () => {
138
+ it('set updates component fields on a live entity', () => {
139
+ const w = new World();
140
+ const e = w.spawn({ component: Position, data: { x: 0, y: 0 } }).unwrap();
141
+ const r = w.set(e, Position, { x: 10 });
142
+ expect(r.ok).toBe(true);
143
+ const pos = w.get(e, Position).unwrap();
144
+ expect(pos.x).toBe(10);
145
+ expect(pos.y).toBe(0);
146
+ });
147
+
148
+ it('set returns component-not-present for missing component', () => {
149
+ const w = new World();
150
+ const e = w.spawn({ component: Position, data: { x: 0, y: 0 } }).unwrap();
151
+ const r = w.set(e, Velocity, { vx: 1 });
152
+ expect(r.ok).toBe(false);
153
+ if (!r.ok) expect(r.error.code).toBe('component-not-present');
154
+ });
155
+
156
+ it('set returns stale-entity for dead entity', () => {
157
+ const w = new World();
158
+ const e = w.spawn({ component: Position, data: { x: 0, y: 0 } }).unwrap();
159
+ w.despawn(e).unwrap();
160
+ const r = w.set(e, Position, { x: 1 });
161
+ expect(r.ok).toBe(false);
162
+ if (!r.ok) expect(r.error.code).toBe('stale-entity');
163
+ });
164
+ });
165
+
166
+ // ──────────────────────────────────────────────────────────────────────
167
+ // addComponent / removeComponent
168
+ // ──────────────────────────────────────────────────────────────────────
169
+
170
+ describe('M1 w1: addComponent / removeComponent characterization', () => {
171
+ it('addComponent adds a component to an existing entity', () => {
172
+ const w = new World();
173
+ const e = w.spawn({ component: Position, data: { x: 0, y: 0 } }).unwrap();
174
+ const r = w.addComponent(e, { component: Velocity, data: { vx: 1, vy: 2 } });
175
+ expect(r.ok).toBe(true);
176
+ const vel = w.get(e, Velocity).unwrap();
177
+ expect(vel.vx).toBe(1);
178
+ });
179
+
180
+ it('addComponent returns component-already-present for duplicate', () => {
181
+ const w = new World();
182
+ const e = w.spawn({ component: Position, data: { x: 0, y: 0 } }).unwrap();
183
+ const r = w.addComponent(e, { component: Position, data: { x: 1 } });
184
+ expect(r.ok).toBe(false);
185
+ if (!r.ok) expect(r.error.code).toBe('component-already-present');
186
+ });
187
+
188
+ it('removeComponent removes a component from an entity', () => {
189
+ const w = new World();
190
+ const e = w
191
+ .spawn(
192
+ { component: Position, data: { x: 0, y: 0 } },
193
+ { component: Velocity, data: { vx: 1, vy: 2 } },
194
+ )
195
+ .unwrap();
196
+ const r = w.removeComponent(e, Position);
197
+ expect(r.ok).toBe(true);
198
+ const gr = w.get(e, Position);
199
+ expect(gr.ok).toBe(false);
200
+ if (!gr.ok) expect(gr.error.code).toBe('component-not-present');
201
+ const vel = w.get(e, Velocity).unwrap();
202
+ expect(vel.vx).toBe(1);
203
+ });
204
+
205
+ it('removeComponent returns component-not-present for missing component', () => {
206
+ const w = new World();
207
+ const e = w.spawn({ component: Position, data: { x: 0, y: 0 } }).unwrap();
208
+ const r = w.removeComponent(e, Velocity);
209
+ expect(r.ok).toBe(false);
210
+ if (!r.ok) expect(r.error.code).toBe('component-not-present');
211
+ });
212
+ });
213
+
214
+ // ──────────────────────────────────────────────────────────────────────
215
+ // update
216
+ // ──────────────────────────────────────────────────────────────────────
217
+
218
+ describe('M1 w1: update characterization', () => {
219
+ it('update runs registered systems', () => {
220
+ const w = new World();
221
+ let called = false;
222
+ w.addSystem(Update, {
223
+ name: 'marker',
224
+ queries: [],
225
+ fn: () => {
226
+ called = true;
227
+ },
228
+ });
229
+ w.update();
230
+ expect(called).toBe(true);
231
+ });
232
+
233
+ it('update on empty world completes silently', () => {
234
+ const w = new World();
235
+ expect(() => w.update()).not.toThrow();
236
+ });
237
+
238
+ it('update dispatches deferred commands (spawn via commands)', () => {
239
+ const w = new World();
240
+ let spawnedEntity: EntityHandle | null = null;
241
+ w.addSystem(Update, {
242
+ name: 'spawner',
243
+ queries: [],
244
+ fn: (_world, _results, commands) => {
245
+ const e = commands.spawn({ component: Position, data: { x: 5, y: 5 } });
246
+ spawnedEntity = e as unknown as EntityHandle;
247
+ },
248
+ });
249
+ w.update();
250
+ expect(spawnedEntity).not.toBeNull();
251
+ if (spawnedEntity === null) throw new Error('spawnedEntity was null');
252
+ const pos = w.get(spawnedEntity, Position).unwrap();
253
+ expect(pos.x).toBe(5);
254
+ });
255
+ });
256
+
257
+ // ──────────────────────────────────────────────────────────────────────
258
+ // resources
259
+ // ──────────────────────────────────────────────────────────────────────
260
+
261
+ describe('M1 w1: resources characterization', () => {
262
+ it('insertResource and getResource round-trip', () => {
263
+ const w = new World();
264
+ w.insertResource('myKey', 42);
265
+ expect(w.hasResource('myKey')).toBe(true);
266
+ expect(w.getResource<number>('myKey')).toBe(42);
267
+ });
268
+
269
+ it('hasResource returns false for unknown key', () => {
270
+ const w = new World();
271
+ expect(w.hasResource('nonexistent')).toBe(false);
272
+ });
273
+
274
+ it('removeResource deletes a resource', () => {
275
+ const w = new World();
276
+ w.insertResource('myKey', 42);
277
+ w.removeResource('myKey');
278
+ expect(w.hasResource('myKey')).toBe(false);
279
+ });
280
+
281
+ it('insertResource overwrites existing resource', () => {
282
+ const w = new World();
283
+ w.insertResource('myKey', 42);
284
+ w.insertResource('myKey', 99);
285
+ expect(w.getResource<number>('myKey')).toBe(99);
286
+ });
287
+ });
288
+
289
+ // ──────────────────────────────────────────────────────────────────────
290
+ // inspection
291
+ // ──────────────────────────────────────────────────────────────────────
292
+
293
+ describe('M1 w1: inspection characterization', () => {
294
+ it('inspect returns entity count', () => {
295
+ const w = new World();
296
+ expect(w.inspect().entityCount).toBe(0);
297
+ w.spawn({ component: Position, data: { x: 0, y: 0 } }).unwrap();
298
+ expect(w.inspect().entityCount).toBe(1);
299
+ });
300
+
301
+ it('inspect returns system count', () => {
302
+ const w = new World();
303
+ expect(w.inspect().systemCount).toBe(0);
304
+ w.addSystem(Update, { name: 's1', queries: [], fn: () => {} });
305
+ expect(w.inspect().systemCount).toBe(1);
306
+ });
307
+
308
+ it('inspect returns resource keys', () => {
309
+ const w = new World();
310
+ // World constructor registers protected Time and FixedTime resources
311
+ const initialKeys = w.inspect().resourceKeys;
312
+ expect(initialKeys).toContain('Time');
313
+ expect(initialKeys).toContain('FixedTime');
314
+ w.insertResource('k1', 1);
315
+ expect(w.inspect().resourceKeys).toContain('k1');
316
+ });
317
+
318
+ it('inspect returns active components', () => {
319
+ const w = new World();
320
+ w.spawn({ component: Position, data: { x: 0, y: 0 } }).unwrap();
321
+ const snap = w.inspect();
322
+ expect(snap.activeComponents).toContain('W1Position');
323
+ });
324
+
325
+ it('inspect returns systems with set membership', () => {
326
+ const w = new World();
327
+ const TestSet = defineSystemSet({ name: 'test-set' });
328
+ w.addSystems(Update, TestSet, [{ name: 's1', queries: [], fn: () => {} }]);
329
+ const snap = w.inspect();
330
+ const sys = snap.systems.find((s) => s.name === 's1');
331
+ expect(sys).toBeDefined();
332
+ expect(sys?.sets).toContain('test-set');
333
+ });
334
+ });
335
+
336
+ // ──────────────────────────────────────────────────────────────────────
337
+ // addSystem / removeSystem / replaceSystem
338
+ // ──────────────────────────────────────────────────────────────────────
339
+
340
+ describe('M1 w1: addSystem / removeSystem / replaceSystem characterization', () => {
341
+ it('addSystem registers a system', () => {
342
+ const w = new World();
343
+ w.addSystem(Update, { name: 'sys1', queries: [], fn: () => {} });
344
+ expect(w.inspect().systemCount).toBe(1);
345
+ });
346
+
347
+ it('removeSystem removes a registered system', () => {
348
+ const w = new World();
349
+ w.addSystem(Update, { name: 'sys1', queries: [], fn: () => {} });
350
+ const r = w.removeSystem(Update, 'sys1');
351
+ expect(r.ok).toBe(true);
352
+ expect(w.inspect().systemCount).toBe(0);
353
+ });
354
+
355
+ it('removeSystem returns error for unknown system', () => {
356
+ const w = new World();
357
+ const r = w.removeSystem(Update, 'nonexistent');
358
+ expect(r.ok).toBe(false);
359
+ if (!r.ok) expect(r.error.code).toBe('system-before-unknown');
360
+ });
361
+
362
+ it('replaceSystem replaces a system descriptor', () => {
363
+ const w = new World();
364
+ w.addSystem(Update, { name: 'sys1', queries: [], fn: () => {} });
365
+ const r = w.replaceSystem(Update, 'sys1', { name: 'sys1', queries: [], fn: () => {} });
366
+ expect(r.ok).toBe(true);
367
+ expect(w.inspect().systemCount).toBe(1);
368
+ });
369
+ });
370
+
371
+ // ──────────────────────────────────────────────────────────────────────
372
+ // addSystems
373
+ // ──────────────────────────────────────────────────────────────────────
374
+
375
+ describe('M1 w1: addSystems characterization', () => {
376
+ it('addSystems registers systems into a set', () => {
377
+ const w = new World();
378
+ const TestSet = defineSystemSet({ name: 'test-set' });
379
+ const r = w.addSystems(Update, TestSet, [
380
+ { name: 's1', queries: [], fn: () => {} },
381
+ { name: 's2', queries: [], fn: () => {} },
382
+ ]);
383
+ expect(r.ok).toBe(true);
384
+ expect(w.inspect().systemCount).toBe(2);
385
+ });
386
+ });
387
+
388
+ // ──────────────────────────────────────────────────────────────────────
389
+ // allocUniqueRef / allocSharedRef
390
+ // ──────────────────────────────────────────────────────────────────────
391
+
392
+ describe('M1 w1: allocUniqueRef / allocSharedRef characterization', () => {
393
+ it('allocUniqueRef returns a unique handle', () => {
394
+ const w = new World();
395
+ const h = w.allocUniqueRef<'Test', number>('Test', 42);
396
+ expect(typeof h).toBe('number');
397
+ });
398
+
399
+ it('allocSharedRef returns a shared handle', () => {
400
+ const w = new World();
401
+ const h = w.allocSharedRef<'Test', number>('Test', 42);
402
+ expect(typeof h).toBe('number');
403
+ });
404
+ });
405
+
406
+ // ──────────────────────────────────────────────────────────────────────
407
+ // Managed arrays use atomic world.set writes.
408
+ // ──────────────────────────────────────────────────────────────────────
@@ -0,0 +1,16 @@
1
+ import { describe, expectTypeOf, it } from 'vitest';
2
+ import { defineComponent } from '../component';
3
+ import type { Query } from '../query/query';
4
+ import { World } from '../world';
5
+
6
+ const Position = defineComponent('WorldQueryInferencePosition', { x: 'f32' });
7
+ const Velocity = defineComponent('WorldQueryInferenceVelocity', { x: 'f32' });
8
+
9
+ describe('World.query consumer inference', () => {
10
+ it('preserves descriptor tuples through Result.unwrap', () => {
11
+ const query = new World().query({ read: [Position], write: [Velocity] }).unwrap();
12
+ expectTypeOf(query).toEqualTypeOf<
13
+ Query<readonly [typeof Position], readonly [typeof Velocity], readonly []>
14
+ >();
15
+ });
16
+ });
@@ -0,0 +1,87 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { defineComponent } from '../component';
3
+ import {
4
+ defineSharedKernel,
5
+ SHARED_KERNEL_EXECUTOR_RESOURCE_KEY,
6
+ type SharedKernelExecutor,
7
+ } from '../execution/shared-kernel';
8
+ import { Update } from '../schedule-token';
9
+ import { World } from '../world';
10
+
11
+ const Position = defineComponent('WorldHealthPosition', { x: 'f32' });
12
+ function integrate(): void {}
13
+
14
+ describe('World execution health', () => {
15
+ it('transitions once to poisoned after a possible partial write and rejects future update', () => {
16
+ const world = new World();
17
+ world.spawn({ component: Position, data: { x: 1 } }).unwrap();
18
+ const executor: SharedKernelExecutor = {
19
+ execute: (_kernel, spans) => {
20
+ spans[0]?.span.mut(Position).x.fill(2);
21
+ return {
22
+ cause: new Error('fixture fault'),
23
+ dispatched: 2,
24
+ completed: 1,
25
+ partialWrite: true,
26
+ };
27
+ },
28
+ };
29
+ world.insertResource(SHARED_KERNEL_EXECUTOR_RESOURCE_KEY, executor);
30
+ world
31
+ .addSystem(
32
+ Update,
33
+ defineSharedKernel(import.meta.url, {
34
+ name: 'faulting',
35
+ minimumRows: 1,
36
+ queries: [{ write: [Position] }],
37
+ run: integrate,
38
+ }),
39
+ )
40
+ .unwrap();
41
+ const failed = world.update();
42
+ expect(failed.ok).toBe(false);
43
+ if (!failed.ok) expect(failed.error.code).toBe('system-failed');
44
+ expect(world.execution.health).toBe('poisoned');
45
+ expect(world.execution.fault?.partialWrite).toBe(true);
46
+ expect(world.execution.fault?.retryable).toBe(false);
47
+ const rejected = world.update();
48
+ expect(rejected.ok).toBe(false);
49
+ if (!rejected.ok) expect(rejected.error.code).toBe('world-poisoned');
50
+ });
51
+
52
+ it('gives every rebuilt World a new identity', () => {
53
+ expect(new World().identity).not.toBe(new World().identity);
54
+ });
55
+
56
+ it('falls back inline when dispatch fails before any shared write', () => {
57
+ const world = new World();
58
+ world.spawn({ component: Position, data: { x: 1 } }).unwrap();
59
+ const executor: SharedKernelExecutor = {
60
+ execute: () => ({
61
+ cause: new Error('pool not ready'),
62
+ dispatched: 0,
63
+ completed: 0,
64
+ partialWrite: false,
65
+ }),
66
+ };
67
+ world.insertResource(SHARED_KERNEL_EXECUTOR_RESOURCE_KEY, executor);
68
+ world
69
+ .addSystem(
70
+ Update,
71
+ defineSharedKernel(import.meta.url, {
72
+ name: 'predispatch-fallback',
73
+ minimumRows: 1,
74
+ queries: [{ write: [Position] }],
75
+ run: function inline(spans) {
76
+ spans[0]?.mut(Position).x.fill(3);
77
+ },
78
+ }),
79
+ )
80
+ .unwrap();
81
+
82
+ expect(world.update().ok).toBe(true);
83
+ expect(world.execution.health).toBe('healthy');
84
+ const [row] = world.query({ read: [Position] }).unwrap();
85
+ expect(row?.get(Position).x).toBe(3);
86
+ });
87
+ });
@@ -0,0 +1,37 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { defineComponent } from '../component';
3
+ import { FixedTime, Time } from '../time';
4
+ import { World } from '../world';
5
+
6
+ describe('detached inspection and readonly clock', () => {
7
+ it('freezes detached inspection data without changing World', () => {
8
+ const Position = defineComponent('InspectionPosition', { x: 'f32' });
9
+ const world = new World();
10
+ world.spawn({ component: Position, data: { x: 1 } }).unwrap();
11
+ const snapshot = world.inspect();
12
+
13
+ expect(Object.isFrozen(snapshot)).toBe(true);
14
+ expect(Object.isFrozen(snapshot.archetypes)).toBe(true);
15
+ expect(() =>
16
+ snapshot.archetypes.push({
17
+ key: 'fake',
18
+ componentNames: [],
19
+ entityCount: 0,
20
+ tableId: -1,
21
+ }),
22
+ ).toThrow();
23
+ expect(world.inspect().entityCount).toBe(1);
24
+ });
25
+
26
+ it('keeps stable clock views while rejecting direct writes', () => {
27
+ const world = new World();
28
+ const time = world.getResource(Time);
29
+ const fixed = world.getResource(FixedTime);
30
+ expect(world.getResource(Time)).toBe(time);
31
+ expect(world.getResource(FixedTime)).toBe(fixed);
32
+ expect(Object.isFrozen(time)).toBe(true);
33
+ expect(Object.isFrozen(fixed)).toBe(true);
34
+ expect(() => ((time as { delta: number }).delta = 1)).toThrow();
35
+ expect(() => ((fixed as { tick: number }).tick = 1)).toThrow();
36
+ });
37
+ });
@@ -0,0 +1,17 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ describe('package-private World internal seam', () => {
4
+ it('shares the World key across split bundled entry points', async () => {
5
+ const indexPath = '../../dist/index.mjs';
6
+ const projectionPath = '../../dist/projection/index.mjs';
7
+ const [{ World }, { createWorldProjection }] = await Promise.all([
8
+ import(indexPath),
9
+ import(projectionPath),
10
+ ]);
11
+
12
+ const world = new World();
13
+ const projection = createWorldProjection(world);
14
+
15
+ expect(projection.poll()).toEqual({ status: 'delta', cursor: 0, changes: [] });
16
+ });
17
+ });