@adobe/data 0.1.2 → 0.2.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 (541) hide show
  1. package/.cursorrules +28 -0
  2. package/.eslintrc.cjs +48 -0
  3. package/.github/CONTRIBUTING.md +47 -0
  4. package/CODE_OF_CONDUCT.md +79 -0
  5. package/LICENSE +21 -0
  6. package/README.md +2 -2
  7. package/asconfig.json +22 -0
  8. package/assembly/index.ts +85 -0
  9. package/assembly/tsconfig.json +17 -0
  10. package/c/build_run.sh +2 -0
  11. package/c/vector_addition +0 -0
  12. package/c/vector_addition.c +125 -0
  13. package/{cache/functions/types.js → config/license.js} +0 -2
  14. package/docs/perftest.html +28 -0
  15. package/index.html +10 -0
  16. package/package.json +50 -27
  17. package/scripts/deploy-docs.sh +41 -0
  18. package/{assembly-test/assembly.test.js → src/assembly-test/assembly.test.ts} +4 -4
  19. package/src/cache/async-cache.ts +38 -0
  20. package/{cache/blob-store.test.js → src/cache/blob-store.test.ts} +41 -7
  21. package/src/cache/blob-store.ts +278 -0
  22. package/src/cache/data-cache.test.ts +61 -0
  23. package/src/cache/data-cache.ts +183 -0
  24. package/src/cache/expiring-data-cache.test.ts +81 -0
  25. package/src/cache/expiring-data-cache.ts +61 -0
  26. package/src/cache/fallback-async-cache.ts +49 -0
  27. package/src/cache/functions/async-data-function.ts +25 -0
  28. package/src/cache/functions/functions.test.ts +84 -0
  29. package/{cache/functions/get-cached.test.js → src/cache/functions/get-cached.test.ts} +24 -7
  30. package/{cache/functions/get-cached.js → src/cache/functions/get-cached.ts} +12 -6
  31. package/{cache/functions/hashing/blob-to-hash.js → src/cache/functions/hashing/blob-to-hash.ts} +20 -18
  32. package/{cache/functions/hashing/buffer-to-hash.js → src/cache/functions/hashing/buffer-to-hash.ts} +7 -7
  33. package/src/cache/functions/hashing/hashing.test.ts +95 -0
  34. package/{cache/functions/hashing/index.js → src/cache/functions/hashing/index.ts} +1 -1
  35. package/{cache/functions/hashing/json-to-hash.js → src/cache/functions/hashing/json-to-hash.ts} +3 -3
  36. package/{cache/functions/hashing/string-to-hash.js → src/cache/functions/hashing/string-to-hash.ts} +11 -10
  37. package/{cache/functions/index.js → src/cache/functions/index.ts} +2 -4
  38. package/{cache/functions/memoize.js → src/cache/functions/memoize.ts} +22 -15
  39. package/src/cache/functions/prevent-parallel-execution.ts +50 -0
  40. package/src/cache/get-persistent-cache.ts +62 -0
  41. package/{cache/index.js → src/cache/index.ts} +9 -3
  42. package/src/cache/managed-array.ts +243 -0
  43. package/{cache/managed-async-cache.browser.test.js → src/cache/managed-async-cache.browser.test.ts} +27 -24
  44. package/src/cache/managed-async-cache.ts +78 -0
  45. package/src/cache/memory-allocator.ts +176 -0
  46. package/src/cache/memory-async-cache.ts +51 -0
  47. package/src/data.ts +38 -0
  48. package/src/ecs/README.md +21 -0
  49. package/src/ecs/archetype/archetype.ts +39 -0
  50. package/src/ecs/archetype/create-archetype.test.ts +115 -0
  51. package/src/ecs/archetype/create-archetype.ts +52 -0
  52. package/src/ecs/archetype/delete-row.test.ts +110 -0
  53. package/src/ecs/archetype/delete-row.ts +37 -0
  54. package/src/ecs/archetype/index.ts +24 -0
  55. package/src/ecs/component-schemas.ts +24 -0
  56. package/src/ecs/core-components.ts +443 -0
  57. package/src/ecs/database/create-database.test.ts +745 -0
  58. package/src/ecs/database/create-database.ts +205 -0
  59. package/src/ecs/database/database.ts +81 -0
  60. package/src/ecs/database/index.ts +24 -0
  61. package/src/ecs/database/observe-dependent-value.test.ts +198 -0
  62. package/src/ecs/database/observe-dependent-value.ts +78 -0
  63. package/src/ecs/database/transactional-store/create-transactional-store.test.ts +250 -0
  64. package/src/ecs/database/transactional-store/create-transactional-store.ts +281 -0
  65. package/{ecs/ecs/ecs-types.js → src/ecs/database/transactional-store/index.ts} +1 -2
  66. package/src/ecs/database/transactional-store/transactional-store.ts +80 -0
  67. package/src/ecs/entity-location-table/create-entity-location-table.test.ts +170 -0
  68. package/src/ecs/entity-location-table/create-entity-location-table.ts +96 -0
  69. package/src/ecs/entity-location-table/entity-location-table.ts +30 -0
  70. package/src/ecs/entity-location-table/entity-location.ts +34 -0
  71. package/src/ecs/entity-location-table/index.ts +23 -0
  72. package/src/ecs/entity.ts +26 -0
  73. package/src/ecs/index.ts +26 -0
  74. package/src/ecs/store/core/core.ts +71 -0
  75. package/src/ecs/store/core/create-core.test.ts +440 -0
  76. package/src/ecs/store/core/create-core.ts +168 -0
  77. package/{cache/async-cache.js → src/ecs/store/core/index.ts} +1 -2
  78. package/src/ecs/store/create-store.test.ts +562 -0
  79. package/src/ecs/store/create-store.ts +97 -0
  80. package/src/ecs/store/index.ts +23 -0
  81. package/{types/types.js → src/ecs/store/resource-components.ts} +2 -6
  82. package/src/ecs/store/store.ts +55 -0
  83. package/src/equals-shallow.test.ts +133 -0
  84. package/src/equals-shallow.ts +37 -0
  85. package/src/equals.test.ts +175 -0
  86. package/src/equals.ts +70 -0
  87. package/src/index.ts +27 -0
  88. package/src/internal/array-buffer-like/copy.ts +469 -0
  89. package/src/internal/array-buffer-like/grow.ts +53 -0
  90. package/{core/index.js → src/internal/array-buffer-like/index.ts} +4 -4
  91. package/src/internal/array-buffer-like/is-array-buffer.ts +445 -0
  92. package/src/internal/array-buffer-like/is-shared-array-buffer.ts +445 -0
  93. package/{core/functions/is-async-generator.js → src/internal/async-generator/is-async-generator.ts} +2 -2
  94. package/{core/schema.js → src/internal/data-view-32/create-data-view-32.ts} +8 -11
  95. package/src/internal/data-view-32/data-view-32.ts +447 -0
  96. package/{ecs/action-ecs/index.js → src/internal/data-view-32/index.ts} +2 -2
  97. package/src/internal/function/memoize-factory.ts +12 -0
  98. package/src/internal/object/index.ts +23 -0
  99. package/{cache/functions/bind-functions.js → src/internal/object/map-entries.ts} +6 -11
  100. package/src/internal/promise/is-promise.ts +28 -0
  101. package/src/internal/typed-array/get-byte-size.ts +50 -0
  102. package/src/internal/typed-array/index.ts +24 -0
  103. package/src/internal/typed-array/typed-array-constructer.ts +32 -0
  104. package/src/internal/typed-array/typed-array.ts +25 -0
  105. package/src/is-data.ts +47 -0
  106. package/src/lit/decorators/apply-decorator.ts +24 -0
  107. package/src/lit/decorators/apply-service-decorators.ts +13 -0
  108. package/src/lit/decorators/index.ts +24 -0
  109. package/src/lit/decorators/require-service.ts +19 -0
  110. package/src/lit/elements/index.ts +3 -0
  111. package/src/lit/elements/service-application.ts +26 -0
  112. package/src/lit/elements/service-context.ts +3 -0
  113. package/src/lit/elements/service-element.ts +18 -0
  114. package/src/lit/hooks/component/component.ts +10 -0
  115. package/src/lit/hooks/component/stack.ts +17 -0
  116. package/src/lit/hooks/index.ts +13 -0
  117. package/src/lit/hooks/use-connected.ts +39 -0
  118. package/src/lit/hooks/use-effect.ts +17 -0
  119. package/src/lit/hooks/use-element.ts +8 -0
  120. package/src/lit/hooks/use-memo.ts +14 -0
  121. package/src/lit/hooks/use-observable-values.ts +9 -0
  122. package/src/lit/hooks/use-observable.ts +13 -0
  123. package/src/lit/hooks/use-ref.ts +6 -0
  124. package/src/lit/hooks/use-resize-observer.ts +27 -0
  125. package/src/lit/hooks/use-state.ts +17 -0
  126. package/src/lit/hooks/use-window-event.ts +14 -0
  127. package/src/lit/hooks/with-hooks.ts +20 -0
  128. package/src/lit/index.ts +3 -0
  129. package/src/mutable-clone.ts +29 -0
  130. package/{core/data.test.js → src/normalize.test.ts} +22 -22
  131. package/src/normalize.ts +37 -0
  132. package/src/observe/create-observable-event.ts +47 -0
  133. package/src/observe/create-observable-state.ts +51 -0
  134. package/src/observe/create-persisted-state.test.ts +143 -0
  135. package/src/observe/create-persisted-state.ts +60 -0
  136. package/src/observe/create-query-state.ts +70 -0
  137. package/{observe/from-array.js → src/observe/from-array.ts} +14 -3
  138. package/{service/service.js → src/observe/from-constant.ts} +13 -4
  139. package/{observe/from-element-id.js → src/observe/from-element-id.ts} +44 -39
  140. package/src/observe/from-element-properties-and-events.ts +47 -0
  141. package/{observe/from-element-property.js → src/observe/from-element-property.ts} +33 -25
  142. package/src/observe/from-promise-with-error.ts +51 -0
  143. package/src/observe/from-promise.ts +49 -0
  144. package/src/observe/from-properties.ts +67 -0
  145. package/{observe/index.js → src/observe/index.ts} +4 -1
  146. package/src/observe/observe.test.ts +467 -0
  147. package/src/observe/to-promise.ts +40 -0
  148. package/src/observe/to-properties.ts +41 -0
  149. package/src/observe/types.ts +40 -0
  150. package/src/observe/with-async-map.ts +37 -0
  151. package/src/observe/with-batch.test.ts +141 -0
  152. package/src/observe/with-batch.ts +67 -0
  153. package/{core/data.js → src/observe/with-cache.ts} +32 -26
  154. package/src/observe/with-copy.ts +32 -0
  155. package/src/observe/with-deduplicate-data.ts +43 -0
  156. package/src/observe/with-deduplicate.ts +41 -0
  157. package/src/observe/with-default.ts +48 -0
  158. package/src/observe/with-lazy.test.ts +68 -0
  159. package/{core/functions/is-promise.js → src/observe/with-lazy.ts} +17 -5
  160. package/{observe/with-map-data.js → src/observe/with-map-data.ts} +9 -3
  161. package/src/observe/with-map.ts +36 -0
  162. package/src/observe/with-optional.ts +47 -0
  163. package/src/observe/with-unwrap.ts +54 -0
  164. package/src/old-ecs/action-ecs/action-ecs.test.ts +420 -0
  165. package/src/old-ecs/action-ecs/action-ecs.ts +274 -0
  166. package/src/old-ecs/action-ecs/action-types.ts +178 -0
  167. package/{core/functions/index.js → src/old-ecs/action-ecs/index.ts} +8 -5
  168. package/{service/sequential-action.js → src/old-ecs/action-ecs/sequential-action.ts} +19 -4
  169. package/src/old-ecs/core-ecs/core-ecs-serialization.test.ts +244 -0
  170. package/src/old-ecs/core-ecs/core-ecs-types.ts +183 -0
  171. package/src/old-ecs/core-ecs/core-ecs.test.ts +474 -0
  172. package/src/old-ecs/core-ecs/core-ecs.ts +640 -0
  173. package/src/old-ecs/core-ecs/index.ts +30 -0
  174. package/src/old-ecs/ecs/ecs-types.ts +189 -0
  175. package/src/old-ecs/ecs/ecs-where-functions.ts +95 -0
  176. package/src/old-ecs/ecs/ecs.test.ts +461 -0
  177. package/src/old-ecs/ecs/ecs.ts +279 -0
  178. package/{ecs/core-ecs/core-ecs-types.js → src/old-ecs/ecs/index.ts} +2 -2
  179. package/src/old-ecs/entity.ts +26 -0
  180. package/{ecs/index.js → src/old-ecs/index.ts} +1 -1
  181. package/{ecs/transaction-ecs/index.js → src/old-ecs/transaction-ecs/index.ts} +0 -1
  182. package/src/old-ecs/transaction-ecs/transaction-ecs.test.ts +725 -0
  183. package/src/old-ecs/transaction-ecs/transaction-ecs.ts +283 -0
  184. package/src/old-ecs/transaction-ecs/transaction-types.ts +248 -0
  185. package/src/old-ecs/transaction-ecs/transactions.ts +243 -0
  186. package/src/perftest/ecs-perf.ts +255 -0
  187. package/src/perftest/helper-functions.ts +31 -0
  188. package/src/perftest/horizon-perf.ts +132 -0
  189. package/{perftest/index.js → src/perftest/index.ts} +9 -7
  190. package/src/perftest/perf-test.ts +193 -0
  191. package/src/perftest/perf.md +90 -0
  192. package/src/perftest/vanilla-perf.ts +136 -0
  193. package/src/schema/boolean.ts +5 -0
  194. package/src/schema/dynamic/deep-merge.test.ts +100 -0
  195. package/src/schema/dynamic/deep-merge.ts +67 -0
  196. package/src/schema/dynamic/enumerate-patches.test.ts +235 -0
  197. package/src/schema/dynamic/enumerate-patches.ts +90 -0
  198. package/src/schema/dynamic/get-dynamic-schema.test.ts +129 -0
  199. package/src/schema/dynamic/get-dynamic-schema.ts +48 -0
  200. package/src/schema/dynamic/index.ts +22 -0
  201. package/src/schema/f32.ts +30 -0
  202. package/src/schema/i32.ts +31 -0
  203. package/src/schema/index.ts +32 -0
  204. package/{cache/functions/omit.js → src/schema/nullable.ts} +10 -7
  205. package/src/schema/schema.ts +229 -0
  206. package/src/schema/time.ts +5 -0
  207. package/src/schema/true.ts +26 -0
  208. package/src/schema/tuple.ts +5 -0
  209. package/src/schema/u32.ts +31 -0
  210. package/src/schema/validation/is-valid.test.ts +43 -0
  211. package/{core/functions/array-equals.js → src/schema/validation/is-valid.ts} +8 -10
  212. package/src/schema/validation/validate.test.ts +120 -0
  213. package/src/schema/validation/validate.ts +41 -0
  214. package/{core/functions/with-validation.test.js → src/schema/validation/with-validation.test.ts} +28 -12
  215. package/{core/functions/with-validation.js → src/schema/validation/with-validation.ts} +14 -10
  216. package/src/schema.test.ts +55 -0
  217. package/src/service/add-observable-actions.ts +207 -0
  218. package/{service/index.js → src/service/index.ts} +4 -4
  219. package/src/service/is-service.ts +7 -0
  220. package/src/service/progressive-result.ts +141 -0
  221. package/src/service/service.ts +27 -0
  222. package/src/table/add-row.ts +42 -0
  223. package/src/table/create-table.ts +36 -0
  224. package/src/table/delete-row.ts +42 -0
  225. package/src/table/ensure-capacity.ts +37 -0
  226. package/src/table/get-row-data.ts +31 -0
  227. package/src/table/index.ts +29 -0
  228. package/src/table/row-index.ts +26 -0
  229. package/src/table/table.ts +32 -0
  230. package/src/table/update-row.ts +35 -0
  231. package/src/tsconfig.json +6 -0
  232. package/src/typed-buffer/copy-to-gpu-buffer.ts +23 -0
  233. package/{cache/expiring-data-cache.js → src/typed-buffer/create-array-buffer.ts} +31 -25
  234. package/src/typed-buffer/create-number-buffer.ts +90 -0
  235. package/src/typed-buffer/create-struct-buffer.ts +93 -0
  236. package/src/typed-buffer/create-typed-buffer.ts +49 -0
  237. package/src/typed-buffer/index.ts +26 -0
  238. package/src/typed-buffer/structs/assert-struct.ts +37 -0
  239. package/src/typed-buffer/structs/create-read-struct.test.ts +202 -0
  240. package/src/typed-buffer/structs/create-read-struct.ts +77 -0
  241. package/src/typed-buffer/structs/create-write-struct.ts +73 -0
  242. package/src/typed-buffer/structs/get-field-offset.ts +36 -0
  243. package/src/typed-buffer/structs/get-struct-layout.test.ts +146 -0
  244. package/src/typed-buffer/structs/get-struct-layout.ts +222 -0
  245. package/src/typed-buffer/structs/index.ts +22 -0
  246. package/src/typed-buffer/structs/read-struct.ts +25 -0
  247. package/src/typed-buffer/structs/struct-layout.ts +465 -0
  248. package/src/typed-buffer/structs/write-struct.test.ts +195 -0
  249. package/src/typed-buffer/structs/write-struct.ts +25 -0
  250. package/src/typed-buffer/typed-buffer.test.ts +253 -0
  251. package/src/typed-buffer/typed-buffer.ts +41 -0
  252. package/src/types/assert.ts +22 -0
  253. package/src/types/equal.ts +24 -0
  254. package/{types/index.js → src/types/index.ts} +3 -1
  255. package/src/types/types.ts +166 -0
  256. package/tsconfig-base.json +25 -0
  257. package/tsconfig.json +8 -0
  258. package/typedoc.json +22 -0
  259. package/vite.config.js +16 -0
  260. package/assembly/index.d.ts +0 -30
  261. package/assembly/index.js +0 -18
  262. package/assembly/index.wasm +0 -0
  263. package/assembly/index.wasm.map +0 -1
  264. package/assembly-test/assembly.test.d.ts +0 -1
  265. package/assembly-test/assembly.test.js.map +0 -1
  266. package/cache/async-cache.d.ts +0 -15
  267. package/cache/async-cache.js.map +0 -1
  268. package/cache/blob-store.d.ts +0 -94
  269. package/cache/blob-store.js +0 -191
  270. package/cache/blob-store.js.map +0 -1
  271. package/cache/blob-store.test.d.ts +0 -1
  272. package/cache/blob-store.test.js.map +0 -1
  273. package/cache/data-cache.d.ts +0 -38
  274. package/cache/data-cache.js +0 -96
  275. package/cache/data-cache.js.map +0 -1
  276. package/cache/data-cache.test.d.ts +0 -1
  277. package/cache/data-cache.test.js +0 -50
  278. package/cache/data-cache.test.js.map +0 -1
  279. package/cache/expiring-data-cache.d.ts +0 -6
  280. package/cache/expiring-data-cache.js.map +0 -1
  281. package/cache/expiring-data-cache.test.d.ts +0 -1
  282. package/cache/expiring-data-cache.test.js +0 -62
  283. package/cache/expiring-data-cache.test.js.map +0 -1
  284. package/cache/fallback-async-cache.d.ts +0 -7
  285. package/cache/fallback-async-cache.js +0 -22
  286. package/cache/fallback-async-cache.js.map +0 -1
  287. package/cache/functions/bind-functions.d.ts +0 -6
  288. package/cache/functions/bind-functions.js.map +0 -1
  289. package/cache/functions/functions.test.d.ts +0 -1
  290. package/cache/functions/functions.test.js +0 -79
  291. package/cache/functions/functions.test.js.map +0 -1
  292. package/cache/functions/get-cached.d.ts +0 -11
  293. package/cache/functions/get-cached.js.map +0 -1
  294. package/cache/functions/get-cached.test.d.ts +0 -1
  295. package/cache/functions/get-cached.test.js.map +0 -1
  296. package/cache/functions/hashing/blob-to-hash.d.ts +0 -4
  297. package/cache/functions/hashing/blob-to-hash.js.map +0 -1
  298. package/cache/functions/hashing/buffer-to-hash.d.ts +0 -4
  299. package/cache/functions/hashing/buffer-to-hash.js.map +0 -1
  300. package/cache/functions/hashing/hashing.test.d.ts +0 -1
  301. package/cache/functions/hashing/hashing.test.js +0 -95
  302. package/cache/functions/hashing/hashing.test.js.map +0 -1
  303. package/cache/functions/hashing/index.d.ts +0 -4
  304. package/cache/functions/hashing/index.js.map +0 -1
  305. package/cache/functions/hashing/json-to-hash.d.ts +0 -4
  306. package/cache/functions/hashing/json-to-hash.js.map +0 -1
  307. package/cache/functions/hashing/string-to-hash.d.ts +0 -4
  308. package/cache/functions/hashing/string-to-hash.js.map +0 -1
  309. package/cache/functions/index.d.ts +0 -5
  310. package/cache/functions/index.js.map +0 -1
  311. package/cache/functions/memoize.d.ts +0 -12
  312. package/cache/functions/memoize.js.map +0 -1
  313. package/cache/functions/omit.d.ts +0 -1
  314. package/cache/functions/omit.js.map +0 -1
  315. package/cache/functions/prevent-parallel-execution.d.ts +0 -7
  316. package/cache/functions/prevent-parallel-execution.js +0 -25
  317. package/cache/functions/prevent-parallel-execution.js.map +0 -1
  318. package/cache/functions/types.d.ts +0 -1
  319. package/cache/functions/types.js.map +0 -1
  320. package/cache/get-persistent-cache.d.ts +0 -12
  321. package/cache/get-persistent-cache.js +0 -23
  322. package/cache/get-persistent-cache.js.map +0 -1
  323. package/cache/index.d.ts +0 -3
  324. package/cache/index.js.map +0 -1
  325. package/cache/managed-array.d.ts +0 -23
  326. package/cache/managed-array.js +0 -160
  327. package/cache/managed-array.js.map +0 -1
  328. package/cache/managed-async-cache.browser.test.d.ts +0 -1
  329. package/cache/managed-async-cache.browser.test.js.map +0 -1
  330. package/cache/managed-async-cache.d.ts +0 -4
  331. package/cache/managed-async-cache.js +0 -45
  332. package/cache/managed-async-cache.js.map +0 -1
  333. package/cache/memory-allocator.d.ts +0 -23
  334. package/cache/memory-allocator.js +0 -94
  335. package/cache/memory-allocator.js.map +0 -1
  336. package/cache/memory-async-cache.d.ts +0 -6
  337. package/cache/memory-async-cache.js +0 -23
  338. package/cache/memory-async-cache.js.map +0 -1
  339. package/core/data.d.ts +0 -22
  340. package/core/data.js.map +0 -1
  341. package/core/data.test.d.ts +0 -1
  342. package/core/data.test.js.map +0 -1
  343. package/core/functions/array-equals.d.ts +0 -1
  344. package/core/functions/array-equals.js.map +0 -1
  345. package/core/functions/deep-merge.d.ts +0 -31
  346. package/core/functions/deep-merge.js +0 -51
  347. package/core/functions/deep-merge.js.map +0 -1
  348. package/core/functions/deep-merge.test.d.ts +0 -1
  349. package/core/functions/deep-merge.test.js +0 -94
  350. package/core/functions/deep-merge.test.js.map +0 -1
  351. package/core/functions/index.d.ts +0 -4
  352. package/core/functions/index.js.map +0 -1
  353. package/core/functions/is-async-generator.d.ts +0 -1
  354. package/core/functions/is-async-generator.js.map +0 -1
  355. package/core/functions/is-promise.d.ts +0 -1
  356. package/core/functions/is-promise.js.map +0 -1
  357. package/core/functions/with-validation.d.ts +0 -5
  358. package/core/functions/with-validation.js.map +0 -1
  359. package/core/functions/with-validation.test.d.ts +0 -1
  360. package/core/functions/with-validation.test.js.map +0 -1
  361. package/core/index.d.ts +0 -3
  362. package/core/index.js.map +0 -1
  363. package/core/schema.d.ts +0 -86
  364. package/core/schema.js.map +0 -1
  365. package/core/schema.test.d.ts +0 -1
  366. package/core/schema.test.js +0 -16
  367. package/core/schema.test.js.map +0 -1
  368. package/ecs/action-ecs/action-ecs.d.ts +0 -19
  369. package/ecs/action-ecs/action-ecs.js +0 -203
  370. package/ecs/action-ecs/action-ecs.js.map +0 -1
  371. package/ecs/action-ecs/action-ecs.test.d.ts +0 -1
  372. package/ecs/action-ecs/action-ecs.test.js +0 -362
  373. package/ecs/action-ecs/action-ecs.test.js.map +0 -1
  374. package/ecs/action-ecs/action-types.d.ts +0 -106
  375. package/ecs/action-ecs/action-types.js +0 -19
  376. package/ecs/action-ecs/action-types.js.map +0 -1
  377. package/ecs/action-ecs/index.d.ts +0 -2
  378. package/ecs/action-ecs/index.js.map +0 -1
  379. package/ecs/core-ecs/core-ecs-serialization.test.d.ts +0 -1
  380. package/ecs/core-ecs/core-ecs-serialization.test.js +0 -230
  381. package/ecs/core-ecs/core-ecs-serialization.test.js.map +0 -1
  382. package/ecs/core-ecs/core-ecs-types.d.ts +0 -141
  383. package/ecs/core-ecs/core-ecs-types.js.map +0 -1
  384. package/ecs/core-ecs/core-ecs.d.ts +0 -7
  385. package/ecs/core-ecs/core-ecs.js +0 -492
  386. package/ecs/core-ecs/core-ecs.js.map +0 -1
  387. package/ecs/core-ecs/core-ecs.test.d.ts +0 -1
  388. package/ecs/core-ecs/core-ecs.test.js +0 -404
  389. package/ecs/core-ecs/core-ecs.test.js.map +0 -1
  390. package/ecs/core-ecs/index.d.ts +0 -1
  391. package/ecs/core-ecs/index.js +0 -2
  392. package/ecs/core-ecs/index.js.map +0 -1
  393. package/ecs/ecs/ecs-types.d.ts +0 -132
  394. package/ecs/ecs/ecs-types.js.map +0 -1
  395. package/ecs/ecs/ecs-where-functions.d.ts +0 -6
  396. package/ecs/ecs/ecs-where-functions.js +0 -91
  397. package/ecs/ecs/ecs-where-functions.js.map +0 -1
  398. package/ecs/ecs/ecs.d.ts +0 -13
  399. package/ecs/ecs/ecs.js +0 -177
  400. package/ecs/ecs/ecs.js.map +0 -1
  401. package/ecs/ecs/ecs.test.d.ts +0 -1
  402. package/ecs/ecs/ecs.test.js +0 -399
  403. package/ecs/ecs/ecs.test.js.map +0 -1
  404. package/ecs/ecs/index.d.ts +0 -3
  405. package/ecs/ecs/index.js +0 -3
  406. package/ecs/ecs/index.js.map +0 -1
  407. package/ecs/index.d.ts +0 -4
  408. package/ecs/index.js.map +0 -1
  409. package/ecs/transaction-ecs/index.d.ts +0 -2
  410. package/ecs/transaction-ecs/index.js.map +0 -1
  411. package/ecs/transaction-ecs/transaction-ecs.d.ts +0 -11
  412. package/ecs/transaction-ecs/transaction-ecs.js +0 -184
  413. package/ecs/transaction-ecs/transaction-ecs.js.map +0 -1
  414. package/ecs/transaction-ecs/transaction-ecs.test.d.ts +0 -1
  415. package/ecs/transaction-ecs/transaction-ecs.test.js +0 -599
  416. package/ecs/transaction-ecs/transaction-ecs.test.js.map +0 -1
  417. package/ecs/transaction-ecs/transaction-types.d.ts +0 -135
  418. package/ecs/transaction-ecs/transaction-types.js +0 -2
  419. package/ecs/transaction-ecs/transaction-types.js.map +0 -1
  420. package/ecs/transaction-ecs/transactions.d.ts +0 -5
  421. package/ecs/transaction-ecs/transactions.js +0 -158
  422. package/ecs/transaction-ecs/transactions.js.map +0 -1
  423. package/index.d.ts +0 -1
  424. package/index.js +0 -23
  425. package/index.js.map +0 -1
  426. package/observe/create-observable-event.d.ts +0 -10
  427. package/observe/create-observable-event.js +0 -22
  428. package/observe/create-observable-event.js.map +0 -1
  429. package/observe/create-observable-state.d.ts +0 -7
  430. package/observe/create-observable-state.js +0 -27
  431. package/observe/create-observable-state.js.map +0 -1
  432. package/observe/create-persisted-state.d.ts +0 -11
  433. package/observe/create-persisted-state.js +0 -31
  434. package/observe/create-persisted-state.js.map +0 -1
  435. package/observe/create-persisted-state.test.d.ts +0 -1
  436. package/observe/create-persisted-state.test.js +0 -124
  437. package/observe/create-persisted-state.test.js.map +0 -1
  438. package/observe/from-array.d.ts +0 -5
  439. package/observe/from-array.js.map +0 -1
  440. package/observe/from-constant.d.ts +0 -5
  441. package/observe/from-constant.js +0 -12
  442. package/observe/from-constant.js.map +0 -1
  443. package/observe/from-element-id.d.ts +0 -7
  444. package/observe/from-element-id.js.map +0 -1
  445. package/observe/from-element-properties-and-events.d.ts +0 -2
  446. package/observe/from-element-properties-and-events.js +0 -18
  447. package/observe/from-element-properties-and-events.js.map +0 -1
  448. package/observe/from-element-property.d.ts +0 -11
  449. package/observe/from-element-property.js.map +0 -1
  450. package/observe/from-promise-with-error.d.ts +0 -7
  451. package/observe/from-promise-with-error.js +0 -27
  452. package/observe/from-promise-with-error.js.map +0 -1
  453. package/observe/from-promise.d.ts +0 -6
  454. package/observe/from-promise.js +0 -22
  455. package/observe/from-promise.js.map +0 -1
  456. package/observe/from-properties.d.ts +0 -10
  457. package/observe/from-properties.js +0 -33
  458. package/observe/from-properties.js.map +0 -1
  459. package/observe/index.d.ts +0 -27
  460. package/observe/index.js.map +0 -1
  461. package/observe/observe.test.d.ts +0 -7
  462. package/observe/observe.test.js +0 -417
  463. package/observe/observe.test.js.map +0 -1
  464. package/observe/to-promise.d.ts +0 -8
  465. package/observe/to-promise.js +0 -18
  466. package/observe/to-promise.js.map +0 -1
  467. package/observe/to-properties.d.ts +0 -11
  468. package/observe/to-properties.js +0 -9
  469. package/observe/to-properties.js.map +0 -1
  470. package/observe/types.d.ts +0 -17
  471. package/observe/types.js +0 -2
  472. package/observe/types.js.map +0 -1
  473. package/observe/with-async-map.d.ts +0 -6
  474. package/observe/with-async-map.js +0 -12
  475. package/observe/with-async-map.js.map +0 -1
  476. package/observe/with-cache.d.ts +0 -6
  477. package/observe/with-cache.js +0 -33
  478. package/observe/with-cache.js.map +0 -1
  479. package/observe/with-copy.d.ts +0 -5
  480. package/observe/with-copy.js +0 -10
  481. package/observe/with-copy.js.map +0 -1
  482. package/observe/with-deduplicate-data.d.ts +0 -7
  483. package/observe/with-deduplicate-data.js +0 -18
  484. package/observe/with-deduplicate-data.js.map +0 -1
  485. package/observe/with-deduplicate.d.ts +0 -6
  486. package/observe/with-deduplicate.js +0 -19
  487. package/observe/with-deduplicate.js.map +0 -1
  488. package/observe/with-default.d.ts +0 -6
  489. package/observe/with-default.js +0 -21
  490. package/observe/with-default.js.map +0 -1
  491. package/observe/with-map-data.d.ts +0 -7
  492. package/observe/with-map-data.js.map +0 -1
  493. package/observe/with-map.d.ts +0 -5
  494. package/observe/with-map.js +0 -11
  495. package/observe/with-map.js.map +0 -1
  496. package/observe/with-optional.d.ts +0 -5
  497. package/observe/with-optional.js +0 -20
  498. package/observe/with-optional.js.map +0 -1
  499. package/observe/with-unwrap.d.ts +0 -5
  500. package/observe/with-unwrap.js +0 -26
  501. package/observe/with-unwrap.js.map +0 -1
  502. package/perftest/ecs-perf.d.ts +0 -49
  503. package/perftest/ecs-perf.js +0 -230
  504. package/perftest/ecs-perf.js.map +0 -1
  505. package/perftest/helper-functions.d.ts +0 -1
  506. package/perftest/helper-functions.js +0 -31
  507. package/perftest/helper-functions.js.map +0 -1
  508. package/perftest/horizon-perf.d.ts +0 -22
  509. package/perftest/horizon-perf.js +0 -126
  510. package/perftest/horizon-perf.js.map +0 -1
  511. package/perftest/index.d.ts +0 -1
  512. package/perftest/index.js.map +0 -1
  513. package/perftest/perf-test.d.ts +0 -18
  514. package/perftest/perf-test.js +0 -124
  515. package/perftest/perf-test.js.map +0 -1
  516. package/perftest/vanilla-perf.d.ts +0 -38
  517. package/perftest/vanilla-perf.js +0 -128
  518. package/perftest/vanilla-perf.js.map +0 -1
  519. package/schemas/index.d.ts +0 -1
  520. package/schemas/index.js +0 -23
  521. package/schemas/index.js.map +0 -1
  522. package/schemas/schemas.d.ts +0 -45
  523. package/schemas/schemas.js +0 -39
  524. package/schemas/schemas.js.map +0 -1
  525. package/service/add-observable-actions.d.ts +0 -29
  526. package/service/add-observable-actions.js +0 -108
  527. package/service/add-observable-actions.js.map +0 -1
  528. package/service/index.d.ts +0 -4
  529. package/service/index.js.map +0 -1
  530. package/service/progressive-result.d.ts +0 -96
  531. package/service/progressive-result.js +0 -99
  532. package/service/progressive-result.js.map +0 -1
  533. package/service/sequential-action.d.ts +0 -18
  534. package/service/sequential-action.js.map +0 -1
  535. package/service/service.d.ts +0 -4
  536. package/service/service.js.map +0 -1
  537. package/tsconfig.tsbuildinfo +0 -1
  538. package/types/index.d.ts +0 -1
  539. package/types/index.js.map +0 -1
  540. package/types/types.d.ts +0 -61
  541. package/types/types.js.map +0 -1
