joist-core 2.3.0-next.97 → 2.3.0-next.99
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/build/BaseEntity.cjs.map +1 -1
- package/build/BaseEntity.js.map +1 -1
- package/build/Entity.cjs.map +1 -1
- package/build/Entity.js.map +1 -1
- package/build/EntityManager.cjs +45 -46
- package/build/EntityManager.cjs.map +1 -1
- package/build/EntityManager.d.cts +7 -7
- package/build/EntityManager.d.cts.map +1 -1
- package/build/EntityManager.d.mts +7 -7
- package/build/EntityManager.d.mts.map +1 -1
- package/build/EntityManager.js +27 -28
- package/build/EntityManager.js.map +1 -1
- package/build/EntityMetadata.cjs +0 -2
- package/build/EntityMetadata.cjs.map +1 -1
- package/build/EntityMetadata.d.cts +3 -3
- package/build/EntityMetadata.d.mts +3 -3
- package/build/EntityMetadata.js +0 -2
- package/build/EntityMetadata.js.map +1 -1
- package/build/IndexManager.cjs +1 -1
- package/build/IndexManager.cjs.map +1 -1
- package/build/IndexManager.js +1 -1
- package/build/IndexManager.js.map +1 -1
- package/build/InstanceData.cjs.map +1 -1
- package/build/InstanceData.js.map +1 -1
- package/build/PluginManager.cjs +0 -1
- package/build/PluginManager.cjs.map +1 -1
- package/build/PluginManager.d.cts +1 -1
- package/build/PluginManager.d.mts +1 -1
- package/build/PluginManager.js +0 -1
- package/build/PluginManager.js.map +1 -1
- package/build/batchloaders/enumCollectionBatchLoader.cjs +1 -1
- package/build/batchloaders/enumCollectionBatchLoader.cjs.map +1 -1
- package/build/batchloaders/enumCollectionBatchLoader.d.cts +1 -1
- package/build/batchloaders/enumCollectionBatchLoader.d.mts +1 -1
- package/build/batchloaders/enumCollectionBatchLoader.js +1 -1
- package/build/batchloaders/enumCollectionBatchLoader.js.map +1 -1
- package/build/batchloaders/loadBatchLoader.cjs +3 -4
- package/build/batchloaders/loadBatchLoader.cjs.map +1 -1
- package/build/batchloaders/loadBatchLoader.d.cts +1 -1
- package/build/batchloaders/loadBatchLoader.d.mts +1 -1
- package/build/batchloaders/loadBatchLoader.js +2 -3
- package/build/batchloaders/loadBatchLoader.js.map +1 -1
- package/build/batchloaders/manyToManyBatchLoader.cjs +1 -1
- package/build/batchloaders/manyToManyBatchLoader.cjs.map +1 -1
- package/build/batchloaders/manyToManyBatchLoader.d.cts +1 -1
- package/build/batchloaders/manyToManyBatchLoader.d.mts +1 -1
- package/build/batchloaders/manyToManyBatchLoader.js +1 -1
- package/build/batchloaders/manyToManyBatchLoader.js.map +1 -1
- package/build/batchloaders/oneToManyBatchLoader.cjs +1 -1
- package/build/batchloaders/oneToManyBatchLoader.cjs.map +1 -1
- package/build/batchloaders/oneToManyBatchLoader.js +1 -1
- package/build/batchloaders/oneToManyBatchLoader.js.map +1 -1
- package/build/batchloaders/oneToOneBatchLoader.cjs +1 -1
- package/build/batchloaders/oneToOneBatchLoader.cjs.map +1 -1
- package/build/batchloaders/oneToOneBatchLoader.js +1 -1
- package/build/batchloaders/oneToOneBatchLoader.js.map +1 -1
- package/build/batchloaders/populateBatchLoader.cjs +11 -12
- package/build/batchloaders/populateBatchLoader.cjs.map +1 -1
- package/build/batchloaders/populateBatchLoader.d.cts +1 -1
- package/build/batchloaders/populateBatchLoader.d.mts +1 -1
- package/build/batchloaders/populateBatchLoader.js +7 -8
- package/build/batchloaders/populateBatchLoader.js.map +1 -1
- package/build/batchloaders/recursiveChildrenBatchLoader.cjs +2 -2
- package/build/batchloaders/recursiveChildrenBatchLoader.cjs.map +1 -1
- package/build/batchloaders/recursiveChildrenBatchLoader.js +2 -2
- package/build/batchloaders/recursiveChildrenBatchLoader.js.map +1 -1
- package/build/batchloaders/recursiveM2mBatchLoader.cjs +2 -2
- package/build/batchloaders/recursiveM2mBatchLoader.cjs.map +1 -1
- package/build/batchloaders/recursiveM2mBatchLoader.js +2 -2
- package/build/batchloaders/recursiveM2mBatchLoader.js.map +1 -1
- package/build/batchloaders/recursiveParentsBatchLoader.cjs +2 -2
- package/build/batchloaders/recursiveParentsBatchLoader.cjs.map +1 -1
- package/build/batchloaders/recursiveParentsBatchLoader.js +2 -2
- package/build/batchloaders/recursiveParentsBatchLoader.js.map +1 -1
- package/build/changes.cjs +2 -3
- package/build/changes.cjs.map +1 -1
- package/build/changes.js +2 -3
- package/build/changes.js.map +1 -1
- package/build/config.cjs +3 -3
- package/build/config.cjs.map +1 -1
- package/build/config.d.cts +2 -2
- package/build/config.d.mts +2 -2
- package/build/config.js +1 -1
- package/build/config.js.map +1 -1
- package/build/configure.cjs +10 -10
- package/build/configure.cjs.map +1 -1
- package/build/configure.js +5 -5
- package/build/configure.js.map +1 -1
- package/build/dataloaders/fastWhereFilterHash.cjs +8 -8
- package/build/dataloaders/fastWhereFilterHash.cjs.map +1 -1
- package/build/dataloaders/fastWhereFilterHash.d.cts.map +1 -1
- package/build/dataloaders/fastWhereFilterHash.d.mts.map +1 -1
- package/build/dataloaders/fastWhereFilterHash.js +3 -3
- package/build/dataloaders/fastWhereFilterHash.js.map +1 -1
- package/build/dataloaders/findByUniqueDataLoader.cjs.map +1 -1
- package/build/dataloaders/findByUniqueDataLoader.d.cts.map +1 -1
- package/build/dataloaders/findByUniqueDataLoader.d.mts.map +1 -1
- package/build/dataloaders/findByUniqueDataLoader.js.map +1 -1
- package/build/dataloaders/findCountDataLoader.cjs +2 -2
- package/build/dataloaders/findCountDataLoader.cjs.map +1 -1
- package/build/dataloaders/findCountDataLoader.js +1 -1
- package/build/dataloaders/findCountDataLoader.js.map +1 -1
- package/build/dataloaders/findDataLoader.cjs +6 -6
- package/build/dataloaders/findDataLoader.cjs.map +1 -1
- package/build/dataloaders/findDataLoader.d.cts +1 -1
- package/build/dataloaders/findDataLoader.d.mts +1 -1
- package/build/dataloaders/findDataLoader.js +3 -3
- package/build/dataloaders/findDataLoader.js.map +1 -1
- package/build/dataloaders/findIdsDataLoader.cjs +3 -3
- package/build/dataloaders/findIdsDataLoader.cjs.map +1 -1
- package/build/dataloaders/findIdsDataLoader.js +2 -2
- package/build/dataloaders/findIdsDataLoader.js.map +1 -1
- package/build/dataloaders/findOrCreateDataLoader.cjs +1 -1
- package/build/dataloaders/findOrCreateDataLoader.cjs.map +1 -1
- package/build/dataloaders/findOrCreateDataLoader.d.cts.map +1 -1
- package/build/dataloaders/findOrCreateDataLoader.d.mts.map +1 -1
- package/build/dataloaders/findOrCreateDataLoader.js +1 -1
- package/build/dataloaders/findOrCreateDataLoader.js.map +1 -1
- package/build/dataloaders/findPaginatedDataLoader.cjs +6 -6
- package/build/dataloaders/findPaginatedDataLoader.cjs.map +1 -1
- package/build/dataloaders/findPaginatedDataLoader.d.cts +1 -1
- package/build/dataloaders/findPaginatedDataLoader.d.mts +1 -1
- package/build/dataloaders/findPaginatedDataLoader.js +3 -3
- package/build/dataloaders/findPaginatedDataLoader.js.map +1 -1
- package/build/dataloaders/lensDataLoader.cjs +3 -3
- package/build/dataloaders/lensDataLoader.cjs.map +1 -1
- package/build/dataloaders/lensDataLoader.d.cts.map +1 -1
- package/build/dataloaders/lensDataLoader.d.mts.map +1 -1
- package/build/dataloaders/lensDataLoader.js +2 -2
- package/build/dataloaders/lensDataLoader.js.map +1 -1
- package/build/dataloaders/manyToManyFindDataLoader.cjs +1 -1
- package/build/dataloaders/manyToManyFindDataLoader.cjs.map +1 -1
- package/build/dataloaders/manyToManyFindDataLoader.d.cts.map +1 -1
- package/build/dataloaders/manyToManyFindDataLoader.d.mts.map +1 -1
- package/build/dataloaders/manyToManyFindDataLoader.js +1 -1
- package/build/dataloaders/manyToManyFindDataLoader.js.map +1 -1
- package/build/dataloaders/oneToManyFindDataLoader.cjs +1 -1
- package/build/dataloaders/oneToManyFindDataLoader.cjs.map +1 -1
- package/build/dataloaders/oneToManyFindDataLoader.d.cts.map +1 -1
- package/build/dataloaders/oneToManyFindDataLoader.d.mts.map +1 -1
- package/build/dataloaders/oneToManyFindDataLoader.js +1 -1
- package/build/dataloaders/oneToManyFindDataLoader.js.map +1 -1
- package/build/defaults.cjs +5 -5
- package/build/defaults.cjs.map +1 -1
- package/build/defaults.d.cts +1 -1
- package/build/defaults.d.cts.map +1 -1
- package/build/defaults.d.mts +1 -1
- package/build/defaults.d.mts.map +1 -1
- package/build/defaults.js +4 -4
- package/build/defaults.js.map +1 -1
- package/build/drivers/Driver.cjs +0 -1
- package/build/drivers/Driver.d.cts +1 -1
- package/build/drivers/Driver.d.mts +1 -1
- package/build/drivers/Driver.js +0 -1
- package/build/drivers/EntityWriter.cjs +6 -7
- package/build/drivers/EntityWriter.cjs.map +1 -1
- package/build/drivers/EntityWriter.d.cts +1 -1
- package/build/drivers/EntityWriter.d.mts +1 -1
- package/build/drivers/EntityWriter.js +2 -3
- package/build/drivers/EntityWriter.js.map +1 -1
- package/build/drivers/IdAssigner.cjs +0 -1
- package/build/drivers/IdAssigner.cjs.map +1 -1
- package/build/drivers/IdAssigner.d.cts +1 -1
- package/build/drivers/IdAssigner.d.mts +1 -1
- package/build/drivers/IdAssigner.js +0 -1
- package/build/drivers/IdAssigner.js.map +1 -1
- package/build/drivers/driverApi.cjs +19 -0
- package/build/drivers/driverApi.cjs.map +1 -0
- package/build/drivers/driverApi.d.cts +22 -0
- package/build/drivers/driverApi.d.cts.map +1 -0
- package/build/drivers/driverApi.d.mts +22 -0
- package/build/drivers/driverApi.d.mts.map +1 -0
- package/build/drivers/driverApi.js +18 -0
- package/build/drivers/driverApi.js.map +1 -0
- package/build/fields.cjs +3 -3
- package/build/fields.cjs.map +1 -1
- package/build/fields.js +2 -2
- package/build/fields.js.map +1 -1
- package/build/{FlushLock.cjs → flush/FlushLock.cjs} +1 -1
- package/build/flush/FlushLock.cjs.map +1 -0
- package/build/{FlushLock.d.cts → flush/FlushLock.d.cts} +1 -1
- package/build/flush/FlushLock.d.cts.map +1 -0
- package/build/{FlushLock.d.mts → flush/FlushLock.d.mts} +1 -1
- package/build/flush/FlushLock.d.mts.map +1 -0
- package/build/{FlushLock.js → flush/FlushLock.js} +1 -1
- package/build/flush/FlushLock.js.map +1 -0
- package/build/{JoinRows.cjs → flush/JoinRows.cjs} +5 -8
- package/build/flush/JoinRows.cjs.map +1 -0
- package/build/{JoinRows.d.cts → flush/JoinRows.d.cts} +5 -5
- package/build/flush/JoinRows.d.cts.map +1 -0
- package/build/{JoinRows.d.mts → flush/JoinRows.d.mts} +5 -5
- package/build/flush/JoinRows.d.mts.map +1 -0
- package/build/{JoinRows.js → flush/JoinRows.js} +5 -8
- package/build/flush/JoinRows.js.map +1 -0
- package/build/{PendingChanges.cjs → flush/PendingChanges.cjs} +0 -1
- package/build/{PendingChanges.d.cts → flush/PendingChanges.d.cts} +2 -2
- package/build/flush/PendingChanges.d.cts.map +1 -0
- package/build/{PendingChanges.d.mts → flush/PendingChanges.d.mts} +2 -2
- package/build/flush/PendingChanges.d.mts.map +1 -0
- package/build/flush/PendingChanges.js +1 -0
- package/build/{Todo.cjs → flush/Todo.cjs} +4 -6
- package/build/flush/Todo.cjs.map +1 -0
- package/build/{Todo.d.cts → flush/Todo.d.cts} +3 -3
- package/build/flush/Todo.d.cts.map +1 -0
- package/build/{Todo.d.mts → flush/Todo.d.mts} +3 -3
- package/build/flush/Todo.d.mts.map +1 -0
- package/build/{Todo.js → flush/Todo.js} +4 -6
- package/build/flush/Todo.js.map +1 -0
- package/build/getProperties.cjs.map +1 -1
- package/build/getProperties.js.map +1 -1
- package/build/index.cjs +100 -100
- package/build/index.cjs.map +1 -1
- package/build/index.d.cts +15 -15
- package/build/index.d.mts +15 -15
- package/build/index.js +42 -42
- package/build/index.js.map +1 -1
- package/build/json.cjs +4 -4
- package/build/json.cjs.map +1 -1
- package/build/json.js +3 -3
- package/build/json.js.map +1 -1
- package/build/keys.cjs +1 -1
- package/build/keys.cjs.map +1 -1
- package/build/keys.js +1 -1
- package/build/keys.js.map +1 -1
- package/build/{HintTree.cjs → loading/HintTree.cjs} +2 -5
- package/build/loading/HintTree.cjs.map +1 -0
- package/build/{HintTree.d.cts → loading/HintTree.d.cts} +3 -3
- package/build/loading/HintTree.d.cts.map +1 -0
- package/build/{HintTree.d.mts → loading/HintTree.d.mts} +3 -3
- package/build/loading/HintTree.d.mts.map +1 -0
- package/build/{HintTree.js → loading/HintTree.js} +2 -5
- package/build/loading/HintTree.js.map +1 -0
- package/build/{IsLoadedCache.cjs → loading/IsLoadedCache.cjs} +2 -3
- package/build/loading/IsLoadedCache.cjs.map +1 -0
- package/build/{IsLoadedCache.d.cts → loading/IsLoadedCache.d.cts} +2 -2
- package/build/loading/IsLoadedCache.d.cts.map +1 -0
- package/build/{IsLoadedCache.d.mts → loading/IsLoadedCache.d.mts} +2 -2
- package/build/loading/IsLoadedCache.d.mts.map +1 -0
- package/build/{IsLoadedCache.js → loading/IsLoadedCache.js} +2 -3
- package/build/{IsLoadedCache.cjs.map → loading/IsLoadedCache.js.map} +1 -1
- package/build/{loadHints.cjs → loading/loadHints.cjs} +6 -11
- package/build/loading/loadHints.cjs.map +1 -0
- package/build/{loadHints.d.cts → loading/loadHints.d.cts} +14 -14
- package/build/loading/loadHints.d.cts.map +1 -0
- package/build/{loadHints.d.mts → loading/loadHints.d.mts} +14 -14
- package/build/loading/loadHints.d.mts.map +1 -0
- package/build/{loadHints.js → loading/loadHints.js} +3 -8
- package/build/loading/loadHints.js.map +1 -0
- package/build/{loadLens.cjs → loading/loadLens.cjs} +8 -9
- package/build/loading/loadLens.cjs.map +1 -0
- package/build/{loadLens.d.cts → loading/loadLens.d.cts} +3 -3
- package/build/loading/loadLens.d.cts.map +1 -0
- package/build/{loadLens.d.mts → loading/loadLens.d.mts} +3 -3
- package/build/loading/loadLens.d.mts.map +1 -0
- package/build/{loadLens.js → loading/loadLens.js} +8 -9
- package/build/loading/loadLens.js.map +1 -0
- package/build/{withLoaded.cjs → loading/withLoaded.cjs} +12 -13
- package/build/loading/withLoaded.cjs.map +1 -0
- package/build/{withLoaded.d.cts → loading/withLoaded.d.cts} +9 -9
- package/build/loading/withLoaded.d.cts.map +1 -0
- package/build/{withLoaded.d.mts → loading/withLoaded.d.mts} +9 -9
- package/build/loading/withLoaded.d.mts.map +1 -0
- package/build/{withLoaded.js → loading/withLoaded.js} +10 -11
- package/build/loading/withLoaded.js.map +1 -0
- package/build/logging/FactoryLogger.cjs.map +1 -1
- package/build/logging/FactoryLogger.d.cts.map +1 -1
- package/build/logging/FactoryLogger.d.mts.map +1 -1
- package/build/logging/FactoryLogger.js.map +1 -1
- package/build/logging/FieldLogger.cjs.map +1 -1
- package/build/logging/FieldLogger.d.cts.map +1 -1
- package/build/logging/FieldLogger.d.mts.map +1 -1
- package/build/logging/FieldLogger.js.map +1 -1
- package/build/logging/ReactionLogger.cjs +0 -2
- package/build/logging/ReactionLogger.cjs.map +1 -1
- package/build/logging/ReactionLogger.d.cts +2 -2
- package/build/logging/ReactionLogger.d.cts.map +1 -1
- package/build/logging/ReactionLogger.d.mts +2 -2
- package/build/logging/ReactionLogger.d.mts.map +1 -1
- package/build/logging/ReactionLogger.js +0 -2
- package/build/logging/ReactionLogger.js.map +1 -1
- package/build/newEntity.cjs.map +1 -1
- package/build/newEntity.js.map +1 -1
- package/build/newTestInstance.cjs +3 -3
- package/build/newTestInstance.cjs.map +1 -1
- package/build/newTestInstance.d.cts +1 -1
- package/build/newTestInstance.d.cts.map +1 -1
- package/build/newTestInstance.d.mts +1 -1
- package/build/newTestInstance.d.mts.map +1 -1
- package/build/newTestInstance.js +2 -2
- package/build/newTestInstance.js.map +1 -1
- package/build/normalizeHints.cjs +0 -2
- package/build/normalizeHints.cjs.map +1 -1
- package/build/normalizeHints.d.cts +2 -2
- package/build/normalizeHints.d.mts +2 -2
- package/build/normalizeHints.js +0 -2
- package/build/normalizeHints.js.map +1 -1
- package/build/nowUTC.cjs +2 -2
- package/build/nowUTC.cjs.map +1 -1
- package/build/nowUTC.d.cts +1 -1
- package/build/nowUTC.d.mts +1 -1
- package/build/nowUTC.js +1 -1
- package/build/nowUTC.js.map +1 -1
- package/build/plugins/ImmutableEntitiesPlugin.cjs.map +1 -1
- package/build/plugins/ImmutableEntitiesPlugin.js.map +1 -1
- package/build/plugins/PreloadPlugin.cjs +0 -2
- package/build/plugins/PreloadPlugin.d.cts +2 -2
- package/build/plugins/PreloadPlugin.d.mts +2 -2
- package/build/plugins/PreloadPlugin.js +0 -2
- package/build/preloading/JsonAggregatePreloader.cjs +1 -4
- package/build/preloading/JsonAggregatePreloader.cjs.map +1 -1
- package/build/preloading/JsonAggregatePreloader.d.cts +2 -2
- package/build/preloading/JsonAggregatePreloader.d.cts.map +1 -1
- package/build/preloading/JsonAggregatePreloader.d.mts +2 -2
- package/build/preloading/JsonAggregatePreloader.d.mts.map +1 -1
- package/build/preloading/JsonAggregatePreloader.js +1 -4
- package/build/preloading/JsonAggregatePreloader.js.map +1 -1
- package/build/preloading/canPreload.cjs.map +1 -1
- package/build/preloading/canPreload.js.map +1 -1
- package/build/preloading/partitionHint.cjs +2 -3
- package/build/preloading/partitionHint.cjs.map +1 -1
- package/build/preloading/partitionHint.d.cts +1 -1
- package/build/preloading/partitionHint.d.mts +1 -1
- package/build/preloading/partitionHint.js +2 -3
- package/build/preloading/partitionHint.js.map +1 -1
- package/build/queries/ConditionBuilder.cjs.map +1 -1
- package/build/queries/ConditionBuilder.d.cts +1 -1
- package/build/queries/ConditionBuilder.d.mts +1 -1
- package/build/queries/ConditionBuilder.js.map +1 -1
- package/build/queries/conditions.cjs.map +1 -1
- package/build/queries/conditions.js.map +1 -1
- package/build/queries/entityQueryUtils.cjs.map +1 -1
- package/build/queries/entityQueryUtils.js.map +1 -1
- package/build/queries/find/Aliases.cjs +1 -1
- package/build/queries/find/Aliases.cjs.map +1 -1
- package/build/queries/find/Aliases.d.cts.map +1 -1
- package/build/queries/find/Aliases.d.mts.map +1 -1
- package/build/queries/find/Aliases.js +1 -1
- package/build/queries/find/Aliases.js.map +1 -1
- package/build/queries/find/DeferredAlias.cjs.map +1 -1
- package/build/queries/find/DeferredAlias.js.map +1 -1
- package/build/queries/find/EntityFilter.cjs.map +1 -1
- package/build/queries/find/EntityFilter.js.map +1 -1
- package/build/queries/find/EntityGraphQLFilter.cjs.map +1 -1
- package/build/queries/find/EntityGraphQLFilter.js.map +1 -1
- package/build/queries/find/QueryParser.cjs +2 -2
- package/build/queries/find/QueryParser.cjs.map +1 -1
- package/build/queries/find/QueryParser.collectionJoins.cjs.map +1 -1
- package/build/queries/find/QueryParser.collectionJoins.js.map +1 -1
- package/build/queries/find/QueryParser.d.cts.map +1 -1
- package/build/queries/find/QueryParser.d.mts.map +1 -1
- package/build/queries/find/QueryParser.js +2 -2
- package/build/queries/find/QueryParser.js.map +1 -1
- package/build/queries/find/QueryParser.pruning.cjs.map +1 -1
- package/build/queries/find/QueryParser.pruning.js.map +1 -1
- package/build/queries/find/QueryVisitor.cjs.map +1 -1
- package/build/queries/find/QueryVisitor.js.map +1 -1
- package/build/queries/find/buildFindQuery.cjs.map +1 -1
- package/build/queries/find/buildFindQuery.js.map +1 -1
- package/build/queries/find/scopes.cjs.map +1 -1
- package/build/queries/find/scopes.d.cts +1 -1
- package/build/queries/find/scopes.d.mts +1 -1
- package/build/queries/find/scopes.js.map +1 -1
- package/build/queries/parsedConditions.cjs.map +1 -1
- package/build/queries/parsedConditions.js.map +1 -1
- package/build/queries/renderConditions.cjs.map +1 -1
- package/build/queries/renderConditions.js.map +1 -1
- package/build/queries/skipCondition.cjs.map +1 -1
- package/build/queries/skipCondition.js.map +1 -1
- package/build/queries/sql/AliasAssigner.cjs.map +1 -1
- package/build/queries/sql/AliasAssigner.js.map +1 -1
- package/build/queries/sql/Expr.cjs +2 -2
- package/build/queries/sql/Expr.cjs.map +1 -1
- package/build/queries/sql/Expr.d.cts +1 -1
- package/build/queries/sql/Expr.d.mts +1 -1
- package/build/queries/sql/Expr.js +1 -1
- package/build/queries/sql/Expr.js.map +1 -1
- package/build/queries/sql/Tables.cjs +1 -1
- package/build/queries/sql/Tables.cjs.map +1 -1
- package/build/queries/sql/Tables.d.cts.map +1 -1
- package/build/queries/sql/Tables.d.mts.map +1 -1
- package/build/queries/sql/Tables.js +1 -1
- package/build/queries/sql/Tables.js.map +1 -1
- package/build/queries/sql/execute.cjs +1 -1
- package/build/queries/sql/execute.cjs.map +1 -1
- package/build/queries/sql/execute.js +1 -1
- package/build/queries/sql/execute.js.map +1 -1
- package/build/queries/sql/expressions/arrayAgg.cjs.map +1 -1
- package/build/queries/sql/expressions/arrayAgg.js.map +1 -1
- package/build/queries/sql/expressions/case.cjs.map +1 -1
- package/build/queries/sql/expressions/case.js.map +1 -1
- package/build/queries/sql/expressions/coalesce.cjs.map +1 -1
- package/build/queries/sql/expressions/coalesce.js.map +1 -1
- package/build/queries/sql/expressions/codecs.cjs +2 -2
- package/build/queries/sql/expressions/codecs.cjs.map +1 -1
- package/build/queries/sql/expressions/codecs.js +1 -1
- package/build/queries/sql/expressions/codecs.js.map +1 -1
- package/build/queries/sql/expressions/expression.cjs.map +1 -1
- package/build/queries/sql/expressions/expression.d.cts.map +1 -1
- package/build/queries/sql/expressions/expression.d.mts.map +1 -1
- package/build/queries/sql/expressions/expression.js.map +1 -1
- package/build/queries/sql/expressions/greatest.cjs.map +1 -1
- package/build/queries/sql/expressions/greatest.js.map +1 -1
- package/build/queries/sql/expressions/least.cjs.map +1 -1
- package/build/queries/sql/expressions/least.js.map +1 -1
- package/build/queries/sql/expressions/nullIf.cjs.map +1 -1
- package/build/queries/sql/expressions/nullIf.js.map +1 -1
- package/build/queries/sql/expressions/parseExpression.cjs.map +1 -1
- package/build/queries/sql/expressions/parseExpression.js.map +1 -1
- package/build/queries/sql/expressions/types.d.cts.map +1 -1
- package/build/queries/sql/expressions/types.d.mts.map +1 -1
- package/build/queries/sql/query.cjs +1 -1
- package/build/queries/sql/query.cjs.map +1 -1
- package/build/queries/sql/query.d.cts +1 -1
- package/build/queries/sql/query.d.mts +1 -1
- package/build/queries/sql/query.js +1 -1
- package/build/queries/sql/query.js.map +1 -1
- package/build/{unnest.cjs → queries/unnest.cjs} +1 -2
- package/build/queries/unnest.cjs.map +1 -0
- package/build/{unnest.d.cts → queries/unnest.d.cts} +3 -3
- package/build/queries/unnest.d.cts.map +1 -0
- package/build/{unnest.d.mts → queries/unnest.d.mts} +3 -3
- package/build/queries/unnest.d.mts.map +1 -0
- package/build/{unnest.js → queries/unnest.js} +1 -2
- package/build/queries/unnest.js.map +1 -0
- package/build/queries/valueFilters.cjs.map +1 -1
- package/build/queries/valueFilters.d.cts +1 -1
- package/build/queries/valueFilters.d.cts.map +1 -1
- package/build/queries/valueFilters.d.mts +1 -1
- package/build/queries/valueFilters.d.mts.map +1 -1
- package/build/queries/valueFilters.js.map +1 -1
- package/build/{ReactionsManager.cjs → reactivity/ReactionsManager.cjs} +8 -10
- package/build/reactivity/ReactionsManager.cjs.map +1 -0
- package/build/{ReactionsManager.d.cts → reactivity/ReactionsManager.d.cts} +5 -6
- package/build/reactivity/ReactionsManager.d.cts.map +1 -0
- package/build/{ReactionsManager.d.mts → reactivity/ReactionsManager.d.mts} +5 -6
- package/build/reactivity/ReactionsManager.d.mts.map +1 -0
- package/build/{ReactionsManager.js → reactivity/ReactionsManager.js} +6 -8
- package/build/reactivity/ReactionsManager.js.map +1 -0
- package/build/{reactiveHints.cjs → reactivity/reactiveHints.cjs} +12 -16
- package/build/reactivity/reactiveHints.cjs.map +1 -0
- package/build/{reactiveHints.d.cts → reactivity/reactiveHints.d.cts} +17 -17
- package/build/reactivity/reactiveHints.d.cts.map +1 -0
- package/build/{reactiveHints.d.mts → reactivity/reactiveHints.d.mts} +17 -17
- package/build/reactivity/reactiveHints.d.mts.map +1 -0
- package/build/{reactiveHints.js → reactivity/reactiveHints.js} +12 -16
- package/build/reactivity/reactiveHints.js.map +1 -0
- package/build/relations/AbstractRelationImpl.cjs.map +1 -1
- package/build/relations/AbstractRelationImpl.js.map +1 -1
- package/build/relations/AsyncProperty.cjs.map +1 -1
- package/build/relations/AsyncProperty.js.map +1 -1
- package/build/relations/AsyncReactiveField.cjs +6 -6
- package/build/relations/AsyncReactiveField.cjs.map +1 -1
- package/build/relations/AsyncReactiveField.d.cts +1 -1
- package/build/relations/AsyncReactiveField.d.mts +1 -1
- package/build/relations/AsyncReactiveField.js +4 -4
- package/build/relations/AsyncReactiveField.js.map +1 -1
- package/build/relations/Collection.cjs +1 -1
- package/build/relations/Collection.cjs.map +1 -1
- package/build/relations/Collection.js +1 -1
- package/build/relations/Collection.js.map +1 -1
- package/build/relations/CustomCollection.cjs.map +1 -1
- package/build/relations/CustomCollection.d.cts +1 -1
- package/build/relations/CustomCollection.d.mts +1 -1
- package/build/relations/CustomCollection.js.map +1 -1
- package/build/relations/CustomReference.cjs +1 -1
- package/build/relations/CustomReference.cjs.map +1 -1
- package/build/relations/CustomReference.d.cts +1 -1
- package/build/relations/CustomReference.d.mts +1 -1
- package/build/relations/CustomReference.js +1 -1
- package/build/relations/CustomReference.js.map +1 -1
- package/build/relations/EnumCollection.cjs.map +1 -1
- package/build/relations/EnumCollection.d.cts +1 -1
- package/build/relations/EnumCollection.d.mts +1 -1
- package/build/relations/EnumCollection.js.map +1 -1
- package/build/relations/LazyField.cjs +4 -4
- package/build/relations/LazyField.cjs.map +1 -1
- package/build/relations/LazyField.js +4 -4
- package/build/relations/LazyField.js.map +1 -1
- package/build/relations/ManyToManyCollection.cjs +3 -3
- package/build/relations/ManyToManyCollection.cjs.map +1 -1
- package/build/relations/ManyToManyCollection.js +3 -3
- package/build/relations/ManyToManyCollection.js.map +1 -1
- package/build/relations/ManyToManyLargeCollection.cjs +3 -3
- package/build/relations/ManyToManyLargeCollection.cjs.map +1 -1
- package/build/relations/ManyToManyLargeCollection.js +3 -3
- package/build/relations/ManyToManyLargeCollection.js.map +1 -1
- package/build/relations/ManyToOneReference.cjs +4 -4
- package/build/relations/ManyToOneReference.cjs.map +1 -1
- package/build/relations/ManyToOneReference.js +4 -4
- package/build/relations/ManyToOneReference.js.map +1 -1
- package/build/relations/OneToManyCollection.cjs +1 -2
- package/build/relations/OneToManyCollection.cjs.map +1 -1
- package/build/relations/OneToManyCollection.d.cts +1 -1
- package/build/relations/OneToManyCollection.d.mts +1 -1
- package/build/relations/OneToManyCollection.js +1 -2
- package/build/relations/OneToManyCollection.js.map +1 -1
- package/build/relations/OneToManyLargeCollection.cjs +1 -1
- package/build/relations/OneToManyLargeCollection.cjs.map +1 -1
- package/build/relations/OneToManyLargeCollection.js +1 -1
- package/build/relations/OneToManyLargeCollection.js.map +1 -1
- package/build/relations/OneToOneReference.cjs +5 -5
- package/build/relations/OneToOneReference.cjs.map +1 -1
- package/build/relations/OneToOneReference.js +5 -5
- package/build/relations/OneToOneReference.js.map +1 -1
- package/build/relations/PolymorphicReference.cjs +3 -3
- package/build/relations/PolymorphicReference.cjs.map +1 -1
- package/build/relations/PolymorphicReference.js +3 -3
- package/build/relations/PolymorphicReference.js.map +1 -1
- package/build/relations/ReactiveField.cjs +5 -6
- package/build/relations/ReactiveField.cjs.map +1 -1
- package/build/relations/ReactiveField.d.cts +2 -2
- package/build/relations/ReactiveField.d.mts +2 -2
- package/build/relations/ReactiveField.js +3 -4
- package/build/relations/ReactiveField.js.map +1 -1
- package/build/relations/ReactiveGetter.cjs +0 -1
- package/build/relations/ReactiveGetter.cjs.map +1 -1
- package/build/relations/ReactiveGetter.d.cts +1 -1
- package/build/relations/ReactiveGetter.d.mts +1 -1
- package/build/relations/ReactiveGetter.js +0 -1
- package/build/relations/ReactiveGetter.js.map +1 -1
- package/build/relations/ReactiveManyToMany.cjs +5 -6
- package/build/relations/ReactiveManyToMany.cjs.map +1 -1
- package/build/relations/ReactiveManyToMany.d.cts +2 -2
- package/build/relations/ReactiveManyToMany.d.cts.map +1 -1
- package/build/relations/ReactiveManyToMany.d.mts +2 -2
- package/build/relations/ReactiveManyToMany.d.mts.map +1 -1
- package/build/relations/ReactiveManyToMany.js +3 -4
- package/build/relations/ReactiveManyToMany.js.map +1 -1
- package/build/relations/ReactiveManyToManyOtherSide.cjs +1 -3
- package/build/relations/ReactiveManyToManyOtherSide.cjs.map +1 -1
- package/build/relations/ReactiveManyToManyOtherSide.d.cts +2 -2
- package/build/relations/ReactiveManyToManyOtherSide.d.mts +2 -2
- package/build/relations/ReactiveManyToManyOtherSide.js +1 -3
- package/build/relations/ReactiveManyToManyOtherSide.js.map +1 -1
- package/build/relations/ReactiveReference.cjs +8 -9
- package/build/relations/ReactiveReference.cjs.map +1 -1
- package/build/relations/ReactiveReference.d.cts +2 -2
- package/build/relations/ReactiveReference.d.cts.map +1 -1
- package/build/relations/ReactiveReference.d.mts +2 -2
- package/build/relations/ReactiveReference.d.mts.map +1 -1
- package/build/relations/ReactiveReference.js +6 -7
- package/build/relations/ReactiveReference.js.map +1 -1
- package/build/relations/ReadOnlyCollection.cjs.map +1 -1
- package/build/relations/ReadOnlyCollection.js.map +1 -1
- package/build/relations/RecursiveCollection.cjs +3 -4
- package/build/relations/RecursiveCollection.cjs.map +1 -1
- package/build/relations/RecursiveCollection.d.cts +1 -1
- package/build/relations/RecursiveCollection.d.mts +1 -1
- package/build/relations/RecursiveCollection.js +3 -4
- package/build/relations/RecursiveCollection.js.map +1 -1
- package/build/relations/RecursiveCycleError.cjs.map +1 -1
- package/build/relations/RecursiveCycleError.js.map +1 -1
- package/build/relations/Reference.cjs +1 -1
- package/build/relations/Reference.cjs.map +1 -1
- package/build/relations/Reference.js +1 -1
- package/build/relations/Reference.js.map +1 -1
- package/build/relations/Relation.cjs.map +1 -1
- package/build/relations/Relation.js.map +1 -1
- package/build/relations/hasAsyncMethod.cjs +2 -2
- package/build/relations/hasAsyncMethod.cjs.map +1 -1
- package/build/relations/hasAsyncMethod.d.cts +1 -1
- package/build/relations/hasAsyncMethod.d.mts +1 -1
- package/build/relations/hasAsyncMethod.js +1 -1
- package/build/relations/hasAsyncMethod.js.map +1 -1
- package/build/relations/hasManyDerived.cjs +3 -3
- package/build/relations/hasManyDerived.cjs.map +1 -1
- package/build/relations/hasManyDerived.d.cts +1 -1
- package/build/relations/hasManyDerived.d.mts +1 -1
- package/build/relations/hasManyDerived.js +2 -2
- package/build/relations/hasManyDerived.js.map +1 -1
- package/build/relations/hasManyThrough.cjs +6 -6
- package/build/relations/hasManyThrough.cjs.map +1 -1
- package/build/relations/hasManyThrough.d.cts +1 -1
- package/build/relations/hasManyThrough.d.mts +1 -1
- package/build/relations/hasManyThrough.js +2 -2
- package/build/relations/hasManyThrough.js.map +1 -1
- package/build/relations/hasOneDerived.cjs +3 -3
- package/build/relations/hasOneDerived.cjs.map +1 -1
- package/build/relations/hasOneDerived.d.cts +1 -1
- package/build/relations/hasOneDerived.d.mts +1 -1
- package/build/relations/hasOneDerived.js +2 -2
- package/build/relations/hasOneDerived.js.map +1 -1
- package/build/relations/hasOneThrough.cjs +7 -7
- package/build/relations/hasOneThrough.cjs.map +1 -1
- package/build/relations/hasOneThrough.d.cts +1 -1
- package/build/relations/hasOneThrough.d.mts +1 -1
- package/build/relations/hasOneThrough.js +2 -2
- package/build/relations/hasOneThrough.js.map +1 -1
- package/build/relations/hasProperty.cjs +4 -4
- package/build/relations/hasProperty.cjs.map +1 -1
- package/build/relations/hasProperty.d.cts +2 -2
- package/build/relations/hasProperty.d.mts +2 -2
- package/build/relations/hasProperty.js +2 -2
- package/build/relations/hasProperty.js.map +1 -1
- package/build/relations/index.cjs +10 -10
- package/build/relations/index.js +10 -10
- package/build/relations/isCascadeDelete.cjs.map +1 -1
- package/build/relations/isCascadeDelete.js.map +1 -1
- package/build/resurrection.cjs.map +1 -1
- package/build/resurrection.js.map +1 -1
- package/build/rules.cjs +3 -4
- package/build/rules.cjs.map +1 -1
- package/build/rules.d.cts +1 -1
- package/build/rules.d.mts +1 -1
- package/build/rules.js +3 -4
- package/build/rules.js.map +1 -1
- package/build/runtimeConfig.cjs.map +1 -1
- package/build/runtimeConfig.js.map +1 -1
- package/build/{TypeInfo.cjs → serde/TypeInfo.cjs} +1 -1
- package/build/serde/TypeInfo.cjs.map +1 -0
- package/build/{TypeInfo.d.cts → serde/TypeInfo.d.cts} +2 -2
- package/build/serde/TypeInfo.d.cts.map +1 -0
- package/build/{TypeInfo.d.mts → serde/TypeInfo.d.mts} +2 -2
- package/build/serde/TypeInfo.d.mts.map +1 -0
- package/build/{TypeInfo.js → serde/TypeInfo.js} +1 -1
- package/build/serde/TypeInfo.js.map +1 -0
- package/build/{columns.cjs → serde/columns.cjs} +1 -1
- package/build/serde/columns.cjs.map +1 -0
- package/build/{columns.d.cts → serde/columns.d.cts} +2 -2
- package/build/serde/columns.d.cts.map +1 -0
- package/build/{columns.d.mts → serde/columns.d.mts} +2 -2
- package/build/serde/columns.d.mts.map +1 -0
- package/build/{columns.js → serde/columns.js} +1 -1
- package/build/serde/columns.js.map +1 -0
- package/build/{fieldSerde.cjs → serde/fieldSerde.cjs} +6 -6
- package/build/serde/fieldSerde.cjs.map +1 -0
- package/build/{fieldSerde.d.cts → serde/fieldSerde.d.cts} +5 -5
- package/build/serde/fieldSerde.d.cts.map +1 -0
- package/build/{fieldSerde.d.mts → serde/fieldSerde.d.mts} +5 -5
- package/build/serde/fieldSerde.d.mts.map +1 -0
- package/build/{fieldSerde.js → serde/fieldSerde.js} +6 -6
- package/build/serde/fieldSerde.js.map +1 -0
- package/build/{serde.cjs → serde/serde.cjs} +25 -26
- package/build/serde/serde.cjs.map +1 -0
- package/build/{serde.d.cts → serde/serde.d.cts} +1 -1
- package/build/serde/serde.d.cts.map +1 -0
- package/build/{serde.d.mts → serde/serde.d.mts} +1 -1
- package/build/serde/serde.d.mts.map +1 -0
- package/build/{serde.js → serde/serde.js} +4 -5
- package/build/serde/serde.js.map +1 -0
- package/build/{temporal.cjs → serde/temporal.cjs} +1 -1
- package/build/serde/temporal.cjs.map +1 -0
- package/build/{temporal.d.cts → serde/temporal.d.cts} +1 -1
- package/build/serde/temporal.d.cts.map +1 -0
- package/build/{temporal.d.mts → serde/temporal.d.mts} +1 -1
- package/build/serde/temporal.d.mts.map +1 -0
- package/build/{temporal.js → serde/temporal.js} +1 -1
- package/build/serde/temporal.js.map +1 -0
- package/build/{temporalMappers.cjs → serde/temporalMappers.cjs} +4 -5
- package/build/serde/temporalMappers.cjs.map +1 -0
- package/build/{temporalMappers.d.cts → serde/temporalMappers.d.cts} +1 -1
- package/build/serde/temporalMappers.d.cts.map +1 -0
- package/build/{temporalMappers.d.mts → serde/temporalMappers.d.mts} +1 -1
- package/build/serde/temporalMappers.d.mts.map +1 -0
- package/build/{temporalMappers.js → serde/temporalMappers.js} +2 -3
- package/build/serde/temporalMappers.js.map +1 -0
- package/build/upsert.cjs +1 -1
- package/build/upsert.cjs.map +1 -1
- package/build/upsert.d.cts.map +1 -1
- package/build/upsert.d.mts.map +1 -1
- package/build/upsert.js +1 -1
- package/build/upsert.js.map +1 -1
- package/build/utils.cjs +0 -1
- package/build/utils.cjs.map +1 -1
- package/build/utils.d.cts +1 -1
- package/build/utils.d.mts +1 -1
- package/build/utils.js +0 -1
- package/build/utils.js.map +1 -1
- package/package.json +2 -2
- package/build/FlushLock.cjs.map +0 -1
- package/build/FlushLock.d.cts.map +0 -1
- package/build/FlushLock.d.mts.map +0 -1
- package/build/FlushLock.js.map +0 -1
- package/build/HintTree.cjs.map +0 -1
- package/build/HintTree.d.cts.map +0 -1
- package/build/HintTree.d.mts.map +0 -1
- package/build/HintTree.js.map +0 -1
- package/build/IsLoadedCache.d.cts.map +0 -1
- package/build/IsLoadedCache.d.mts.map +0 -1
- package/build/IsLoadedCache.js.map +0 -1
- package/build/JoinRows.cjs.map +0 -1
- package/build/JoinRows.d.cts.map +0 -1
- package/build/JoinRows.d.mts.map +0 -1
- package/build/JoinRows.js.map +0 -1
- package/build/PendingChanges.d.cts.map +0 -1
- package/build/PendingChanges.d.mts.map +0 -1
- package/build/PendingChanges.js +0 -2
- package/build/ReactionsManager.cjs.map +0 -1
- package/build/ReactionsManager.d.cts.map +0 -1
- package/build/ReactionsManager.d.mts.map +0 -1
- package/build/ReactionsManager.js.map +0 -1
- package/build/Todo.cjs.map +0 -1
- package/build/Todo.d.cts.map +0 -1
- package/build/Todo.d.mts.map +0 -1
- package/build/Todo.js.map +0 -1
- package/build/TypeInfo.cjs.map +0 -1
- package/build/TypeInfo.d.cts.map +0 -1
- package/build/TypeInfo.d.mts.map +0 -1
- package/build/TypeInfo.js.map +0 -1
- package/build/columns.cjs.map +0 -1
- package/build/columns.d.cts.map +0 -1
- package/build/columns.d.mts.map +0 -1
- package/build/columns.js.map +0 -1
- package/build/driverApi.cjs +0 -18
- package/build/driverApi.cjs.map +0 -1
- package/build/driverApi.d.cts +0 -22
- package/build/driverApi.d.cts.map +0 -1
- package/build/driverApi.d.mts +0 -22
- package/build/driverApi.d.mts.map +0 -1
- package/build/driverApi.js +0 -18
- package/build/driverApi.js.map +0 -1
- package/build/fieldSerde.cjs.map +0 -1
- package/build/fieldSerde.d.cts.map +0 -1
- package/build/fieldSerde.d.mts.map +0 -1
- package/build/fieldSerde.js.map +0 -1
- package/build/loadHints.cjs.map +0 -1
- package/build/loadHints.d.cts.map +0 -1
- package/build/loadHints.d.mts.map +0 -1
- package/build/loadHints.js.map +0 -1
- package/build/loadLens.cjs.map +0 -1
- package/build/loadLens.d.cts.map +0 -1
- package/build/loadLens.d.mts.map +0 -1
- package/build/loadLens.js.map +0 -1
- package/build/reactiveHints.cjs.map +0 -1
- package/build/reactiveHints.d.cts.map +0 -1
- package/build/reactiveHints.d.mts.map +0 -1
- package/build/reactiveHints.js.map +0 -1
- package/build/serde.cjs.map +0 -1
- package/build/serde.d.cts.map +0 -1
- package/build/serde.d.mts.map +0 -1
- package/build/serde.js.map +0 -1
- package/build/temporal.cjs.map +0 -1
- package/build/temporal.d.cts.map +0 -1
- package/build/temporal.d.mts.map +0 -1
- package/build/temporal.js.map +0 -1
- package/build/temporalMappers.cjs.map +0 -1
- package/build/temporalMappers.d.cts.map +0 -1
- package/build/temporalMappers.d.mts.map +0 -1
- package/build/temporalMappers.js.map +0 -1
- package/build/unnest.cjs.map +0 -1
- package/build/unnest.d.cts.map +0 -1
- package/build/unnest.d.mts.map +0 -1
- package/build/unnest.js.map +0 -1
- package/build/withLoaded.cjs.map +0 -1
- package/build/withLoaded.d.cts.map +0 -1
- package/build/withLoaded.d.mts.map +0 -1
- package/build/withLoaded.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { JoinRowTodo, Todo } from "../Todo.cjs";
|
|
1
|
+
import { JoinRowTodo, Todo } from "../flush/Todo.cjs";
|
|
2
2
|
import { ParsedFindQuery } from "../queries/find/QueryParser.cjs";
|
|
3
3
|
import { RowData } from "../RowData.cjs";
|
|
4
4
|
import { PreloadPlugin } from "../plugins/PreloadPlugin.cjs";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { JoinRowTodo, Todo } from "../Todo.mjs";
|
|
1
|
+
import { JoinRowTodo, Todo } from "../flush/Todo.mjs";
|
|
2
2
|
import { ParsedFindQuery } from "../queries/find/QueryParser.mjs";
|
|
3
3
|
import { RowData } from "../RowData.mjs";
|
|
4
4
|
import { PreloadPlugin } from "../plugins/PreloadPlugin.mjs";
|
package/build/drivers/Driver.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_fields = require("../fields.cjs");
|
|
3
|
-
require("../Todo.cjs");
|
|
4
|
-
const require_utils = require("../utils.cjs");
|
|
5
3
|
const require_keys = require("../keys.cjs");
|
|
6
|
-
const
|
|
4
|
+
const require_utils = require("../utils.cjs");
|
|
5
|
+
const require_serde_fieldSerde = require("../serde/fieldSerde.cjs");
|
|
7
6
|
const require_EntityMetadata = require("../EntityMetadata.cjs");
|
|
8
7
|
require("../Entity.cjs");
|
|
9
8
|
const require_BaseEntity = require("../BaseEntity.cjs");
|
|
@@ -47,7 +46,7 @@ function addInserts(ops, todo, fixups) {
|
|
|
47
46
|
}
|
|
48
47
|
}
|
|
49
48
|
function newInsertOp(meta, entities, fixups) {
|
|
50
|
-
const columns = Object.values(meta.fields).filter(
|
|
49
|
+
const columns = Object.values(meta.fields).filter(require_serde_fieldSerde.hasSerde).flatMap((f) => f.serde.columns);
|
|
51
50
|
const columnValues = collectBindings(entities, meta.tableName, columns, fixups);
|
|
52
51
|
return {
|
|
53
52
|
tableName: meta.tableName,
|
|
@@ -56,7 +55,7 @@ function newInsertOp(meta, entities, fixups) {
|
|
|
56
55
|
};
|
|
57
56
|
}
|
|
58
57
|
function newStiInsertOp(root, entities, fixups) {
|
|
59
|
-
const columns = Object.values(require_EntityMetadata.getMetadata(entities[0]).allFields).filter(
|
|
58
|
+
const columns = Object.values(require_EntityMetadata.getMetadata(entities[0]).allFields).filter(require_serde_fieldSerde.hasSerde).flatMap((f) => f.serde.columns);
|
|
60
59
|
const columnValues = collectBindings(entities, root.tableName, columns, fixups);
|
|
61
60
|
return {
|
|
62
61
|
tableName: root.tableName,
|
|
@@ -96,7 +95,7 @@ function addLazyUpdates(ops, meta, entities) {
|
|
|
96
95
|
const idColumn = meta.fields["id"].serde.columns[0];
|
|
97
96
|
for (const fieldName of meta.lazyFieldNames) {
|
|
98
97
|
const field = meta.fields[fieldName];
|
|
99
|
-
if (!
|
|
98
|
+
if (!require_serde_fieldSerde.hasSerde(field)) continue;
|
|
100
99
|
const changed = entities.filter((e) => fieldName in require_BaseEntity.getInstanceData(e).changedData);
|
|
101
100
|
if (changed.length === 0) continue;
|
|
102
101
|
const columns = [idColumn, ...field.serde.columns];
|
|
@@ -121,7 +120,7 @@ function newUpdateOp(meta, entities) {
|
|
|
121
120
|
const { data } = require_BaseEntity.getInstanceData(entity);
|
|
122
121
|
for (const key of changedFields) if (!(key in data) && require_fields.isChangeableField(entity, key) && !lazyFieldNames.has(key)) require_fields.getField(entity, key);
|
|
123
122
|
}
|
|
124
|
-
const columns = (meta.inheritanceType === "sti" ? require_EntityMetadata.getBaseSelfAndSubMetas(meta).flatMap((meta) => meta.stiDiscriminatorField ? Object.values(meta.fields) : Object.values(meta.fields).filter((f) => f.fieldName !== "id")) : Object.values(meta.fields)).filter((f) => changedFields.has(f.fieldName)).filter((f) => !lazyFieldNames.has(f.fieldName)).filter(
|
|
123
|
+
const columns = (meta.inheritanceType === "sti" ? require_EntityMetadata.getBaseSelfAndSubMetas(meta).flatMap((meta) => meta.stiDiscriminatorField ? Object.values(meta.fields) : Object.values(meta.fields).filter((f) => f.fieldName !== "id")) : Object.values(meta.fields)).filter((f) => changedFields.has(f.fieldName)).filter((f) => !lazyFieldNames.has(f.fieldName)).filter(require_serde_fieldSerde.hasSerde).flatMap((f) => f.serde.columns);
|
|
125
124
|
if (columns.length === 1) return;
|
|
126
125
|
if (updatedAt) {
|
|
127
126
|
const serde = meta.fields[updatedAt].serde;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityWriter.cjs","names":["groupBy","getMetadata","hasSerde","getInstanceData","isChangeableField","getBaseSelfAndSubMetas","keyToNumber","getBaseAndSelfMetas"],"sources":["../../src/drivers/EntityWriter.ts"],"sourcesContent":["import { getInstanceData } from \"../BaseEntity.ts\";\nimport { type Entity } from \"../Entity.ts\";\nimport {\n type EntityMetadata,\n type Field,\n type PrimitiveField,\n getBaseAndSelfMetas,\n getBaseSelfAndSubMetas,\n getMetadata,\n} from \"../EntityMetadata.ts\";\nimport { getField, isChangeableField } from \"../fields.ts\";\nimport { type FieldColumn, type TimestampSerde, hasSerde } from \"../fieldSerde.ts\";\nimport { keyToNumber } from \"../keys.ts\";\nimport { type Todo } from \"../Todo.ts\";\nimport { groupBy } from \"../utils.ts\";\n\n/** A simplified view of columns, with only the keys necessary to create SQL statements. */\nexport type OpColumn = { columnName: string; dbType: string; isNullableArray?: boolean };\nexport type InsertOp = { tableName: string; columns: OpColumn[]; columnValues: any[][] };\n/**\n * A logical `update` operation.\n *\n * If we're using op locks, `columns` will include both the new `updatedAt` value (as bumped\n * by the `EntityManager` on mutate), as well as an extra/last \"original updated at\" column\n * (with respective pre-update values in the `rows` data), for including in the conditional\n * update clause.\n */\nexport type UpdateOp = {\n tableName: string;\n columns: OpColumn[];\n columnValues: any[][];\n updatedAt: string | undefined;\n};\nexport type DeleteOp = { tableName: string; ids: any[] };\n\ntype Ops = { inserts: InsertOp[]; updates: UpdateOp[]; deletes: DeleteOp[] };\n\n/**\n * In schemas with entity FK cycles, we may insert a dummy/null value, and later fix it up\n * before the transaction commits.\n *\n * I.e. `INSERT author.favorite_book_id` as `NULL` and then later do an `UPDATE author\n * SET favorite_book_id = 1` after the book has been inserted/we have the id.\n */\nexport type InsertFixup = {\n entity: Entity;\n tableName: string;\n column: OpColumn;\n value: any;\n};\n\n/**\n * Builds AST-ish `Ops` for the inserts/updates/deletes in `todos`.\n *\n * This helps decouple the database-specific driver/library from the knowledge\n * of turning entities into table operations, i.e. so they can be unaware of\n * complexities like field -> column mapping, oplocks, and class table inheritance.\n *\n * We still assume Postgres b/c we assume all ids have been pre-assigned for INSERTs,\n * and don't do any topological sorting of cross-row FK dependencies.\n *\n * But this should let us experiment with knex vs. raw client/etc.\n */\nexport function generateOps(todos: Record<string, Todo>): Ops {\n const ops: Ops = { inserts: [], updates: [], deletes: [] };\n const fixups: InsertFixup[] = [];\n // Would be nice to conditionally sort\n const sorted = Object.values(todos).sort(\n (a, b) => (a.metadata.nonDeferredFkOrder ?? 0) - (b.metadata.nonDeferredFkOrder ?? 0),\n );\n for (const todo of sorted) {\n addInserts(ops, todo, fixups);\n addUpdates(ops, todo);\n addDeletes(ops, todo);\n }\n if (fixups.length > 0) translateFixupsIntoUpdates(ops, fixups);\n return ops;\n}\n\nfunction addInserts(ops: Ops, todo: Todo, fixups: InsertFixup[]): void {\n if (todo.inserts.length > 0) {\n // If we have subtypes, this todo.metadata will always be the base type\n const meta = todo.metadata;\n if (meta.subTypes.length > 0) {\n if (meta.inheritanceType === \"cti\") {\n // Insert into each of the CTI tables\n for (const [meta, group] of groupEntitiesByTable(todo.inserts)) {\n ops.inserts.push(newInsertOp(meta, group, fixups));\n }\n } else if (meta.inheritanceType === \"sti\") {\n // One INSERT per subtype, so each statement's column list spans exactly what that subtype can\n // set. A single statement across subtypes has to bind NULL for the other subtypes' columns,\n // which defeats their database defaults, and outright fails for notNull ones.\n for (const group of groupBy(todo.inserts, (e) => getMetadata(e)).values()) {\n ops.inserts.push(newStiInsertOp(meta, group, fixups));\n }\n } else {\n throw new Error(`Found ${meta.tableName} subTypes without a known inheritanceType ${meta.inheritanceType}`);\n }\n } else {\n ops.inserts.push(newInsertOp(meta, todo.inserts, fixups));\n }\n }\n}\n\nfunction newInsertOp(meta: EntityMetadata, entities: Entity[], fixups: InsertFixup[]): InsertOp {\n // Purposefully use `meta.fields` instead of `allFields` b/c each CTI table has its own `InsertOp`\n const columns = Object.values(meta.fields)\n .filter(hasSerde)\n .flatMap((f) => f.serde.columns);\n const columnValues = collectBindings(entities, meta.tableName, columns, fixups);\n return { tableName: meta.tableName, columns, columnValues };\n}\n\nfunction newStiInsertOp(root: EntityMetadata, entities: Entity[], fixups: InsertFixup[]): InsertOp {\n // `allFields` is the base's fields plus this subtype's own, i.e. everything this subtype can write.\n // Anything it can't write is left out of the statement entirely, so the database applies its default.\n const fields: Field[] = Object.values(getMetadata(entities[0]).allFields);\n const columns = fields.filter(hasSerde).flatMap((f) => f.serde.columns);\n const columnValues = collectBindings(entities, root.tableName, columns, fixups);\n return { tableName: root.tableName, columns, columnValues };\n}\n\nfunction addUpdates(ops: Ops, todo: Todo): void {\n if (todo.updates.length > 0) {\n const meta = todo.metadata;\n if (meta.subTypes.length > 0) {\n if (meta.inheritanceType === \"cti\") {\n for (const [meta, group] of groupEntitiesByTable(todo.updates)) {\n const op = newUpdateOp(meta, group);\n if (op) ops.updates.push(op);\n addLazyUpdates(ops, meta, group);\n }\n } else if (meta.inheritanceType === \"sti\") {\n const op = newUpdateOp(meta, todo.updates);\n if (op) ops.updates.push(op);\n addLazyUpdates(ops, meta, todo.updates);\n } else {\n throw new Error(`Found ${meta.tableName} subTypes without a known inheritanceType ${meta.inheritanceType}`);\n }\n } else {\n const op = newUpdateOp(meta, todo.updates);\n if (op) ops.updates.push(op);\n addLazyUpdates(ops, meta, todo.updates);\n }\n }\n}\n\n/**\n * Writes changed `lazy` columns via a targeted `UPDATE table SET lazy_col = ... WHERE id in (...)`.\n *\n * Lazy columns are excluded from the main batch UPDATE (which spans the batch's union of changed fields),\n * so that entities in the batch that never loaded a lazy column keep their existing db value instead of\n * being overwritten with null. Here we write each lazy column only for the entities that actually changed it.\n */\nfunction addLazyUpdates(ops: Ops, meta: EntityMetadata, entities: Entity[]): void {\n const idColumn = meta.fields[\"id\"].serde!.columns[0];\n for (const fieldName of meta.lazyFieldNames!) {\n const field = meta.fields[fieldName];\n if (!hasSerde(field)) continue;\n const changed = entities.filter((e) => fieldName in getInstanceData(e).changedData);\n if (changed.length === 0) continue;\n const columns: BindingColumn[] = [idColumn, ...field.serde.columns];\n const columnValues = collectBindings(changed, meta.tableName, columns, undefined);\n ops.updates.push({ tableName: meta.tableName, columns, columnValues, updatedAt: undefined });\n }\n}\n\nfunction newUpdateOp(meta: EntityMetadata, entities: Entity[]): UpdateOp | undefined {\n // We only include changed fields in our `UPDATE`--maybe we could change this\n // to always use the same fields, to take advantage of Prepared Statements.\n const changedFields = new Set<string>();\n for (const entity of entities) {\n for (const fieldName in getInstanceData(entity).changedData) changedFields.add(fieldName);\n }\n // Sometimes with derived fields, an instance will be marked as an update, but if the derived field hasn't\n // actually changed, it'll be a noop, so just short-circuit if it looks like that happened. Unless touched.\n if (changedFields.size === 0 && !entities.some((e) => getInstanceData(e).isTouched)) {\n return undefined;\n }\n\n // We may have loaded a1 and a2, and changed a1.firstName, and a2.lastName, but either one\n // might be missing the other's changed fields in it's lazy-initialized data field...\n // (Use `?` because subtypes won't have the updatedAt, and it will be handled by the base type\n // `newUpdateUp`--except STI where we're doing it all in one go, probably needs checked here.)\n const updatedAt = meta.timestampFields?.updatedAt;\n changedFields.add(\"id\");\n if (updatedAt) changedFields.add(updatedAt);\n // `lazy` columns are deliberately excluded from the batch UPDATE and written by `addLazyUpdates`; an\n // entity that never loaded a lazy column isn't in `row`, so forcing `getField` here would clobber it to null.\n const lazyFieldNames = meta.lazyFieldNames!;\n for (const entity of entities) {\n const { data } = getInstanceData(entity);\n for (const key of changedFields) {\n // Check isChangeableField because we might be updating the base `publishers` table\n // and `originalData` might have fields from a subclass `large_publishers` table.\n if (!(key in data) && isChangeableField(entity, key) && !lazyFieldNames.has(key)) {\n getField(entity, key);\n }\n }\n }\n\n const columns: Array<BindingColumn> = (\n meta.inheritanceType === \"sti\"\n ? // Hack this one handling of STI into here...\n getBaseSelfAndSubMetas(meta).flatMap((meta) =>\n meta.stiDiscriminatorField\n ? Object.values(meta.fields)\n : Object.values(meta.fields).filter((f) => f.fieldName !== \"id\"),\n )\n : Object.values(meta.fields)\n )\n .filter((f) => changedFields.has(f.fieldName))\n .filter((f) => !lazyFieldNames.has(f.fieldName))\n .filter(hasSerde)\n .flatMap((f) => f.serde.columns);\n\n // If we're using class table inheritance, base/child tables may not have any columns to update\n if (columns.length === 1) {\n return undefined;\n }\n\n // We already have the bumped updated_at column, but also include the original updated_at for the data CTE\n if (updatedAt) {\n const serde = meta.fields[updatedAt].serde as TimestampSerde<unknown>;\n columns.push({\n columnName: \"__original_updated_at\",\n dbType: \"timestamptz\",\n dbValue: (_, entity) => serde.dbValue(getInstanceData(entity).originalData),\n });\n }\n\n const columnValues = collectBindings(entities, meta.tableName, columns, []);\n const updatedAtColumn = updatedAt ? (meta.fields[updatedAt] as PrimitiveField).serde.columns[0] : undefined;\n return { tableName: meta.tableName, columns, updatedAt: updatedAtColumn?.columnName, columnValues };\n}\n\nfunction addDeletes(ops: Ops, todo: Todo): void {\n if (todo.deletes.length > 0) {\n const meta = todo.metadata;\n const ids = todo.deletes.map((e) => keyToNumber(meta, e.idTagged!).toString());\n if (meta.subTypes.length > 0) {\n getBaseSelfAndSubMetas(meta).forEach((meta) => {\n ops.deletes.push({ tableName: meta.tableName, ids });\n });\n } else {\n ops.deletes.push({ tableName: meta.tableName, ids });\n }\n }\n}\n\nfunction groupEntitiesByTable(entities: Entity[]): Array<[EntityMetadata, Entity[]]> {\n const entitiesByType: Map<EntityMetadata, Entity[]> = new Map();\n for (const e of entities) {\n for (const m of getBaseAndSelfMetas(getMetadata(e))) {\n let list = entitiesByType.get(m);\n if (!list) {\n list = [];\n entitiesByType.set(m, list);\n }\n list.push(e);\n }\n }\n return [...entitiesByType.entries()];\n}\n\ntype BindingColumn = OpColumn & Pick<FieldColumn, \"dbValue\">;\ntype EntityWithData = Entity & { __data: { data: Record<string, unknown> } };\n\n/**\n * Builds a *columnar* array of bindings for the given `entities` and `columns`.\n *\n * We use a columnar approach, instead of `rows[]`, to best match the unnest-based\n * column operations in our `batchInsert` / `batchUpdate` SQL statements.\n */\nfunction collectBindings(\n entities: Entity[],\n tableName: string,\n columns: BindingColumn[],\n fixups: InsertFixup[] | undefined,\n): any[][] {\n const entityCount = entities.length;\n const bindings: any[][] = new Array(columns.length);\n const entitiesWithData = entities as EntityWithData[];\n // Cache data separately; this benchmarks faster than `entities[i].__data.data` in the inner loop.\n const entityData = new Array(entityCount);\n for (let i = 0; i < entityCount; i++) entityData[i] = entitiesWithData[i].__data.data;\n for (let columnIndex = 0; columnIndex < columns.length; columnIndex++) {\n const column = columns[columnIndex];\n const columnValues: any[] = new Array(entityCount);\n for (let entityIndex = 0; entityIndex < entityCount; entityIndex++) {\n columnValues[entityIndex] =\n column.dbValue(entityData[entityIndex], entities[entityIndex], tableName, fixups) ?? null;\n }\n bindings[columnIndex] = columnValues;\n }\n return bindings;\n}\n/**\n * Given `fixups` that indicate where we inserted `NULL` into non-deferred FKs, create `UPDATE`s\n * that insert the value now that the FK check will succeed.\n */\nfunction translateFixupsIntoUpdates(ops: Ops, fixups: InsertFixup[]): void {\n // Create a single `UPDATE` for the N fixups we might have for each table/column combination\n groupBy(fixups, (f) => `${f.tableName}.${f.column.columnName}`).forEach((fixups) => {\n const { tableName, entity, column } = fixups[0];\n ops.updates.push({\n tableName,\n columns: [getMetadata(entity).fields[\"id\"].serde!.columns[0], column],\n columnValues: [\n // Make 1 column of ids, and 1 column of values\n fixups.map((fixup) => fixup.entity.id),\n fixups.map((fixup) => fixup.value),\n ],\n updatedAt: undefined,\n });\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EntityWriter.cjs","names":["groupBy","getMetadata","hasSerde","getInstanceData","isChangeableField","getBaseSelfAndSubMetas","keyToNumber","getBaseAndSelfMetas"],"sources":["../../src/drivers/EntityWriter.ts"],"sourcesContent":["import { getInstanceData } from \"src/BaseEntity.ts\";\nimport { type Entity } from \"src/Entity.ts\";\nimport {\n type EntityMetadata,\n type Field,\n type PrimitiveField,\n getBaseAndSelfMetas,\n getBaseSelfAndSubMetas,\n getMetadata,\n} from \"src/EntityMetadata.ts\";\nimport { getField, isChangeableField } from \"src/fields.ts\";\nimport type { Todo } from \"src/flush/Todo.ts\";\nimport { keyToNumber } from \"src/keys.ts\";\nimport { type FieldColumn, type TimestampSerde, hasSerde } from \"src/serde/fieldSerde.ts\";\nimport { groupBy } from \"src/utils.ts\";\n\n/** A simplified view of columns, with only the keys necessary to create SQL statements. */\nexport type OpColumn = { columnName: string; dbType: string; isNullableArray?: boolean };\nexport type InsertOp = { tableName: string; columns: OpColumn[]; columnValues: any[][] };\n/**\n * A logical `update` operation.\n *\n * If we're using op locks, `columns` will include both the new `updatedAt` value (as bumped\n * by the `EntityManager` on mutate), as well as an extra/last \"original updated at\" column\n * (with respective pre-update values in the `rows` data), for including in the conditional\n * update clause.\n */\nexport type UpdateOp = {\n tableName: string;\n columns: OpColumn[];\n columnValues: any[][];\n updatedAt: string | undefined;\n};\nexport type DeleteOp = { tableName: string; ids: any[] };\n\ntype Ops = { inserts: InsertOp[]; updates: UpdateOp[]; deletes: DeleteOp[] };\n\n/**\n * In schemas with entity FK cycles, we may insert a dummy/null value, and later fix it up\n * before the transaction commits.\n *\n * I.e. `INSERT author.favorite_book_id` as `NULL` and then later do an `UPDATE author\n * SET favorite_book_id = 1` after the book has been inserted/we have the id.\n */\nexport type InsertFixup = {\n entity: Entity;\n tableName: string;\n column: OpColumn;\n value: any;\n};\n\n/**\n * Builds AST-ish `Ops` for the inserts/updates/deletes in `todos`.\n *\n * This helps decouple the database-specific driver/library from the knowledge\n * of turning entities into table operations, i.e. so they can be unaware of\n * complexities like field -> column mapping, oplocks, and class table inheritance.\n *\n * We still assume Postgres b/c we assume all ids have been pre-assigned for INSERTs,\n * and don't do any topological sorting of cross-row FK dependencies.\n *\n * But this should let us experiment with knex vs. raw client/etc.\n */\nexport function generateOps(todos: Record<string, Todo>): Ops {\n const ops: Ops = { inserts: [], updates: [], deletes: [] };\n const fixups: InsertFixup[] = [];\n // Would be nice to conditionally sort\n const sorted = Object.values(todos).sort(\n (a, b) => (a.metadata.nonDeferredFkOrder ?? 0) - (b.metadata.nonDeferredFkOrder ?? 0),\n );\n for (const todo of sorted) {\n addInserts(ops, todo, fixups);\n addUpdates(ops, todo);\n addDeletes(ops, todo);\n }\n if (fixups.length > 0) translateFixupsIntoUpdates(ops, fixups);\n return ops;\n}\n\nfunction addInserts(ops: Ops, todo: Todo, fixups: InsertFixup[]): void {\n if (todo.inserts.length > 0) {\n // If we have subtypes, this todo.metadata will always be the base type\n const meta = todo.metadata;\n if (meta.subTypes.length > 0) {\n if (meta.inheritanceType === \"cti\") {\n // Insert into each of the CTI tables\n for (const [meta, group] of groupEntitiesByTable(todo.inserts)) {\n ops.inserts.push(newInsertOp(meta, group, fixups));\n }\n } else if (meta.inheritanceType === \"sti\") {\n // One INSERT per subtype, so each statement's column list spans exactly what that subtype can\n // set. A single statement across subtypes has to bind NULL for the other subtypes' columns,\n // which defeats their database defaults, and outright fails for notNull ones.\n for (const group of groupBy(todo.inserts, (e) => getMetadata(e)).values()) {\n ops.inserts.push(newStiInsertOp(meta, group, fixups));\n }\n } else {\n throw new Error(`Found ${meta.tableName} subTypes without a known inheritanceType ${meta.inheritanceType}`);\n }\n } else {\n ops.inserts.push(newInsertOp(meta, todo.inserts, fixups));\n }\n }\n}\n\nfunction newInsertOp(meta: EntityMetadata, entities: Entity[], fixups: InsertFixup[]): InsertOp {\n // Purposefully use `meta.fields` instead of `allFields` b/c each CTI table has its own `InsertOp`\n const columns = Object.values(meta.fields)\n .filter(hasSerde)\n .flatMap((f) => f.serde.columns);\n const columnValues = collectBindings(entities, meta.tableName, columns, fixups);\n return { tableName: meta.tableName, columns, columnValues };\n}\n\nfunction newStiInsertOp(root: EntityMetadata, entities: Entity[], fixups: InsertFixup[]): InsertOp {\n // `allFields` is the base's fields plus this subtype's own, i.e. everything this subtype can write.\n // Anything it can't write is left out of the statement entirely, so the database applies its default.\n const fields: Field[] = Object.values(getMetadata(entities[0]).allFields);\n const columns = fields.filter(hasSerde).flatMap((f) => f.serde.columns);\n const columnValues = collectBindings(entities, root.tableName, columns, fixups);\n return { tableName: root.tableName, columns, columnValues };\n}\n\nfunction addUpdates(ops: Ops, todo: Todo): void {\n if (todo.updates.length > 0) {\n const meta = todo.metadata;\n if (meta.subTypes.length > 0) {\n if (meta.inheritanceType === \"cti\") {\n for (const [meta, group] of groupEntitiesByTable(todo.updates)) {\n const op = newUpdateOp(meta, group);\n if (op) ops.updates.push(op);\n addLazyUpdates(ops, meta, group);\n }\n } else if (meta.inheritanceType === \"sti\") {\n const op = newUpdateOp(meta, todo.updates);\n if (op) ops.updates.push(op);\n addLazyUpdates(ops, meta, todo.updates);\n } else {\n throw new Error(`Found ${meta.tableName} subTypes without a known inheritanceType ${meta.inheritanceType}`);\n }\n } else {\n const op = newUpdateOp(meta, todo.updates);\n if (op) ops.updates.push(op);\n addLazyUpdates(ops, meta, todo.updates);\n }\n }\n}\n\n/**\n * Writes changed `lazy` columns via a targeted `UPDATE table SET lazy_col = ... WHERE id in (...)`.\n *\n * Lazy columns are excluded from the main batch UPDATE (which spans the batch's union of changed fields),\n * so that entities in the batch that never loaded a lazy column keep their existing db value instead of\n * being overwritten with null. Here we write each lazy column only for the entities that actually changed it.\n */\nfunction addLazyUpdates(ops: Ops, meta: EntityMetadata, entities: Entity[]): void {\n const idColumn = meta.fields[\"id\"].serde!.columns[0];\n for (const fieldName of meta.lazyFieldNames!) {\n const field = meta.fields[fieldName];\n if (!hasSerde(field)) continue;\n const changed = entities.filter((e) => fieldName in getInstanceData(e).changedData);\n if (changed.length === 0) continue;\n const columns: BindingColumn[] = [idColumn, ...field.serde.columns];\n const columnValues = collectBindings(changed, meta.tableName, columns, undefined);\n ops.updates.push({ tableName: meta.tableName, columns, columnValues, updatedAt: undefined });\n }\n}\n\nfunction newUpdateOp(meta: EntityMetadata, entities: Entity[]): UpdateOp | undefined {\n // We only include changed fields in our `UPDATE`--maybe we could change this\n // to always use the same fields, to take advantage of Prepared Statements.\n const changedFields = new Set<string>();\n for (const entity of entities) {\n for (const fieldName in getInstanceData(entity).changedData) changedFields.add(fieldName);\n }\n // Sometimes with derived fields, an instance will be marked as an update, but if the derived field hasn't\n // actually changed, it'll be a noop, so just short-circuit if it looks like that happened. Unless touched.\n if (changedFields.size === 0 && !entities.some((e) => getInstanceData(e).isTouched)) {\n return undefined;\n }\n\n // We may have loaded a1 and a2, and changed a1.firstName, and a2.lastName, but either one\n // might be missing the other's changed fields in it's lazy-initialized data field...\n // (Use `?` because subtypes won't have the updatedAt, and it will be handled by the base type\n // `newUpdateUp`--except STI where we're doing it all in one go, probably needs checked here.)\n const updatedAt = meta.timestampFields?.updatedAt;\n changedFields.add(\"id\");\n if (updatedAt) changedFields.add(updatedAt);\n // `lazy` columns are deliberately excluded from the batch UPDATE and written by `addLazyUpdates`; an\n // entity that never loaded a lazy column isn't in `row`, so forcing `getField` here would clobber it to null.\n const lazyFieldNames = meta.lazyFieldNames!;\n for (const entity of entities) {\n const { data } = getInstanceData(entity);\n for (const key of changedFields) {\n // Check isChangeableField because we might be updating the base `publishers` table\n // and `originalData` might have fields from a subclass `large_publishers` table.\n if (!(key in data) && isChangeableField(entity, key) && !lazyFieldNames.has(key)) {\n getField(entity, key);\n }\n }\n }\n\n const columns: Array<BindingColumn> = (\n meta.inheritanceType === \"sti\"\n ? // Hack this one handling of STI into here...\n getBaseSelfAndSubMetas(meta).flatMap((meta) =>\n meta.stiDiscriminatorField\n ? Object.values(meta.fields)\n : Object.values(meta.fields).filter((f) => f.fieldName !== \"id\"),\n )\n : Object.values(meta.fields)\n )\n .filter((f) => changedFields.has(f.fieldName))\n .filter((f) => !lazyFieldNames.has(f.fieldName))\n .filter(hasSerde)\n .flatMap((f) => f.serde.columns);\n\n // If we're using class table inheritance, base/child tables may not have any columns to update\n if (columns.length === 1) {\n return undefined;\n }\n\n // We already have the bumped updated_at column, but also include the original updated_at for the data CTE\n if (updatedAt) {\n const serde = meta.fields[updatedAt].serde as TimestampSerde<unknown>;\n columns.push({\n columnName: \"__original_updated_at\",\n dbType: \"timestamptz\",\n dbValue: (_, entity) => serde.dbValue(getInstanceData(entity).originalData),\n });\n }\n\n const columnValues = collectBindings(entities, meta.tableName, columns, []);\n const updatedAtColumn = updatedAt ? (meta.fields[updatedAt] as PrimitiveField).serde.columns[0] : undefined;\n return { tableName: meta.tableName, columns, updatedAt: updatedAtColumn?.columnName, columnValues };\n}\n\nfunction addDeletes(ops: Ops, todo: Todo): void {\n if (todo.deletes.length > 0) {\n const meta = todo.metadata;\n const ids = todo.deletes.map((e) => keyToNumber(meta, e.idTagged!).toString());\n if (meta.subTypes.length > 0) {\n getBaseSelfAndSubMetas(meta).forEach((meta) => {\n ops.deletes.push({ tableName: meta.tableName, ids });\n });\n } else {\n ops.deletes.push({ tableName: meta.tableName, ids });\n }\n }\n}\n\nfunction groupEntitiesByTable(entities: Entity[]): Array<[EntityMetadata, Entity[]]> {\n const entitiesByType: Map<EntityMetadata, Entity[]> = new Map();\n for (const e of entities) {\n for (const m of getBaseAndSelfMetas(getMetadata(e))) {\n let list = entitiesByType.get(m);\n if (!list) {\n list = [];\n entitiesByType.set(m, list);\n }\n list.push(e);\n }\n }\n return [...entitiesByType.entries()];\n}\n\ntype BindingColumn = OpColumn & Pick<FieldColumn, \"dbValue\">;\ntype EntityWithData = Entity & { __data: { data: Record<string, unknown> } };\n\n/**\n * Builds a *columnar* array of bindings for the given `entities` and `columns`.\n *\n * We use a columnar approach, instead of `rows[]`, to best match the unnest-based\n * column operations in our `batchInsert` / `batchUpdate` SQL statements.\n */\nfunction collectBindings(\n entities: Entity[],\n tableName: string,\n columns: BindingColumn[],\n fixups: InsertFixup[] | undefined,\n): any[][] {\n const entityCount = entities.length;\n const bindings: any[][] = new Array(columns.length);\n const entitiesWithData = entities as EntityWithData[];\n // Cache data separately; this benchmarks faster than `entities[i].__data.data` in the inner loop.\n const entityData = new Array(entityCount);\n for (let i = 0; i < entityCount; i++) entityData[i] = entitiesWithData[i].__data.data;\n for (let columnIndex = 0; columnIndex < columns.length; columnIndex++) {\n const column = columns[columnIndex];\n const columnValues: any[] = new Array(entityCount);\n for (let entityIndex = 0; entityIndex < entityCount; entityIndex++) {\n columnValues[entityIndex] =\n column.dbValue(entityData[entityIndex], entities[entityIndex], tableName, fixups) ?? null;\n }\n bindings[columnIndex] = columnValues;\n }\n return bindings;\n}\n/**\n * Given `fixups` that indicate where we inserted `NULL` into non-deferred FKs, create `UPDATE`s\n * that insert the value now that the FK check will succeed.\n */\nfunction translateFixupsIntoUpdates(ops: Ops, fixups: InsertFixup[]): void {\n // Create a single `UPDATE` for the N fixups we might have for each table/column combination\n groupBy(fixups, (f) => `${f.tableName}.${f.column.columnName}`).forEach((fixups) => {\n const { tableName, entity, column } = fixups[0];\n ops.updates.push({\n tableName,\n columns: [getMetadata(entity).fields[\"id\"].serde!.columns[0], column],\n columnValues: [\n // Make 1 column of ids, and 1 column of values\n fixups.map((fixup) => fixup.entity.id),\n fixups.map((fixup) => fixup.value),\n ],\n updatedAt: undefined,\n });\n });\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { getField, isChangeableField } from "../fields.js";
|
|
2
|
-
import "../Todo.js";
|
|
3
|
-
import { groupBy } from "../utils.js";
|
|
4
2
|
import { keyToNumber } from "../keys.js";
|
|
5
|
-
import {
|
|
3
|
+
import { groupBy } from "../utils.js";
|
|
4
|
+
import { hasSerde } from "../serde/fieldSerde.js";
|
|
6
5
|
import { getBaseAndSelfMetas, getBaseSelfAndSubMetas, getMetadata } from "../EntityMetadata.js";
|
|
7
6
|
import "../Entity.js";
|
|
8
7
|
import { getInstanceData } from "../BaseEntity.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityWriter.js","names":[],"sources":["../../src/drivers/EntityWriter.ts"],"sourcesContent":["import { getInstanceData } from \"../BaseEntity.ts\";\nimport { type Entity } from \"../Entity.ts\";\nimport {\n type EntityMetadata,\n type Field,\n type PrimitiveField,\n getBaseAndSelfMetas,\n getBaseSelfAndSubMetas,\n getMetadata,\n} from \"../EntityMetadata.ts\";\nimport { getField, isChangeableField } from \"../fields.ts\";\nimport { type FieldColumn, type TimestampSerde, hasSerde } from \"../fieldSerde.ts\";\nimport { keyToNumber } from \"../keys.ts\";\nimport { type Todo } from \"../Todo.ts\";\nimport { groupBy } from \"../utils.ts\";\n\n/** A simplified view of columns, with only the keys necessary to create SQL statements. */\nexport type OpColumn = { columnName: string; dbType: string; isNullableArray?: boolean };\nexport type InsertOp = { tableName: string; columns: OpColumn[]; columnValues: any[][] };\n/**\n * A logical `update` operation.\n *\n * If we're using op locks, `columns` will include both the new `updatedAt` value (as bumped\n * by the `EntityManager` on mutate), as well as an extra/last \"original updated at\" column\n * (with respective pre-update values in the `rows` data), for including in the conditional\n * update clause.\n */\nexport type UpdateOp = {\n tableName: string;\n columns: OpColumn[];\n columnValues: any[][];\n updatedAt: string | undefined;\n};\nexport type DeleteOp = { tableName: string; ids: any[] };\n\ntype Ops = { inserts: InsertOp[]; updates: UpdateOp[]; deletes: DeleteOp[] };\n\n/**\n * In schemas with entity FK cycles, we may insert a dummy/null value, and later fix it up\n * before the transaction commits.\n *\n * I.e. `INSERT author.favorite_book_id` as `NULL` and then later do an `UPDATE author\n * SET favorite_book_id = 1` after the book has been inserted/we have the id.\n */\nexport type InsertFixup = {\n entity: Entity;\n tableName: string;\n column: OpColumn;\n value: any;\n};\n\n/**\n * Builds AST-ish `Ops` for the inserts/updates/deletes in `todos`.\n *\n * This helps decouple the database-specific driver/library from the knowledge\n * of turning entities into table operations, i.e. so they can be unaware of\n * complexities like field -> column mapping, oplocks, and class table inheritance.\n *\n * We still assume Postgres b/c we assume all ids have been pre-assigned for INSERTs,\n * and don't do any topological sorting of cross-row FK dependencies.\n *\n * But this should let us experiment with knex vs. raw client/etc.\n */\nexport function generateOps(todos: Record<string, Todo>): Ops {\n const ops: Ops = { inserts: [], updates: [], deletes: [] };\n const fixups: InsertFixup[] = [];\n // Would be nice to conditionally sort\n const sorted = Object.values(todos).sort(\n (a, b) => (a.metadata.nonDeferredFkOrder ?? 0) - (b.metadata.nonDeferredFkOrder ?? 0),\n );\n for (const todo of sorted) {\n addInserts(ops, todo, fixups);\n addUpdates(ops, todo);\n addDeletes(ops, todo);\n }\n if (fixups.length > 0) translateFixupsIntoUpdates(ops, fixups);\n return ops;\n}\n\nfunction addInserts(ops: Ops, todo: Todo, fixups: InsertFixup[]): void {\n if (todo.inserts.length > 0) {\n // If we have subtypes, this todo.metadata will always be the base type\n const meta = todo.metadata;\n if (meta.subTypes.length > 0) {\n if (meta.inheritanceType === \"cti\") {\n // Insert into each of the CTI tables\n for (const [meta, group] of groupEntitiesByTable(todo.inserts)) {\n ops.inserts.push(newInsertOp(meta, group, fixups));\n }\n } else if (meta.inheritanceType === \"sti\") {\n // One INSERT per subtype, so each statement's column list spans exactly what that subtype can\n // set. A single statement across subtypes has to bind NULL for the other subtypes' columns,\n // which defeats their database defaults, and outright fails for notNull ones.\n for (const group of groupBy(todo.inserts, (e) => getMetadata(e)).values()) {\n ops.inserts.push(newStiInsertOp(meta, group, fixups));\n }\n } else {\n throw new Error(`Found ${meta.tableName} subTypes without a known inheritanceType ${meta.inheritanceType}`);\n }\n } else {\n ops.inserts.push(newInsertOp(meta, todo.inserts, fixups));\n }\n }\n}\n\nfunction newInsertOp(meta: EntityMetadata, entities: Entity[], fixups: InsertFixup[]): InsertOp {\n // Purposefully use `meta.fields` instead of `allFields` b/c each CTI table has its own `InsertOp`\n const columns = Object.values(meta.fields)\n .filter(hasSerde)\n .flatMap((f) => f.serde.columns);\n const columnValues = collectBindings(entities, meta.tableName, columns, fixups);\n return { tableName: meta.tableName, columns, columnValues };\n}\n\nfunction newStiInsertOp(root: EntityMetadata, entities: Entity[], fixups: InsertFixup[]): InsertOp {\n // `allFields` is the base's fields plus this subtype's own, i.e. everything this subtype can write.\n // Anything it can't write is left out of the statement entirely, so the database applies its default.\n const fields: Field[] = Object.values(getMetadata(entities[0]).allFields);\n const columns = fields.filter(hasSerde).flatMap((f) => f.serde.columns);\n const columnValues = collectBindings(entities, root.tableName, columns, fixups);\n return { tableName: root.tableName, columns, columnValues };\n}\n\nfunction addUpdates(ops: Ops, todo: Todo): void {\n if (todo.updates.length > 0) {\n const meta = todo.metadata;\n if (meta.subTypes.length > 0) {\n if (meta.inheritanceType === \"cti\") {\n for (const [meta, group] of groupEntitiesByTable(todo.updates)) {\n const op = newUpdateOp(meta, group);\n if (op) ops.updates.push(op);\n addLazyUpdates(ops, meta, group);\n }\n } else if (meta.inheritanceType === \"sti\") {\n const op = newUpdateOp(meta, todo.updates);\n if (op) ops.updates.push(op);\n addLazyUpdates(ops, meta, todo.updates);\n } else {\n throw new Error(`Found ${meta.tableName} subTypes without a known inheritanceType ${meta.inheritanceType}`);\n }\n } else {\n const op = newUpdateOp(meta, todo.updates);\n if (op) ops.updates.push(op);\n addLazyUpdates(ops, meta, todo.updates);\n }\n }\n}\n\n/**\n * Writes changed `lazy` columns via a targeted `UPDATE table SET lazy_col = ... WHERE id in (...)`.\n *\n * Lazy columns are excluded from the main batch UPDATE (which spans the batch's union of changed fields),\n * so that entities in the batch that never loaded a lazy column keep their existing db value instead of\n * being overwritten with null. Here we write each lazy column only for the entities that actually changed it.\n */\nfunction addLazyUpdates(ops: Ops, meta: EntityMetadata, entities: Entity[]): void {\n const idColumn = meta.fields[\"id\"].serde!.columns[0];\n for (const fieldName of meta.lazyFieldNames!) {\n const field = meta.fields[fieldName];\n if (!hasSerde(field)) continue;\n const changed = entities.filter((e) => fieldName in getInstanceData(e).changedData);\n if (changed.length === 0) continue;\n const columns: BindingColumn[] = [idColumn, ...field.serde.columns];\n const columnValues = collectBindings(changed, meta.tableName, columns, undefined);\n ops.updates.push({ tableName: meta.tableName, columns, columnValues, updatedAt: undefined });\n }\n}\n\nfunction newUpdateOp(meta: EntityMetadata, entities: Entity[]): UpdateOp | undefined {\n // We only include changed fields in our `UPDATE`--maybe we could change this\n // to always use the same fields, to take advantage of Prepared Statements.\n const changedFields = new Set<string>();\n for (const entity of entities) {\n for (const fieldName in getInstanceData(entity).changedData) changedFields.add(fieldName);\n }\n // Sometimes with derived fields, an instance will be marked as an update, but if the derived field hasn't\n // actually changed, it'll be a noop, so just short-circuit if it looks like that happened. Unless touched.\n if (changedFields.size === 0 && !entities.some((e) => getInstanceData(e).isTouched)) {\n return undefined;\n }\n\n // We may have loaded a1 and a2, and changed a1.firstName, and a2.lastName, but either one\n // might be missing the other's changed fields in it's lazy-initialized data field...\n // (Use `?` because subtypes won't have the updatedAt, and it will be handled by the base type\n // `newUpdateUp`--except STI where we're doing it all in one go, probably needs checked here.)\n const updatedAt = meta.timestampFields?.updatedAt;\n changedFields.add(\"id\");\n if (updatedAt) changedFields.add(updatedAt);\n // `lazy` columns are deliberately excluded from the batch UPDATE and written by `addLazyUpdates`; an\n // entity that never loaded a lazy column isn't in `row`, so forcing `getField` here would clobber it to null.\n const lazyFieldNames = meta.lazyFieldNames!;\n for (const entity of entities) {\n const { data } = getInstanceData(entity);\n for (const key of changedFields) {\n // Check isChangeableField because we might be updating the base `publishers` table\n // and `originalData` might have fields from a subclass `large_publishers` table.\n if (!(key in data) && isChangeableField(entity, key) && !lazyFieldNames.has(key)) {\n getField(entity, key);\n }\n }\n }\n\n const columns: Array<BindingColumn> = (\n meta.inheritanceType === \"sti\"\n ? // Hack this one handling of STI into here...\n getBaseSelfAndSubMetas(meta).flatMap((meta) =>\n meta.stiDiscriminatorField\n ? Object.values(meta.fields)\n : Object.values(meta.fields).filter((f) => f.fieldName !== \"id\"),\n )\n : Object.values(meta.fields)\n )\n .filter((f) => changedFields.has(f.fieldName))\n .filter((f) => !lazyFieldNames.has(f.fieldName))\n .filter(hasSerde)\n .flatMap((f) => f.serde.columns);\n\n // If we're using class table inheritance, base/child tables may not have any columns to update\n if (columns.length === 1) {\n return undefined;\n }\n\n // We already have the bumped updated_at column, but also include the original updated_at for the data CTE\n if (updatedAt) {\n const serde = meta.fields[updatedAt].serde as TimestampSerde<unknown>;\n columns.push({\n columnName: \"__original_updated_at\",\n dbType: \"timestamptz\",\n dbValue: (_, entity) => serde.dbValue(getInstanceData(entity).originalData),\n });\n }\n\n const columnValues = collectBindings(entities, meta.tableName, columns, []);\n const updatedAtColumn = updatedAt ? (meta.fields[updatedAt] as PrimitiveField).serde.columns[0] : undefined;\n return { tableName: meta.tableName, columns, updatedAt: updatedAtColumn?.columnName, columnValues };\n}\n\nfunction addDeletes(ops: Ops, todo: Todo): void {\n if (todo.deletes.length > 0) {\n const meta = todo.metadata;\n const ids = todo.deletes.map((e) => keyToNumber(meta, e.idTagged!).toString());\n if (meta.subTypes.length > 0) {\n getBaseSelfAndSubMetas(meta).forEach((meta) => {\n ops.deletes.push({ tableName: meta.tableName, ids });\n });\n } else {\n ops.deletes.push({ tableName: meta.tableName, ids });\n }\n }\n}\n\nfunction groupEntitiesByTable(entities: Entity[]): Array<[EntityMetadata, Entity[]]> {\n const entitiesByType: Map<EntityMetadata, Entity[]> = new Map();\n for (const e of entities) {\n for (const m of getBaseAndSelfMetas(getMetadata(e))) {\n let list = entitiesByType.get(m);\n if (!list) {\n list = [];\n entitiesByType.set(m, list);\n }\n list.push(e);\n }\n }\n return [...entitiesByType.entries()];\n}\n\ntype BindingColumn = OpColumn & Pick<FieldColumn, \"dbValue\">;\ntype EntityWithData = Entity & { __data: { data: Record<string, unknown> } };\n\n/**\n * Builds a *columnar* array of bindings for the given `entities` and `columns`.\n *\n * We use a columnar approach, instead of `rows[]`, to best match the unnest-based\n * column operations in our `batchInsert` / `batchUpdate` SQL statements.\n */\nfunction collectBindings(\n entities: Entity[],\n tableName: string,\n columns: BindingColumn[],\n fixups: InsertFixup[] | undefined,\n): any[][] {\n const entityCount = entities.length;\n const bindings: any[][] = new Array(columns.length);\n const entitiesWithData = entities as EntityWithData[];\n // Cache data separately; this benchmarks faster than `entities[i].__data.data` in the inner loop.\n const entityData = new Array(entityCount);\n for (let i = 0; i < entityCount; i++) entityData[i] = entitiesWithData[i].__data.data;\n for (let columnIndex = 0; columnIndex < columns.length; columnIndex++) {\n const column = columns[columnIndex];\n const columnValues: any[] = new Array(entityCount);\n for (let entityIndex = 0; entityIndex < entityCount; entityIndex++) {\n columnValues[entityIndex] =\n column.dbValue(entityData[entityIndex], entities[entityIndex], tableName, fixups) ?? null;\n }\n bindings[columnIndex] = columnValues;\n }\n return bindings;\n}\n/**\n * Given `fixups` that indicate where we inserted `NULL` into non-deferred FKs, create `UPDATE`s\n * that insert the value now that the FK check will succeed.\n */\nfunction translateFixupsIntoUpdates(ops: Ops, fixups: InsertFixup[]): void {\n // Create a single `UPDATE` for the N fixups we might have for each table/column combination\n groupBy(fixups, (f) => `${f.tableName}.${f.column.columnName}`).forEach((fixups) => {\n const { tableName, entity, column } = fixups[0];\n ops.updates.push({\n tableName,\n columns: [getMetadata(entity).fields[\"id\"].serde!.columns[0], column],\n columnValues: [\n // Make 1 column of ids, and 1 column of values\n fixups.map((fixup) => fixup.entity.id),\n fixups.map((fixup) => fixup.value),\n ],\n updatedAt: undefined,\n });\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EntityWriter.js","names":[],"sources":["../../src/drivers/EntityWriter.ts"],"sourcesContent":["import { getInstanceData } from \"src/BaseEntity.ts\";\nimport { type Entity } from \"src/Entity.ts\";\nimport {\n type EntityMetadata,\n type Field,\n type PrimitiveField,\n getBaseAndSelfMetas,\n getBaseSelfAndSubMetas,\n getMetadata,\n} from \"src/EntityMetadata.ts\";\nimport { getField, isChangeableField } from \"src/fields.ts\";\nimport type { Todo } from \"src/flush/Todo.ts\";\nimport { keyToNumber } from \"src/keys.ts\";\nimport { type FieldColumn, type TimestampSerde, hasSerde } from \"src/serde/fieldSerde.ts\";\nimport { groupBy } from \"src/utils.ts\";\n\n/** A simplified view of columns, with only the keys necessary to create SQL statements. */\nexport type OpColumn = { columnName: string; dbType: string; isNullableArray?: boolean };\nexport type InsertOp = { tableName: string; columns: OpColumn[]; columnValues: any[][] };\n/**\n * A logical `update` operation.\n *\n * If we're using op locks, `columns` will include both the new `updatedAt` value (as bumped\n * by the `EntityManager` on mutate), as well as an extra/last \"original updated at\" column\n * (with respective pre-update values in the `rows` data), for including in the conditional\n * update clause.\n */\nexport type UpdateOp = {\n tableName: string;\n columns: OpColumn[];\n columnValues: any[][];\n updatedAt: string | undefined;\n};\nexport type DeleteOp = { tableName: string; ids: any[] };\n\ntype Ops = { inserts: InsertOp[]; updates: UpdateOp[]; deletes: DeleteOp[] };\n\n/**\n * In schemas with entity FK cycles, we may insert a dummy/null value, and later fix it up\n * before the transaction commits.\n *\n * I.e. `INSERT author.favorite_book_id` as `NULL` and then later do an `UPDATE author\n * SET favorite_book_id = 1` after the book has been inserted/we have the id.\n */\nexport type InsertFixup = {\n entity: Entity;\n tableName: string;\n column: OpColumn;\n value: any;\n};\n\n/**\n * Builds AST-ish `Ops` for the inserts/updates/deletes in `todos`.\n *\n * This helps decouple the database-specific driver/library from the knowledge\n * of turning entities into table operations, i.e. so they can be unaware of\n * complexities like field -> column mapping, oplocks, and class table inheritance.\n *\n * We still assume Postgres b/c we assume all ids have been pre-assigned for INSERTs,\n * and don't do any topological sorting of cross-row FK dependencies.\n *\n * But this should let us experiment with knex vs. raw client/etc.\n */\nexport function generateOps(todos: Record<string, Todo>): Ops {\n const ops: Ops = { inserts: [], updates: [], deletes: [] };\n const fixups: InsertFixup[] = [];\n // Would be nice to conditionally sort\n const sorted = Object.values(todos).sort(\n (a, b) => (a.metadata.nonDeferredFkOrder ?? 0) - (b.metadata.nonDeferredFkOrder ?? 0),\n );\n for (const todo of sorted) {\n addInserts(ops, todo, fixups);\n addUpdates(ops, todo);\n addDeletes(ops, todo);\n }\n if (fixups.length > 0) translateFixupsIntoUpdates(ops, fixups);\n return ops;\n}\n\nfunction addInserts(ops: Ops, todo: Todo, fixups: InsertFixup[]): void {\n if (todo.inserts.length > 0) {\n // If we have subtypes, this todo.metadata will always be the base type\n const meta = todo.metadata;\n if (meta.subTypes.length > 0) {\n if (meta.inheritanceType === \"cti\") {\n // Insert into each of the CTI tables\n for (const [meta, group] of groupEntitiesByTable(todo.inserts)) {\n ops.inserts.push(newInsertOp(meta, group, fixups));\n }\n } else if (meta.inheritanceType === \"sti\") {\n // One INSERT per subtype, so each statement's column list spans exactly what that subtype can\n // set. A single statement across subtypes has to bind NULL for the other subtypes' columns,\n // which defeats their database defaults, and outright fails for notNull ones.\n for (const group of groupBy(todo.inserts, (e) => getMetadata(e)).values()) {\n ops.inserts.push(newStiInsertOp(meta, group, fixups));\n }\n } else {\n throw new Error(`Found ${meta.tableName} subTypes without a known inheritanceType ${meta.inheritanceType}`);\n }\n } else {\n ops.inserts.push(newInsertOp(meta, todo.inserts, fixups));\n }\n }\n}\n\nfunction newInsertOp(meta: EntityMetadata, entities: Entity[], fixups: InsertFixup[]): InsertOp {\n // Purposefully use `meta.fields` instead of `allFields` b/c each CTI table has its own `InsertOp`\n const columns = Object.values(meta.fields)\n .filter(hasSerde)\n .flatMap((f) => f.serde.columns);\n const columnValues = collectBindings(entities, meta.tableName, columns, fixups);\n return { tableName: meta.tableName, columns, columnValues };\n}\n\nfunction newStiInsertOp(root: EntityMetadata, entities: Entity[], fixups: InsertFixup[]): InsertOp {\n // `allFields` is the base's fields plus this subtype's own, i.e. everything this subtype can write.\n // Anything it can't write is left out of the statement entirely, so the database applies its default.\n const fields: Field[] = Object.values(getMetadata(entities[0]).allFields);\n const columns = fields.filter(hasSerde).flatMap((f) => f.serde.columns);\n const columnValues = collectBindings(entities, root.tableName, columns, fixups);\n return { tableName: root.tableName, columns, columnValues };\n}\n\nfunction addUpdates(ops: Ops, todo: Todo): void {\n if (todo.updates.length > 0) {\n const meta = todo.metadata;\n if (meta.subTypes.length > 0) {\n if (meta.inheritanceType === \"cti\") {\n for (const [meta, group] of groupEntitiesByTable(todo.updates)) {\n const op = newUpdateOp(meta, group);\n if (op) ops.updates.push(op);\n addLazyUpdates(ops, meta, group);\n }\n } else if (meta.inheritanceType === \"sti\") {\n const op = newUpdateOp(meta, todo.updates);\n if (op) ops.updates.push(op);\n addLazyUpdates(ops, meta, todo.updates);\n } else {\n throw new Error(`Found ${meta.tableName} subTypes without a known inheritanceType ${meta.inheritanceType}`);\n }\n } else {\n const op = newUpdateOp(meta, todo.updates);\n if (op) ops.updates.push(op);\n addLazyUpdates(ops, meta, todo.updates);\n }\n }\n}\n\n/**\n * Writes changed `lazy` columns via a targeted `UPDATE table SET lazy_col = ... WHERE id in (...)`.\n *\n * Lazy columns are excluded from the main batch UPDATE (which spans the batch's union of changed fields),\n * so that entities in the batch that never loaded a lazy column keep their existing db value instead of\n * being overwritten with null. Here we write each lazy column only for the entities that actually changed it.\n */\nfunction addLazyUpdates(ops: Ops, meta: EntityMetadata, entities: Entity[]): void {\n const idColumn = meta.fields[\"id\"].serde!.columns[0];\n for (const fieldName of meta.lazyFieldNames!) {\n const field = meta.fields[fieldName];\n if (!hasSerde(field)) continue;\n const changed = entities.filter((e) => fieldName in getInstanceData(e).changedData);\n if (changed.length === 0) continue;\n const columns: BindingColumn[] = [idColumn, ...field.serde.columns];\n const columnValues = collectBindings(changed, meta.tableName, columns, undefined);\n ops.updates.push({ tableName: meta.tableName, columns, columnValues, updatedAt: undefined });\n }\n}\n\nfunction newUpdateOp(meta: EntityMetadata, entities: Entity[]): UpdateOp | undefined {\n // We only include changed fields in our `UPDATE`--maybe we could change this\n // to always use the same fields, to take advantage of Prepared Statements.\n const changedFields = new Set<string>();\n for (const entity of entities) {\n for (const fieldName in getInstanceData(entity).changedData) changedFields.add(fieldName);\n }\n // Sometimes with derived fields, an instance will be marked as an update, but if the derived field hasn't\n // actually changed, it'll be a noop, so just short-circuit if it looks like that happened. Unless touched.\n if (changedFields.size === 0 && !entities.some((e) => getInstanceData(e).isTouched)) {\n return undefined;\n }\n\n // We may have loaded a1 and a2, and changed a1.firstName, and a2.lastName, but either one\n // might be missing the other's changed fields in it's lazy-initialized data field...\n // (Use `?` because subtypes won't have the updatedAt, and it will be handled by the base type\n // `newUpdateUp`--except STI where we're doing it all in one go, probably needs checked here.)\n const updatedAt = meta.timestampFields?.updatedAt;\n changedFields.add(\"id\");\n if (updatedAt) changedFields.add(updatedAt);\n // `lazy` columns are deliberately excluded from the batch UPDATE and written by `addLazyUpdates`; an\n // entity that never loaded a lazy column isn't in `row`, so forcing `getField` here would clobber it to null.\n const lazyFieldNames = meta.lazyFieldNames!;\n for (const entity of entities) {\n const { data } = getInstanceData(entity);\n for (const key of changedFields) {\n // Check isChangeableField because we might be updating the base `publishers` table\n // and `originalData` might have fields from a subclass `large_publishers` table.\n if (!(key in data) && isChangeableField(entity, key) && !lazyFieldNames.has(key)) {\n getField(entity, key);\n }\n }\n }\n\n const columns: Array<BindingColumn> = (\n meta.inheritanceType === \"sti\"\n ? // Hack this one handling of STI into here...\n getBaseSelfAndSubMetas(meta).flatMap((meta) =>\n meta.stiDiscriminatorField\n ? Object.values(meta.fields)\n : Object.values(meta.fields).filter((f) => f.fieldName !== \"id\"),\n )\n : Object.values(meta.fields)\n )\n .filter((f) => changedFields.has(f.fieldName))\n .filter((f) => !lazyFieldNames.has(f.fieldName))\n .filter(hasSerde)\n .flatMap((f) => f.serde.columns);\n\n // If we're using class table inheritance, base/child tables may not have any columns to update\n if (columns.length === 1) {\n return undefined;\n }\n\n // We already have the bumped updated_at column, but also include the original updated_at for the data CTE\n if (updatedAt) {\n const serde = meta.fields[updatedAt].serde as TimestampSerde<unknown>;\n columns.push({\n columnName: \"__original_updated_at\",\n dbType: \"timestamptz\",\n dbValue: (_, entity) => serde.dbValue(getInstanceData(entity).originalData),\n });\n }\n\n const columnValues = collectBindings(entities, meta.tableName, columns, []);\n const updatedAtColumn = updatedAt ? (meta.fields[updatedAt] as PrimitiveField).serde.columns[0] : undefined;\n return { tableName: meta.tableName, columns, updatedAt: updatedAtColumn?.columnName, columnValues };\n}\n\nfunction addDeletes(ops: Ops, todo: Todo): void {\n if (todo.deletes.length > 0) {\n const meta = todo.metadata;\n const ids = todo.deletes.map((e) => keyToNumber(meta, e.idTagged!).toString());\n if (meta.subTypes.length > 0) {\n getBaseSelfAndSubMetas(meta).forEach((meta) => {\n ops.deletes.push({ tableName: meta.tableName, ids });\n });\n } else {\n ops.deletes.push({ tableName: meta.tableName, ids });\n }\n }\n}\n\nfunction groupEntitiesByTable(entities: Entity[]): Array<[EntityMetadata, Entity[]]> {\n const entitiesByType: Map<EntityMetadata, Entity[]> = new Map();\n for (const e of entities) {\n for (const m of getBaseAndSelfMetas(getMetadata(e))) {\n let list = entitiesByType.get(m);\n if (!list) {\n list = [];\n entitiesByType.set(m, list);\n }\n list.push(e);\n }\n }\n return [...entitiesByType.entries()];\n}\n\ntype BindingColumn = OpColumn & Pick<FieldColumn, \"dbValue\">;\ntype EntityWithData = Entity & { __data: { data: Record<string, unknown> } };\n\n/**\n * Builds a *columnar* array of bindings for the given `entities` and `columns`.\n *\n * We use a columnar approach, instead of `rows[]`, to best match the unnest-based\n * column operations in our `batchInsert` / `batchUpdate` SQL statements.\n */\nfunction collectBindings(\n entities: Entity[],\n tableName: string,\n columns: BindingColumn[],\n fixups: InsertFixup[] | undefined,\n): any[][] {\n const entityCount = entities.length;\n const bindings: any[][] = new Array(columns.length);\n const entitiesWithData = entities as EntityWithData[];\n // Cache data separately; this benchmarks faster than `entities[i].__data.data` in the inner loop.\n const entityData = new Array(entityCount);\n for (let i = 0; i < entityCount; i++) entityData[i] = entitiesWithData[i].__data.data;\n for (let columnIndex = 0; columnIndex < columns.length; columnIndex++) {\n const column = columns[columnIndex];\n const columnValues: any[] = new Array(entityCount);\n for (let entityIndex = 0; entityIndex < entityCount; entityIndex++) {\n columnValues[entityIndex] =\n column.dbValue(entityData[entityIndex], entities[entityIndex], tableName, fixups) ?? null;\n }\n bindings[columnIndex] = columnValues;\n }\n return bindings;\n}\n/**\n * Given `fixups` that indicate where we inserted `NULL` into non-deferred FKs, create `UPDATE`s\n * that insert the value now that the FK check will succeed.\n */\nfunction translateFixupsIntoUpdates(ops: Ops, fixups: InsertFixup[]): void {\n // Create a single `UPDATE` for the N fixups we might have for each table/column combination\n groupBy(fixups, (f) => `${f.tableName}.${f.column.columnName}`).forEach((fixups) => {\n const { tableName, entity, column } = fixups[0];\n ops.updates.push({\n tableName,\n columns: [getMetadata(entity).fields[\"id\"].serde!.columns[0], column],\n columnValues: [\n // Make 1 column of ids, and 1 column of values\n fixups.map((fixup) => fixup.entity.id),\n fixups.map((fixup) => fixup.value),\n ],\n updatedAt: undefined,\n });\n });\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
|
|
3
|
-
require("../Todo.cjs");
|
|
4
3
|
const require_keys = require("../keys.cjs");
|
|
5
4
|
const require_BaseEntity = require("../BaseEntity.cjs");
|
|
6
5
|
let crypto = require("crypto");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IdAssigner.cjs","names":["#runner","keyToTaggedId"],"sources":["../../src/drivers/IdAssigner.ts"],"sourcesContent":["import * as crypto from \"crypto\";\n\nimport { getInstanceData } from \"
|
|
1
|
+
{"version":3,"file":"IdAssigner.cjs","names":["#runner","keyToTaggedId"],"sources":["../../src/drivers/IdAssigner.ts"],"sourcesContent":["import * as crypto from \"crypto\";\n\nimport { getInstanceData } from \"src/BaseEntity.ts\";\nimport type { Todo } from \"src/flush/Todo.ts\";\nimport { keyToTaggedId } from \"src/keys.ts\";\n\nexport interface IdAssigner {\n assignNewIds(todos: Record<string, Todo>): Promise<void>;\n}\n\n/** Super-small/dumb wrapper around maybe-Knex/maybe-postgres.js/maybe-Bun-sql libraries. */\ntype QueryRunner = (sql: string) => Promise<any[]>;\n\n/**\n * Assigns all new entities an id directly from their corresponding sequence generator, instead of via INSERTs.\n *\n * This lets us avoid cyclic issues with some INSERTs having foreign keys to other rows that themselves\n * need to first be INSERTed.\n */\nexport class SequenceIdAssigner implements IdAssigner {\n #runner: QueryRunner;\n\n public constructor(runner: QueryRunner) {\n this.#runner = runner;\n }\n\n async assignNewIds(todos: Record<string, Todo>): Promise<void> {\n const seqStatements: string[] = [];\n Object.values(todos).forEach((todo) => {\n // Even if we have INSERTs, the user may have already assigned ids...\n const needsIds = todo.inserts.filter((e) => e.idMaybe === undefined);\n if (needsIds.length > 0) {\n const sequenceName = `${todo.metadata.tableName}_id_seq`;\n const sql = `select nextval('${sequenceName}') from generate_series(1, ${needsIds.length})`;\n seqStatements.push(sql);\n }\n });\n if (seqStatements.length > 0) {\n // There will be 1 per table; 1 single insert should be fine but we might need to batch for super-large schemas?\n const sql = seqStatements.join(\" UNION ALL \");\n const result = await this.#runner(sql);\n let i = 0;\n Object.values(todos).forEach((todo) => {\n for (const insert of todo.inserts.filter((e) => e.idMaybe === undefined)) {\n // Use todo.metadata so that all subtypes get their base type's tag\n getInstanceData(insert).data[\"id\"] = keyToTaggedId(todo.metadata, result[i++][\"nextval\"]);\n }\n });\n }\n }\n}\n\n/**\n * Creates random UUIDs for uuid-based keys in production environments.\n *\n * See {@link TestUuidAssigner} for creating stable-ish ids for tests\n */\nexport class RandomUuidAssigner implements IdAssigner {\n async assignNewIds(todos: Record<string, Todo>): Promise<void> {\n Object.values(todos).forEach((todo) => {\n for (const insert of todo.inserts) {\n getInstanceData(insert).data[\"id\"] = keyToTaggedId(todo.metadata, crypto.randomUUID());\n }\n });\n }\n}\n\n/**\n * Creates deterministic / stable-ish UUIDs for test suites.\n *\n * We use each entity's tag as the 3rd group of digits, and a per-entity incrementing integer as\n * the 4th group of digits.\n *\n * E.g. a test with two Authors (tag `a`) and three Books (tag `b`) will get these ids:\n *\n * ```\n * 00000000-0000-0000-000a-000000000000\n * 00000000-0000-0000-000a-000000000001\n * 00000000-0000-0000-000b-000000000000\n * 00000000-0000-0000-000b-000000000001\n * 00000000-0000-0000-000b-000000000002\n * ```\n */\nexport class TestUuidAssigner implements IdAssigner {\n private nextId: Record<string, number> = {};\n\n async assignNewIds(todos: Record<string, Todo>): Promise<void> {\n Object.entries(todos).forEach(([, todo]) => {\n if (todo.inserts.length > 0) {\n const tag = todo.metadata.tagName.substring(0, 4).padStart(4, \"0\");\n this.nextId[tag] ??= 0;\n for (const insert of todo.inserts) {\n const id = String(this.nextId[tag]++);\n const uuid = `00000000-0000-0000-${tag}-${id.padStart(12, \"0\")}`;\n getInstanceData(insert).data[\"id\"] = keyToTaggedId(todo.metadata, uuid);\n }\n }\n });\n }\n\n reset() {\n this.nextId = {};\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAmBA,IAAa,qBAAb,MAAsD;CACpD;CAEA,YAAmB,QAAqB;EACtC,KAAKA,UAAU;CACjB;CAEA,MAAM,aAAa,OAA4C;EAC7D,MAAM,gBAA0B,CAAC;EACjC,OAAO,OAAO,KAAK,CAAC,CAAC,SAAS,SAAS;GAErC,MAAM,WAAW,KAAK,QAAQ,QAAQ,MAAM,EAAE,YAAY,KAAA,CAAS;GACnE,IAAI,SAAS,SAAS,GAAG;IAEvB,MAAM,MAAM,mBAAmB,GADP,KAAK,SAAS,UAAU,SACJ,6BAA6B,SAAS,OAAO;IACzF,cAAc,KAAK,GAAG;GACxB;EACF,CAAC;EACD,IAAI,cAAc,SAAS,GAAG;GAE5B,MAAM,MAAM,cAAc,KAAK,aAAa;GAC5C,MAAM,SAAS,MAAM,KAAKA,QAAQ,GAAG;GACrC,IAAI,IAAI;GACR,OAAO,OAAO,KAAK,CAAC,CAAC,SAAS,SAAS;IACrC,KAAK,MAAM,UAAU,KAAK,QAAQ,QAAQ,MAAM,EAAE,YAAY,KAAA,CAAS,GAErE,mBAAA,gBAAgB,MAAM,CAAC,CAAC,KAAK,QAAQC,aAAAA,cAAc,KAAK,UAAU,OAAO,IAAI,CAAC,UAAU;GAE5F,CAAC;EACH;CACF;AACF;;;;;;AAOA,IAAa,qBAAb,MAAsD;CACpD,MAAM,aAAa,OAA4C;EAC7D,OAAO,OAAO,KAAK,CAAC,CAAC,SAAS,SAAS;GACrC,KAAK,MAAM,UAAU,KAAK,SACxB,mBAAA,gBAAgB,MAAM,CAAC,CAAC,KAAK,QAAQA,aAAAA,cAAc,KAAK,UAAU,OAAO,WAAW,CAAC;EAEzF,CAAC;CACH;AACF;;;;;;;;;;;;;;;;;AAkBA,IAAa,mBAAb,MAAoD;CAClD,SAAyC,CAAC;CAE1C,MAAM,aAAa,OAA4C;EAC7D,OAAO,QAAQ,KAAK,CAAC,CAAC,SAAS,GAAG,UAAU;GAC1C,IAAI,KAAK,QAAQ,SAAS,GAAG;IAC3B,MAAM,MAAM,KAAK,SAAS,QAAQ,UAAU,GAAG,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;IACjE,KAAK,OAAO,SAAS;IACrB,KAAK,MAAM,UAAU,KAAK,SAAS;KAEjC,MAAM,OAAO,sBAAsB,IAAI,GAD5B,OAAO,KAAK,OAAO,IAAI,EACS,CAAC,CAAC,SAAS,IAAI,GAAG;KAC7D,mBAAA,gBAAgB,MAAM,CAAC,CAAC,KAAK,QAAQA,aAAAA,cAAc,KAAK,UAAU,IAAI;IACxE;GACF;EACF,CAAC;CACH;CAEA,QAAQ;EACN,KAAK,SAAS,CAAC;CACjB;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IdAssigner.js","names":["#runner"],"sources":["../../src/drivers/IdAssigner.ts"],"sourcesContent":["import * as crypto from \"crypto\";\n\nimport { getInstanceData } from \"
|
|
1
|
+
{"version":3,"file":"IdAssigner.js","names":["#runner"],"sources":["../../src/drivers/IdAssigner.ts"],"sourcesContent":["import * as crypto from \"crypto\";\n\nimport { getInstanceData } from \"src/BaseEntity.ts\";\nimport type { Todo } from \"src/flush/Todo.ts\";\nimport { keyToTaggedId } from \"src/keys.ts\";\n\nexport interface IdAssigner {\n assignNewIds(todos: Record<string, Todo>): Promise<void>;\n}\n\n/** Super-small/dumb wrapper around maybe-Knex/maybe-postgres.js/maybe-Bun-sql libraries. */\ntype QueryRunner = (sql: string) => Promise<any[]>;\n\n/**\n * Assigns all new entities an id directly from their corresponding sequence generator, instead of via INSERTs.\n *\n * This lets us avoid cyclic issues with some INSERTs having foreign keys to other rows that themselves\n * need to first be INSERTed.\n */\nexport class SequenceIdAssigner implements IdAssigner {\n #runner: QueryRunner;\n\n public constructor(runner: QueryRunner) {\n this.#runner = runner;\n }\n\n async assignNewIds(todos: Record<string, Todo>): Promise<void> {\n const seqStatements: string[] = [];\n Object.values(todos).forEach((todo) => {\n // Even if we have INSERTs, the user may have already assigned ids...\n const needsIds = todo.inserts.filter((e) => e.idMaybe === undefined);\n if (needsIds.length > 0) {\n const sequenceName = `${todo.metadata.tableName}_id_seq`;\n const sql = `select nextval('${sequenceName}') from generate_series(1, ${needsIds.length})`;\n seqStatements.push(sql);\n }\n });\n if (seqStatements.length > 0) {\n // There will be 1 per table; 1 single insert should be fine but we might need to batch for super-large schemas?\n const sql = seqStatements.join(\" UNION ALL \");\n const result = await this.#runner(sql);\n let i = 0;\n Object.values(todos).forEach((todo) => {\n for (const insert of todo.inserts.filter((e) => e.idMaybe === undefined)) {\n // Use todo.metadata so that all subtypes get their base type's tag\n getInstanceData(insert).data[\"id\"] = keyToTaggedId(todo.metadata, result[i++][\"nextval\"]);\n }\n });\n }\n }\n}\n\n/**\n * Creates random UUIDs for uuid-based keys in production environments.\n *\n * See {@link TestUuidAssigner} for creating stable-ish ids for tests\n */\nexport class RandomUuidAssigner implements IdAssigner {\n async assignNewIds(todos: Record<string, Todo>): Promise<void> {\n Object.values(todos).forEach((todo) => {\n for (const insert of todo.inserts) {\n getInstanceData(insert).data[\"id\"] = keyToTaggedId(todo.metadata, crypto.randomUUID());\n }\n });\n }\n}\n\n/**\n * Creates deterministic / stable-ish UUIDs for test suites.\n *\n * We use each entity's tag as the 3rd group of digits, and a per-entity incrementing integer as\n * the 4th group of digits.\n *\n * E.g. a test with two Authors (tag `a`) and three Books (tag `b`) will get these ids:\n *\n * ```\n * 00000000-0000-0000-000a-000000000000\n * 00000000-0000-0000-000a-000000000001\n * 00000000-0000-0000-000b-000000000000\n * 00000000-0000-0000-000b-000000000001\n * 00000000-0000-0000-000b-000000000002\n * ```\n */\nexport class TestUuidAssigner implements IdAssigner {\n private nextId: Record<string, number> = {};\n\n async assignNewIds(todos: Record<string, Todo>): Promise<void> {\n Object.entries(todos).forEach(([, todo]) => {\n if (todo.inserts.length > 0) {\n const tag = todo.metadata.tagName.substring(0, 4).padStart(4, \"0\");\n this.nextId[tag] ??= 0;\n for (const insert of todo.inserts) {\n const id = String(this.nextId[tag]++);\n const uuid = `00000000-0000-0000-${tag}-${id.padStart(12, \"0\")}`;\n getInstanceData(insert).data[\"id\"] = keyToTaggedId(todo.metadata, uuid);\n }\n }\n });\n }\n\n reset() {\n this.nextId = {};\n }\n}\n"],"mappings":";;;;;;;;;;AAmBA,IAAa,qBAAb,MAAsD;CACpD;CAEA,YAAmB,QAAqB;EACtC,KAAKA,UAAU;CACjB;CAEA,MAAM,aAAa,OAA4C;EAC7D,MAAM,gBAA0B,CAAC;EACjC,OAAO,OAAO,KAAK,CAAC,CAAC,SAAS,SAAS;GAErC,MAAM,WAAW,KAAK,QAAQ,QAAQ,MAAM,EAAE,YAAY,KAAA,CAAS;GACnE,IAAI,SAAS,SAAS,GAAG;IAEvB,MAAM,MAAM,mBAAmB,GADP,KAAK,SAAS,UAAU,SACJ,6BAA6B,SAAS,OAAO;IACzF,cAAc,KAAK,GAAG;GACxB;EACF,CAAC;EACD,IAAI,cAAc,SAAS,GAAG;GAE5B,MAAM,MAAM,cAAc,KAAK,aAAa;GAC5C,MAAM,SAAS,MAAM,KAAKA,QAAQ,GAAG;GACrC,IAAI,IAAI;GACR,OAAO,OAAO,KAAK,CAAC,CAAC,SAAS,SAAS;IACrC,KAAK,MAAM,UAAU,KAAK,QAAQ,QAAQ,MAAM,EAAE,YAAY,KAAA,CAAS,GAErE,gBAAgB,MAAM,CAAC,CAAC,KAAK,QAAQ,cAAc,KAAK,UAAU,OAAO,IAAI,CAAC,UAAU;GAE5F,CAAC;EACH;CACF;AACF;;;;;;AAOA,IAAa,qBAAb,MAAsD;CACpD,MAAM,aAAa,OAA4C;EAC7D,OAAO,OAAO,KAAK,CAAC,CAAC,SAAS,SAAS;GACrC,KAAK,MAAM,UAAU,KAAK,SACxB,gBAAgB,MAAM,CAAC,CAAC,KAAK,QAAQ,cAAc,KAAK,UAAU,OAAO,WAAW,CAAC;EAEzF,CAAC;CACH;AACF;;;;;;;;;;;;;;;;;AAkBA,IAAa,mBAAb,MAAoD;CAClD,SAAyC,CAAC;CAE1C,MAAM,aAAa,OAA4C;EAC7D,OAAO,QAAQ,KAAK,CAAC,CAAC,SAAS,GAAG,UAAU;GAC1C,IAAI,KAAK,QAAQ,SAAS,GAAG;IAC3B,MAAM,MAAM,KAAK,SAAS,QAAQ,UAAU,GAAG,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;IACjE,KAAK,OAAO,SAAS;IACrB,KAAK,MAAM,UAAU,KAAK,SAAS;KAEjC,MAAM,OAAO,sBAAsB,IAAI,GAD5B,OAAO,KAAK,OAAO,IAAI,EACS,CAAC,CAAC,SAAS,IAAI,GAAG;KAC7D,gBAAgB,MAAM,CAAC,CAAC,KAAK,QAAQ,cAAc,KAAK,UAAU,IAAI;IACxE;GACF;EACF,CAAC;CACH;CAEA,QAAQ;EACN,KAAK,SAAS,CAAC;CACjB;AACF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_utils = require("../utils.cjs");
|
|
3
|
+
const require_runtimeConfig = require("../runtimeConfig.cjs");
|
|
4
|
+
const require_queries_find_buildFindQuery = require("../queries/find/buildFindQuery.cjs");
|
|
5
|
+
const require_dataloaders_findDataLoader = require("../dataloaders/findDataLoader.cjs");
|
|
6
|
+
const require_drivers_EntityWriter = require("./EntityWriter.cjs");
|
|
7
|
+
//#region src/drivers/driverApi.ts
|
|
8
|
+
const driverApi = {
|
|
9
|
+
buildValuesCte: require_dataloaders_findDataLoader.buildValuesCte,
|
|
10
|
+
generateOps: require_drivers_EntityWriter.generateOps,
|
|
11
|
+
buildCteSql: require_queries_find_buildFindQuery.buildCteSql,
|
|
12
|
+
getRuntimeConfig: require_runtimeConfig.getRuntimeConfig,
|
|
13
|
+
batched: require_utils.batched,
|
|
14
|
+
cleanSql: require_utils.cleanSql
|
|
15
|
+
};
|
|
16
|
+
//#endregion
|
|
17
|
+
exports.driverApi = driverApi;
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=driverApi.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driverApi.cjs","names":[],"sources":["../../src/drivers/driverApi.ts"],"sourcesContent":["import { buildValuesCte } from \"src/dataloaders/findDataLoader.ts\";\nimport { type DeleteOp, type InsertOp, type UpdateOp, generateOps } from \"src/drivers/EntityWriter.ts\";\nimport { buildCteSql } from \"src/queries/find/buildFindQuery.ts\";\nimport { getRuntimeConfig } from \"src/runtimeConfig.ts\";\nimport { batched, cleanSql } from \"src/utils.ts\";\n\nexport const driverApi = {\n buildValuesCte,\n generateOps,\n buildCteSql,\n getRuntimeConfig,\n batched,\n cleanSql,\n};\n\nexport type driverApi = {\n DeleteOp: DeleteOp;\n UpdateOp: UpdateOp;\n InsertOp: InsertOp;\n};\n"],"mappings":";;;;;;;AAMA,MAAa,YAAY;CACvB,gBAAA,mCAAA;CACA,aAAA,6BAAA;CACA,aAAA,oCAAA;CACA,kBAAA,sBAAA;CACA,SAAA,cAAA;CACA,UAAA,cAAA;AACF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { batched, cleanSql } from "../utils.cjs";
|
|
2
|
+
import { DeleteOp, InsertOp, UpdateOp, generateOps } from "./EntityWriter.cjs";
|
|
3
|
+
import { buildCteSql } from "../queries/find/buildFindQuery.cjs";
|
|
4
|
+
import { buildValuesCte } from "../dataloaders/findDataLoader.cjs";
|
|
5
|
+
import { getRuntimeConfig } from "../runtimeConfig.cjs";
|
|
6
|
+
//#region src/drivers/driverApi.d.ts
|
|
7
|
+
declare const driverApi: {
|
|
8
|
+
buildValuesCte: typeof buildValuesCte;
|
|
9
|
+
generateOps: typeof generateOps;
|
|
10
|
+
buildCteSql: typeof buildCteSql;
|
|
11
|
+
getRuntimeConfig: typeof getRuntimeConfig;
|
|
12
|
+
batched: typeof batched;
|
|
13
|
+
cleanSql: typeof cleanSql;
|
|
14
|
+
};
|
|
15
|
+
type driverApi = {
|
|
16
|
+
DeleteOp: DeleteOp;
|
|
17
|
+
UpdateOp: UpdateOp;
|
|
18
|
+
InsertOp: InsertOp;
|
|
19
|
+
};
|
|
20
|
+
//#endregion
|
|
21
|
+
export { driverApi };
|
|
22
|
+
//# sourceMappingURL=driverApi.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driverApi.d.cts","names":[],"sources":["../../src/drivers/driverApi.ts"],"mappings":";;;;;;cAMa;;;;;;;;KASD;EACV,UAAU;EACV,UAAU;EACV,UAAU"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { batched, cleanSql } from "../utils.mjs";
|
|
2
|
+
import { DeleteOp, InsertOp, UpdateOp, generateOps } from "./EntityWriter.mjs";
|
|
3
|
+
import { buildCteSql } from "../queries/find/buildFindQuery.mjs";
|
|
4
|
+
import { buildValuesCte } from "../dataloaders/findDataLoader.mjs";
|
|
5
|
+
import { getRuntimeConfig } from "../runtimeConfig.mjs";
|
|
6
|
+
//#region src/drivers/driverApi.d.ts
|
|
7
|
+
declare const driverApi: {
|
|
8
|
+
buildValuesCte: typeof buildValuesCte;
|
|
9
|
+
generateOps: typeof generateOps;
|
|
10
|
+
buildCteSql: typeof buildCteSql;
|
|
11
|
+
getRuntimeConfig: typeof getRuntimeConfig;
|
|
12
|
+
batched: typeof batched;
|
|
13
|
+
cleanSql: typeof cleanSql;
|
|
14
|
+
};
|
|
15
|
+
type driverApi = {
|
|
16
|
+
DeleteOp: DeleteOp;
|
|
17
|
+
UpdateOp: UpdateOp;
|
|
18
|
+
InsertOp: InsertOp;
|
|
19
|
+
};
|
|
20
|
+
//#endregion
|
|
21
|
+
export { driverApi };
|
|
22
|
+
//# sourceMappingURL=driverApi.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driverApi.d.mts","names":[],"sources":["../../src/drivers/driverApi.ts"],"mappings":";;;;;;cAMa;;;;;;;;KASD;EACV,UAAU;EACV,UAAU;EACV,UAAU"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { batched, cleanSql } from "../utils.js";
|
|
2
|
+
import { getRuntimeConfig } from "../runtimeConfig.js";
|
|
3
|
+
import { buildCteSql } from "../queries/find/buildFindQuery.js";
|
|
4
|
+
import { buildValuesCte } from "../dataloaders/findDataLoader.js";
|
|
5
|
+
import { generateOps } from "./EntityWriter.js";
|
|
6
|
+
//#region src/drivers/driverApi.ts
|
|
7
|
+
const driverApi = {
|
|
8
|
+
buildValuesCte,
|
|
9
|
+
generateOps,
|
|
10
|
+
buildCteSql,
|
|
11
|
+
getRuntimeConfig,
|
|
12
|
+
batched,
|
|
13
|
+
cleanSql
|
|
14
|
+
};
|
|
15
|
+
//#endregion
|
|
16
|
+
export { driverApi };
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=driverApi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driverApi.js","names":[],"sources":["../../src/drivers/driverApi.ts"],"sourcesContent":["import { buildValuesCte } from \"src/dataloaders/findDataLoader.ts\";\nimport { type DeleteOp, type InsertOp, type UpdateOp, generateOps } from \"src/drivers/EntityWriter.ts\";\nimport { buildCteSql } from \"src/queries/find/buildFindQuery.ts\";\nimport { getRuntimeConfig } from \"src/runtimeConfig.ts\";\nimport { batched, cleanSql } from \"src/utils.ts\";\n\nexport const driverApi = {\n buildValuesCte,\n generateOps,\n buildCteSql,\n getRuntimeConfig,\n batched,\n cleanSql,\n};\n\nexport type driverApi = {\n DeleteOp: DeleteOp;\n UpdateOp: UpdateOp;\n InsertOp: InsertOp;\n};\n"],"mappings":";;;;;;AAMA,MAAa,YAAY;CACvB;CACA;CACA;CACA;CACA;CACA;AACF"}
|
package/build/fields.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const
|
|
3
|
-
const require_utils = require("./utils.cjs");
|
|
2
|
+
const require_serde_temporal = require("./serde/temporal.cjs");
|
|
4
3
|
const require_keys = require("./keys.cjs");
|
|
4
|
+
const require_utils = require("./utils.cjs");
|
|
5
5
|
const require_EntityMetadata = require("./EntityMetadata.cjs");
|
|
6
6
|
const require_index = require("./index.cjs");
|
|
7
7
|
const require_EntityManager = require("./EntityManager.cjs");
|
|
@@ -105,7 +105,7 @@ function equalArrays(a, b) {
|
|
|
105
105
|
if (a.length !== b.length) return false;
|
|
106
106
|
return a.every((_, i) => equal(a[i], b[i]));
|
|
107
107
|
}
|
|
108
|
-
const Temporal =
|
|
108
|
+
const Temporal = require_serde_temporal.maybeRequireTemporal()?.Temporal;
|
|
109
109
|
function equal(a, b) {
|
|
110
110
|
if (a === b) return true;
|
|
111
111
|
if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
|
package/build/fields.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fields.cjs","names":["getEmInternalApi","getInstanceData","getMetadata","fail","cleanStringValue","isEntity","maybeResolveReferenceToId","maybeRequireTemporal"],"sources":["../src/fields.ts"],"sourcesContent":["import { getInstanceData } from \"./BaseEntity.ts\";\nimport { type Entity, isEntity } from \"./Entity.ts\";\nimport { getEmInternalApi } from \"./EntityManager.ts\";\nimport { type Field, getMetadata } from \"./EntityMetadata.ts\";\nimport { cleanStringValue, ensureNotDeleted, maybeResolveReferenceToId } from \"./index.ts\";\nimport { maybeRequireTemporal } from \"./temporal.ts\";\nimport { fail } from \"./utils.ts\";\n\n/**\n * Returns the current value of `fieldName`, this is an internal method that should\n * only be called by the code-generated getters.\n *\n * We skip any typing like `fieldName: keyof T` because this method should only be\n * called by trusted codegen anyway.\n */\nexport function getField(entity: Entity, fieldName: string): any {\n const { em } = entity;\n const api = getEmInternalApi(em);\n api.pluginManager.beforeGetField(entity, fieldName);\n // We may not have converted the database column value into domain values yet\n const instanceData = getInstanceData(entity);\n const { data } = instanceData;\n if (fieldName in data) {\n return data[fieldName];\n } else {\n if (!entity.isNewEntity) {\n const field = getMetadata(entity).allFields[fieldName];\n const serde = field?.serde ?? fail(`Missing serde for ${fieldName}`);\n data[fieldName] = serde.fromRow(instanceData.rowData, instanceData.rowIndex);\n }\n return data[fieldName];\n }\n}\n\n/** Returns whether `fieldName` is a field/column on `entity` that can be changed. */\nexport function isChangeableField(entity: Entity, fieldName: string): boolean {\n return !!getMetadata(entity).allFields[fieldName]?.serde;\n}\n\n/** Returns whether `fieldName` has been set, even if it's undefined, on `entity`. */\nexport function isFieldSet(entity: Entity, fieldName: string): boolean {\n const { data } = getInstanceData(entity);\n if (fieldName in data) return true;\n // Avoid calling `getField` on new entities because it populates the field as a side effect.\n if (entity.isNewEntity) return false;\n // We may not have converted the database column value into domain values yet.\n getField(entity, fieldName);\n return fieldName in data;\n}\n\n/**\n * Sets the current value of `fieldName`, this is an internal method that should\n * only be called by the code-generated setters.\n *\n * We skip any typing like `fieldName: keyof T` because this method should only be\n * called by trusted codegen anyway.\n *\n * Returns `true` if the value was changed, or `false` if it was a noop.\n */\nexport function setField(entity: Entity, fieldName: string, newValue: any): boolean {\n ensureNotDeleted(entity, \"pending\");\n const { em } = entity;\n const api = getEmInternalApi(em);\n const { rm, pluginManager, indexManager, fieldLogger, isLoadedCache } = api;\n\n // If we're flushing, only allow writes from hooks\n api.checkWritesAllowed();\n\n // Tell any `#isLoaded` or `#value` caches that they might be stale\n isLoadedCache.resetIsLoaded(entity, fieldName);\n\n const instanceData = getInstanceData(entity);\n const { data, originalData, flushedData } = instanceData;\n\n // Do string sanitization\n const field = getMetadata(entity).allFields[fieldName];\n if (field.kind === \"primitive\" && field.type === \"string\" && field.sanitize !== false) {\n newValue = cleanStringValue(newValue);\n }\n\n const currentValue = getField(entity, fieldName);\n const isReference = field.kind === \"m2o\" || field.kind === \"poly\";\n const currentEqualsNew = fieldValueEquals(field, currentValue, newValue);\n // Remember every prior reference value so `followReverseHint` can rewalk both original and transient owners.\n if (isReference && !currentEqualsNew) {\n instanceData.rememberReferenceValue(fieldName, currentValue);\n }\n\n // If a `set` occurs during the AsyncReactiveField-loop, copy the last-flushed value to flushedData.\n // Then our `pendingOperation` logic can tell \"do we need another micro-flush?\" separately\n // from our public-facing changed fields logic.\n if (flushedData) {\n if (fieldName in flushedData) {\n // We've already copied the last-micro-flush value into flushedData,\n // are we changing back to that? If so, we won't need another micro-flush.\n if (equalOrSameEntity(flushedData[fieldName], newValue)) {\n delete flushedData[fieldName];\n } else {\n // Otherwise just let data[fieldName] get the even-newer value, and keep\n // flushedData[fieldName] as the last-micro-flushed value.\n }\n } else if (!currentEqualsNew) {\n // This is the 1st rqf-loop change for this field, so let data[fieldName]\n // get the even newer value, but keep the last-micro-flushed value in flushedData.\n flushedData[fieldName] = currentValue;\n }\n }\n\n // \"Un-dirty\" our originalData if newValue is reverting to originalData\n if (fieldName in originalData) {\n if (fieldValueEquals(field, originalData[fieldName], newValue)) {\n indexManager.maybeUpdateFieldIndex(entity, fieldName, currentValue, newValue);\n\n pluginManager.beforeSetField(entity, fieldName, newValue);\n data[fieldName] = newValue;\n instanceData.markFieldClean(fieldName);\n\n fieldLogger.logSet(entity, fieldName, newValue);\n if (isReference && instanceData.getReferenceHistory(fieldName).length > 0) {\n rm.queueDownstreamReactables(entity, fieldName);\n } else {\n // For normal reverts, the field is clean again, so any pending downstream work can be removed.\n rm.dequeueDownstreamReactables(entity, fieldName);\n }\n\n return true;\n }\n }\n\n // Push this logic into a field serde type abstraction?\n if (currentEqualsNew) {\n // If we're doing `entity.field = undefined`, we'll be equal, but mark ourselves as \"set\"\n // so that defaults know to respect the intent of keeping this field undefined.\n if (!(fieldName in data)) data[fieldName] = undefined;\n return false;\n }\n\n // Only save the currentValue on the 1st change of this field\n if (!(fieldName in originalData)) {\n instanceData.markFieldDirty(fieldName, currentValue);\n }\n fieldLogger.logSet(entity, fieldName, newValue);\n rm.queueDownstreamReactables(entity, fieldName);\n\n indexManager.maybeUpdateFieldIndex(entity, fieldName, currentValue, newValue);\n\n pluginManager.beforeSetField(entity, fieldName, newValue);\n data[fieldName] = newValue;\n return true;\n}\n\nfunction fieldValueEquals(field: Field, a: unknown, b: unknown): boolean {\n // Primitive scalar sets are the common path, so avoid Date/Temporal/entity checks when both values cannot need them.\n if (field.kind !== \"m2o\" && field.kind !== \"poly\" && isNonObjectValue(a) && isNonObjectValue(b)) return a === b;\n return equalOrSameEntity(a, b);\n}\n\nfunction isNonObjectValue(value: unknown): boolean {\n return value === null || typeof value !== \"object\";\n}\n\nfunction equalOrSameEntity(a: any, b: any): boolean {\n return (\n equal(a, b) ||\n (Array.isArray(a) && Array.isArray(b) && equalArrays(a, b)) ||\n // This is kind of gross, but make sure not to compare two both-new entities\n (((isEntity(a) && !a.isNewEntity) || (isEntity(b) && !b.isNewEntity)) &&\n maybeResolveReferenceToId(a) === maybeResolveReferenceToId(b))\n );\n}\n\nexport function equalArrays(a: any[], b: any[]): boolean {\n if (a.length !== b.length) return false;\n return a.every((_: any, i) => equal(a[i], b[i]));\n}\n\nconst Temporal = maybeRequireTemporal()?.Temporal;\nexport function equal(a: any, b: any): boolean {\n if (a === b) return true;\n if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();\n if (Temporal) {\n if (a instanceof Temporal.ZonedDateTime && b instanceof Temporal.ZonedDateTime) return a.equals(b);\n if (a instanceof Temporal.PlainDateTime && b instanceof Temporal.PlainDateTime) return a.equals(b);\n if (a instanceof Temporal.PlainDate && b instanceof Temporal.PlainDate) return a.equals(b);\n }\n return false;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fields.cjs","names":["getEmInternalApi","getInstanceData","getMetadata","fail","cleanStringValue","isEntity","maybeResolveReferenceToId","maybeRequireTemporal"],"sources":["../src/fields.ts"],"sourcesContent":["import { getInstanceData } from \"src/BaseEntity.ts\";\nimport { type Entity, isEntity } from \"src/Entity.ts\";\nimport { getEmInternalApi } from \"src/EntityManager.ts\";\nimport { type Field, getMetadata } from \"src/EntityMetadata.ts\";\nimport { cleanStringValue, ensureNotDeleted, maybeResolveReferenceToId } from \"src/index.ts\";\nimport { maybeRequireTemporal } from \"src/serde/temporal.ts\";\nimport { fail } from \"src/utils.ts\";\n\n/**\n * Returns the current value of `fieldName`, this is an internal method that should\n * only be called by the code-generated getters.\n *\n * We skip any typing like `fieldName: keyof T` because this method should only be\n * called by trusted codegen anyway.\n */\nexport function getField(entity: Entity, fieldName: string): any {\n const { em } = entity;\n const api = getEmInternalApi(em);\n api.pluginManager.beforeGetField(entity, fieldName);\n // We may not have converted the database column value into domain values yet\n const instanceData = getInstanceData(entity);\n const { data } = instanceData;\n if (fieldName in data) {\n return data[fieldName];\n } else {\n if (!entity.isNewEntity) {\n const field = getMetadata(entity).allFields[fieldName];\n const serde = field?.serde ?? fail(`Missing serde for ${fieldName}`);\n data[fieldName] = serde.fromRow(instanceData.rowData, instanceData.rowIndex);\n }\n return data[fieldName];\n }\n}\n\n/** Returns whether `fieldName` is a field/column on `entity` that can be changed. */\nexport function isChangeableField(entity: Entity, fieldName: string): boolean {\n return !!getMetadata(entity).allFields[fieldName]?.serde;\n}\n\n/** Returns whether `fieldName` has been set, even if it's undefined, on `entity`. */\nexport function isFieldSet(entity: Entity, fieldName: string): boolean {\n const { data } = getInstanceData(entity);\n if (fieldName in data) return true;\n // Avoid calling `getField` on new entities because it populates the field as a side effect.\n if (entity.isNewEntity) return false;\n // We may not have converted the database column value into domain values yet.\n getField(entity, fieldName);\n return fieldName in data;\n}\n\n/**\n * Sets the current value of `fieldName`, this is an internal method that should\n * only be called by the code-generated setters.\n *\n * We skip any typing like `fieldName: keyof T` because this method should only be\n * called by trusted codegen anyway.\n *\n * Returns `true` if the value was changed, or `false` if it was a noop.\n */\nexport function setField(entity: Entity, fieldName: string, newValue: any): boolean {\n ensureNotDeleted(entity, \"pending\");\n const { em } = entity;\n const api = getEmInternalApi(em);\n const { rm, pluginManager, indexManager, fieldLogger, isLoadedCache } = api;\n\n // If we're flushing, only allow writes from hooks\n api.checkWritesAllowed();\n\n // Tell any `#isLoaded` or `#value` caches that they might be stale\n isLoadedCache.resetIsLoaded(entity, fieldName);\n\n const instanceData = getInstanceData(entity);\n const { data, originalData, flushedData } = instanceData;\n\n // Do string sanitization\n const field = getMetadata(entity).allFields[fieldName];\n if (field.kind === \"primitive\" && field.type === \"string\" && field.sanitize !== false) {\n newValue = cleanStringValue(newValue);\n }\n\n const currentValue = getField(entity, fieldName);\n const isReference = field.kind === \"m2o\" || field.kind === \"poly\";\n const currentEqualsNew = fieldValueEquals(field, currentValue, newValue);\n // Remember every prior reference value so `followReverseHint` can rewalk both original and transient owners.\n if (isReference && !currentEqualsNew) {\n instanceData.rememberReferenceValue(fieldName, currentValue);\n }\n\n // If a `set` occurs during the AsyncReactiveField-loop, copy the last-flushed value to flushedData.\n // Then our `pendingOperation` logic can tell \"do we need another micro-flush?\" separately\n // from our public-facing changed fields logic.\n if (flushedData) {\n if (fieldName in flushedData) {\n // We've already copied the last-micro-flush value into flushedData,\n // are we changing back to that? If so, we won't need another micro-flush.\n if (equalOrSameEntity(flushedData[fieldName], newValue)) {\n delete flushedData[fieldName];\n } else {\n // Otherwise just let data[fieldName] get the even-newer value, and keep\n // flushedData[fieldName] as the last-micro-flushed value.\n }\n } else if (!currentEqualsNew) {\n // This is the 1st rqf-loop change for this field, so let data[fieldName]\n // get the even newer value, but keep the last-micro-flushed value in flushedData.\n flushedData[fieldName] = currentValue;\n }\n }\n\n // \"Un-dirty\" our originalData if newValue is reverting to originalData\n if (fieldName in originalData) {\n if (fieldValueEquals(field, originalData[fieldName], newValue)) {\n indexManager.maybeUpdateFieldIndex(entity, fieldName, currentValue, newValue);\n\n pluginManager.beforeSetField(entity, fieldName, newValue);\n data[fieldName] = newValue;\n instanceData.markFieldClean(fieldName);\n\n fieldLogger.logSet(entity, fieldName, newValue);\n if (isReference && instanceData.getReferenceHistory(fieldName).length > 0) {\n rm.queueDownstreamReactables(entity, fieldName);\n } else {\n // For normal reverts, the field is clean again, so any pending downstream work can be removed.\n rm.dequeueDownstreamReactables(entity, fieldName);\n }\n\n return true;\n }\n }\n\n // Push this logic into a field serde type abstraction?\n if (currentEqualsNew) {\n // If we're doing `entity.field = undefined`, we'll be equal, but mark ourselves as \"set\"\n // so that defaults know to respect the intent of keeping this field undefined.\n if (!(fieldName in data)) data[fieldName] = undefined;\n return false;\n }\n\n // Only save the currentValue on the 1st change of this field\n if (!(fieldName in originalData)) {\n instanceData.markFieldDirty(fieldName, currentValue);\n }\n fieldLogger.logSet(entity, fieldName, newValue);\n rm.queueDownstreamReactables(entity, fieldName);\n\n indexManager.maybeUpdateFieldIndex(entity, fieldName, currentValue, newValue);\n\n pluginManager.beforeSetField(entity, fieldName, newValue);\n data[fieldName] = newValue;\n return true;\n}\n\nfunction fieldValueEquals(field: Field, a: unknown, b: unknown): boolean {\n // Primitive scalar sets are the common path, so avoid Date/Temporal/entity checks when both values cannot need them.\n if (field.kind !== \"m2o\" && field.kind !== \"poly\" && isNonObjectValue(a) && isNonObjectValue(b)) return a === b;\n return equalOrSameEntity(a, b);\n}\n\nfunction isNonObjectValue(value: unknown): boolean {\n return value === null || typeof value !== \"object\";\n}\n\nfunction equalOrSameEntity(a: any, b: any): boolean {\n return (\n equal(a, b) ||\n (Array.isArray(a) && Array.isArray(b) && equalArrays(a, b)) ||\n // This is kind of gross, but make sure not to compare two both-new entities\n (((isEntity(a) && !a.isNewEntity) || (isEntity(b) && !b.isNewEntity)) &&\n maybeResolveReferenceToId(a) === maybeResolveReferenceToId(b))\n );\n}\n\nexport function equalArrays(a: any[], b: any[]): boolean {\n if (a.length !== b.length) return false;\n return a.every((_: any, i) => equal(a[i], b[i]));\n}\n\nconst Temporal = maybeRequireTemporal()?.Temporal;\nexport function equal(a: any, b: any): boolean {\n if (a === b) return true;\n if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();\n if (Temporal) {\n if (a instanceof Temporal.ZonedDateTime && b instanceof Temporal.ZonedDateTime) return a.equals(b);\n if (a instanceof Temporal.PlainDateTime && b instanceof Temporal.PlainDateTime) return a.equals(b);\n if (a instanceof Temporal.PlainDate && b instanceof Temporal.PlainDate) return a.equals(b);\n }\n return false;\n}\n"],"mappings":"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"}
|
package/build/fields.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { maybeRequireTemporal } from "./temporal.js";
|
|
2
|
-
import { cleanStringValue, fail } from "./utils.js";
|
|
1
|
+
import { maybeRequireTemporal } from "./serde/temporal.js";
|
|
3
2
|
import { maybeResolveReferenceToId } from "./keys.js";
|
|
3
|
+
import { cleanStringValue, fail } from "./utils.js";
|
|
4
4
|
import { getMetadata } from "./EntityMetadata.js";
|
|
5
5
|
import { ensureNotDeleted } from "./index.js";
|
|
6
6
|
import { getEmInternalApi } from "./EntityManager.js";
|