@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.
- 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 +50 -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/src/ecs/entity-location-table/entity-location.ts +34 -0
- 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/{core/functions/index.js → src/old-ecs/action-ecs/index.ts} +8 -5
- 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/src/old-ecs/core-ecs/index.ts +30 -0
- 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/src/schema/dynamic/enumerate-patches.test.ts +235 -0
- package/src/schema/dynamic/enumerate-patches.ts +90 -0
- package/src/schema/dynamic/get-dynamic-schema.test.ts +129 -0
- 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/src/schema/validation/is-valid.test.ts +43 -0
- package/{core/functions/array-equals.js → src/schema/validation/is-valid.ts} +8 -10
- package/src/schema/validation/validate.test.ts +120 -0
- package/src/schema/validation/validate.ts +41 -0
- 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 -31
- package/core/functions/deep-merge.js +0 -51
- 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 -4
- 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.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/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 -404
- 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,250 @@
|
|
|
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 } from "vitest";
|
|
23
|
+
import { createTransactionalStore } from "./create-transactional-store.js";
|
|
24
|
+
import { createStore } from "../../store/create-store.js";
|
|
25
|
+
import { F32Schema } from "../../../schema/f32.js";
|
|
26
|
+
import { Schema } from "../../../schema/schema.js";
|
|
27
|
+
|
|
28
|
+
// Test schemas
|
|
29
|
+
const positionSchema = {
|
|
30
|
+
type: "object",
|
|
31
|
+
properties: {
|
|
32
|
+
x: F32Schema,
|
|
33
|
+
y: F32Schema,
|
|
34
|
+
z: F32Schema,
|
|
35
|
+
}
|
|
36
|
+
} as const satisfies Schema;
|
|
37
|
+
|
|
38
|
+
const healthSchema = {
|
|
39
|
+
type: "object",
|
|
40
|
+
properties: {
|
|
41
|
+
current: F32Schema,
|
|
42
|
+
max: F32Schema,
|
|
43
|
+
}
|
|
44
|
+
} as const satisfies Schema;
|
|
45
|
+
|
|
46
|
+
describe("createTransactionalStore", () => {
|
|
47
|
+
it("should create transactional store with basic components", () => {
|
|
48
|
+
const baseStore = createStore(
|
|
49
|
+
{ position: positionSchema, health: healthSchema },
|
|
50
|
+
{ time: { delta: 0.016, elapsed: 0 } }
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const store = createTransactionalStore(baseStore);
|
|
54
|
+
|
|
55
|
+
expect(store).toBeDefined();
|
|
56
|
+
expect(store.componentSchemas).toHaveProperty("id");
|
|
57
|
+
expect(store.componentSchemas).toHaveProperty("position");
|
|
58
|
+
expect(store.componentSchemas).toHaveProperty("health");
|
|
59
|
+
expect(store.resources).toHaveProperty("time");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("should execute transactions successfully", () => {
|
|
63
|
+
const baseStore = createStore(
|
|
64
|
+
{ position: positionSchema, health: healthSchema },
|
|
65
|
+
{ time: { delta: 0.016, elapsed: 0 } }
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const store = createTransactionalStore(baseStore);
|
|
69
|
+
|
|
70
|
+
const result = store.execute((transactionStore) => {
|
|
71
|
+
// Create an entity
|
|
72
|
+
const archetype = transactionStore.ensureArchetype(["id", "position"]);
|
|
73
|
+
const entity = archetype.insert({ position: { x: 1, y: 2, z: 3 } });
|
|
74
|
+
|
|
75
|
+
// Update the entity
|
|
76
|
+
transactionStore.update(entity, { position: { x: 10, y: 20, z: 30 } });
|
|
77
|
+
|
|
78
|
+
// Update resources
|
|
79
|
+
transactionStore.resources.time = { delta: 0.032, elapsed: 1 };
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
expect(result).toBeDefined();
|
|
83
|
+
expect(result.redo).toHaveLength(3); // insert + update
|
|
84
|
+
expect(result.undo).toHaveLength(3); // delete + insert with old values
|
|
85
|
+
expect(result.changedEntities.size).toBe(2);
|
|
86
|
+
expect(result.changedComponents.size).toBe(2); // position
|
|
87
|
+
expect(result.changedArchetypes.size).toBe(2);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("should rollback on error", () => {
|
|
91
|
+
const baseStore = createStore(
|
|
92
|
+
{ position: positionSchema, health: healthSchema },
|
|
93
|
+
{ time: { delta: 0.016, elapsed: 0 } }
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
const store = createTransactionalStore(baseStore);
|
|
97
|
+
|
|
98
|
+
// Create initial entity in a transaction
|
|
99
|
+
let entity: number = -1;
|
|
100
|
+
store.execute((transactionStore) => {
|
|
101
|
+
const archetype = transactionStore.ensureArchetype(["id", "position"]);
|
|
102
|
+
entity = archetype.insert({ position: { x: 1, y: 2, z: 3 } });
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Verify initial state
|
|
106
|
+
const initialData = store.read(entity);
|
|
107
|
+
expect(initialData?.position).toEqual({ x: 1, y: 2, z: 3 });
|
|
108
|
+
|
|
109
|
+
// Execute transaction that throws an error
|
|
110
|
+
expect(() => {
|
|
111
|
+
store.execute((transactionStore) => {
|
|
112
|
+
// Update entity
|
|
113
|
+
transactionStore.update(entity, { position: { x: 10, y: 20, z: 30 } });
|
|
114
|
+
|
|
115
|
+
// This should cause rollback
|
|
116
|
+
throw new Error("Transaction failed");
|
|
117
|
+
});
|
|
118
|
+
}).toThrow("Transaction failed");
|
|
119
|
+
|
|
120
|
+
// Verify rollback occurred
|
|
121
|
+
const finalData = store.read(entity);
|
|
122
|
+
expect(finalData?.position).toEqual({ x: 1, y: 2, z: 3 });
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("should combine multiple updates to the same entity", () => {
|
|
126
|
+
const baseStore = createStore(
|
|
127
|
+
{ position: positionSchema, health: healthSchema },
|
|
128
|
+
{ time: { delta: 0.016, elapsed: 0 } }
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
const store = createTransactionalStore(baseStore);
|
|
132
|
+
|
|
133
|
+
const result = store.execute((transactionStore) => {
|
|
134
|
+
const archetype = transactionStore.ensureArchetype(["id", "position", "health"]);
|
|
135
|
+
const entity = archetype.insert({
|
|
136
|
+
position: { x: 1, y: 2, z: 3 },
|
|
137
|
+
health: { current: 100, max: 100 }
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// Multiple updates to the same entity should be combined
|
|
141
|
+
transactionStore.update(entity, { position: { x: 10, y: 20, z: 30 } });
|
|
142
|
+
transactionStore.update(entity, { health: { current: 50, max: 100 } });
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// Should have combined updates
|
|
146
|
+
expect(result.redo).toHaveLength(2); // insert + combined update
|
|
147
|
+
expect(result.undo).toHaveLength(2); // delete + insert with old values
|
|
148
|
+
|
|
149
|
+
const updateOperation = result.redo.find(op => op.type === "update");
|
|
150
|
+
expect(updateOperation?.type).toBe("update");
|
|
151
|
+
if (updateOperation?.type === "update") {
|
|
152
|
+
expect(updateOperation.values).toHaveProperty("position");
|
|
153
|
+
expect(updateOperation.values).toHaveProperty("health");
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("should track changed entities, components, and archetypes", () => {
|
|
158
|
+
const baseStore = createStore(
|
|
159
|
+
{ position: positionSchema, health: healthSchema },
|
|
160
|
+
{ time: { delta: 0.016, elapsed: 0 } }
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
const store = createTransactionalStore(baseStore);
|
|
164
|
+
|
|
165
|
+
const result = store.execute((transactionStore) => {
|
|
166
|
+
// Create entities in different archetypes
|
|
167
|
+
const posArchetype = transactionStore.ensureArchetype(["id", "position"]);
|
|
168
|
+
const healthArchetype = transactionStore.ensureArchetype(["id", "health"]);
|
|
169
|
+
|
|
170
|
+
const entity1 = posArchetype.insert({ position: { x: 1, y: 2, z: 3 } });
|
|
171
|
+
const entity2 = healthArchetype.insert({ health: { current: 100, max: 100 } });
|
|
172
|
+
|
|
173
|
+
// Update resources
|
|
174
|
+
transactionStore.resources.time = { delta: 0.032, elapsed: 1 };
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
expect(result.changedEntities.size).toBe(3);
|
|
178
|
+
expect(result.changedComponents.size).toBe(3); // position, health
|
|
179
|
+
expect(result.changedArchetypes.size).toBe(3); // two different archetypes
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it("should preserve base store functionality", () => {
|
|
183
|
+
const baseStore = createStore(
|
|
184
|
+
{ position: positionSchema, health: healthSchema },
|
|
185
|
+
{ time: { delta: 0.016, elapsed: 0 } }
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
const store = createTransactionalStore(baseStore);
|
|
189
|
+
|
|
190
|
+
// Verify all base store methods are available
|
|
191
|
+
expect(store.componentSchemas).toBeDefined();
|
|
192
|
+
expect(store.resources).toBeDefined();
|
|
193
|
+
expect(store.queryArchetypes).toBeDefined();
|
|
194
|
+
expect(store.ensureArchetype).toBeDefined();
|
|
195
|
+
expect(store.locate).toBeDefined();
|
|
196
|
+
expect(store.read).toBeDefined();
|
|
197
|
+
expect(store.execute).toBeDefined();
|
|
198
|
+
|
|
199
|
+
// Verify we can use the store normally for read operations
|
|
200
|
+
const archetypes = store.queryArchetypes(["id"]);
|
|
201
|
+
expect(archetypes.length).toBeGreaterThan(0);
|
|
202
|
+
|
|
203
|
+
// Verify we can create entities through transactions
|
|
204
|
+
store.execute((transactionStore) => {
|
|
205
|
+
const archetype = transactionStore.ensureArchetype(["id", "position"]);
|
|
206
|
+
const entity = archetype.insert({ position: { x: 1, y: 2, z: 3 } });
|
|
207
|
+
expect(store.read(entity)).toBeDefined();
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it("should support transient transactions", () => {
|
|
212
|
+
const baseStore = createStore(
|
|
213
|
+
{ position: positionSchema, health: healthSchema },
|
|
214
|
+
{ time: { delta: 0.016, elapsed: 0 } }
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
const store = createTransactionalStore(baseStore);
|
|
218
|
+
|
|
219
|
+
// Execute a regular transaction (non-transient)
|
|
220
|
+
const regularResult = store.execute((transactionStore) => {
|
|
221
|
+
const archetype = transactionStore.ensureArchetype(["id", "position"]);
|
|
222
|
+
archetype.insert({ position: { x: 1, y: 2, z: 3 } });
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
expect(regularResult.transient).toBe(false);
|
|
226
|
+
|
|
227
|
+
// Execute a transient transaction
|
|
228
|
+
const transientResult = store.execute((transactionStore) => {
|
|
229
|
+
const archetype = transactionStore.ensureArchetype(["id", "position"]);
|
|
230
|
+
archetype.insert({ position: { x: 10, y: 20, z: 30 } });
|
|
231
|
+
}, { transient: true });
|
|
232
|
+
|
|
233
|
+
expect(transientResult.transient).toBe(true);
|
|
234
|
+
|
|
235
|
+
// Both transactions should have the same structure but different transient flags
|
|
236
|
+
expect(regularResult).toHaveProperty("value");
|
|
237
|
+
expect(regularResult).toHaveProperty("redo");
|
|
238
|
+
expect(regularResult).toHaveProperty("undo");
|
|
239
|
+
expect(regularResult).toHaveProperty("changedEntities");
|
|
240
|
+
expect(regularResult).toHaveProperty("changedComponents");
|
|
241
|
+
expect(regularResult).toHaveProperty("changedArchetypes");
|
|
242
|
+
|
|
243
|
+
expect(transientResult).toHaveProperty("value");
|
|
244
|
+
expect(transientResult).toHaveProperty("redo");
|
|
245
|
+
expect(transientResult).toHaveProperty("undo");
|
|
246
|
+
expect(transientResult).toHaveProperty("changedEntities");
|
|
247
|
+
expect(transientResult).toHaveProperty("changedComponents");
|
|
248
|
+
expect(transientResult).toHaveProperty("changedArchetypes");
|
|
249
|
+
});
|
|
250
|
+
});
|
|
@@ -0,0 +1,281 @@
|
|
|
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 { ArchetypeId, EntityInsertValues } from "../../archetype/index.js";
|
|
23
|
+
import { CoreComponents } from "../../core-components.js";
|
|
24
|
+
import { ResourceComponents } from "../../store/resource-components.js";
|
|
25
|
+
import { Store } from "../../store/index.js";
|
|
26
|
+
import { Entity } from "../../entity.js";
|
|
27
|
+
import { EntityUpdateValues } from "../../store/core/index.js";
|
|
28
|
+
import { TransactionalStore, TransactionResult, TransactionWriteOperation } from "./transactional-store.js";
|
|
29
|
+
import { StringKeyof } from "../../../types/types.js";
|
|
30
|
+
|
|
31
|
+
// Sentinel value used to indicate a component should be deleted
|
|
32
|
+
const DELETE: unknown = "_$_DELETE_$_";
|
|
33
|
+
|
|
34
|
+
export function createTransactionalStore<C extends CoreComponents, R extends ResourceComponents>(
|
|
35
|
+
store: Store<C, R>,
|
|
36
|
+
): TransactionalStore<C, R> {
|
|
37
|
+
|
|
38
|
+
// Transaction state (mutable during transaction execution)
|
|
39
|
+
let undoOperationsInReverseOrder: TransactionWriteOperation<C>[] = [];
|
|
40
|
+
let redoOperations: TransactionWriteOperation<C>[] = [];
|
|
41
|
+
const changed = {
|
|
42
|
+
entities: new Set<Entity>(),
|
|
43
|
+
components: new Set<keyof C>(),
|
|
44
|
+
archetypes: new Set<ArchetypeId>(),
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// Wrap archetype creation to track operations
|
|
48
|
+
const wrapArchetype = (archetype: any) => {
|
|
49
|
+
const { id } = archetype;
|
|
50
|
+
return {
|
|
51
|
+
...archetype,
|
|
52
|
+
insert: (values: EntityInsertValues<C>) => {
|
|
53
|
+
const entity = archetype.insert(values);
|
|
54
|
+
redoOperations.push({
|
|
55
|
+
type: "insert",
|
|
56
|
+
values: values,
|
|
57
|
+
});
|
|
58
|
+
undoOperationsInReverseOrder.push({ type: "delete", entity });
|
|
59
|
+
changed.entities.add(entity);
|
|
60
|
+
changed.archetypes.add(id);
|
|
61
|
+
for (const key in values) {
|
|
62
|
+
changed.components.add(key as keyof C);
|
|
63
|
+
}
|
|
64
|
+
return entity;
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// Create wrapped archetypes for transaction tracking
|
|
70
|
+
const wrappedArchetypes = new Map<ArchetypeId, any>();
|
|
71
|
+
|
|
72
|
+
const getWrappedArchetype = (archetype: any) => {
|
|
73
|
+
if (!wrappedArchetypes.has(archetype.id)) {
|
|
74
|
+
wrappedArchetypes.set(archetype.id, wrapArchetype(archetype));
|
|
75
|
+
}
|
|
76
|
+
return wrappedArchetypes.get(archetype.id);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// Transaction-aware update function
|
|
80
|
+
const updateEntity = (entity: Entity, values: EntityUpdateValues<C>) => {
|
|
81
|
+
const oldValues = store.read(entity);
|
|
82
|
+
if (!oldValues) {
|
|
83
|
+
throw new Error(`Entity not found: ${entity}`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const replacedValues: any = {};
|
|
87
|
+
for (const name in values) {
|
|
88
|
+
let newValue = (values as any)[name];
|
|
89
|
+
if (newValue === DELETE) {
|
|
90
|
+
newValue = undefined;
|
|
91
|
+
}
|
|
92
|
+
let oldValue = (oldValues as any)[name];
|
|
93
|
+
if (newValue !== oldValue) {
|
|
94
|
+
if (oldValue === undefined) {
|
|
95
|
+
oldValue = DELETE;
|
|
96
|
+
}
|
|
97
|
+
replacedValues[name] = oldValue;
|
|
98
|
+
changed.components.add(name as keyof C);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
changed.entities.add(entity);
|
|
103
|
+
const location = store.locate(entity);
|
|
104
|
+
if (location) {
|
|
105
|
+
changed.archetypes.add(location.archetype);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Perform the actual update
|
|
109
|
+
store.update(entity, values as any);
|
|
110
|
+
|
|
111
|
+
// Check if archetype changed after update
|
|
112
|
+
const newLocation = store.locate(entity);
|
|
113
|
+
if (newLocation) {
|
|
114
|
+
changed.archetypes.add(newLocation.archetype);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Add operations with potential combining
|
|
118
|
+
addUpdateOperationsMaybeCombineLast(undoOperationsInReverseOrder, redoOperations, entity, values, replacedValues);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// Transaction-aware delete function
|
|
122
|
+
const deleteEntity = (entity: Entity) => {
|
|
123
|
+
const location = store.locate(entity);
|
|
124
|
+
if (location) {
|
|
125
|
+
changed.archetypes.add(location.archetype);
|
|
126
|
+
}
|
|
127
|
+
changed.entities.add(entity);
|
|
128
|
+
|
|
129
|
+
const oldValues = store.read(entity);
|
|
130
|
+
if (!oldValues) {
|
|
131
|
+
throw new Error(`Entity not found: ${entity}`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const { id: _ignore, ...oldValuesWithoutId } = oldValues as any;
|
|
135
|
+
for (const key in oldValuesWithoutId) {
|
|
136
|
+
changed.components.add(key as keyof C);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
store.delete(entity);
|
|
140
|
+
redoOperations.push({ type: "delete", entity });
|
|
141
|
+
undoOperationsInReverseOrder.push({ type: "insert", values: oldValuesWithoutId });
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const resources = {} as { [K in keyof R]: R[K] };
|
|
145
|
+
for (const name of Object.keys(store.resources)) {
|
|
146
|
+
const resourceId = name as keyof C;
|
|
147
|
+
const archetype = store.ensureArchetype(["id", resourceId] as StringKeyof<C>[]);
|
|
148
|
+
const entityId = archetype.columns.id.get(0);
|
|
149
|
+
Object.defineProperty(resources, name, {
|
|
150
|
+
get: Object.getOwnPropertyDescriptor(store.resources, name)!.get,
|
|
151
|
+
set: (newValue) => {
|
|
152
|
+
updateEntity(entityId, { [resourceId]: newValue } as any);
|
|
153
|
+
},
|
|
154
|
+
enumerable: true,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
// Create transaction-aware store
|
|
160
|
+
const transactionStore: Store<C, R> = {
|
|
161
|
+
...store,
|
|
162
|
+
resources,
|
|
163
|
+
ensureArchetype: (componentNames) => {
|
|
164
|
+
const archetype = store.ensureArchetype(componentNames);
|
|
165
|
+
return getWrappedArchetype(archetype);
|
|
166
|
+
},
|
|
167
|
+
update: updateEntity,
|
|
168
|
+
delete: deleteEntity,
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// Execute transaction function
|
|
172
|
+
const execute = (
|
|
173
|
+
transactionFunction: (store: Store<C, R>) => Entity | void,
|
|
174
|
+
options?: {
|
|
175
|
+
transient?: boolean;
|
|
176
|
+
}
|
|
177
|
+
): TransactionResult<C> => {
|
|
178
|
+
// Reset transaction state
|
|
179
|
+
undoOperationsInReverseOrder = [];
|
|
180
|
+
redoOperations = [];
|
|
181
|
+
changed.entities.clear();
|
|
182
|
+
changed.components.clear();
|
|
183
|
+
changed.archetypes.clear();
|
|
184
|
+
|
|
185
|
+
try {
|
|
186
|
+
// Execute the transaction
|
|
187
|
+
const value = transactionFunction(transactionStore);
|
|
188
|
+
|
|
189
|
+
// Return the transaction result
|
|
190
|
+
const result: TransactionResult<C> = {
|
|
191
|
+
value: value ?? undefined,
|
|
192
|
+
transient: options?.transient ?? false,
|
|
193
|
+
redo: [...redoOperations],
|
|
194
|
+
undo: [...undoOperationsInReverseOrder.reverse()],
|
|
195
|
+
changedEntities: new Set(changed.entities),
|
|
196
|
+
changedComponents: new Set(changed.components),
|
|
197
|
+
changedArchetypes: new Set(changed.archetypes),
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
return result;
|
|
201
|
+
} catch (error) {
|
|
202
|
+
// Rollback on error by applying undo operations in reverse
|
|
203
|
+
applyWriteOperations(store, undoOperationsInReverseOrder.reverse());
|
|
204
|
+
throw error;
|
|
205
|
+
} finally {
|
|
206
|
+
// Clean up transaction state
|
|
207
|
+
undoOperationsInReverseOrder = [];
|
|
208
|
+
redoOperations = [];
|
|
209
|
+
changed.entities.clear();
|
|
210
|
+
changed.components.clear();
|
|
211
|
+
changed.archetypes.clear();
|
|
212
|
+
wrappedArchetypes.clear();
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
// Create the transactional store interface
|
|
217
|
+
const transactionalStore: TransactionalStore<C, R> = {
|
|
218
|
+
...store,
|
|
219
|
+
execute,
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
return transactionalStore as any;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Helper function to combine update operations for the same entity
|
|
226
|
+
function addUpdateOperationsMaybeCombineLast<C>(
|
|
227
|
+
undoOperationsInReverseOrder: TransactionWriteOperation<C>[],
|
|
228
|
+
redoOperations: TransactionWriteOperation<C>[],
|
|
229
|
+
entity: Entity,
|
|
230
|
+
values: EntityUpdateValues<C>,
|
|
231
|
+
replacedValues: EntityUpdateValues<C>
|
|
232
|
+
) {
|
|
233
|
+
const lastUndoOperation: TransactionWriteOperation<C> | undefined =
|
|
234
|
+
undoOperationsInReverseOrder[undoOperationsInReverseOrder.length - 1];
|
|
235
|
+
|
|
236
|
+
if (
|
|
237
|
+
lastUndoOperation?.type === "update" &&
|
|
238
|
+
lastUndoOperation.entity === entity
|
|
239
|
+
) {
|
|
240
|
+
// Combine with previous update operation
|
|
241
|
+
const lastRedoOperation = redoOperations[redoOperations.length - 1];
|
|
242
|
+
if (lastRedoOperation?.type === "update") {
|
|
243
|
+
lastRedoOperation.values = { ...lastRedoOperation.values, ...values };
|
|
244
|
+
lastUndoOperation.values = {
|
|
245
|
+
...replacedValues,
|
|
246
|
+
...lastUndoOperation.values,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
} else {
|
|
250
|
+
// Add new update operations
|
|
251
|
+
redoOperations.push({ type: "update", entity, values });
|
|
252
|
+
undoOperationsInReverseOrder.push({
|
|
253
|
+
type: "update",
|
|
254
|
+
entity,
|
|
255
|
+
values: replacedValues,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Helper function to apply write operations for rollback
|
|
261
|
+
function applyWriteOperations<C extends CoreComponents, R extends ResourceComponents>(
|
|
262
|
+
store: Store<C, R>,
|
|
263
|
+
operations: TransactionWriteOperation<C>[]
|
|
264
|
+
): void {
|
|
265
|
+
for (const operation of operations) {
|
|
266
|
+
switch (operation.type) {
|
|
267
|
+
case "insert": {
|
|
268
|
+
const componentNames = ["id", ...Object.keys(operation.values)] as StringKeyof<C>[];
|
|
269
|
+
const archetype = store.ensureArchetype(componentNames);
|
|
270
|
+
archetype.insert(operation.values);
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
case "update":
|
|
274
|
+
store.update(operation.entity, operation.values);
|
|
275
|
+
break;
|
|
276
|
+
case "delete":
|
|
277
|
+
store.delete(operation.entity);
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
@@ -19,5 +19,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
SOFTWARE.*/
|
|
22
|
-
export
|
|
23
|
-
//# sourceMappingURL=ecs-types.js.map
|
|
22
|
+
export * from "./transactional-store.js";
|
|
@@ -0,0 +1,80 @@
|
|
|
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 { ArchetypeId, EntityInsertValues } from "../../archetype/index.js";
|
|
23
|
+
import { CoreComponents } from "../../core-components.js";
|
|
24
|
+
import { ResourceComponents } from "../../store/resource-components.js";
|
|
25
|
+
import { ReadonlyStore, Store } from "../../store/index.js";
|
|
26
|
+
import { Entity } from "../../entity.js";
|
|
27
|
+
import { EntityUpdateValues } from "../../store/core/index.js";
|
|
28
|
+
|
|
29
|
+
export interface TransactionalStore<
|
|
30
|
+
C extends CoreComponents = CoreComponents,
|
|
31
|
+
R extends ResourceComponents = never
|
|
32
|
+
> extends ReadonlyStore<C, R> {
|
|
33
|
+
/**
|
|
34
|
+
* Execute a transaction on the store.
|
|
35
|
+
* The transactionFunction must NOT directly mutate archetype rows as those changes would not be captured.
|
|
36
|
+
* Instead, use the store's update and delete and archetype insert methods to make changes.
|
|
37
|
+
* @param transactionFunction - A function that takes the store as an argument and performs some operations on it.
|
|
38
|
+
* @returns A promise that resolves when the transaction is complete.
|
|
39
|
+
*/
|
|
40
|
+
execute(
|
|
41
|
+
transactionFunction: (store: Store<C, R>) => Entity | void,
|
|
42
|
+
options?: {
|
|
43
|
+
transient?: boolean;
|
|
44
|
+
}
|
|
45
|
+
): TransactionResult<C>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type TransactionInsertOperation<C> = {
|
|
49
|
+
type: "insert";
|
|
50
|
+
values: EntityInsertValues<C>;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export type TransactionUpdateOperation<C> = {
|
|
54
|
+
type: "update";
|
|
55
|
+
entity: Entity;
|
|
56
|
+
values: EntityUpdateValues<C>;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export type TransactionDeleteOperation = {
|
|
60
|
+
type: "delete";
|
|
61
|
+
entity: Entity
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export type TransactionWriteOperation<C> =
|
|
65
|
+
| TransactionInsertOperation<C>
|
|
66
|
+
| TransactionUpdateOperation<C>
|
|
67
|
+
| TransactionDeleteOperation;
|
|
68
|
+
|
|
69
|
+
export interface TransactionResult<C> {
|
|
70
|
+
/**
|
|
71
|
+
* The Entity value if any returned by the transaction function.
|
|
72
|
+
*/
|
|
73
|
+
readonly value: Entity | void;
|
|
74
|
+
readonly transient: boolean;
|
|
75
|
+
readonly redo: TransactionWriteOperation<C>[];
|
|
76
|
+
readonly undo: TransactionWriteOperation<C>[];
|
|
77
|
+
readonly changedEntities: Set<Entity>;
|
|
78
|
+
readonly changedComponents: Set<keyof C>;
|
|
79
|
+
readonly changedArchetypes: Set<ArchetypeId>;
|
|
80
|
+
}
|