@@ -0,0 +1,745 @@
1
+ /*MIT License
2
+
3
+ © Copyright 2025 Adobe. All rights reserved.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.*/
22
+ import { describe, it, expect, vi } from "vitest";
23
+ import { createDatabase } from "./create-database.js";
24
+ import { createStore } from "../store/create-store.js";
25
+ import { FromSchema, Schema } from "../../schema/schema.js";
26
+ import { Entity } from "../entity.js";
27
+ import { F32Schema } from "../../schema/f32.js";
28
+
29
+ // Test schemas
30
+ const positionSchema = {
31
+ type: "object",
32
+ properties: {
33
+ x: F32Schema,
34
+ y: F32Schema,
35
+ z: F32Schema,
36
+ }
37
+ } as const satisfies Schema;
38
+ type Position = FromSchema<typeof positionSchema>;
39
+
40
+ const healthSchema = {
41
+ type: "object",
42
+ properties: {
43
+ current: F32Schema,
44
+ max: F32Schema,
45
+ }
46
+ } as const satisfies Schema;
47
+ type Health = FromSchema<typeof healthSchema>;
48
+
49
+ const nameSchema = {
50
+ type: "string",
51
+ maxLength: 50,
52
+ } as const satisfies Schema;
53
+ type Name = FromSchema<typeof nameSchema>;
54
+
55
+ function createTestObservableStore() {
56
+ const baseStore = createStore(
57
+ { position: positionSchema, health: healthSchema, name: nameSchema },
58
+ { time: { delta: 0.016, elapsed: 0 } }
59
+ );
60
+
61
+ return createDatabase(baseStore, {
62
+ createPositionEntity(db, args: { position: { x: number, y: number, z: number } }) {
63
+ const archetype = db.ensureArchetype(["id", "position"]);
64
+ return archetype.insert(args);
65
+ },
66
+ createPositionHealthEntity(db, args: { position: { x: number, y: number, z: number }, health: { current: number, max: number } }) {
67
+ const archetype = db.ensureArchetype(["id", "position", "health"]);
68
+ return archetype.insert(args);
69
+ },
70
+ createPositionNameEntity(db, args: { position: { x: number, y: number, z: number }, name: string }) {
71
+ const archetype = db.ensureArchetype(["id", "position", "name"]);
72
+ return archetype.insert(args);
73
+ },
74
+ createFullEntity(db, args: { position: { x: number, y: number, z: number }, health: { current: number, max: number }, name: string }) {
75
+ const archetype = db.ensureArchetype(["id", "position", "health", "name"]);
76
+ return archetype.insert(args);
77
+ },
78
+ createEntityAndReturn(db, args: { position: Position, name: Name }) {
79
+ const archetype = db.ensureArchetype(["id", "position", "name"]);
80
+ const entity = archetype.insert(args);
81
+ return entity;
82
+ },
83
+ updateEntity(db, args: {
84
+ entity: Entity,
85
+ values: Partial<{
86
+ position: { x: number, y: number, z: number },
87
+ health: { current: number, max: number },
88
+ name: string
89
+ }>
90
+ }) {
91
+ db.update(args.entity, args.values);
92
+ },
93
+ deleteEntity(db, args: { entity: Entity }) {
94
+ db.delete(args.entity);
95
+ },
96
+ updateTime(db, args: { delta: number, elapsed: number }) {
97
+ db.resources.time = args;
98
+ }
99
+ });
100
+ }
101
+
102
+ describe("createDatabase", () => {
103
+ it("should notify component observers when components change", () => {
104
+ const store = createTestObservableStore();
105
+ const positionObserver = vi.fn();
106
+ const nameObserver = vi.fn();
107
+
108
+ // Subscribe to component changes
109
+ const unsubscribePosition = store.observe.component.position(positionObserver);
110
+ const unsubscribeName = store.observe.component.name(nameObserver);
111
+
112
+ // Create an entity that affects both components
113
+ const testEntity = store.transactions.createFullEntity({
114
+ position: { x: 1, y: 2, z: 3 },
115
+ name: "Test",
116
+ health: { current: 100, max: 100 }
117
+ });
118
+
119
+ // Both observers should be notified
120
+ expect(positionObserver).toHaveBeenCalledTimes(1);
121
+ expect(nameObserver).toHaveBeenCalledTimes(1);
122
+
123
+ // Update only position
124
+ store.transactions.updateEntity({
125
+ entity: testEntity,
126
+ values: { position: { x: 4, y: 5, z: 6 } }
127
+ });
128
+
129
+ // Only position observer should be notified
130
+ expect(positionObserver).toHaveBeenCalledTimes(2);
131
+ expect(nameObserver).toHaveBeenCalledTimes(1);
132
+
133
+ // Unsubscribe and verify no more notifications
134
+ unsubscribePosition();
135
+ unsubscribeName();
136
+
137
+ store.transactions.updateEntity({
138
+ entity: testEntity,
139
+ values: { position: { x: 7, y: 8, z: 9 }, name: "Updated" }
140
+ });
141
+
142
+ expect(positionObserver).toHaveBeenCalledTimes(2);
143
+ expect(nameObserver).toHaveBeenCalledTimes(1);
144
+ });
145
+
146
+ it("should notify entity observers with correct values", () => {
147
+ const store = createTestObservableStore();
148
+
149
+ // Create initial entity
150
+ const testEntity = store.transactions.createFullEntity({
151
+ position: { x: 1, y: 2, z: 3 },
152
+ name: "Test",
153
+ health: { current: 100, max: 100 }
154
+ });
155
+
156
+ // Subscribe to entity changes
157
+ const observer = vi.fn();
158
+ const unsubscribe = store.observe.entity(testEntity)(observer);
159
+
160
+ // Initial notification should have current values
161
+ expect(observer).toHaveBeenCalledWith(expect.objectContaining({
162
+ position: { x: 1, y: 2, z: 3 },
163
+ name: "Test",
164
+ health: { current: 100, max: 100 }
165
+ }));
166
+
167
+ // Update entity
168
+ store.transactions.updateEntity({
169
+ entity: testEntity,
170
+ values: { name: "Updated", health: { current: 50, max: 100 } }
171
+ });
172
+
173
+ // Observer should be notified with new values
174
+ expect(observer).toHaveBeenCalledWith(expect.objectContaining({
175
+ position: { x: 1, y: 2, z: 3 }, // unchanged
176
+ name: "Updated",
177
+ health: { current: 50, max: 100 }
178
+ }));
179
+
180
+ // Delete entity
181
+ store.transactions.deleteEntity({ entity: testEntity });
182
+
183
+ // Observer should be notified with null
184
+ expect(observer).toHaveBeenCalledWith(null);
185
+
186
+ unsubscribe();
187
+ });
188
+
189
+ it("should notify transaction observers with full transaction results", () => {
190
+ const store = createTestObservableStore();
191
+ const transactionObserver = vi.fn();
192
+
193
+ const unsubscribe = store.observe.transactions(transactionObserver);
194
+
195
+ // Execute a transaction with multiple operations
196
+ store.transactions.createFullEntity({
197
+ position: { x: 1, y: 2, z: 3 },
198
+ name: "Test",
199
+ health: { current: 100, max: 100 }
200
+ });
201
+
202
+ // Transaction observer should be called with the full result
203
+ expect(transactionObserver).toHaveBeenCalledWith(expect.objectContaining({
204
+ changedEntities: expect.any(Set),
205
+ changedComponents: expect.any(Set),
206
+ changedArchetypes: expect.any(Set),
207
+ redo: expect.any(Array),
208
+ undo: expect.any(Array)
209
+ }));
210
+
211
+ const result = transactionObserver.mock.calls[0][0];
212
+ expect(result.changedEntities.size).toBe(1);
213
+ expect(result.changedComponents.has("position")).toBe(true);
214
+ expect(result.changedComponents.has("name")).toBe(true);
215
+
216
+ unsubscribe();
217
+ });
218
+
219
+ it("should notify archetype observers when entities change archetypes", () => {
220
+ const store = createTestObservableStore();
221
+
222
+ // Create initial entity
223
+ const entity = store.transactions.createPositionEntity({
224
+ position: { x: 1, y: 2, z: 3 }
225
+ });
226
+
227
+ const archetype = store.locate(entity)?.archetype;
228
+ expect(archetype).toBeDefined();
229
+
230
+ const archetypeObserver = vi.fn();
231
+ const unsubscribe = store.observe.archetype(archetype!)(archetypeObserver);
232
+
233
+ // No initial notification for archetype observers
234
+ expect(archetypeObserver).toHaveBeenCalledTimes(0);
235
+
236
+ // Update entity to add name component, potentially changing archetype
237
+ store.transactions.updateEntity({
238
+ entity,
239
+ values: { name: "Test" }
240
+ });
241
+
242
+ // Archetype observer should be notified of the change
243
+ expect(archetypeObserver).toHaveBeenCalledTimes(1);
244
+
245
+ unsubscribe();
246
+ });
247
+
248
+ it("should notify resource observers with immediate and update notifications", () => {
249
+ const store = createTestObservableStore();
250
+
251
+ const timeObserver = vi.fn();
252
+
253
+ // Subscribe to resource changes
254
+ const unsubscribeTime = store.observe.resource.time(timeObserver);
255
+
256
+ // Observer should be notified immediately with initial value
257
+ expect(timeObserver).toHaveBeenCalledWith({ delta: 0.016, elapsed: 0 });
258
+
259
+ // Update time resource
260
+ store.transactions.updateTime({ delta: 0.032, elapsed: 1 });
261
+
262
+ // Observer should be notified with new value
263
+ expect(timeObserver).toHaveBeenCalledWith({ delta: 0.032, elapsed: 1 });
264
+ });
265
+
266
+ it("should support multiple observers for the same target", () => {
267
+ const store = createTestObservableStore();
268
+
269
+ const observer1 = vi.fn();
270
+ const observer2 = vi.fn();
271
+ const observer3 = vi.fn();
272
+
273
+ // Subscribe multiple observers to the same component
274
+ const unsubscribe1 = store.observe.component.position(observer1);
275
+ const unsubscribe2 = store.observe.component.position(observer2);
276
+ const unsubscribe3 = store.observe.component.position(observer3);
277
+
278
+ // Create entity with position
279
+ const entity = store.transactions.createPositionEntity({
280
+ position: { x: 1, y: 2, z: 3 }
281
+ });
282
+
283
+ // All observers should be notified
284
+ expect(observer1).toHaveBeenCalledTimes(1);
285
+ expect(observer2).toHaveBeenCalledTimes(1);
286
+ expect(observer3).toHaveBeenCalledTimes(1);
287
+
288
+ // Unsubscribe one observer
289
+ unsubscribe2();
290
+
291
+ // Update position
292
+ store.transactions.updateEntity({
293
+ entity,
294
+ values: { position: { x: 4, y: 5, z: 6 } }
295
+ });
296
+
297
+ // Only remaining observers should be notified
298
+ expect(observer1).toHaveBeenCalledTimes(2);
299
+ expect(observer2).toHaveBeenCalledTimes(1); // No more calls
300
+ expect(observer3).toHaveBeenCalledTimes(2);
301
+
302
+ unsubscribe1();
303
+ unsubscribe3();
304
+ });
305
+
306
+ it("should handle observer cleanup correctly", () => {
307
+ const store = createTestObservableStore();
308
+
309
+ const observer = vi.fn();
310
+ const unsubscribe = store.observe.component.position(observer);
311
+
312
+ // Create entity
313
+ const entity = store.transactions.createPositionEntity({
314
+ position: { x: 1, y: 2, z: 3 }
315
+ });
316
+
317
+ expect(observer).toHaveBeenCalledTimes(1);
318
+
319
+ // Unsubscribe
320
+ unsubscribe();
321
+
322
+ // Update entity
323
+ store.transactions.updateEntity({
324
+ entity,
325
+ values: { position: { x: 4, y: 5, z: 6 } }
326
+ });
327
+
328
+ // Observer should not be called after unsubscribe
329
+ expect(observer).toHaveBeenCalledTimes(1);
330
+ });
331
+
332
+ it("should handle observing non-existent entities", () => {
333
+ const store = createTestObservableStore();
334
+
335
+ const observer = vi.fn();
336
+ const unsubscribe = store.observe.entity(999 as Entity)(observer);
337
+
338
+ // Should be notified with null for non-existent entity
339
+ expect(observer).toHaveBeenCalledWith(null);
340
+
341
+ unsubscribe();
342
+ });
343
+
344
+ it("should handle complex transaction scenarios with multiple observers", () => {
345
+ const store = createTestObservableStore();
346
+
347
+ const positionObserver = vi.fn();
348
+ const healthObserver = vi.fn();
349
+ const transactionObserver = vi.fn();
350
+ const entityObserver = vi.fn();
351
+
352
+ // Subscribe to various observers
353
+ const unsubscribePosition = store.observe.component.position(positionObserver);
354
+ const unsubscribeHealth = store.observe.component.health(healthObserver);
355
+ const unsubscribeTransaction = store.observe.transactions(transactionObserver);
356
+
357
+ // Create entity
358
+ const entity = store.transactions.createPositionHealthEntity({
359
+ position: { x: 1, y: 2, z: 3 },
360
+ health: { current: 100, max: 100 }
361
+ });
362
+
363
+ const unsubscribeEntity = store.observe.entity(entity)(entityObserver);
364
+
365
+ // All observers should be notified
366
+ expect(positionObserver).toHaveBeenCalledTimes(1);
367
+ expect(healthObserver).toHaveBeenCalledTimes(1);
368
+ expect(transactionObserver).toHaveBeenCalledTimes(1);
369
+ expect(entityObserver).toHaveBeenCalledTimes(1);
370
+
371
+ // Update multiple components
372
+ store.transactions.updateEntity({
373
+ entity,
374
+ values: {
375
+ position: { x: 4, y: 5, z: 6 },
376
+ health: { current: 50, max: 100 }
377
+ }
378
+ });
379
+
380
+ // All observers should be notified again
381
+ expect(positionObserver).toHaveBeenCalledTimes(2);
382
+ expect(healthObserver).toHaveBeenCalledTimes(2);
383
+ expect(transactionObserver).toHaveBeenCalledTimes(2);
384
+ expect(entityObserver).toHaveBeenCalledTimes(2);
385
+
386
+ // Verify entity observer received correct values
387
+ expect(entityObserver).toHaveBeenCalledWith(expect.objectContaining({
388
+ position: { x: 4, y: 5, z: 6 },
389
+ health: { current: 50, max: 100 }
390
+ }));
391
+
392
+ unsubscribePosition();
393
+ unsubscribeHealth();
394
+ unsubscribeTransaction();
395
+ unsubscribeEntity();
396
+ });
397
+
398
+ it("should handle rapid successive changes efficiently", () => {
399
+ const store = createTestObservableStore();
400
+
401
+ const observer = vi.fn();
402
+ const unsubscribe = store.observe.component.position(observer);
403
+
404
+ // Create entity
405
+ const entity = store.transactions.createPositionEntity({
406
+ position: { x: 1, y: 2, z: 3 }
407
+ });
408
+
409
+ // Make rapid successive updates
410
+ for (let i = 0; i < 5; i++) {
411
+ store.transactions.updateEntity({
412
+ entity,
413
+ values: { position: { x: i, y: i, z: i } }
414
+ });
415
+ }
416
+
417
+ // Observer should be called for each change
418
+ expect(observer).toHaveBeenCalledTimes(6); // 1 for create + 5 for updates
419
+
420
+ unsubscribe();
421
+ });
422
+
423
+ it("should support transaction functions that return an Entity", () => {
424
+ const store = createTestObservableStore();
425
+
426
+ // Execute a transaction that returns an Entity
427
+ const returnedEntity = store.transactions.createEntityAndReturn({
428
+ position: { x: 10, y: 20, z: 30 },
429
+ name: "ReturnedEntity"
430
+ });
431
+
432
+ // Verify that an Entity was returned
433
+ expect(returnedEntity).toBeDefined();
434
+ expect(typeof returnedEntity).toBe("number");
435
+
436
+ // Verify the entity exists in the store
437
+ const entityValues = store.read(returnedEntity);
438
+ expect(entityValues).toBeDefined();
439
+ expect(entityValues?.position).toEqual({ x: 10, y: 20, z: 30 });
440
+ expect(entityValues?.name).toBe("ReturnedEntity");
441
+
442
+ // Verify the entity can be found in the store using select
443
+ const selectedEntities = store.select(["id", "position", "name"]);
444
+ expect(selectedEntities).toContain(returnedEntity);
445
+ });
446
+
447
+ describe("AsyncArgs Support", () => {
448
+ it("should handle Promise-based async arguments", async () => {
449
+ const store = createTestObservableStore();
450
+ const observer = vi.fn();
451
+ const unsubscribe = store.observe.component.position(observer);
452
+
453
+ // Create a promise that resolves to entity data
454
+ const entityDataPromise = Promise.resolve({
455
+ position: { x: 100, y: 200, z: 300 },
456
+ name: "AsyncEntity"
457
+ });
458
+
459
+ // Execute transaction with promise argument wrapped in function
460
+ store.transactions.createPositionNameEntity(() => entityDataPromise);
461
+
462
+ // Wait for the promise to resolve
463
+ await new Promise(resolve => setTimeout(resolve, 0));
464
+
465
+ // Verify the entity was created with the resolved data
466
+ const entities = store.select(["id", "position", "name"]);
467
+ const createdEntity = entities.find(entityId => {
468
+ const values = store.read(entityId);
469
+ return values?.name === "AsyncEntity";
470
+ });
471
+
472
+ expect(createdEntity).toBeDefined();
473
+ const entityValues = store.read(createdEntity!);
474
+ expect(entityValues?.position).toEqual({ x: 100, y: 200, z: 300 });
475
+ expect(entityValues?.name).toBe("AsyncEntity");
476
+
477
+ // Verify observer was notified
478
+ expect(observer).toHaveBeenCalledTimes(1);
479
+
480
+ unsubscribe();
481
+ });
482
+
483
+ it("should handle AsyncGenerator streaming arguments", async () => {
484
+ const store = createTestObservableStore();
485
+ const observer = vi.fn();
486
+ const unsubscribe = store.observe.component.position(observer);
487
+
488
+ // Create an async generator that yields multiple entity data
489
+ async function* entityDataStream() {
490
+ yield { position: { x: 1, y: 1, z: 1 }, name: "Stream1" };
491
+ yield { position: { x: 2, y: 2, z: 2 }, name: "Stream2" };
492
+ yield { position: { x: 3, y: 3, z: 3 }, name: "Stream3" };
493
+ }
494
+
495
+ // Execute transaction with async generator wrapped in function
496
+ store.transactions.createPositionNameEntity(() => entityDataStream());
497
+
498
+ // Wait for all entities to be processed
499
+ await new Promise(resolve => setTimeout(resolve, 10));
500
+
501
+ // Verify all entities were created
502
+ const entities = store.select(["id", "position", "name"]);
503
+ const streamEntities = entities.filter(entityId => {
504
+ const values = store.read(entityId);
505
+ return values?.name?.startsWith("Stream");
506
+ });
507
+
508
+ expect(streamEntities).toHaveLength(3);
509
+
510
+ // Verify each entity has correct data
511
+ const entity1 = store.read(streamEntities[0]);
512
+ const entity2 = store.read(streamEntities[1]);
513
+ const entity3 = store.read(streamEntities[2]);
514
+
515
+ expect(entity1?.position).toEqual({ x: 1, y: 1, z: 1 });
516
+ expect(entity1?.name).toBe("Stream1");
517
+ expect(entity2?.position).toEqual({ x: 2, y: 2, z: 2 });
518
+ expect(entity2?.name).toBe("Stream2");
519
+ expect(entity3?.position).toEqual({ x: 3, y: 3, z: 3 });
520
+ expect(entity3?.name).toBe("Stream3");
521
+
522
+ // Verify observer was notified for each entity
523
+ expect(observer).toHaveBeenCalledTimes(3);
524
+
525
+ unsubscribe();
526
+ });
527
+
528
+ it("should handle AsyncGenerator with delays", async () => {
529
+ const store = createTestObservableStore();
530
+ const observer = vi.fn();
531
+ const unsubscribe = store.observe.component.position(observer);
532
+
533
+ // Create an async generator with delays
534
+ async function* delayedEntityStream() {
535
+ yield { position: { x: 10, y: 10, z: 10 }, name: "Delayed1" };
536
+ await new Promise(resolve => setTimeout(resolve, 5));
537
+ yield { position: { x: 20, y: 20, z: 20 }, name: "Delayed2" };
538
+ await new Promise(resolve => setTimeout(resolve, 5));
539
+ yield { position: { x: 30, y: 30, z: 30 }, name: "Delayed3" };
540
+ }
541
+
542
+ // Execute transaction with delayed async generator wrapped in function
543
+ store.transactions.createPositionNameEntity(() => delayedEntityStream());
544
+
545
+ // Wait for all entities to be processed
546
+ await new Promise(resolve => setTimeout(resolve, 20));
547
+
548
+ // Verify all entities were created
549
+ const entities = store.select(["id", "position", "name"]);
550
+ const delayedEntities = entities.filter(entityId => {
551
+ const values = store.read(entityId);
552
+ return values?.name?.startsWith("Delayed");
553
+ });
554
+
555
+ expect(delayedEntities).toHaveLength(3);
556
+ expect(observer).toHaveBeenCalledTimes(3);
557
+
558
+ unsubscribe();
559
+ });
560
+
561
+ it("should handle mixed sync and async arguments in the same transaction", async () => {
562
+ const store = createTestObservableStore();
563
+ const observer = vi.fn();
564
+ const unsubscribe = store.observe.component.position(observer);
565
+
566
+ // Create entities with different argument types
567
+ store.transactions.createPositionNameEntity({
568
+ position: { x: 1, y: 1, z: 1 },
569
+ name: "SyncEntity"
570
+ });
571
+
572
+ store.transactions.createPositionNameEntity(
573
+ () => Promise.resolve({
574
+ position: { x: 2, y: 2, z: 2 },
575
+ name: "PromiseEntity"
576
+ })
577
+ );
578
+
579
+ async function* streamEntityGenerator() {
580
+ yield { position: { x: 3, y: 3, z: 3 }, name: "StreamEntity" };
581
+ }
582
+
583
+ store.transactions.createPositionNameEntity(() => streamEntityGenerator());
584
+
585
+ // Wait for async operations
586
+ await new Promise(resolve => setTimeout(resolve, 10));
587
+
588
+ // Verify all entities were created
589
+ const entities = store.select(["id", "position", "name"]);
590
+ const testEntities = entities.filter(entityId => {
591
+ const values = store.read(entityId);
592
+ return values?.name?.endsWith("Entity");
593
+ });
594
+
595
+ expect(testEntities).toHaveLength(3);
596
+
597
+ const syncEntity = store.read(testEntities.find(e => store.read(e)?.name === "SyncEntity")!);
598
+ const promiseEntity = store.read(testEntities.find(e => store.read(e)?.name === "PromiseEntity")!);
599
+ const streamEntity = store.read(testEntities.find(e => store.read(e)?.name === "StreamEntity")!);
600
+
601
+ expect(syncEntity?.position).toEqual({ x: 1, y: 1, z: 1 });
602
+ expect(promiseEntity?.position).toEqual({ x: 2, y: 2, z: 2 });
603
+ expect(streamEntity?.position).toEqual({ x: 3, y: 3, z: 3 });
604
+
605
+ expect(observer).toHaveBeenCalledTimes(3);
606
+
607
+ unsubscribe();
608
+ });
609
+
610
+ it("should handle AsyncGenerator that yields no values", async () => {
611
+ const store = createTestObservableStore();
612
+ const observer = vi.fn();
613
+ const unsubscribe = store.observe.component.position(observer);
614
+
615
+ // Create an empty async generator
616
+ async function* emptyStream() {
617
+ // Yields nothing
618
+ }
619
+
620
+ // Execute transaction with empty async generator wrapped in function
621
+ store.transactions.createPositionNameEntity(() => emptyStream());
622
+
623
+ // Wait for processing
624
+ await new Promise(resolve => setTimeout(resolve, 10));
625
+
626
+ // Verify no entities were created
627
+ const entities = store.select(["id", "position", "name"]);
628
+ expect(entities).toHaveLength(0);
629
+ expect(observer).toHaveBeenCalledTimes(0);
630
+
631
+ unsubscribe();
632
+ });
633
+
634
+ it("should handle AsyncGenerator with error handling", async () => {
635
+ const store = createTestObservableStore();
636
+ const observer = vi.fn();
637
+ const unsubscribe = store.observe.component.position(observer);
638
+
639
+ // Create an async generator that throws an error
640
+ async function* errorStream() {
641
+ yield { position: { x: 1, y: 1, z: 1 }, name: "BeforeError" };
642
+ throw new Error("Test error");
643
+ }
644
+
645
+ // Execute transaction with error-throwing async generator wrapped in function
646
+ store.transactions.createPositionNameEntity(() => errorStream());
647
+
648
+ // Wait for processing
649
+ await new Promise(resolve => setTimeout(resolve, 10));
650
+
651
+ // Verify only the first entity was created before the error
652
+ const entities = store.select(["id", "position", "name"]);
653
+ const beforeErrorEntity = entities.find(entityId => {
654
+ const values = store.read(entityId);
655
+ return values?.name === "BeforeError";
656
+ });
657
+
658
+ expect(beforeErrorEntity).toBeDefined();
659
+ expect(observer).toHaveBeenCalledTimes(1);
660
+
661
+ unsubscribe();
662
+ });
663
+
664
+ it("should handle complex AsyncGenerator with conditional yielding", async () => {
665
+ const store = createTestObservableStore();
666
+ const observer = vi.fn();
667
+ const unsubscribe = store.observe.component.position(observer);
668
+
669
+ // Create a complex async generator with conditional logic
670
+ async function* conditionalStream() {
671
+ for (let i = 0; i < 5; i++) {
672
+ if (i % 2 === 0) {
673
+ yield {
674
+ position: { x: i, y: i * 2, z: i * 3 },
675
+ name: `Even${i}`
676
+ };
677
+ }
678
+ await new Promise(resolve => setTimeout(resolve, 1));
679
+ }
680
+ }
681
+
682
+ // Execute transaction with conditional async generator wrapped in function
683
+ store.transactions.createPositionNameEntity(() => conditionalStream());
684
+
685
+ // Wait for processing
686
+ await new Promise(resolve => setTimeout(resolve, 20));
687
+
688
+ // Verify only even-numbered entities were created
689
+ const entities = store.select(["id", "position", "name"]);
690
+ const evenEntities = entities.filter(entityId => {
691
+ const values = store.read(entityId);
692
+ return values?.name?.startsWith("Even");
693
+ });
694
+
695
+ expect(evenEntities).toHaveLength(3); // Even 0, 2, 4
696
+
697
+ // Verify correct data for each entity
698
+ const even0 = store.read(evenEntities.find(e => store.read(e)?.name === "Even0")!);
699
+ const even2 = store.read(evenEntities.find(e => store.read(e)?.name === "Even2")!);
700
+ const even4 = store.read(evenEntities.find(e => store.read(e)?.name === "Even4")!);
701
+
702
+ expect(even0?.position).toEqual({ x: 0, y: 0, z: 0 });
703
+ expect(even2?.position).toEqual({ x: 2, y: 4, z: 6 });
704
+ expect(even4?.position).toEqual({ x: 4, y: 8, z: 12 });
705
+
706
+ expect(observer).toHaveBeenCalledTimes(3);
707
+
708
+ unsubscribe();
709
+ });
710
+
711
+ it("should maintain transaction integrity with async operations", async () => {
712
+ const store = createTestObservableStore();
713
+ const transactionObserver = vi.fn();
714
+ const unsubscribe = store.observe.transactions(transactionObserver);
715
+
716
+ // Create a promise that resolves to entity data
717
+ const entityDataPromise = Promise.resolve({
718
+ position: { x: 100, y: 200, z: 300 },
719
+ name: "TransactionTest"
720
+ });
721
+
722
+ // Execute transaction with promise wrapped in function
723
+ store.transactions.createPositionNameEntity(() => entityDataPromise);
724
+
725
+ // Wait for the promise to resolve
726
+ await new Promise(resolve => setTimeout(resolve, 10));
727
+
728
+ // Verify transaction observer was called with proper transaction result
729
+ expect(transactionObserver).toHaveBeenCalledWith(expect.objectContaining({
730
+ changedEntities: expect.any(Set),
731
+ changedComponents: expect.any(Set),
732
+ changedArchetypes: expect.any(Set),
733
+ redo: expect.any(Array),
734
+ undo: expect.any(Array)
735
+ }));
736
+
737
+ const result = transactionObserver.mock.calls[0][0];
738
+ expect(result.changedEntities.size).toBe(1);
739
+ expect(result.changedComponents.has("position")).toBe(true);
740
+ expect(result.changedComponents.has("name")).toBe(true);
741
+
742
+ unsubscribe();
743
+ });
744
+ });
745
+ });