@adobe/data 0.1.3 → 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.
- package/.cursorrules +28 -0
- package/.eslintrc.cjs +48 -0
- package/.github/CONTRIBUTING.md +47 -0
- package/CODE_OF_CONDUCT.md +79 -0
- package/LICENSE +21 -0
- package/README.md +2 -2
- package/asconfig.json +22 -0
- package/assembly/index.ts +85 -0
- package/assembly/tsconfig.json +17 -0
- package/c/build_run.sh +2 -0
- package/c/vector_addition +0 -0
- package/c/vector_addition.c +125 -0
- package/{cache/functions/types.js → config/license.js} +0 -2
- package/docs/perftest.html +28 -0
- package/index.html +10 -0
- package/package.json +49 -27
- package/scripts/deploy-docs.sh +41 -0
- package/{assembly-test/assembly.test.js → src/assembly-test/assembly.test.ts} +4 -4
- package/src/cache/async-cache.ts +38 -0
- package/{cache/blob-store.test.js → src/cache/blob-store.test.ts} +41 -7
- package/src/cache/blob-store.ts +278 -0
- package/src/cache/data-cache.test.ts +61 -0
- package/src/cache/data-cache.ts +183 -0
- package/src/cache/expiring-data-cache.test.ts +81 -0
- package/src/cache/expiring-data-cache.ts +61 -0
- package/src/cache/fallback-async-cache.ts +49 -0
- package/src/cache/functions/async-data-function.ts +25 -0
- package/src/cache/functions/functions.test.ts +84 -0
- package/{cache/functions/get-cached.test.js → src/cache/functions/get-cached.test.ts} +24 -7
- package/{cache/functions/get-cached.js → src/cache/functions/get-cached.ts} +12 -6
- package/{cache/functions/hashing/blob-to-hash.js → src/cache/functions/hashing/blob-to-hash.ts} +20 -18
- package/{cache/functions/hashing/buffer-to-hash.js → src/cache/functions/hashing/buffer-to-hash.ts} +7 -7
- package/src/cache/functions/hashing/hashing.test.ts +95 -0
- package/{cache/functions/hashing/index.js → src/cache/functions/hashing/index.ts} +1 -1
- package/{cache/functions/hashing/json-to-hash.js → src/cache/functions/hashing/json-to-hash.ts} +3 -3
- package/{cache/functions/hashing/string-to-hash.js → src/cache/functions/hashing/string-to-hash.ts} +11 -10
- package/{cache/functions/index.js → src/cache/functions/index.ts} +2 -4
- package/{cache/functions/memoize.js → src/cache/functions/memoize.ts} +22 -15
- package/src/cache/functions/prevent-parallel-execution.ts +50 -0
- package/src/cache/get-persistent-cache.ts +62 -0
- package/{cache/index.js → src/cache/index.ts} +9 -3
- package/src/cache/managed-array.ts +243 -0
- package/{cache/managed-async-cache.browser.test.js → src/cache/managed-async-cache.browser.test.ts} +27 -24
- package/src/cache/managed-async-cache.ts +78 -0
- package/src/cache/memory-allocator.ts +176 -0
- package/src/cache/memory-async-cache.ts +51 -0
- package/src/data.ts +38 -0
- package/src/ecs/README.md +21 -0
- package/src/ecs/archetype/archetype.ts +39 -0
- package/src/ecs/archetype/create-archetype.test.ts +115 -0
- package/src/ecs/archetype/create-archetype.ts +52 -0
- package/src/ecs/archetype/delete-row.test.ts +110 -0
- package/src/ecs/archetype/delete-row.ts +37 -0
- package/src/ecs/archetype/index.ts +24 -0
- package/src/ecs/component-schemas.ts +24 -0
- package/src/ecs/core-components.ts +443 -0
- package/src/ecs/database/create-database.test.ts +745 -0
- package/src/ecs/database/create-database.ts +205 -0
- package/src/ecs/database/database.ts +81 -0
- package/src/ecs/database/index.ts +24 -0
- package/src/ecs/database/observe-dependent-value.test.ts +198 -0
- package/src/ecs/database/observe-dependent-value.ts +78 -0
- package/src/ecs/database/transactional-store/create-transactional-store.test.ts +250 -0
- package/src/ecs/database/transactional-store/create-transactional-store.ts +281 -0
- package/{ecs/ecs/ecs-types.js → src/ecs/database/transactional-store/index.ts} +1 -2
- package/src/ecs/database/transactional-store/transactional-store.ts +80 -0
- package/src/ecs/entity-location-table/create-entity-location-table.test.ts +170 -0
- package/src/ecs/entity-location-table/create-entity-location-table.ts +96 -0
- package/src/ecs/entity-location-table/entity-location-table.ts +30 -0
- package/{core/schema/schema.js → src/ecs/entity-location-table/entity-location.ts} +11 -11
- package/src/ecs/entity-location-table/index.ts +23 -0
- package/src/ecs/entity.ts +26 -0
- package/src/ecs/index.ts +26 -0
- package/src/ecs/store/core/core.ts +71 -0
- package/src/ecs/store/core/create-core.test.ts +440 -0
- package/src/ecs/store/core/create-core.ts +168 -0
- package/{cache/async-cache.js → src/ecs/store/core/index.ts} +1 -2
- package/src/ecs/store/create-store.test.ts +562 -0
- package/src/ecs/store/create-store.ts +97 -0
- package/src/ecs/store/index.ts +23 -0
- package/{types/types.js → src/ecs/store/resource-components.ts} +2 -6
- package/src/ecs/store/store.ts +55 -0
- package/src/equals-shallow.test.ts +133 -0
- package/src/equals-shallow.ts +37 -0
- package/src/equals.test.ts +175 -0
- package/src/equals.ts +70 -0
- package/src/index.ts +27 -0
- package/src/internal/array-buffer-like/copy.ts +469 -0
- package/src/internal/array-buffer-like/grow.ts +53 -0
- package/{core/index.js → src/internal/array-buffer-like/index.ts} +4 -4
- package/src/internal/array-buffer-like/is-array-buffer.ts +445 -0
- package/src/internal/array-buffer-like/is-shared-array-buffer.ts +445 -0
- package/{core/functions/is-async-generator.js → src/internal/async-generator/is-async-generator.ts} +2 -2
- package/{core/schema.js → src/internal/data-view-32/create-data-view-32.ts} +8 -11
- package/src/internal/data-view-32/data-view-32.ts +447 -0
- package/{ecs/action-ecs/index.js → src/internal/data-view-32/index.ts} +2 -2
- package/src/internal/function/memoize-factory.ts +12 -0
- package/src/internal/object/index.ts +23 -0
- package/{cache/functions/bind-functions.js → src/internal/object/map-entries.ts} +6 -11
- package/src/internal/promise/is-promise.ts +28 -0
- package/src/internal/typed-array/get-byte-size.ts +50 -0
- package/src/internal/typed-array/index.ts +24 -0
- package/src/internal/typed-array/typed-array-constructer.ts +32 -0
- package/src/internal/typed-array/typed-array.ts +25 -0
- package/src/is-data.ts +47 -0
- package/src/lit/decorators/apply-decorator.ts +24 -0
- package/src/lit/decorators/apply-service-decorators.ts +13 -0
- package/src/lit/decorators/index.ts +24 -0
- package/src/lit/decorators/require-service.ts +19 -0
- package/src/lit/elements/index.ts +3 -0
- package/src/lit/elements/service-application.ts +26 -0
- package/src/lit/elements/service-context.ts +3 -0
- package/src/lit/elements/service-element.ts +18 -0
- package/src/lit/hooks/component/component.ts +10 -0
- package/src/lit/hooks/component/stack.ts +17 -0
- package/src/lit/hooks/index.ts +13 -0
- package/src/lit/hooks/use-connected.ts +39 -0
- package/src/lit/hooks/use-effect.ts +17 -0
- package/src/lit/hooks/use-element.ts +8 -0
- package/src/lit/hooks/use-memo.ts +14 -0
- package/src/lit/hooks/use-observable-values.ts +9 -0
- package/src/lit/hooks/use-observable.ts +13 -0
- package/src/lit/hooks/use-ref.ts +6 -0
- package/src/lit/hooks/use-resize-observer.ts +27 -0
- package/src/lit/hooks/use-state.ts +17 -0
- package/src/lit/hooks/use-window-event.ts +14 -0
- package/src/lit/hooks/with-hooks.ts +20 -0
- package/src/lit/index.ts +3 -0
- package/src/mutable-clone.ts +29 -0
- package/{core/data.test.js → src/normalize.test.ts} +22 -22
- package/src/normalize.ts +37 -0
- package/src/observe/create-observable-event.ts +47 -0
- package/src/observe/create-observable-state.ts +51 -0
- package/src/observe/create-persisted-state.test.ts +143 -0
- package/src/observe/create-persisted-state.ts +60 -0
- package/src/observe/create-query-state.ts +70 -0
- package/{observe/from-array.js → src/observe/from-array.ts} +14 -3
- package/{service/service.js → src/observe/from-constant.ts} +13 -4
- package/{observe/from-element-id.js → src/observe/from-element-id.ts} +44 -39
- package/src/observe/from-element-properties-and-events.ts +47 -0
- package/{observe/from-element-property.js → src/observe/from-element-property.ts} +33 -25
- package/src/observe/from-promise-with-error.ts +51 -0
- package/src/observe/from-promise.ts +49 -0
- package/src/observe/from-properties.ts +67 -0
- package/{observe/index.js → src/observe/index.ts} +4 -1
- package/src/observe/observe.test.ts +467 -0
- package/src/observe/to-promise.ts +40 -0
- package/src/observe/to-properties.ts +41 -0
- package/src/observe/types.ts +40 -0
- package/src/observe/with-async-map.ts +37 -0
- package/src/observe/with-batch.test.ts +141 -0
- package/src/observe/with-batch.ts +67 -0
- package/{core/data.js → src/observe/with-cache.ts} +32 -26
- package/src/observe/with-copy.ts +32 -0
- package/src/observe/with-deduplicate-data.ts +43 -0
- package/src/observe/with-deduplicate.ts +41 -0
- package/src/observe/with-default.ts +48 -0
- package/src/observe/with-lazy.test.ts +68 -0
- package/{core/functions/is-promise.js → src/observe/with-lazy.ts} +17 -5
- package/{observe/with-map-data.js → src/observe/with-map-data.ts} +9 -3
- package/src/observe/with-map.ts +36 -0
- package/src/observe/with-optional.ts +47 -0
- package/src/observe/with-unwrap.ts +54 -0
- package/src/old-ecs/action-ecs/action-ecs.test.ts +420 -0
- package/src/old-ecs/action-ecs/action-ecs.ts +274 -0
- package/src/old-ecs/action-ecs/action-types.ts +178 -0
- package/src/old-ecs/action-ecs/index.ts +29 -0
- package/{service/sequential-action.js → src/old-ecs/action-ecs/sequential-action.ts} +19 -4
- package/src/old-ecs/core-ecs/core-ecs-serialization.test.ts +244 -0
- package/src/old-ecs/core-ecs/core-ecs-types.ts +183 -0
- package/src/old-ecs/core-ecs/core-ecs.test.ts +474 -0
- package/src/old-ecs/core-ecs/core-ecs.ts +640 -0
- package/{core/functions/index.js → src/old-ecs/core-ecs/index.ts} +9 -4
- package/src/old-ecs/ecs/ecs-types.ts +189 -0
- package/src/old-ecs/ecs/ecs-where-functions.ts +95 -0
- package/src/old-ecs/ecs/ecs.test.ts +461 -0
- package/src/old-ecs/ecs/ecs.ts +279 -0
- package/{ecs/core-ecs/core-ecs-types.js → src/old-ecs/ecs/index.ts} +2 -2
- package/src/old-ecs/entity.ts +26 -0
- package/{ecs/index.js → src/old-ecs/index.ts} +1 -1
- package/{ecs/transaction-ecs/index.js → src/old-ecs/transaction-ecs/index.ts} +0 -1
- package/src/old-ecs/transaction-ecs/transaction-ecs.test.ts +725 -0
- package/src/old-ecs/transaction-ecs/transaction-ecs.ts +283 -0
- package/src/old-ecs/transaction-ecs/transaction-types.ts +248 -0
- package/src/old-ecs/transaction-ecs/transactions.ts +243 -0
- package/src/perftest/ecs-perf.ts +255 -0
- package/src/perftest/helper-functions.ts +31 -0
- package/src/perftest/horizon-perf.ts +132 -0
- package/{perftest/index.js → src/perftest/index.ts} +9 -7
- package/src/perftest/perf-test.ts +193 -0
- package/src/perftest/perf.md +90 -0
- package/src/perftest/vanilla-perf.ts +136 -0
- package/src/schema/boolean.ts +5 -0
- package/src/schema/dynamic/deep-merge.test.ts +100 -0
- package/src/schema/dynamic/deep-merge.ts +67 -0
- package/{core/schema/dynamic/enumerate-patches.test.js → src/schema/dynamic/enumerate-patches.test.ts} +49 -23
- package/{core/schema/dynamic/enumerate-patches.js → src/schema/dynamic/enumerate-patches.ts} +44 -4
- package/{core/schema/dynamic/get-dynamic-schema.test.js → src/schema/dynamic/get-dynamic-schema.test.ts} +41 -6
- package/src/schema/dynamic/get-dynamic-schema.ts +48 -0
- package/src/schema/dynamic/index.ts +22 -0
- package/src/schema/f32.ts +30 -0
- package/src/schema/i32.ts +31 -0
- package/src/schema/index.ts +32 -0
- package/{cache/functions/omit.js → src/schema/nullable.ts} +10 -7
- package/src/schema/schema.ts +229 -0
- package/src/schema/time.ts +5 -0
- package/src/schema/true.ts +26 -0
- package/src/schema/tuple.ts +5 -0
- package/src/schema/u32.ts +31 -0
- package/{core/schema/validation/is-valid.test.js → src/schema/validation/is-valid.test.ts} +6 -3
- package/{core/functions/array-equals.js → src/schema/validation/is-valid.ts} +8 -10
- package/{core/schema/validation/validate.test.js → src/schema/validation/validate.test.ts} +18 -4
- package/{core/schema/validation/validate.js → src/schema/validation/validate.ts} +9 -6
- package/{core/functions/with-validation.test.js → src/schema/validation/with-validation.test.ts} +28 -12
- package/{core/functions/with-validation.js → src/schema/validation/with-validation.ts} +14 -10
- package/src/schema.test.ts +55 -0
- package/src/service/add-observable-actions.ts +207 -0
- package/{service/index.js → src/service/index.ts} +4 -4
- package/src/service/is-service.ts +7 -0
- package/src/service/progressive-result.ts +141 -0
- package/src/service/service.ts +27 -0
- package/src/table/add-row.ts +42 -0
- package/src/table/create-table.ts +36 -0
- package/src/table/delete-row.ts +42 -0
- package/src/table/ensure-capacity.ts +37 -0
- package/src/table/get-row-data.ts +31 -0
- package/src/table/index.ts +29 -0
- package/src/table/row-index.ts +26 -0
- package/src/table/table.ts +32 -0
- package/src/table/update-row.ts +35 -0
- package/src/tsconfig.json +6 -0
- package/src/typed-buffer/copy-to-gpu-buffer.ts +23 -0
- package/{cache/expiring-data-cache.js → src/typed-buffer/create-array-buffer.ts} +31 -25
- package/src/typed-buffer/create-number-buffer.ts +90 -0
- package/src/typed-buffer/create-struct-buffer.ts +93 -0
- package/src/typed-buffer/create-typed-buffer.ts +49 -0
- package/src/typed-buffer/index.ts +26 -0
- package/src/typed-buffer/structs/assert-struct.ts +37 -0
- package/src/typed-buffer/structs/create-read-struct.test.ts +202 -0
- package/src/typed-buffer/structs/create-read-struct.ts +77 -0
- package/src/typed-buffer/structs/create-write-struct.ts +73 -0
- package/src/typed-buffer/structs/get-field-offset.ts +36 -0
- package/src/typed-buffer/structs/get-struct-layout.test.ts +146 -0
- package/src/typed-buffer/structs/get-struct-layout.ts +222 -0
- package/src/typed-buffer/structs/index.ts +22 -0
- package/src/typed-buffer/structs/read-struct.ts +25 -0
- package/src/typed-buffer/structs/struct-layout.ts +465 -0
- package/src/typed-buffer/structs/write-struct.test.ts +195 -0
- package/src/typed-buffer/structs/write-struct.ts +25 -0
- package/src/typed-buffer/typed-buffer.test.ts +253 -0
- package/src/typed-buffer/typed-buffer.ts +41 -0
- package/src/types/assert.ts +22 -0
- package/src/types/equal.ts +24 -0
- package/{types/index.js → src/types/index.ts} +3 -1
- package/src/types/types.ts +166 -0
- package/tsconfig-base.json +25 -0
- package/tsconfig.json +8 -0
- package/typedoc.json +22 -0
- package/vite.config.js +16 -0
- package/assembly/index.d.ts +0 -30
- package/assembly/index.js +0 -18
- package/assembly/index.wasm +0 -0
- package/assembly/index.wasm.map +0 -1
- package/assembly-test/assembly.test.d.ts +0 -1
- package/assembly-test/assembly.test.js.map +0 -1
- package/cache/async-cache.d.ts +0 -15
- package/cache/async-cache.js.map +0 -1
- package/cache/blob-store.d.ts +0 -94
- package/cache/blob-store.js +0 -191
- package/cache/blob-store.js.map +0 -1
- package/cache/blob-store.test.d.ts +0 -1
- package/cache/blob-store.test.js.map +0 -1
- package/cache/data-cache.d.ts +0 -38
- package/cache/data-cache.js +0 -96
- package/cache/data-cache.js.map +0 -1
- package/cache/data-cache.test.d.ts +0 -1
- package/cache/data-cache.test.js +0 -50
- package/cache/data-cache.test.js.map +0 -1
- package/cache/expiring-data-cache.d.ts +0 -6
- package/cache/expiring-data-cache.js.map +0 -1
- package/cache/expiring-data-cache.test.d.ts +0 -1
- package/cache/expiring-data-cache.test.js +0 -62
- package/cache/expiring-data-cache.test.js.map +0 -1
- package/cache/fallback-async-cache.d.ts +0 -7
- package/cache/fallback-async-cache.js +0 -22
- package/cache/fallback-async-cache.js.map +0 -1
- package/cache/functions/bind-functions.d.ts +0 -6
- package/cache/functions/bind-functions.js.map +0 -1
- package/cache/functions/functions.test.d.ts +0 -1
- package/cache/functions/functions.test.js +0 -79
- package/cache/functions/functions.test.js.map +0 -1
- package/cache/functions/get-cached.d.ts +0 -11
- package/cache/functions/get-cached.js.map +0 -1
- package/cache/functions/get-cached.test.d.ts +0 -1
- package/cache/functions/get-cached.test.js.map +0 -1
- package/cache/functions/hashing/blob-to-hash.d.ts +0 -4
- package/cache/functions/hashing/blob-to-hash.js.map +0 -1
- package/cache/functions/hashing/buffer-to-hash.d.ts +0 -4
- package/cache/functions/hashing/buffer-to-hash.js.map +0 -1
- package/cache/functions/hashing/hashing.test.d.ts +0 -1
- package/cache/functions/hashing/hashing.test.js +0 -95
- package/cache/functions/hashing/hashing.test.js.map +0 -1
- package/cache/functions/hashing/index.d.ts +0 -4
- package/cache/functions/hashing/index.js.map +0 -1
- package/cache/functions/hashing/json-to-hash.d.ts +0 -4
- package/cache/functions/hashing/json-to-hash.js.map +0 -1
- package/cache/functions/hashing/string-to-hash.d.ts +0 -4
- package/cache/functions/hashing/string-to-hash.js.map +0 -1
- package/cache/functions/index.d.ts +0 -5
- package/cache/functions/index.js.map +0 -1
- package/cache/functions/memoize.d.ts +0 -12
- package/cache/functions/memoize.js.map +0 -1
- package/cache/functions/omit.d.ts +0 -1
- package/cache/functions/omit.js.map +0 -1
- package/cache/functions/prevent-parallel-execution.d.ts +0 -7
- package/cache/functions/prevent-parallel-execution.js +0 -25
- package/cache/functions/prevent-parallel-execution.js.map +0 -1
- package/cache/functions/types.d.ts +0 -1
- package/cache/functions/types.js.map +0 -1
- package/cache/get-persistent-cache.d.ts +0 -12
- package/cache/get-persistent-cache.js +0 -23
- package/cache/get-persistent-cache.js.map +0 -1
- package/cache/index.d.ts +0 -3
- package/cache/index.js.map +0 -1
- package/cache/managed-array.d.ts +0 -23
- package/cache/managed-array.js +0 -160
- package/cache/managed-array.js.map +0 -1
- package/cache/managed-async-cache.browser.test.d.ts +0 -1
- package/cache/managed-async-cache.browser.test.js.map +0 -1
- package/cache/managed-async-cache.d.ts +0 -4
- package/cache/managed-async-cache.js +0 -45
- package/cache/managed-async-cache.js.map +0 -1
- package/cache/memory-allocator.d.ts +0 -23
- package/cache/memory-allocator.js +0 -94
- package/cache/memory-allocator.js.map +0 -1
- package/cache/memory-async-cache.d.ts +0 -6
- package/cache/memory-async-cache.js +0 -23
- package/cache/memory-async-cache.js.map +0 -1
- package/core/data.d.ts +0 -22
- package/core/data.js.map +0 -1
- package/core/data.test.d.ts +0 -1
- package/core/data.test.js.map +0 -1
- package/core/functions/array-equals.d.ts +0 -1
- package/core/functions/array-equals.js.map +0 -1
- package/core/functions/deep-merge.d.ts +0 -32
- package/core/functions/deep-merge.js +0 -54
- package/core/functions/deep-merge.js.map +0 -1
- package/core/functions/deep-merge.test.d.ts +0 -1
- package/core/functions/deep-merge.test.js +0 -94
- package/core/functions/deep-merge.test.js.map +0 -1
- package/core/functions/index.d.ts +0 -3
- package/core/functions/index.js.map +0 -1
- package/core/functions/is-async-generator.d.ts +0 -1
- package/core/functions/is-async-generator.js.map +0 -1
- package/core/functions/is-promise.d.ts +0 -1
- package/core/functions/is-promise.js.map +0 -1
- package/core/functions/with-validation.d.ts +0 -5
- package/core/functions/with-validation.js.map +0 -1
- package/core/functions/with-validation.test.d.ts +0 -1
- package/core/functions/with-validation.test.js.map +0 -1
- package/core/index.d.ts +0 -3
- package/core/index.js.map +0 -1
- package/core/schema/dynamic/dynamic-schema.d.ts +0 -27
- package/core/schema/dynamic/dynamic-schema.js +0 -2
- package/core/schema/dynamic/dynamic-schema.js.map +0 -1
- package/core/schema/dynamic/enumerate-patches.d.ts +0 -9
- package/core/schema/dynamic/enumerate-patches.js.map +0 -1
- package/core/schema/dynamic/enumerate-patches.test.d.ts +0 -134
- package/core/schema/dynamic/enumerate-patches.test.js.map +0 -1
- package/core/schema/dynamic/get-dynamic-schema.d.ts +0 -5
- package/core/schema/dynamic/get-dynamic-schema.js +0 -26
- package/core/schema/dynamic/get-dynamic-schema.js.map +0 -1
- package/core/schema/dynamic/get-dynamic-schema.test.d.ts +0 -1
- package/core/schema/dynamic/get-dynamic-schema.test.js.map +0 -1
- package/core/schema/dynamic/index.d.ts +0 -1
- package/core/schema/dynamic/index.js +0 -2
- package/core/schema/dynamic/index.js.map +0 -1
- package/core/schema/dynamic/schema-path-value-path.d.ts +0 -5
- package/core/schema/dynamic/schema-path-value-path.js +0 -12
- package/core/schema/dynamic/schema-path-value-path.js.map +0 -1
- package/core/schema/dynamic-schema.d.ts +0 -27
- package/core/schema/dynamic-schema.js +0 -2
- package/core/schema/dynamic-schema.js.map +0 -1
- package/core/schema/index.d.ts +0 -4
- package/core/schema/index.js +0 -26
- package/core/schema/index.js.map +0 -1
- package/core/schema/schema.d.ts +0 -122
- package/core/schema/schema.js.map +0 -1
- package/core/schema/schemas.d.ts +0 -45
- package/core/schema/schemas.js +0 -39
- package/core/schema/schemas.js.map +0 -1
- package/core/schema/ui-schema.d.ts +0 -25
- package/core/schema/ui-schema.js +0 -2
- package/core/schema/ui-schema.js.map +0 -1
- package/core/schema/validation/is-valid.d.ts +0 -2
- package/core/schema/validation/is-valid.js +0 -14
- package/core/schema/validation/is-valid.js.map +0 -1
- package/core/schema/validation/is-valid.test.d.ts +0 -1
- package/core/schema/validation/is-valid.test.js.map +0 -1
- package/core/schema/validation/validate.d.ts +0 -2
- package/core/schema/validation/validate.js.map +0 -1
- package/core/schema/validation/validate.test.d.ts +0 -1
- package/core/schema/validation/validate.test.js.map +0 -1
- package/core/schema/validation/with-validation.d.ts +0 -5
- package/core/schema/validation/with-validation.js +0 -16
- package/core/schema/validation/with-validation.js.map +0 -1
- package/core/schema/validation/with-validation.test.d.ts +0 -1
- package/core/schema/validation/with-validation.test.js +0 -96
- package/core/schema/validation/with-validation.test.js.map +0 -1
- package/core/schema.d.ts +0 -86
- package/core/schema.js.map +0 -1
- package/core/schema.test.d.ts +0 -1
- package/core/schema.test.js +0 -16
- package/core/schema.test.js.map +0 -1
- package/core/schemas.d.ts +0 -45
- package/core/schemas.js +0 -39
- package/core/schemas.js.map +0 -1
- package/ecs/action-ecs/action-ecs.d.ts +0 -19
- package/ecs/action-ecs/action-ecs.js +0 -203
- package/ecs/action-ecs/action-ecs.js.map +0 -1
- package/ecs/action-ecs/action-ecs.test.d.ts +0 -1
- package/ecs/action-ecs/action-ecs.test.js +0 -362
- package/ecs/action-ecs/action-ecs.test.js.map +0 -1
- package/ecs/action-ecs/action-types.d.ts +0 -106
- package/ecs/action-ecs/action-types.js +0 -19
- package/ecs/action-ecs/action-types.js.map +0 -1
- package/ecs/action-ecs/index.d.ts +0 -2
- package/ecs/action-ecs/index.js.map +0 -1
- package/ecs/core-ecs/core-ecs-serialization.test.d.ts +0 -1
- package/ecs/core-ecs/core-ecs-serialization.test.js +0 -230
- package/ecs/core-ecs/core-ecs-serialization.test.js.map +0 -1
- package/ecs/core-ecs/core-ecs-types.d.ts +0 -141
- package/ecs/core-ecs/core-ecs-types.js.map +0 -1
- package/ecs/core-ecs/core-ecs.d.ts +0 -7
- package/ecs/core-ecs/core-ecs.js +0 -492
- package/ecs/core-ecs/core-ecs.js.map +0 -1
- package/ecs/core-ecs/core-ecs.test.d.ts +0 -1
- package/ecs/core-ecs/core-ecs.test.js +0 -425
- package/ecs/core-ecs/core-ecs.test.js.map +0 -1
- package/ecs/core-ecs/index.d.ts +0 -1
- package/ecs/core-ecs/index.js +0 -2
- package/ecs/core-ecs/index.js.map +0 -1
- package/ecs/ecs/ecs-types.d.ts +0 -132
- package/ecs/ecs/ecs-types.js.map +0 -1
- package/ecs/ecs/ecs-where-functions.d.ts +0 -6
- package/ecs/ecs/ecs-where-functions.js +0 -91
- package/ecs/ecs/ecs-where-functions.js.map +0 -1
- package/ecs/ecs/ecs.d.ts +0 -13
- package/ecs/ecs/ecs.js +0 -177
- package/ecs/ecs/ecs.js.map +0 -1
- package/ecs/ecs/ecs.test.d.ts +0 -1
- package/ecs/ecs/ecs.test.js +0 -399
- package/ecs/ecs/ecs.test.js.map +0 -1
- package/ecs/ecs/index.d.ts +0 -3
- package/ecs/ecs/index.js +0 -3
- package/ecs/ecs/index.js.map +0 -1
- package/ecs/index.d.ts +0 -4
- package/ecs/index.js.map +0 -1
- package/ecs/transaction-ecs/index.d.ts +0 -2
- package/ecs/transaction-ecs/index.js.map +0 -1
- package/ecs/transaction-ecs/transaction-ecs.d.ts +0 -11
- package/ecs/transaction-ecs/transaction-ecs.js +0 -184
- package/ecs/transaction-ecs/transaction-ecs.js.map +0 -1
- package/ecs/transaction-ecs/transaction-ecs.test.d.ts +0 -1
- package/ecs/transaction-ecs/transaction-ecs.test.js +0 -599
- package/ecs/transaction-ecs/transaction-ecs.test.js.map +0 -1
- package/ecs/transaction-ecs/transaction-types.d.ts +0 -135
- package/ecs/transaction-ecs/transaction-types.js +0 -2
- package/ecs/transaction-ecs/transaction-types.js.map +0 -1
- package/ecs/transaction-ecs/transactions.d.ts +0 -5
- package/ecs/transaction-ecs/transactions.js +0 -158
- package/ecs/transaction-ecs/transactions.js.map +0 -1
- package/index.d.ts +0 -1
- package/index.js +0 -23
- package/index.js.map +0 -1
- package/observe/create-observable-event.d.ts +0 -10
- package/observe/create-observable-event.js +0 -22
- package/observe/create-observable-event.js.map +0 -1
- package/observe/create-observable-state.d.ts +0 -7
- package/observe/create-observable-state.js +0 -27
- package/observe/create-observable-state.js.map +0 -1
- package/observe/create-persisted-state.d.ts +0 -11
- package/observe/create-persisted-state.js +0 -31
- package/observe/create-persisted-state.js.map +0 -1
- package/observe/create-persisted-state.test.d.ts +0 -1
- package/observe/create-persisted-state.test.js +0 -124
- package/observe/create-persisted-state.test.js.map +0 -1
- package/observe/from-array.d.ts +0 -5
- package/observe/from-array.js.map +0 -1
- package/observe/from-constant.d.ts +0 -5
- package/observe/from-constant.js +0 -12
- package/observe/from-constant.js.map +0 -1
- package/observe/from-element-id.d.ts +0 -7
- package/observe/from-element-id.js.map +0 -1
- package/observe/from-element-properties-and-events.d.ts +0 -2
- package/observe/from-element-properties-and-events.js +0 -18
- package/observe/from-element-properties-and-events.js.map +0 -1
- package/observe/from-element-property.d.ts +0 -11
- package/observe/from-element-property.js.map +0 -1
- package/observe/from-promise-with-error.d.ts +0 -7
- package/observe/from-promise-with-error.js +0 -27
- package/observe/from-promise-with-error.js.map +0 -1
- package/observe/from-promise.d.ts +0 -6
- package/observe/from-promise.js +0 -22
- package/observe/from-promise.js.map +0 -1
- package/observe/from-properties.d.ts +0 -10
- package/observe/from-properties.js +0 -33
- package/observe/from-properties.js.map +0 -1
- package/observe/index.d.ts +0 -27
- package/observe/index.js.map +0 -1
- package/observe/observe.test.d.ts +0 -7
- package/observe/observe.test.js +0 -417
- package/observe/observe.test.js.map +0 -1
- package/observe/to-promise.d.ts +0 -8
- package/observe/to-promise.js +0 -18
- package/observe/to-promise.js.map +0 -1
- package/observe/to-properties.d.ts +0 -11
- package/observe/to-properties.js +0 -9
- package/observe/to-properties.js.map +0 -1
- package/observe/types.d.ts +0 -17
- package/observe/types.js +0 -2
- package/observe/types.js.map +0 -1
- package/observe/with-async-map.d.ts +0 -6
- package/observe/with-async-map.js +0 -12
- package/observe/with-async-map.js.map +0 -1
- package/observe/with-cache.d.ts +0 -6
- package/observe/with-cache.js +0 -33
- package/observe/with-cache.js.map +0 -1
- package/observe/with-copy.d.ts +0 -5
- package/observe/with-copy.js +0 -10
- package/observe/with-copy.js.map +0 -1
- package/observe/with-deduplicate-data.d.ts +0 -7
- package/observe/with-deduplicate-data.js +0 -18
- package/observe/with-deduplicate-data.js.map +0 -1
- package/observe/with-deduplicate.d.ts +0 -6
- package/observe/with-deduplicate.js +0 -19
- package/observe/with-deduplicate.js.map +0 -1
- package/observe/with-default.d.ts +0 -6
- package/observe/with-default.js +0 -21
- package/observe/with-default.js.map +0 -1
- package/observe/with-map-data.d.ts +0 -7
- package/observe/with-map-data.js.map +0 -1
- package/observe/with-map.d.ts +0 -5
- package/observe/with-map.js +0 -11
- package/observe/with-map.js.map +0 -1
- package/observe/with-optional.d.ts +0 -5
- package/observe/with-optional.js +0 -20
- package/observe/with-optional.js.map +0 -1
- package/observe/with-unwrap.d.ts +0 -5
- package/observe/with-unwrap.js +0 -26
- package/observe/with-unwrap.js.map +0 -1
- package/perftest/ecs-perf.d.ts +0 -49
- package/perftest/ecs-perf.js +0 -230
- package/perftest/ecs-perf.js.map +0 -1
- package/perftest/helper-functions.d.ts +0 -1
- package/perftest/helper-functions.js +0 -31
- package/perftest/helper-functions.js.map +0 -1
- package/perftest/horizon-perf.d.ts +0 -22
- package/perftest/horizon-perf.js +0 -126
- package/perftest/horizon-perf.js.map +0 -1
- package/perftest/index.d.ts +0 -1
- package/perftest/index.js.map +0 -1
- package/perftest/perf-test.d.ts +0 -18
- package/perftest/perf-test.js +0 -124
- package/perftest/perf-test.js.map +0 -1
- package/perftest/vanilla-perf.d.ts +0 -38
- package/perftest/vanilla-perf.js +0 -128
- package/perftest/vanilla-perf.js.map +0 -1
- package/schemas/index.d.ts +0 -1
- package/schemas/index.js +0 -23
- package/schemas/index.js.map +0 -1
- package/schemas/schemas.d.ts +0 -45
- package/schemas/schemas.js +0 -39
- package/schemas/schemas.js.map +0 -1
- package/service/add-observable-actions.d.ts +0 -29
- package/service/add-observable-actions.js +0 -108
- package/service/add-observable-actions.js.map +0 -1
- package/service/index.d.ts +0 -4
- package/service/index.js.map +0 -1
- package/service/progressive-result.d.ts +0 -96
- package/service/progressive-result.js +0 -99
- package/service/progressive-result.js.map +0 -1
- package/service/sequential-action.d.ts +0 -18
- package/service/sequential-action.js.map +0 -1
- package/service/service.d.ts +0 -4
- package/service/service.js.map +0 -1
- package/tsconfig.tsbuildinfo +0 -1
- package/types/index.d.ts +0 -1
- package/types/index.js.map +0 -1
- package/types/types.d.ts +0 -61
- 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
|
+
});
|