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
package/build/JoinRows.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"JoinRows.js","names":["#reactToChange","#dbValue","#doAdd","#doRemove"],"sources":["../src/JoinRows.ts"],"sourcesContent":["import { type Entity } from \"./Entity.ts\";\nimport { getEmInternalApi } from \"./EntityManager.ts\";\nimport { type EntityMetadata, getBaseAndSelfMetas } from \"./EntityMetadata.ts\";\nimport { type EnumMetadata } from \"./EnumMetadata.ts\";\nimport { keyToNumber, keyToTaggedId } from \"./keys.ts\";\nimport { type ReactionsManager } from \"./ReactionsManager.ts\";\nimport { type JoinRowTodo } from \"./Todo.ts\";\nimport { remove } from \"./utils.ts\";\n\n/**\n * A simplified interface for ManyToManyCollection-like relations.\n *\n * Specifically lets ReactiveManyToMany & ReactiveManyToManyOtherSide use JoinRows\n * as if they were full-fledged m2m relations.\n *\n * The \"other\" side of the join table is usually a second entity, but for `EnumCollection`s\n * (i.e. `Publisher.logoColors`) it is an enum table; in that case `otherEnum` is set and the\n * other column's value is the enum's numeric id rather than an `Entity` (there is also no\n * `otherMeta`/`otherFieldName`, since enums have no reverse collection to keep in sync).\n */\nexport type ManyToManyLike = {\n entity: Entity;\n joinTableName: string;\n columnName: string;\n otherColumnName: string;\n fieldName: string;\n meta: EntityMetadata;\n /** Undefined when the other side is an enum. */\n otherFieldName?: string;\n /** Undefined when the other side is an enum. */\n otherMeta?: EntityMetadata;\n /** Set when the other side is an enum table, for mapping enum codes <-> their numeric ids. */\n otherEnum?: EnumMetadata<any, any, number>;\n /** Whether the join table has a surrogate `id` PK; if false the FK pair is the composite PK. */\n hasJoinTableId: boolean;\n};\n\n/** The value of a join row's column: an `Entity`, or an enum's numeric id for `EnumCollection`s. */\nexport type JoinColumnValue = Entity | number;\n\n/** Whether a join column points at a not-yet-inserted entity (enum ids are never \"new\"). */\nfunction isNewColumn(value: JoinColumnValue): boolean {\n return typeof value !== \"number\" && value.isNewEntity;\n}\n\n/** A small holder around m2m join rows, which we treat as psuedo-entities. */\nexport class JoinRows {\n // The in-memory rows for our m2m table.\n private readonly rows: JoinRow[] = [];\n private readonly index: ManyToManyIndex;\n\n constructor(\n // This could be either side of the m2m relation, depending on which is accessed first.\n // Regardless of which m2m side, we still have a single `JoinRows` instance in memory per m2m table.\n readonly m2m: ManyToManyLike,\n private rm: ReactionsManager,\n ) {\n this.index = new ManyToManyIndex(m2m);\n }\n\n /** Adds a new join row to this table. */\n addNew(m2m: ManyToManyLike, e1: Entity, e2: JoinColumnValue): void {\n if (!e1) throw new Error(`Cannot add a m2m row with an entity that is ${e1}`);\n if (!e2) throw new Error(`Cannot add a m2m row with an entity that is ${e2}`);\n const existing = this.index.get(m2m, e1, e2);\n if (existing) {\n existing.deleted = false;\n existing.op = JoinRowOperation.Pending;\n } else {\n const row = {\n op: JoinRowOperation.Pending,\n id: undefined,\n persisted: false,\n columns: { [m2m.columnName]: e1, [m2m.otherColumnName]: e2 },\n } satisfies JoinRow;\n this.rows.push(row);\n this.index.add(m2m, e1, e2, row);\n }\n this.#reactToChange(m2m, e1, e2);\n }\n\n /** Adds a new remove to this table. */\n addRemove(m2m: ManyToManyLike, e1: Entity, e2: JoinColumnValue): void {\n const existing = this.index.get(m2m, e1, e2);\n if (existing) {\n if (!existing.persisted) {\n // It was only added in-memory and never persisted, so just drop it\n remove(this.rows, existing);\n this.index.remove(existing);\n } else {\n existing.deleted = true;\n }\n existing.op = JoinRowOperation.Pending;\n } else {\n // We're removing against an unloaded collection, so assume the row exists in the database\n // (persisted: true) and queue a delete; the delete keys off the (col1, col2) composite.\n const row = {\n op: JoinRowOperation.Pending,\n id: undefined,\n persisted: true,\n columns: { [m2m.columnName]: e1, [m2m.otherColumnName]: e2 },\n deleted: true,\n } satisfies JoinRow;\n this.rows.push(row);\n this.index.add(m2m, e1, e2, row);\n }\n this.#reactToChange(m2m, e1, e2);\n }\n\n /** Return any \"old values\" for a m2m collection that might need reactivity checks. */\n removedFor(m2m: ManyToManyLike, e1: Entity): JoinColumnValue[] {\n const { otherColumnName } = m2m;\n // I.e. if we did `t1.books.remove(b1)` find all join rows that have\n // `tag_id=t1`, are marked for deletion, and then `.map` them to the removed book.\n const removedRows = this.index.getOthers(m2m.columnName, e1).filter((r) => r.deleted);\n return removedRows.map((r) => r.columns[otherColumnName]);\n }\n\n addedFor(m2m: ManyToManyLike, e1: Entity): JoinColumnValue[] {\n const { otherColumnName } = m2m;\n const addedRows = this.index\n .getOthers(m2m.columnName, e1)\n .filter(\n (r) =>\n ((!r.persisted && r.op === JoinRowOperation.Pending) || r.op === JoinRowOperation.Flushed) &&\n r.deleted !== true,\n );\n return addedRows.map((r) => r.columns[otherColumnName]);\n }\n\n /** Adds an existing join row to this table. */\n addPreloadedRow(m2m: ManyToManyLike, id: number | undefined, e1: Entity, e2: JoinColumnValue): void {\n const existing = this.index.get(m2m, e1, e2);\n if (existing) {\n // Treat any existing WIP change as source-of-truth, so leave it alone\n } else {\n const row = {\n op: JoinRowOperation.Pending,\n id,\n persisted: true,\n columns: { [m2m.columnName]: e1, [m2m.otherColumnName]: e2 },\n } satisfies JoinRow;\n this.rows.push(row);\n this.index.add(m2m, e1, e2, row);\n }\n }\n\n /** Look up/create our internal JoinRow psuedo-entities for the db rows. */\n async loadRows(tuples: [string, string][], dbRows: any[]): Promise<void> {\n const { em } = this.m2m.entity;\n const { columnName: column1, otherColumnName: column2, meta: meta1, otherMeta: meta2, otherEnum } = this.m2m;\n\n const oneIds: string[] = [];\n // Tagged ids for an entity other-side, or raw enum ids for an enum other-side.\n const twoVals: JoinColumnValue[] = [];\n for (const dbRow of dbRows) {\n oneIds.push(keyToTaggedId(meta1, dbRow[column1])!);\n twoVals.push(\n otherEnum ? (dbRow[column2] as number) : (em.getEntity(keyToTaggedId(meta2!, dbRow[column2])!) as any),\n );\n }\n\n // Make sure we have entities in memory for all the joined-to tables. The enum side has no\n // entities to load; the entity sides do (and `twoVals` is re-resolved to entities below).\n await Promise.all([\n em.loadAll(meta1.cstr, oneIds),\n otherEnum\n ? Promise.resolve([])\n : em.loadAll(\n meta2!.cstr,\n dbRows.map((dbRow) => keyToTaggedId(meta2!, dbRow[column2])!),\n ),\n ]);\n\n // If we're doing a em.refresh/reload, we need to watch for rows that are no longer here. For an\n // enum other-side, only persisted rows are delete-candidates (pending in-memory adds are kept,\n // since `EnumCollection` relies on `JoinRows` to hold them rather than re-asserting on load).\n const existingRows = new Set<JoinRow>();\n for (const [columnName, id] of tuples) {\n const others = this.index.getOthers(columnName, em.getEntity(id)!);\n for (const row of others) if (!otherEnum || row.persisted) existingRows.add(row);\n }\n\n let i = 0;\n for (const dbRow of dbRows) {\n const e1 = em.getEntity(oneIds[i])!;\n const e2 = otherEnum ? (dbRow[column2] as number) : em.getEntity(keyToTaggedId(meta2!, dbRow[column2])!)!;\n i++;\n let row = this.index.get(this.m2m, e1, e2);\n if (!row) {\n row = {\n op: JoinRowOperation.Completed,\n id: dbRow.id,\n persisted: true,\n columns: { [column1]: e1, [column2]: e2 },\n created_at: dbRow.created_at,\n };\n this.rows.push(row);\n this.index.add(this.m2m, e1, e2, row);\n } else {\n // If a placeholder row was created while a ManyToManyCollection was unloaded, and we find it during\n // a subsequent load/query, update its id to be what is in the database and mark it persisted.\n row.id = dbRow.id;\n row.persisted = true;\n // Mark this row as still valid\n existingRows.delete(row);\n }\n }\n\n // Mark all no-longer-there rows as deleted\n for (const row of existingRows) row.deleted = true;\n }\n\n getOthers(columnName: string, entity: Entity): JoinColumnValue[] {\n const others = this.index.getOthers(columnName, entity);\n if (others.length === 0) return [];\n const [c1, c2] = Object.keys(others[0].columns);\n const c = others[0].columns[c1] === entity ? c2 : c1;\n return others.filter((o) => !o.deleted).map((row) => row.columns[c]);\n }\n\n /** Drops all in-memory rows where `entity` is on `columnName`, e.g. when it is being deleted. */\n removeAllFor(columnName: string, entity: Entity): void {\n for (const row of this.index.getOthers(columnName, entity)) {\n remove(this.rows, row);\n this.index.remove(row);\n }\n }\n\n /** Drops a single `(e1, e2)` row without queuing a flush, e.g. when mirroring another em's removal. */\n removePreloadedRow(m2m: ManyToManyLike, e1: Entity, e2: JoinColumnValue): void {\n const row = this.index.get(m2m, e1, e2);\n if (row) {\n remove(this.rows, row);\n this.index.remove(row);\n }\n }\n\n /** Scans our `rows` for newly-added/newly-deleted rows that need `INSERT`s/`UPDATE`s. */\n toTodo(): JoinRowTodo | undefined {\n const newRows = this.rows.filter((r) => !r.persisted && r.deleted !== true && r.op === \"pending\");\n const deletedRows = this.rows.filter((r) => r.persisted && r.deleted === true && r.op === \"pending\");\n if (newRows.length === 0 && deletedRows.length === 0) {\n return undefined;\n }\n return {\n m2m: this.m2m,\n newRows,\n deletedRows,\n resetAfterFlushed: () => {\n for (const row of this.rows) {\n if (row.op === JoinRowOperation.Pending || row.op === JoinRowOperation.Flushed)\n row.op = JoinRowOperation.Completed;\n }\n },\n // The driver flushes pure (int, int) FK pairs; resolve them here so it never has to know\n // whether a column points at an entity (use its id) or an enum (its value is already the id).\n dbValue: (row, columnName) => this.#dbValue(row, columnName),\n isNew: (row, columnName) => isNewColumn(row.columns[columnName]),\n };\n }\n\n get hasChanges() {\n return this.rows.some(({ op }) => op === JoinRowOperation.Pending || op === JoinRowOperation.Flushed);\n }\n\n /** The db int value for `row`'s `columnName`: an entity's id, or (for enums) the enum's id itself. */\n #dbValue(row: JoinRow, columnName: string): number {\n const value = row.columns[columnName];\n if (typeof value === \"number\") return value;\n const meta = columnName === this.m2m.columnName ? this.m2m.meta : this.m2m.otherMeta!;\n return keyToNumber(meta, value.idTagged)!;\n }\n\n /**\n * Invalidates caches & queues reactivity for a join-row change.\n *\n * The owning entity (`e1`) always reacts; the \"other\" side only reacts when it is an entity,\n * since enum other-sides have no `em`/reverse-field to keep in sync.\n */\n #reactToChange(m2m: ManyToManyLike, e1: Entity, e2: JoinColumnValue): void {\n const { em } = this.m2m.entity;\n const api = getEmInternalApi(e1.em);\n api.isLoadedCache.resetIsLoaded(e1, m2m.fieldName);\n this.rm.queueDownstreamReactables(e1, m2m.fieldName);\n if (getBaseAndSelfMetas(e1).some((meta) => meta.config.__data.touchOnChange.has(m2m.fieldName))) {\n em.touch(e1);\n }\n if (!m2m.otherEnum) {\n const other = e2 as Entity;\n const otherFieldName = m2m.otherFieldName!;\n api.isLoadedCache.resetIsLoaded(other, otherFieldName);\n this.rm.queueDownstreamReactables(other, otherFieldName);\n if (getBaseAndSelfMetas(other).some((meta) => meta.config.__data.touchOnChange.has(otherFieldName))) {\n em.touch(other);\n }\n }\n }\n}\n\n/**\n * A \"psuedo-entity\" for a join row.\n *\n * We treat this as a special entity, i.e. it has two \"relations\" to each entity for the current\n * row, an optional surrogate `id` primary key, and an optional `created_at` column.\n *\n * These rows are immutable, i.e. once created we don't change either FK, and instead make\n * collection changes only by inserting new rows and deleting old rows.\n *\n * This makes the column1+column2 combination a composite key. For id-less join tables, that\n * composite is the actual primary key and `id` is always undefined.\n */\nexport interface JoinRow {\n /**\n * Whether our relation has been processed or not.\n *\n * - `pending` means we've not flushed it to the Database\n * - `flushed` means we've flushed but `em.flush` hasn't fully completed yet, likely due to AsyncReactiveField calcs\n * - `completed` means we've been flushed and `em.flush` has completed\n */\n op: JoinRowOperation;\n /** The surrogate key for id-ful join tables; always undefined for id-less tables. */\n id: number | undefined;\n /**\n * Whether this row exists (or is assumed to exist) in the database.\n *\n * This is orthogonal to `op` (the flush lifecycle) and is what distinguishes a pending insert\n * from a pending delete: a `pending` row that is `!persisted` is a pending INSERT (added in\n * memory, not yet in the db), while a `pending` row that is `persisted` is a pending DELETE\n * (in the db, marked `deleted`). `op` alone cannot tell these apart, because both inserts and\n * deletes walk the same `pending -> flushed -> completed` progression.\n *\n * We track this as its own flag rather than inferring it from `id` being set/unset, because\n * id-less join tables (whose PK is just the composite of the two FKs) never have an `id` — so\n * `id === undefined` would be ambiguous. `persisted` is the id-agnostic generalization of the\n * `id`-is-set check that id-ful tables historically relied on.\n *\n * It must survive add/remove/re-add sequences: e.g. loading a row (persisted), removing it\n * (pending delete), then re-adding it (`deleted` flipped back to false, `op` back to `pending`)\n * leaves a `pending && !deleted` row that looks identical to a fresh insert — but it is still in\n * the db, so a subsequent remove must issue a DELETE, which only `persisted` can tell us.\n */\n persisted: boolean;\n /** Maps each FK column to its value: an `Entity`, or (for `EnumCollection`s) an enum's numeric id. */\n columns: Record<string, JoinColumnValue>;\n created_at?: Date;\n deleted?: boolean;\n}\n\n/** An enum to track our insert/delete state progression. */\nexport enum JoinRowOperation {\n Pending = \"pending\",\n Flushed = \"flushed\",\n Completed = \"completed\",\n}\n\n/** Keep an in-memory index to avoid sequentially scanning `rows`. */\nclass ManyToManyIndex {\n private indexes: Record<string, Map<JoinColumnValue, Map<JoinColumnValue, JoinRow>>> = {};\n\n constructor(private readonly m2m: ManyToManyLike) {\n this.indexes[m2m.columnName] = new Map();\n this.indexes[m2m.otherColumnName] = new Map();\n }\n\n add(m2m: ManyToManyLike, e1: JoinColumnValue, e2: JoinColumnValue, value: JoinRow): void {\n // Store both e1+e2 => value and e2+e1 => value so we can do lookups from either side\n this.#doAdd(this.indexes[m2m.columnName], e1, e2, value);\n this.#doAdd(this.indexes[m2m.otherColumnName], e2, e1, value);\n }\n\n remove(value: JoinRow): void {\n const [[column1, e1], [column2, e2]] = Object.entries(value.columns);\n this.#doRemove(this.indexes[column1], e1, e2);\n this.#doRemove(this.indexes[column2], e2, e1);\n }\n\n get(m2m: ManyToManyLike, e1: JoinColumnValue, e2: JoinColumnValue): JoinRow | undefined {\n return this.indexes[m2m.columnName].get(e1)?.get(e2);\n }\n\n /** Cheat and use the index to return \"the other entities\" for `entity`. */\n getOthers(columnName: string, entity: JoinColumnValue): JoinRow[] {\n // It's empty m2m collection won't have any other entities, and so no index entries\n const map = this.indexes[columnName].get(entity);\n if (!map) return [];\n // Sort for a stable order regardless of how many batches contributed rows — the underlying\n // Map preserves insertion order, which depends on DataLoader timing and is non-deterministic\n // across processes. New rows (no key yet) sort last.\n const rows = Array.from(map.values());\n if (this.m2m.hasJoinTableId) {\n // Sort by join-row id.\n return rows.sort((a, b) => (a.id ?? Infinity) - (b.id ?? Infinity));\n }\n // Id-less tables have no surrogate id, so sort by the other side's id.\n const otherColumn = columnName === this.m2m.columnName ? this.m2m.otherColumnName : this.m2m.columnName;\n if (this.m2m.otherEnum && otherColumn === this.m2m.otherColumnName) {\n // The other side is an enum, so its column value is already its numeric id.\n return rows.sort((a, b) => (a.columns[otherColumn] as number) - (b.columns[otherColumn] as number));\n }\n const otherMeta = columnName === this.m2m.columnName ? this.m2m.otherMeta! : this.m2m.meta;\n const key = (r: JoinRow) => {\n const other = r.columns[otherColumn] as Entity;\n return other.isNewEntity ? Infinity : keyToNumber(otherMeta, other.id)!;\n };\n return rows.sort((a, b) => key(a) - key(b));\n }\n\n #doAdd(\n index: Map<JoinColumnValue, Map<JoinColumnValue, JoinRow>>,\n e1: JoinColumnValue,\n e2: JoinColumnValue,\n value: JoinRow,\n ): void {\n const map = index.get(e1) ?? new Map();\n if (map.size === 0) index.set(e1, map);\n map.set(e2, value);\n }\n\n #doRemove(\n index: Map<JoinColumnValue, Map<JoinColumnValue, JoinRow>>,\n e1: JoinColumnValue,\n e2: JoinColumnValue,\n ): void {\n index.get(e1)?.delete(e2);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PendingChanges.d.cts","names":[],"sources":["../src/PendingChanges.ts"],"mappings":";;;UAGiB;EACf;EACA,QAAQ;;;UAIO;EACf;EACA,QAAQ;;;UAIO;EACf;EACA,QAAQ;;;UAIO;EACf;EACA;EACA;EACA,WAAW,QAAQ;;;KAIT,gBAAgB,gBAAgB,gBAAgB,gBAAgB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PendingChanges.d.mts","names":[],"sources":["../src/PendingChanges.ts"],"mappings":";;;UAGiB;EACf;EACA,QAAQ;;;UAIO;EACf;EACA,QAAQ;;;UAIO;EACf;EACA,QAAQ;;;UAIO;EACf;EACA;EACA;EACA,WAAW,QAAQ;;;KAIT,gBAAgB,gBAAgB,gBAAgB,gBAAgB"}
|
package/build/PendingChanges.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ReactionsManager.cjs","names":["globalLogger","noopReactionLogger","#needsRecalc","getMetadata","followReverseHint","runInTrustedContext","#doAction","NoIdError","getEmInternalApi"],"sources":["../src/ReactionsManager.ts"],"sourcesContent":["import { type Reactable } from \"./config.ts\";\nimport { type Entity } from \"./Entity.ts\";\nimport { type EntityMetadata, getMetadata } from \"./EntityMetadata.ts\";\nimport { type EntityManager, NoIdError, getEmInternalApi } from \"./index.ts\";\nimport { type ReactionLogger, globalLogger, noopReactionLogger } from \"./logging/ReactionLogger.ts\";\nimport { followReverseHint } from \"./reactiveHints.ts\";\nimport { runInTrustedContext } from \"./trusted.ts\";\n\nexport type ReactiveAction = { r: Reactable; entity: Entity };\n/**\n * Manages the reactivity of tracking which source fields have changed and finding/recalculating\n * their downstream derived fields.\n *\n * Source fields are usually regular/dumb primitives, i.e. `Author.age` is a source field\n * of `Book.isPublic`, but derived fields can themselves be source fields as well.\n */\nexport class ReactionsManager {\n /** Stores all source `Reactables`s that have been marked for later traversal. */\n private pendingReactables: Map<Reactable, { todo: Set<Entity>; done: Set<Entity> }> = new Map();\n /** Failed actions to retry post-hooks, deduped by target field name -> entity (rare error path). */\n private actionsPendingTypeErrors: Map<string, Map<Entity, ReactiveAction>> = new Map();\n /**\n * A map of entity tagName -> fields that have been marked as dirty.\n *\n * The key of the map is \"just\" the tag name, instead of a specific entity, b/c at the time of\n * being marked dirty, we only have the upstream/source entity + fieldName that has changed, and\n * not the 1-or-more downstream/target entities that will actually recalc.\n *\n * Instead, we just track the dirty fields by type-of-entity, which is enough for `isPendingRecalc`.\n */\n private dirtyFields: Map<string, Set<string>> = new Map();\n /**\n * Tracks which entities have already run a `runOnce` reactable, keyed by the target field\n * name -> entities. We key on `r.name` (not `r` itself) b/c two `Reactable`s reverse-indexed\n * from different source paths can target the same derived field, and must dedupe together.\n * Keying the outer map by field name (of which there are few) instead of by entity (of which\n * there are many) means we allocate just one `Set` per distinct field name, rather than a\n * `Set` per entity or the old per-action `${entity.toTaggedString()}_${r.name}` key strings.\n */\n private processedActions: Map<string, Set<Entity>> = new Map();\n #needsRecalc = { populate: false, query: false, reaction: false };\n // Accessible for EntityManager.runValidation to reuse\n logger: ReactionLogger = globalLogger ?? noopReactionLogger;\n private em: EntityManager;\n /** These are NPEs that *might* have been from invalid m2o fields, so we only throw them after validation. */\n private suppressedTypeErrors: Error[] = [];\n\n constructor(em: EntityManager) {\n this.em = em;\n }\n\n /**\n * Queue all downstream reactive fields that depend on `fieldName` as a source field.\n *\n * This method can be synchronous b/c we internally queue the `Reactable` reverse\n * indexes on the given source `fieldName`, and don't crawl/walk back to the downstream\n * entities/fields until `recalcPendingReactables` is called.\n */\n queueDownstreamReactables(entity: Entity, fieldName: string): void {\n // Use the reverse index of Reactables that configureMetadata sets up\n for (const r of this.getReactablesByField(entity, fieldName)) {\n // We always queue the reactable/entity, even if we're mid-flush or even mid-recalc, to avoid:\n // - firstName is changed from a1 to a2\n // - this triggers firstName's reactable to `Author.initials` to be queued\n // - during the 1st em.flush loop, we recalc `Author.initials` and it didn't change\n // - during the 1st em.flush loop, a hook changes firstName from a2 to b2\n // - if we skip re-queuing firstName's reactables, we will miss that initials needs\n // its `.load()` called again so that it's `setField` marks `initials` as\n // dirty, otherwise it will be left out of any INSERTs/UPDATEs.\n this.getPending(r).todo.add(entity);\n this.#needsRecalc[r.kind] = true;\n this.logger.logQueued(entity, fieldName, r);\n }\n }\n\n /** Dequeues reactivity on `fieldName`, i.e. if it's no longer dirty. */\n dequeueDownstreamReactables(entity: Entity, fieldName: string): void {\n // Use the reverse index of Reactables that configureMetadata sets up\n for (const r of this.getReactablesByField(entity, fieldName)) {\n const pending = this.getPending(r);\n if (pending.done.has(entity)) {\n // Ironically, if we've already run this reactable, asking to dequeue probably means\n // we need to run it again (to recalc its value), b/c this could be a mid-flush change, i.e.:\n // - firstName = a1 from db\n // - firstName is changed to a2, triggers initials reactable\n // - firstName is changed back to a1, which is the original value, so setField\n // thinks we can dequeue the reactable\n // - but actually our reactable needs to be re-run with the restored value\n pending.todo.add(entity);\n this.#needsRecalc[r.kind] = true;\n } else if (r.fields.length === 1) {\n // We can only delete/dequeue a reaction if `fieldName` is the only or last field\n // that had triggered `r` to run. Since we don't track that currently, i.e. we'd\n // need to have a `Pending.dirtyFields`, for now just only dequeue if `r` only\n // has one field (which is us) anyway.\n pending.todo.delete(entity);\n }\n }\n }\n\n /** Queue all downstream reactive fields that depend on this entity being created or deleted. */\n queueAllDownstreamFields(entity: Entity, reason: \"created\" | \"deleted\"): void {\n for (const r of this.getReactables(entity)) {\n this.getPending(r).todo.add(entity);\n this.#needsRecalc[r.kind] = true;\n this.logger.logQueuedAll(entity, reason, r);\n }\n }\n\n /**\n * Returns whether this field might be pending recalc.\n *\n * This is technically a guess, b/c our reaction infra may not yet have crawled from an upstream\n * source field down to the `N` specific target entities that need recalced, and instead just\n * knows \"it will need to do that soon\" i.e. at the next `em.flush`.\n *\n * So, instead this is a heuristic that reports if `fieldName` has been marked dirty for _some_\n * entities of type `entity`, but we don't technically know if that's _this_ entity.\n *\n * I.e. this might return false positives, but should never return false negatives.\n */\n isMaybePendingRecalc(entity: Entity, fieldName: string): boolean {\n return this.getDirtyFields(getMetadata(entity)).has(fieldName);\n }\n\n hasPendingReactiveQueries(): boolean {\n return this.#needsRecalc.query;\n }\n\n /**\n * Given source `Reactable` \"reverse indexes\" that have been queued as dirty by calls\n * to setters, `em.register`, or `em.delete`, asynchronously walks/crawls to the downstream\n * derived fields and calls `.load()` on them to calc.\n *\n * We also do this in a loop to handle reactive fields depending on other reactive fields.\n */\n async recalcPendingReactables(kind: \"reactables\" | \"reactiveQueries\") {\n if (this.needsRecalc(kind)) this.logger.logStartingRecalc(this.em, kind);\n\n let loops = 0;\n while (this.needsRecalc(kind)) {\n // ...we probably should only loop for `kind=reactables` Reactables, and `kind=reactiveQueries`\n // AsyncReactiveFields should probably only have a single loop, after which we return and\n // let `em.flush` push the latest values to the db, so our 2nd-order AsyncReactiveFields\n // will see the latest value.\n if (kind === \"reactables\") {\n this.#needsRecalc.populate = false;\n this.#needsRecalc.reaction = false;\n } else {\n this.#needsRecalc.query = false;\n }\n\n // Dedupe actions by (target field name, entity); see the `processedActions` docs for why\n // we key on `r.name` instead of `r` or the old per-action key strings\n const seen: Map<string, Set<Entity>> = new Map();\n const actions: ReactiveAction[] = [];\n\n const walks = await Promise.all(\n [...this.pendingReactables.entries()].map(async ([r, pending]) => {\n // Skip reactive queries until post-flush\n if (kind === \"reactables\" && r.kind === \"query\") return undefined;\n if (kind === \"reactiveQueries\" && (r.kind === \"populate\" || r.kind === \"reaction\")) return undefined;\n // Copy pending and clear it\n const todo = [...pending.todo];\n if (todo.length === 0) return undefined;\n pending.todo.clear();\n for (const doing of todo) pending.done.add(doing);\n // Walk back from the source to any downstream entities\n const entities = r.path.length === 0 ? todo : await followReverseHint(r.name, todo, r.path);\n const actionableEntities = entities.filter((entity) => !entity.isDeletedEntity && entity instanceof r.cstr);\n let seenEntities = seen.get(r.name);\n if (!seenEntities) seen.set(r.name, (seenEntities = new Set()));\n const processed = r.runOnce ? this.processedActions.get(r.name) : undefined;\n for (const entity of actionableEntities) {\n // We could arrive at the same reactable from multiple paths (eg, 2 dependent fields changed), so we need to\n // dedupe based on the entity and reactable to only run each action once for any given entity per loop\n if (seenEntities.has(entity)) continue;\n // If this reactable has already run and shouldn't run again, then skip it\n if (processed && processed.has(entity)) continue;\n seenEntities.add(entity);\n actions.push({ r, entity });\n }\n return { r, todo, entities: actionableEntities };\n }),\n );\n this.logger.logWalks(walks, \"recalc\");\n this.logger.logLoadingStart(this.em, actions);\n // Use allSettled so that we can watch for derived values that want to use an entity's id\n // i.e. they can fail, but we'll queue them from later.\n const startTime = this.logger.now();\n const results = await runInTrustedContext(() => Promise.allSettled(actions.map((a) => this.#doAction(a))));\n const endTime = this.logger.now();\n this.logger.logLoadingEnd(this.em, endTime - startTime);\n\n // This loop's actions are already unique by (name, entity), so a plain array dedupes fine\n const actionsPendingAssignedIds: ReactiveAction[] = [];\n const failures: any[] = [];\n results.forEach((result, i) => {\n if (result.status === \"rejected\") {\n // Let `author.id` and `book.author.get.firstName` errors run again after flush/hooks fills them in\n if (result.reason instanceof NoIdError) {\n actionsPendingAssignedIds.push(actions[i]);\n } else if (result.reason instanceof TypeError) {\n this.addPendingTypeError(actions[i]);\n } else {\n failures.push(result.reason);\n }\n }\n });\n\n // If we have any actions that need to be re-run because they failed due to a missing id, then we assign ids and\n // re-run them.\n if (actionsPendingAssignedIds.length > 0) {\n await this.em.assignNewIds();\n this.logger.logLoadingStart(this.em, actionsPendingAssignedIds);\n const startTime = this.logger.now();\n const results = await runInTrustedContext(() =>\n Promise.allSettled(actionsPendingAssignedIds.map((a) => this.#doAction(a))),\n );\n const endTime = this.logger.now();\n this.logger.logLoadingEnd(this.em, endTime - startTime);\n results.forEach((result, i) => {\n if (result.status === \"rejected\") {\n if (result.reason instanceof TypeError) {\n this.addPendingTypeError(actionsPendingAssignedIds[i]);\n } else {\n failures.push(result.reason);\n }\n }\n });\n }\n\n if (failures.length > 0) throw failures[0];\n // Record any successful actions that should only run once so we don't run them again\n for (const action of actions) {\n if (action.r.runOnce) {\n let set = this.processedActions.get(action.r.name);\n if (!set) this.processedActions.set(action.r.name, (set = new Set()));\n set.add(action.entity);\n }\n }\n // This should generally not happen, only if two reactive fields depend on each other,\n // which in theory should probably be caught/blow up in the `configureMetadata` step,\n // but if it's not caught sooner, at least don't infinite loop.\n if (loops++ > 50) {\n throw new Error(\"recalc looped too many times, probably a circular dependency\");\n }\n }\n }\n\n async recalcPendingTypeErrors() {\n const actions: ReactiveAction[] = [];\n for (const byEntity of this.actionsPendingTypeErrors.values()) {\n for (const action of byEntity.values()) actions.push(action);\n }\n this.actionsPendingTypeErrors.clear();\n\n const startTime = this.logger.now();\n const results = await runInTrustedContext(() =>\n Promise.allSettled(actions.filter((a) => !a.entity.isDeletedEntity).map((a) => this.#doAction(a))),\n );\n const endTime = this.logger.now();\n this.logger.logLoadingEnd(this.em, endTime - startTime);\n\n const failures: any[] = [];\n results.forEach((result) => {\n if (result.status === \"rejected\") {\n if (result.reason instanceof TypeError) {\n // Defer to the validation error to catch this\n this.suppressedTypeErrors.push(result.reason);\n } else {\n failures.push(result.reason);\n }\n }\n });\n if (failures.length > 0) throw failures[0];\n }\n\n get hasPendingTypeErrors(): boolean {\n return this.actionsPendingTypeErrors.size > 0;\n }\n\n /** Clears all the pending source fields, i.e. after `em.flush` is complete. */\n clear(): void {\n this.pendingReactables = new Map();\n this.processedActions.clear();\n }\n\n setLogger(logger: ReactionLogger | undefined): void {\n this.logger = logger ?? noopReactionLogger;\n }\n\n clearSuppressedTypeErrors(): void {\n this.suppressedTypeErrors = [];\n }\n\n throwIfAnySuppressedTypeErrors(): void {\n if (this.suppressedTypeErrors.length > 0) {\n throw this.suppressedTypeErrors[0];\n }\n }\n\n #doAction(action: ReactiveAction) {\n const { r, entity } = action;\n return r.kind === \"reaction\" ? r.fn(entity, this.em.ctx) : (entity as any)[r.name].load();\n }\n\n /** Remembers a TypeError'd action to retry post-hooks, deduped by (target field name, entity). */\n private addPendingTypeError(action: ReactiveAction): void {\n let byEntity = this.actionsPendingTypeErrors.get(action.r.name);\n if (!byEntity) this.actionsPendingTypeErrors.set(action.r.name, (byEntity = new Map()));\n byEntity.set(action.entity, action);\n }\n\n needsRecalc(kind: \"reactables\" | \"reactiveQueries\"): boolean {\n return kind === \"reactables\" ? this.#needsRecalc.populate || this.#needsRecalc.reaction : this.#needsRecalc.query;\n }\n\n private getPending(r: Reactable): { todo: Set<Entity>; done: Set<Entity> } {\n let pending = this.pendingReactables.get(r);\n if (!pending) {\n pending = { todo: new Set(), done: new Set() };\n this.pendingReactables.set(r, pending);\n // The dirty field name is constant per reactable, so mark it once on the first\n // queue instead of paying the `getMetadata` + map lookup on every queued entity.\n this.getDirtyFields(getMetadata(r.cstr)).add(r.name);\n }\n return pending;\n }\n\n private getDirtyFields(meta: EntityMetadata): Set<string> {\n let dirty = this.dirtyFields.get(meta.tagName);\n if (!dirty) {\n dirty = new Set();\n this.dirtyFields.set(meta.tagName, dirty);\n }\n return dirty;\n }\n\n private getReactables(entity: Entity): Reactable[] {\n // If two books are getting merged, and so a normally-immutable `BookReview.book` is being changed,\n // then even normally-immutable fields need to be recalculated.\n const meta = getMetadata(entity);\n return getEmInternalApi(this.em).isMerging(entity) ? meta.reactablesIncludingReadOnly! : meta.reactables!;\n }\n\n private getReactablesByField(entity: Entity, fieldName: string): readonly Reactable[] {\n const meta = getMetadata(entity);\n const byField = getEmInternalApi(this.em).isMerging(entity)\n ? meta.reactablesIncludingReadOnlyByField!\n : meta.reactablesByField!;\n // Most fields have no reactables, so return a shared empty array instead of allocating one per set\n return byField.get(fieldName) ?? noReactables;\n }\n}\n\n/** A shared frozen array for fields with no downstream reactables. */\nconst noReactables: readonly Reactable[] = Object.freeze([]);\n"],"mappings":";;;;;;;;;;;;;;;;;AAgBA,IAAa,mBAAb,MAA8B;;CAE5B,oCAAsF,IAAI,IAAI;;CAE9F,2CAA6E,IAAI,IAAI;;;;;;;;;;CAUrF,8BAAgD,IAAI,IAAI;;;;;;;;;CASxD,mCAAqD,IAAI,IAAI;CAC7D,eAAe;EAAE,UAAU;EAAO,OAAO;EAAO,UAAU;CAAM;CAEhE,SAAyBA,+BAAAA,gBAAgBC,+BAAAA;CACzC;;CAEA,uBAAwC,CAAC;CAEzC,YAAY,IAAmB;EAC7B,KAAK,KAAK;CACZ;;;;;;;;CASA,0BAA0B,QAAgB,WAAyB;EAEjE,KAAK,MAAM,KAAK,KAAK,qBAAqB,QAAQ,SAAS,GAAG;GAS5D,KAAK,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,MAAM;GAClC,KAAKC,aAAa,EAAE,QAAQ;GAC5B,KAAK,OAAO,UAAU,QAAQ,WAAW,CAAC;EAC5C;CACF;;CAGA,4BAA4B,QAAgB,WAAyB;EAEnE,KAAK,MAAM,KAAK,KAAK,qBAAqB,QAAQ,SAAS,GAAG;GAC5D,MAAM,UAAU,KAAK,WAAW,CAAC;GACjC,IAAI,QAAQ,KAAK,IAAI,MAAM,GAAG;IAQ5B,QAAQ,KAAK,IAAI,MAAM;IACvB,KAAKA,aAAa,EAAE,QAAQ;GAC9B,OAAO,IAAI,EAAE,OAAO,WAAW,GAK7B,QAAQ,KAAK,OAAO,MAAM;EAE9B;CACF;;CAGA,yBAAyB,QAAgB,QAAqC;EAC5E,KAAK,MAAM,KAAK,KAAK,cAAc,MAAM,GAAG;GAC1C,KAAK,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,MAAM;GAClC,KAAKA,aAAa,EAAE,QAAQ;GAC5B,KAAK,OAAO,aAAa,QAAQ,QAAQ,CAAC;EAC5C;CACF;;;;;;;;;;;;;CAcA,qBAAqB,QAAgB,WAA4B;EAC/D,OAAO,KAAK,eAAeC,uBAAAA,YAAY,MAAM,CAAC,CAAC,CAAC,IAAI,SAAS;CAC/D;CAEA,4BAAqC;EACnC,OAAO,KAAKD,aAAa;CAC3B;;;;;;;;CASA,MAAM,wBAAwB,MAAwC;EACpE,IAAI,KAAK,YAAY,IAAI,GAAG,KAAK,OAAO,kBAAkB,KAAK,IAAI,IAAI;EAEvE,IAAI,QAAQ;EACZ,OAAO,KAAK,YAAY,IAAI,GAAG;GAK7B,IAAI,SAAS,cAAc;IACzB,KAAKA,aAAa,WAAW;IAC7B,KAAKA,aAAa,WAAW;GAC/B,OACE,KAAKA,aAAa,QAAQ;GAK5B,MAAM,uBAAiC,IAAI,IAAI;GAC/C,MAAM,UAA4B,CAAC;GAEnC,MAAM,QAAQ,MAAM,QAAQ,IAC1B,CAAC,GAAG,KAAK,kBAAkB,QAAQ,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,aAAa;IAEhE,IAAI,SAAS,gBAAgB,EAAE,SAAS,SAAS,OAAO,KAAA;IACxD,IAAI,SAAS,sBAAsB,EAAE,SAAS,cAAc,EAAE,SAAS,aAAa,OAAO,KAAA;IAE3F,MAAM,OAAO,CAAC,GAAG,QAAQ,IAAI;IAC7B,IAAI,KAAK,WAAW,GAAG,OAAO,KAAA;IAC9B,QAAQ,KAAK,MAAM;IACnB,KAAK,MAAM,SAAS,MAAM,QAAQ,KAAK,IAAI,KAAK;IAGhD,MAAM,sBADW,EAAE,KAAK,WAAW,IAAI,OAAO,MAAME,sBAAAA,kBAAkB,EAAE,MAAM,MAAM,EAAE,IAAI,EAAA,CACtD,QAAQ,WAAW,CAAC,OAAO,mBAAmB,kBAAkB,EAAE,IAAI;IAC1G,IAAI,eAAe,KAAK,IAAI,EAAE,IAAI;IAClC,IAAI,CAAC,cAAc,KAAK,IAAI,EAAE,MAAO,+BAAe,IAAI,IAAI,CAAE;IAC9D,MAAM,YAAY,EAAE,UAAU,KAAK,iBAAiB,IAAI,EAAE,IAAI,IAAI,KAAA;IAClE,KAAK,MAAM,UAAU,oBAAoB;KAGvC,IAAI,aAAa,IAAI,MAAM,GAAG;KAE9B,IAAI,aAAa,UAAU,IAAI,MAAM,GAAG;KACxC,aAAa,IAAI,MAAM;KACvB,QAAQ,KAAK;MAAE;MAAG;KAAO,CAAC;IAC5B;IACA,OAAO;KAAE;KAAG;KAAM,UAAU;IAAmB;GACjD,CAAC,CACH;GACA,KAAK,OAAO,SAAS,OAAO,QAAQ;GACpC,KAAK,OAAO,gBAAgB,KAAK,IAAI,OAAO;GAG5C,MAAM,YAAY,KAAK,OAAO,IAAI;GAClC,MAAM,UAAU,MAAMC,gBAAAA,0BAA0B,QAAQ,WAAW,QAAQ,KAAK,MAAM,KAAKC,UAAU,CAAC,CAAC,CAAC,CAAC;GACzG,MAAM,UAAU,KAAK,OAAO,IAAI;GAChC,KAAK,OAAO,cAAc,KAAK,IAAI,UAAU,SAAS;GAGtD,MAAM,4BAA8C,CAAC;GACrD,MAAM,WAAkB,CAAC;GACzB,QAAQ,SAAS,QAAQ,MAAM;IAC7B,IAAI,OAAO,WAAW,YAAY;KAEhC,IAAI,OAAO,kBAAkBC,cAAAA,WAC3B,0BAA0B,KAAK,QAAQ,EAAE;UACpC,IAAI,OAAO,kBAAkB,WAClC,KAAK,oBAAoB,QAAQ,EAAE;UAEnC,SAAS,KAAK,OAAO,MAAM;IAE/B;GACF,CAAC;GAID,IAAI,0BAA0B,SAAS,GAAG;IACxC,MAAM,KAAK,GAAG,aAAa;IAC3B,KAAK,OAAO,gBAAgB,KAAK,IAAI,yBAAyB;IAC9D,MAAM,YAAY,KAAK,OAAO,IAAI;IAClC,MAAM,UAAU,MAAMF,gBAAAA,0BACpB,QAAQ,WAAW,0BAA0B,KAAK,MAAM,KAAKC,UAAU,CAAC,CAAC,CAAC,CAC5E;IACA,MAAM,UAAU,KAAK,OAAO,IAAI;IAChC,KAAK,OAAO,cAAc,KAAK,IAAI,UAAU,SAAS;IACtD,QAAQ,SAAS,QAAQ,MAAM;KAC7B,IAAI,OAAO,WAAW,YAAY;MAChC,IAAI,OAAO,kBAAkB,WAC3B,KAAK,oBAAoB,0BAA0B,EAAE;WAErD,SAAS,KAAK,OAAO,MAAM;KAE/B;IACF,CAAC;GACH;GAEA,IAAI,SAAS,SAAS,GAAG,MAAM,SAAS;GAExC,KAAK,MAAM,UAAU,SACnB,IAAI,OAAO,EAAE,SAAS;IACpB,IAAI,MAAM,KAAK,iBAAiB,IAAI,OAAO,EAAE,IAAI;IACjD,IAAI,CAAC,KAAK,KAAK,iBAAiB,IAAI,OAAO,EAAE,MAAO,sBAAM,IAAI,IAAI,CAAE;IACpE,IAAI,IAAI,OAAO,MAAM;GACvB;GAKF,IAAI,UAAU,IACZ,MAAM,IAAI,MAAM,8DAA8D;EAElF;CACF;CAEA,MAAM,0BAA0B;EAC9B,MAAM,UAA4B,CAAC;EACnC,KAAK,MAAM,YAAY,KAAK,yBAAyB,OAAO,GAC1D,KAAK,MAAM,UAAU,SAAS,OAAO,GAAG,QAAQ,KAAK,MAAM;EAE7D,KAAK,yBAAyB,MAAM;EAEpC,MAAM,YAAY,KAAK,OAAO,IAAI;EAClC,MAAM,UAAU,MAAMD,gBAAAA,0BACpB,QAAQ,WAAW,QAAQ,QAAQ,MAAM,CAAC,EAAE,OAAO,eAAe,CAAC,CAAC,KAAK,MAAM,KAAKC,UAAU,CAAC,CAAC,CAAC,CACnG;EACA,MAAM,UAAU,KAAK,OAAO,IAAI;EAChC,KAAK,OAAO,cAAc,KAAK,IAAI,UAAU,SAAS;EAEtD,MAAM,WAAkB,CAAC;EACzB,QAAQ,SAAS,WAAW;GAC1B,IAAI,OAAO,WAAW,YAAY;IAChC,IAAI,OAAO,kBAAkB,WAE3B,KAAK,qBAAqB,KAAK,OAAO,MAAM;SAE5C,SAAS,KAAK,OAAO,MAAM;GAE/B;EACF,CAAC;EACD,IAAI,SAAS,SAAS,GAAG,MAAM,SAAS;CAC1C;CAEA,IAAI,uBAAgC;EAClC,OAAO,KAAK,yBAAyB,OAAO;CAC9C;;CAGA,QAAc;EACZ,KAAK,oCAAoB,IAAI,IAAI;EACjC,KAAK,iBAAiB,MAAM;CAC9B;CAEA,UAAU,QAA0C;EAClD,KAAK,SAAS,UAAUL,+BAAAA;CAC1B;CAEA,4BAAkC;EAChC,KAAK,uBAAuB,CAAC;CAC/B;CAEA,iCAAuC;EACrC,IAAI,KAAK,qBAAqB,SAAS,GACrC,MAAM,KAAK,qBAAqB;CAEpC;CAEA,UAAU,QAAwB;EAChC,MAAM,EAAE,GAAG,WAAW;EACtB,OAAO,EAAE,SAAS,aAAa,EAAE,GAAG,QAAQ,KAAK,GAAG,GAAG,IAAK,OAAe,EAAE,KAAK,CAAC,KAAK;CAC1F;;CAGA,oBAA4B,QAA8B;EACxD,IAAI,WAAW,KAAK,yBAAyB,IAAI,OAAO,EAAE,IAAI;EAC9D,IAAI,CAAC,UAAU,KAAK,yBAAyB,IAAI,OAAO,EAAE,MAAO,2BAAW,IAAI,IAAI,CAAE;EACtF,SAAS,IAAI,OAAO,QAAQ,MAAM;CACpC;CAEA,YAAY,MAAiD;EAC3D,OAAO,SAAS,eAAe,KAAKC,aAAa,YAAY,KAAKA,aAAa,WAAW,KAAKA,aAAa;CAC9G;CAEA,WAAmB,GAAwD;EACzE,IAAI,UAAU,KAAK,kBAAkB,IAAI,CAAC;EAC1C,IAAI,CAAC,SAAS;GACZ,UAAU;IAAE,sBAAM,IAAI,IAAI;IAAG,sBAAM,IAAI,IAAI;GAAE;GAC7C,KAAK,kBAAkB,IAAI,GAAG,OAAO;GAGrC,KAAK,eAAeC,uBAAAA,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI;EACrD;EACA,OAAO;CACT;CAEA,eAAuB,MAAmC;EACxD,IAAI,QAAQ,KAAK,YAAY,IAAI,KAAK,OAAO;EAC7C,IAAI,CAAC,OAAO;GACV,wBAAQ,IAAI,IAAI;GAChB,KAAK,YAAY,IAAI,KAAK,SAAS,KAAK;EAC1C;EACA,OAAO;CACT;CAEA,cAAsB,QAA6B;EAGjD,MAAM,OAAOA,uBAAAA,YAAY,MAAM;EAC/B,OAAOK,sBAAAA,iBAAiB,KAAK,EAAE,CAAC,CAAC,UAAU,MAAM,IAAI,KAAK,8BAA+B,KAAK;CAChG;CAEA,qBAA6B,QAAgB,WAAyC;EACpF,MAAM,OAAOL,uBAAAA,YAAY,MAAM;EAK/B,QAJgBK,sBAAAA,iBAAiB,KAAK,EAAE,CAAC,CAAC,UAAU,MAAM,IACtD,KAAK,qCACL,KAAK,kBAAA,CAEM,IAAI,SAAS,KAAK;CACnC;AACF;;AAGA,MAAM,eAAqC,OAAO,OAAO,CAAC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ReactionsManager.d.cts","names":[],"sources":["../src/ReactionsManager.ts"],"mappings":";;;;;;KAQY;EAAmB,GAAG;EAAW,QAAQ;;;;;;;;;cAQxC;;;UAEH;;UAEA;;;;;;;;;;UAUA;;;;;;;;;UASA;EAGR,QAAQ;UACA;;UAEA;EAER,YAAY,IAAI;;;;;;;;EAWhB,0BAA0B,QAAQ,QAAQ;;EAkB1C,4BAA4B,QAAQ,QAAQ;;EAyB5C,yBAAyB,QAAQ,QAAQ;;;;;;;;;;;;;EAoBzC,qBAAqB,QAAQ,QAAQ;EAIrC;;;;;;;;EAWM,wBAAwB,yCAAsC;EAkH9D,2BAAuB;MA4BzB;;EAKJ;EAKA,UAAU,QAAQ;EAIlB;EAIA;;UAYQ;EAMR,YAAY;UAIJ;UAYA;UASA;UAOA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ReactionsManager.d.mts","names":[],"sources":["../src/ReactionsManager.ts"],"mappings":";;;;;;KAQY;EAAmB,GAAG;EAAW,QAAQ;;;;;;;;;cAQxC;;;UAEH;;UAEA;;;;;;;;;;UAUA;;;;;;;;;UASA;EAGR,QAAQ;UACA;;UAEA;EAER,YAAY,IAAI;;;;;;;;EAWhB,0BAA0B,QAAQ,QAAQ;;EAkB1C,4BAA4B,QAAQ,QAAQ;;EAyB5C,yBAAyB,QAAQ,QAAQ;;;;;;;;;;;;;EAoBzC,qBAAqB,QAAQ,QAAQ;EAIrC;;;;;;;;EAWM,wBAAwB,yCAAsC;EAkH9D,2BAAuB;MA4BzB;;EAKJ;EAKA,UAAU,QAAQ;EAIlB;EAIA;;UAYQ;EAMR,YAAY;UAIJ;UAYA;UASA;UAOA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ReactionsManager.js","names":["#needsRecalc","#doAction"],"sources":["../src/ReactionsManager.ts"],"sourcesContent":["import { type Reactable } from \"./config.ts\";\nimport { type Entity } from \"./Entity.ts\";\nimport { type EntityMetadata, getMetadata } from \"./EntityMetadata.ts\";\nimport { type EntityManager, NoIdError, getEmInternalApi } from \"./index.ts\";\nimport { type ReactionLogger, globalLogger, noopReactionLogger } from \"./logging/ReactionLogger.ts\";\nimport { followReverseHint } from \"./reactiveHints.ts\";\nimport { runInTrustedContext } from \"./trusted.ts\";\n\nexport type ReactiveAction = { r: Reactable; entity: Entity };\n/**\n * Manages the reactivity of tracking which source fields have changed and finding/recalculating\n * their downstream derived fields.\n *\n * Source fields are usually regular/dumb primitives, i.e. `Author.age` is a source field\n * of `Book.isPublic`, but derived fields can themselves be source fields as well.\n */\nexport class ReactionsManager {\n /** Stores all source `Reactables`s that have been marked for later traversal. */\n private pendingReactables: Map<Reactable, { todo: Set<Entity>; done: Set<Entity> }> = new Map();\n /** Failed actions to retry post-hooks, deduped by target field name -> entity (rare error path). */\n private actionsPendingTypeErrors: Map<string, Map<Entity, ReactiveAction>> = new Map();\n /**\n * A map of entity tagName -> fields that have been marked as dirty.\n *\n * The key of the map is \"just\" the tag name, instead of a specific entity, b/c at the time of\n * being marked dirty, we only have the upstream/source entity + fieldName that has changed, and\n * not the 1-or-more downstream/target entities that will actually recalc.\n *\n * Instead, we just track the dirty fields by type-of-entity, which is enough for `isPendingRecalc`.\n */\n private dirtyFields: Map<string, Set<string>> = new Map();\n /**\n * Tracks which entities have already run a `runOnce` reactable, keyed by the target field\n * name -> entities. We key on `r.name` (not `r` itself) b/c two `Reactable`s reverse-indexed\n * from different source paths can target the same derived field, and must dedupe together.\n * Keying the outer map by field name (of which there are few) instead of by entity (of which\n * there are many) means we allocate just one `Set` per distinct field name, rather than a\n * `Set` per entity or the old per-action `${entity.toTaggedString()}_${r.name}` key strings.\n */\n private processedActions: Map<string, Set<Entity>> = new Map();\n #needsRecalc = { populate: false, query: false, reaction: false };\n // Accessible for EntityManager.runValidation to reuse\n logger: ReactionLogger = globalLogger ?? noopReactionLogger;\n private em: EntityManager;\n /** These are NPEs that *might* have been from invalid m2o fields, so we only throw them after validation. */\n private suppressedTypeErrors: Error[] = [];\n\n constructor(em: EntityManager) {\n this.em = em;\n }\n\n /**\n * Queue all downstream reactive fields that depend on `fieldName` as a source field.\n *\n * This method can be synchronous b/c we internally queue the `Reactable` reverse\n * indexes on the given source `fieldName`, and don't crawl/walk back to the downstream\n * entities/fields until `recalcPendingReactables` is called.\n */\n queueDownstreamReactables(entity: Entity, fieldName: string): void {\n // Use the reverse index of Reactables that configureMetadata sets up\n for (const r of this.getReactablesByField(entity, fieldName)) {\n // We always queue the reactable/entity, even if we're mid-flush or even mid-recalc, to avoid:\n // - firstName is changed from a1 to a2\n // - this triggers firstName's reactable to `Author.initials` to be queued\n // - during the 1st em.flush loop, we recalc `Author.initials` and it didn't change\n // - during the 1st em.flush loop, a hook changes firstName from a2 to b2\n // - if we skip re-queuing firstName's reactables, we will miss that initials needs\n // its `.load()` called again so that it's `setField` marks `initials` as\n // dirty, otherwise it will be left out of any INSERTs/UPDATEs.\n this.getPending(r).todo.add(entity);\n this.#needsRecalc[r.kind] = true;\n this.logger.logQueued(entity, fieldName, r);\n }\n }\n\n /** Dequeues reactivity on `fieldName`, i.e. if it's no longer dirty. */\n dequeueDownstreamReactables(entity: Entity, fieldName: string): void {\n // Use the reverse index of Reactables that configureMetadata sets up\n for (const r of this.getReactablesByField(entity, fieldName)) {\n const pending = this.getPending(r);\n if (pending.done.has(entity)) {\n // Ironically, if we've already run this reactable, asking to dequeue probably means\n // we need to run it again (to recalc its value), b/c this could be a mid-flush change, i.e.:\n // - firstName = a1 from db\n // - firstName is changed to a2, triggers initials reactable\n // - firstName is changed back to a1, which is the original value, so setField\n // thinks we can dequeue the reactable\n // - but actually our reactable needs to be re-run with the restored value\n pending.todo.add(entity);\n this.#needsRecalc[r.kind] = true;\n } else if (r.fields.length === 1) {\n // We can only delete/dequeue a reaction if `fieldName` is the only or last field\n // that had triggered `r` to run. Since we don't track that currently, i.e. we'd\n // need to have a `Pending.dirtyFields`, for now just only dequeue if `r` only\n // has one field (which is us) anyway.\n pending.todo.delete(entity);\n }\n }\n }\n\n /** Queue all downstream reactive fields that depend on this entity being created or deleted. */\n queueAllDownstreamFields(entity: Entity, reason: \"created\" | \"deleted\"): void {\n for (const r of this.getReactables(entity)) {\n this.getPending(r).todo.add(entity);\n this.#needsRecalc[r.kind] = true;\n this.logger.logQueuedAll(entity, reason, r);\n }\n }\n\n /**\n * Returns whether this field might be pending recalc.\n *\n * This is technically a guess, b/c our reaction infra may not yet have crawled from an upstream\n * source field down to the `N` specific target entities that need recalced, and instead just\n * knows \"it will need to do that soon\" i.e. at the next `em.flush`.\n *\n * So, instead this is a heuristic that reports if `fieldName` has been marked dirty for _some_\n * entities of type `entity`, but we don't technically know if that's _this_ entity.\n *\n * I.e. this might return false positives, but should never return false negatives.\n */\n isMaybePendingRecalc(entity: Entity, fieldName: string): boolean {\n return this.getDirtyFields(getMetadata(entity)).has(fieldName);\n }\n\n hasPendingReactiveQueries(): boolean {\n return this.#needsRecalc.query;\n }\n\n /**\n * Given source `Reactable` \"reverse indexes\" that have been queued as dirty by calls\n * to setters, `em.register`, or `em.delete`, asynchronously walks/crawls to the downstream\n * derived fields and calls `.load()` on them to calc.\n *\n * We also do this in a loop to handle reactive fields depending on other reactive fields.\n */\n async recalcPendingReactables(kind: \"reactables\" | \"reactiveQueries\") {\n if (this.needsRecalc(kind)) this.logger.logStartingRecalc(this.em, kind);\n\n let loops = 0;\n while (this.needsRecalc(kind)) {\n // ...we probably should only loop for `kind=reactables` Reactables, and `kind=reactiveQueries`\n // AsyncReactiveFields should probably only have a single loop, after which we return and\n // let `em.flush` push the latest values to the db, so our 2nd-order AsyncReactiveFields\n // will see the latest value.\n if (kind === \"reactables\") {\n this.#needsRecalc.populate = false;\n this.#needsRecalc.reaction = false;\n } else {\n this.#needsRecalc.query = false;\n }\n\n // Dedupe actions by (target field name, entity); see the `processedActions` docs for why\n // we key on `r.name` instead of `r` or the old per-action key strings\n const seen: Map<string, Set<Entity>> = new Map();\n const actions: ReactiveAction[] = [];\n\n const walks = await Promise.all(\n [...this.pendingReactables.entries()].map(async ([r, pending]) => {\n // Skip reactive queries until post-flush\n if (kind === \"reactables\" && r.kind === \"query\") return undefined;\n if (kind === \"reactiveQueries\" && (r.kind === \"populate\" || r.kind === \"reaction\")) return undefined;\n // Copy pending and clear it\n const todo = [...pending.todo];\n if (todo.length === 0) return undefined;\n pending.todo.clear();\n for (const doing of todo) pending.done.add(doing);\n // Walk back from the source to any downstream entities\n const entities = r.path.length === 0 ? todo : await followReverseHint(r.name, todo, r.path);\n const actionableEntities = entities.filter((entity) => !entity.isDeletedEntity && entity instanceof r.cstr);\n let seenEntities = seen.get(r.name);\n if (!seenEntities) seen.set(r.name, (seenEntities = new Set()));\n const processed = r.runOnce ? this.processedActions.get(r.name) : undefined;\n for (const entity of actionableEntities) {\n // We could arrive at the same reactable from multiple paths (eg, 2 dependent fields changed), so we need to\n // dedupe based on the entity and reactable to only run each action once for any given entity per loop\n if (seenEntities.has(entity)) continue;\n // If this reactable has already run and shouldn't run again, then skip it\n if (processed && processed.has(entity)) continue;\n seenEntities.add(entity);\n actions.push({ r, entity });\n }\n return { r, todo, entities: actionableEntities };\n }),\n );\n this.logger.logWalks(walks, \"recalc\");\n this.logger.logLoadingStart(this.em, actions);\n // Use allSettled so that we can watch for derived values that want to use an entity's id\n // i.e. they can fail, but we'll queue them from later.\n const startTime = this.logger.now();\n const results = await runInTrustedContext(() => Promise.allSettled(actions.map((a) => this.#doAction(a))));\n const endTime = this.logger.now();\n this.logger.logLoadingEnd(this.em, endTime - startTime);\n\n // This loop's actions are already unique by (name, entity), so a plain array dedupes fine\n const actionsPendingAssignedIds: ReactiveAction[] = [];\n const failures: any[] = [];\n results.forEach((result, i) => {\n if (result.status === \"rejected\") {\n // Let `author.id` and `book.author.get.firstName` errors run again after flush/hooks fills them in\n if (result.reason instanceof NoIdError) {\n actionsPendingAssignedIds.push(actions[i]);\n } else if (result.reason instanceof TypeError) {\n this.addPendingTypeError(actions[i]);\n } else {\n failures.push(result.reason);\n }\n }\n });\n\n // If we have any actions that need to be re-run because they failed due to a missing id, then we assign ids and\n // re-run them.\n if (actionsPendingAssignedIds.length > 0) {\n await this.em.assignNewIds();\n this.logger.logLoadingStart(this.em, actionsPendingAssignedIds);\n const startTime = this.logger.now();\n const results = await runInTrustedContext(() =>\n Promise.allSettled(actionsPendingAssignedIds.map((a) => this.#doAction(a))),\n );\n const endTime = this.logger.now();\n this.logger.logLoadingEnd(this.em, endTime - startTime);\n results.forEach((result, i) => {\n if (result.status === \"rejected\") {\n if (result.reason instanceof TypeError) {\n this.addPendingTypeError(actionsPendingAssignedIds[i]);\n } else {\n failures.push(result.reason);\n }\n }\n });\n }\n\n if (failures.length > 0) throw failures[0];\n // Record any successful actions that should only run once so we don't run them again\n for (const action of actions) {\n if (action.r.runOnce) {\n let set = this.processedActions.get(action.r.name);\n if (!set) this.processedActions.set(action.r.name, (set = new Set()));\n set.add(action.entity);\n }\n }\n // This should generally not happen, only if two reactive fields depend on each other,\n // which in theory should probably be caught/blow up in the `configureMetadata` step,\n // but if it's not caught sooner, at least don't infinite loop.\n if (loops++ > 50) {\n throw new Error(\"recalc looped too many times, probably a circular dependency\");\n }\n }\n }\n\n async recalcPendingTypeErrors() {\n const actions: ReactiveAction[] = [];\n for (const byEntity of this.actionsPendingTypeErrors.values()) {\n for (const action of byEntity.values()) actions.push(action);\n }\n this.actionsPendingTypeErrors.clear();\n\n const startTime = this.logger.now();\n const results = await runInTrustedContext(() =>\n Promise.allSettled(actions.filter((a) => !a.entity.isDeletedEntity).map((a) => this.#doAction(a))),\n );\n const endTime = this.logger.now();\n this.logger.logLoadingEnd(this.em, endTime - startTime);\n\n const failures: any[] = [];\n results.forEach((result) => {\n if (result.status === \"rejected\") {\n if (result.reason instanceof TypeError) {\n // Defer to the validation error to catch this\n this.suppressedTypeErrors.push(result.reason);\n } else {\n failures.push(result.reason);\n }\n }\n });\n if (failures.length > 0) throw failures[0];\n }\n\n get hasPendingTypeErrors(): boolean {\n return this.actionsPendingTypeErrors.size > 0;\n }\n\n /** Clears all the pending source fields, i.e. after `em.flush` is complete. */\n clear(): void {\n this.pendingReactables = new Map();\n this.processedActions.clear();\n }\n\n setLogger(logger: ReactionLogger | undefined): void {\n this.logger = logger ?? noopReactionLogger;\n }\n\n clearSuppressedTypeErrors(): void {\n this.suppressedTypeErrors = [];\n }\n\n throwIfAnySuppressedTypeErrors(): void {\n if (this.suppressedTypeErrors.length > 0) {\n throw this.suppressedTypeErrors[0];\n }\n }\n\n #doAction(action: ReactiveAction) {\n const { r, entity } = action;\n return r.kind === \"reaction\" ? r.fn(entity, this.em.ctx) : (entity as any)[r.name].load();\n }\n\n /** Remembers a TypeError'd action to retry post-hooks, deduped by (target field name, entity). */\n private addPendingTypeError(action: ReactiveAction): void {\n let byEntity = this.actionsPendingTypeErrors.get(action.r.name);\n if (!byEntity) this.actionsPendingTypeErrors.set(action.r.name, (byEntity = new Map()));\n byEntity.set(action.entity, action);\n }\n\n needsRecalc(kind: \"reactables\" | \"reactiveQueries\"): boolean {\n return kind === \"reactables\" ? this.#needsRecalc.populate || this.#needsRecalc.reaction : this.#needsRecalc.query;\n }\n\n private getPending(r: Reactable): { todo: Set<Entity>; done: Set<Entity> } {\n let pending = this.pendingReactables.get(r);\n if (!pending) {\n pending = { todo: new Set(), done: new Set() };\n this.pendingReactables.set(r, pending);\n // The dirty field name is constant per reactable, so mark it once on the first\n // queue instead of paying the `getMetadata` + map lookup on every queued entity.\n this.getDirtyFields(getMetadata(r.cstr)).add(r.name);\n }\n return pending;\n }\n\n private getDirtyFields(meta: EntityMetadata): Set<string> {\n let dirty = this.dirtyFields.get(meta.tagName);\n if (!dirty) {\n dirty = new Set();\n this.dirtyFields.set(meta.tagName, dirty);\n }\n return dirty;\n }\n\n private getReactables(entity: Entity): Reactable[] {\n // If two books are getting merged, and so a normally-immutable `BookReview.book` is being changed,\n // then even normally-immutable fields need to be recalculated.\n const meta = getMetadata(entity);\n return getEmInternalApi(this.em).isMerging(entity) ? meta.reactablesIncludingReadOnly! : meta.reactables!;\n }\n\n private getReactablesByField(entity: Entity, fieldName: string): readonly Reactable[] {\n const meta = getMetadata(entity);\n const byField = getEmInternalApi(this.em).isMerging(entity)\n ? meta.reactablesIncludingReadOnlyByField!\n : meta.reactablesByField!;\n // Most fields have no reactables, so return a shared empty array instead of allocating one per set\n return byField.get(fieldName) ?? noReactables;\n }\n}\n\n/** A shared frozen array for fields with no downstream reactables. */\nconst noReactables: readonly Reactable[] = Object.freeze([]);\n"],"mappings":"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"}
|
package/build/Todo.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Todo.cjs","names":["groupBy","getMetadata","getInstanceData"],"sources":["../src/Todo.ts"],"sourcesContent":["/** The operations for a given entity type, so they can be executed in bulk. */\nimport { getInstanceData } from \"./BaseEntity.ts\";\nimport { type Entity } from \"./Entity.ts\";\nimport { type EntityMetadata, getMetadata } from \"./EntityMetadata.ts\";\nimport { type JoinRow, type JoinRows, type ManyToManyLike } from \"./JoinRows.ts\";\nimport { groupBy } from \"./utils.ts\";\n\n/** A group of insert/update/delete operations for a given entity. */\nexport class Todo {\n /** Groups `todos` by their base/subtype, currently only inserts. */\n static groupInsertsByTypeAndSubType(todos: Record<string, Todo>): Map<EntityMetadata, Entity[]> {\n const map = new Map<EntityMetadata, Entity[]>();\n for (const todoKey in todos) {\n const todo = todos[todoKey];\n // Skip update/delete-only todos so hook loops don't allocate entries for empty insert lists\n if (todo.inserts.length === 0) continue;\n if (todo.metadata.inheritanceType) {\n for (const [meta, inserts] of groupBy(todo.inserts, (e) => getMetadata(e))) {\n map.set(meta, inserts);\n }\n } else {\n map.set(todo.metadata, todo.inserts);\n }\n }\n return map;\n }\n\n inserts: Entity[] = [];\n updates: Entity[] = [];\n deletes: Entity[] = [];\n\n constructor(\n /** The metadata for entities in this todo; it will be the base metadata for any subtypes. */\n public metadata: EntityMetadata,\n ) {}\n}\n\n/**\n * Scans `entities` for new/updated entities and groups them by type (by base type if applicable).\n */\nexport function createTodos(entities: Iterable<Entity>): Record<string, Todo> {\n const todos: Record<string, Todo> = {};\n for (const entity of entities) {\n const op = getInstanceData(entity).pendingOperation;\n if (op !== \"none\") {\n const todo = getTodo(todos, entity);\n switch (op) {\n case \"insert\":\n todo.inserts.push(entity);\n break;\n case \"update\":\n todo.updates.push(entity);\n break;\n case \"delete\":\n todo.deletes.push(entity);\n break;\n }\n }\n }\n return todos;\n}\n\n/** getOrSets a `Todo` for `entity` in `todos`. */\nexport function getTodo(todos: Record<string, Todo>, entity: Entity): Todo {\n const meta = getMetadata(entity);\n // Always create todos around the base table, so that we get the best batching against it\n const maybeBase = meta.baseTypes[0] || meta;\n return (todos[maybeBase.type] ??= new Todo(maybeBase));\n}\n\nexport interface JoinRowTodo {\n // Store the m2m reference (either side of the m2m, it doesn't matter which) to help tag/untag the foreign keys\n m2m: ManyToManyLike;\n newRows: JoinRow[];\n deletedRows: JoinRow[];\n resetAfterFlushed: () => void;\n /** Resolves a join row's column to the int FK value to flush (an entity's id, or an enum's id). */\n dbValue(row: JoinRow, columnName: string): number;\n /** Whether a join row's column points at a not-yet-inserted entity (always false for enum columns). */\n isNew(row: JoinRow, columnName: string): boolean;\n}\n\n/** Given a list of `JoinRow`s for a given table, combine them into a single logical `JoinRowTodo`. */\nexport function combineJoinRows(joinRows: Record<string, JoinRows>): Record<string, JoinRowTodo> {\n const todos: Record<string, JoinRowTodo> = {};\n for (const [joinTableName, rows] of Object.entries(joinRows)) {\n const todo = rows.toTodo();\n if (todo) todos[joinTableName] = todo;\n }\n return todos;\n}\n"],"mappings":";;;;;;;;;AAQA,IAAa,OAAb,MAAkB;CAyBP;;CAvBT,OAAO,6BAA6B,OAA4D;EAC9F,MAAM,sBAAM,IAAI,IAA8B;EAC9C,KAAK,MAAM,WAAW,OAAO;GAC3B,MAAM,OAAO,MAAM;GAEnB,IAAI,KAAK,QAAQ,WAAW,GAAG;GAC/B,IAAI,KAAK,SAAS,iBAChB,KAAK,MAAM,CAAC,MAAM,YAAYA,cAAAA,QAAQ,KAAK,UAAU,MAAMC,uBAAAA,YAAY,CAAC,CAAC,GACvE,IAAI,IAAI,MAAM,OAAO;QAGvB,IAAI,IAAI,KAAK,UAAU,KAAK,OAAO;EAEvC;EACA,OAAO;CACT;CAEA,UAAoB,CAAC;CACrB,UAAoB,CAAC;CACrB,UAAoB,CAAC;CAErB,YAEE,UACA;EADO,KAAA,WAAA;CACN;AACL;;;;AAKA,SAAgB,YAAY,UAAkD;CAC5E,MAAM,QAA8B,CAAC;CACrC,KAAK,MAAM,UAAU,UAAU;EAC7B,MAAM,KAAKC,mBAAAA,gBAAgB,MAAM,CAAC,CAAC;EACnC,IAAI,OAAO,QAAQ;GACjB,MAAM,OAAO,QAAQ,OAAO,MAAM;GAClC,QAAQ,IAAR;IACE,KAAK;KACH,KAAK,QAAQ,KAAK,MAAM;KACxB;IACF,KAAK;KACH,KAAK,QAAQ,KAAK,MAAM;KACxB;IACF,KAAK,UACH,KAAK,QAAQ,KAAK,MAAM;GAE5B;EACF;CACF;CACA,OAAO;AACT;;AAGA,SAAgB,QAAQ,OAA6B,QAAsB;CACzE,MAAM,OAAOD,uBAAAA,YAAY,MAAM;CAE/B,MAAM,YAAY,KAAK,UAAU,MAAM;CACvC,OAAQ,MAAM,UAAU,UAAU,IAAI,KAAK,SAAS;AACtD;;AAeA,SAAgB,gBAAgB,UAAiE;CAC/F,MAAM,QAAqC,CAAC;CAC5C,KAAK,MAAM,CAAC,eAAe,SAAS,OAAO,QAAQ,QAAQ,GAAG;EAC5D,MAAM,OAAO,KAAK,OAAO;EACzB,IAAI,MAAM,MAAM,iBAAiB;CACnC;CACA,OAAO;AACT"}
|
package/build/Todo.d.cts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Todo.d.cts","names":[],"sources":["../src/Todo.ts"],"mappings":";;;;;cAQa;;EAyBF,UAAU;;SAvBZ,6BAA6B,OAAO,eAAe,QAAQ,IAAI,gBAAgB;EAiBtF,SAAS;EACT,SAAS;EACT,SAAS;EAET,YAES;;EAAA,UAAU;;;;;iBAOL,YAAY,UAAU,SAAS,UAAU,eAAe;;iBAuBxD,QAAQ,OAAO,eAAe,OAAO,QAAQ,SAAS;UAOrD;EAEf,KAAK;EACL,SAAS;EACT,aAAa;EACb;;EAEA,QAAQ,KAAK,SAAS;;EAEtB,MAAM,KAAK,SAAS;;;iBAIN,gBAAgB,UAAU,eAAe,YAAY,eAAe"}
|
package/build/Todo.d.mts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Todo.d.mts","names":[],"sources":["../src/Todo.ts"],"mappings":";;;;;cAQa;;EAyBF,UAAU;;SAvBZ,6BAA6B,OAAO,eAAe,QAAQ,IAAI,gBAAgB;EAiBtF,SAAS;EACT,SAAS;EACT,SAAS;EAET,YAES;;EAAA,UAAU;;;;;iBAOL,YAAY,UAAU,SAAS,UAAU,eAAe;;iBAuBxD,QAAQ,OAAO,eAAe,OAAO,QAAQ,SAAS;UAOrD;EAEf,KAAK;EACL,SAAS;EACT,aAAa;EACb;;EAEA,QAAQ,KAAK,SAAS;;EAEtB,MAAM,KAAK,SAAS;;;iBAIN,gBAAgB,UAAU,eAAe,YAAY,eAAe"}
|
package/build/Todo.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Todo.js","names":[],"sources":["../src/Todo.ts"],"sourcesContent":["/** The operations for a given entity type, so they can be executed in bulk. */\nimport { getInstanceData } from \"./BaseEntity.ts\";\nimport { type Entity } from \"./Entity.ts\";\nimport { type EntityMetadata, getMetadata } from \"./EntityMetadata.ts\";\nimport { type JoinRow, type JoinRows, type ManyToManyLike } from \"./JoinRows.ts\";\nimport { groupBy } from \"./utils.ts\";\n\n/** A group of insert/update/delete operations for a given entity. */\nexport class Todo {\n /** Groups `todos` by their base/subtype, currently only inserts. */\n static groupInsertsByTypeAndSubType(todos: Record<string, Todo>): Map<EntityMetadata, Entity[]> {\n const map = new Map<EntityMetadata, Entity[]>();\n for (const todoKey in todos) {\n const todo = todos[todoKey];\n // Skip update/delete-only todos so hook loops don't allocate entries for empty insert lists\n if (todo.inserts.length === 0) continue;\n if (todo.metadata.inheritanceType) {\n for (const [meta, inserts] of groupBy(todo.inserts, (e) => getMetadata(e))) {\n map.set(meta, inserts);\n }\n } else {\n map.set(todo.metadata, todo.inserts);\n }\n }\n return map;\n }\n\n inserts: Entity[] = [];\n updates: Entity[] = [];\n deletes: Entity[] = [];\n\n constructor(\n /** The metadata for entities in this todo; it will be the base metadata for any subtypes. */\n public metadata: EntityMetadata,\n ) {}\n}\n\n/**\n * Scans `entities` for new/updated entities and groups them by type (by base type if applicable).\n */\nexport function createTodos(entities: Iterable<Entity>): Record<string, Todo> {\n const todos: Record<string, Todo> = {};\n for (const entity of entities) {\n const op = getInstanceData(entity).pendingOperation;\n if (op !== \"none\") {\n const todo = getTodo(todos, entity);\n switch (op) {\n case \"insert\":\n todo.inserts.push(entity);\n break;\n case \"update\":\n todo.updates.push(entity);\n break;\n case \"delete\":\n todo.deletes.push(entity);\n break;\n }\n }\n }\n return todos;\n}\n\n/** getOrSets a `Todo` for `entity` in `todos`. */\nexport function getTodo(todos: Record<string, Todo>, entity: Entity): Todo {\n const meta = getMetadata(entity);\n // Always create todos around the base table, so that we get the best batching against it\n const maybeBase = meta.baseTypes[0] || meta;\n return (todos[maybeBase.type] ??= new Todo(maybeBase));\n}\n\nexport interface JoinRowTodo {\n // Store the m2m reference (either side of the m2m, it doesn't matter which) to help tag/untag the foreign keys\n m2m: ManyToManyLike;\n newRows: JoinRow[];\n deletedRows: JoinRow[];\n resetAfterFlushed: () => void;\n /** Resolves a join row's column to the int FK value to flush (an entity's id, or an enum's id). */\n dbValue(row: JoinRow, columnName: string): number;\n /** Whether a join row's column points at a not-yet-inserted entity (always false for enum columns). */\n isNew(row: JoinRow, columnName: string): boolean;\n}\n\n/** Given a list of `JoinRow`s for a given table, combine them into a single logical `JoinRowTodo`. */\nexport function combineJoinRows(joinRows: Record<string, JoinRows>): Record<string, JoinRowTodo> {\n const todos: Record<string, JoinRowTodo> = {};\n for (const [joinTableName, rows] of Object.entries(joinRows)) {\n const todo = rows.toTodo();\n if (todo) todos[joinTableName] = todo;\n }\n return todos;\n}\n"],"mappings":";;;;;;;;AAQA,IAAa,OAAb,MAAkB;CAyBP;;CAvBT,OAAO,6BAA6B,OAA4D;EAC9F,MAAM,sBAAM,IAAI,IAA8B;EAC9C,KAAK,MAAM,WAAW,OAAO;GAC3B,MAAM,OAAO,MAAM;GAEnB,IAAI,KAAK,QAAQ,WAAW,GAAG;GAC/B,IAAI,KAAK,SAAS,iBAChB,KAAK,MAAM,CAAC,MAAM,YAAY,QAAQ,KAAK,UAAU,MAAM,YAAY,CAAC,CAAC,GACvE,IAAI,IAAI,MAAM,OAAO;QAGvB,IAAI,IAAI,KAAK,UAAU,KAAK,OAAO;EAEvC;EACA,OAAO;CACT;CAEA,UAAoB,CAAC;CACrB,UAAoB,CAAC;CACrB,UAAoB,CAAC;CAErB,YAEE,UACA;EADO,KAAA,WAAA;CACN;AACL;;;;AAKA,SAAgB,YAAY,UAAkD;CAC5E,MAAM,QAA8B,CAAC;CACrC,KAAK,MAAM,UAAU,UAAU;EAC7B,MAAM,KAAK,gBAAgB,MAAM,CAAC,CAAC;EACnC,IAAI,OAAO,QAAQ;GACjB,MAAM,OAAO,QAAQ,OAAO,MAAM;GAClC,QAAQ,IAAR;IACE,KAAK;KACH,KAAK,QAAQ,KAAK,MAAM;KACxB;IACF,KAAK;KACH,KAAK,QAAQ,KAAK,MAAM;KACxB;IACF,KAAK,UACH,KAAK,QAAQ,KAAK,MAAM;GAE5B;EACF;CACF;CACA,OAAO;AACT;;AAGA,SAAgB,QAAQ,OAA6B,QAAsB;CACzE,MAAM,OAAO,YAAY,MAAM;CAE/B,MAAM,YAAY,KAAK,UAAU,MAAM;CACvC,OAAQ,MAAM,UAAU,UAAU,IAAI,KAAK,SAAS;AACtD;;AAeA,SAAgB,gBAAgB,UAAiE;CAC/F,MAAM,QAAqC,CAAC;CAC5C,KAAK,MAAM,CAAC,eAAe,SAAS,OAAO,QAAQ,QAAQ,GAAG;EAC5D,MAAM,OAAO,KAAK,OAAO;EACzB,IAAI,MAAM,MAAM,iBAAiB;CACnC;CACA,OAAO;AACT"}
|
package/build/TypeInfo.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TypeInfo.cjs","names":[],"sources":["../src/TypeInfo.ts"],"sourcesContent":["// Keep compatibility metadata a runtime leaf in both CJS and ESM builds.\nimport type { EntityMetadata } from \"./EntityMetadata.ts\";\n\n/**\n * Runtime proof that values can share scalar conversions.\n *\n * PostgreSQL compares projected SQL rows and chooses a common SQL type before Joist decodes them.\n * A compound uses one decoder per output column and retains an encoder for later comparisons and\n * coalesce fallbacks. TypeScript result types are erased, and equal SQL storage types do not imply\n * equal logical domains.\n *\n * I.e. Author.id and Book.author_id are compatible Author IDs despite having separate serdes, while\n * Book.id must not decode as an Author ID just because both use int4. Author.age and Author.age.sum()\n * both expose TypeScript numbers but produce int4 and int8 driver values. Enum, custom-mapper, and\n * JSON-schema domain tokens also prevent unrelated conversions from mixing.\n *\n * Compatibility requires exact equality of canonical `dbType`, `domain`, and `idMeta`. An absent\n * descriptor is unknown, not an identity codec. `idMeta` identifies scalar IDs only; arrays retain\n * their element domain separately so they cannot select a polymorphic IN component. Raw `sql<R>`\n * annotations supply no runtime evidence. This descriptor does not implement conversions.\n */\nexport interface TypeInfo {\n dbType: string;\n domain: unknown;\n idMeta?: EntityMetadata;\n /** Internal conversion proof, consistent for equal dbType/domain/idMeta; not another compatibility key. */\n arrayElementSafe?: boolean;\n}\n\n/**\n * Normalizes known PostgreSQL type synonyms without treating coercible types or user types as equal.\n * The output compatibility checks compare these names, so normalize only spellings of the same type.\n *\n * I.e. `integer` and `int` both mean `int4`; `integer[]` and `int4[]` also describe the same SQL type.\n * Keeping these spellings distinct would reject compatible outputs just because their serdes use\n * different names for the same representation.\n *\n * I.e. `int4` can be promoted to `int8`, but they are not synonyms: classic pg returns int4 as a number\n * and int8 as a string. Treating them as equal could admit a compound whose first operand's decoder\n * cannot handle the common SQL type. This function does not choose or apply a conversion.\n *\n * I.e. `citext` must stay distinct from `text`: they disagree on whether 'Alice' and 'alice' are equal,\n * which matters when a set operation compares rows. A user-defined `app.email` domain over text can\n * also impose constraints that text does not. Unknown names remain unchanged, including their schema\n * and quoting; neither coercibility nor a shared base type proves that their outputs are compatible.\n */\nexport function canonicalDbType(dbType: string): string {\n if (dbType.endsWith(\"[]\")) return `${canonicalDbType(dbType.slice(0, -2))}[]`;\n switch (dbType) {\n case \"smallint\":\n return \"int2\";\n case \"int\":\n case \"integer\":\n return \"int4\";\n case \"bigint\":\n return \"int8\";\n case \"decimal\":\n return \"numeric\";\n case \"real\":\n return \"float4\";\n case \"double precision\":\n return \"float8\";\n case \"boolean\":\n return \"bool\";\n case \"character varying\":\n return \"varchar\";\n case \"character\":\n return \"bpchar\";\n case \"timestamp without time zone\":\n return \"timestamp\";\n case \"timestamp with time zone\":\n return \"timestamptz\";\n case \"time without time zone\":\n return \"time\";\n case \"time with time zone\":\n return \"timetz\";\n default:\n return dbType;\n }\n}\n\nconst arrayDomains = new Map<unknown, Map<EntityMetadata | undefined, symbol>>();\n\n// Both classic pg and lazy binary reads decode these physical arrays, not an unparsed array string.\nconst arrayElementDbTypes = new Set([\n \"bool\",\n \"bytea\",\n \"int2\",\n \"int4\",\n \"int8\",\n \"float4\",\n \"float8\",\n \"numeric\",\n \"text\",\n \"varchar\",\n \"bpchar\",\n \"uuid\",\n \"json\",\n \"jsonb\",\n]);\n\n/**\n * Describes elementwise conversion only for known physical array parsers and stable domain conversion.\n *\n * I.e. `a.id.arrayAgg()` wraps Author's tag and `idMeta` in its domain token, but has no scalar\n * `idMeta` of its own. Repeated expressions share the token; IDs of subtypes with a shared tag do not.\n * Native enum/citext, date/time, and nested SQL arrays remain unknown. Numeric elements can be numbers\n * in classic pg and strings in lazy binary reads, so a scalar string-only mapper is not sufficient.\n */\nexport function arrayOutputType(outputType: TypeInfo | undefined): TypeInfo | undefined {\n if (!outputType?.arrayElementSafe || !arrayElementDbTypes.has(outputType.dbType)) return undefined;\n let domains = arrayDomains.get(outputType.domain);\n if (!domains) arrayDomains.set(outputType.domain, (domains = new Map()));\n let domain = domains.get(outputType.idMeta);\n if (!domain) domains.set(outputType.idMeta, (domain = Symbol(\"joist.arrayOutput\")));\n return { dbType: `${outputType.dbType}[]`, domain };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA8CA,SAAgB,gBAAgB,QAAwB;CACtD,IAAI,OAAO,SAAS,IAAI,GAAG,OAAO,GAAG,gBAAgB,OAAO,MAAM,GAAG,EAAE,CAAC,EAAE;CAC1E,QAAQ,QAAR;EACE,KAAK,YACH,OAAO;EACT,KAAK;EACL,KAAK,WACH,OAAO;EACT,KAAK,UACH,OAAO;EACT,KAAK,WACH,OAAO;EACT,KAAK,QACH,OAAO;EACT,KAAK,oBACH,OAAO;EACT,KAAK,WACH,OAAO;EACT,KAAK,qBACH,OAAO;EACT,KAAK,aACH,OAAO;EACT,KAAK,+BACH,OAAO;EACT,KAAK,4BACH,OAAO;EACT,KAAK,0BACH,OAAO;EACT,KAAK,uBACH,OAAO;EACT,SACE,OAAO;CACX;AACF;AAEA,MAAM,+BAAe,IAAI,IAAsD;AAG/E,MAAM,sCAAsB,IAAI,IAAI;CAClC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;;;;;;;;AAUD,SAAgB,gBAAgB,YAAwD;CACtF,IAAI,CAAC,YAAY,oBAAoB,CAAC,oBAAoB,IAAI,WAAW,MAAM,GAAG,OAAO,KAAA;CACzF,IAAI,UAAU,aAAa,IAAI,WAAW,MAAM;CAChD,IAAI,CAAC,SAAS,aAAa,IAAI,WAAW,QAAS,0BAAU,IAAI,IAAI,CAAE;CACvE,IAAI,SAAS,QAAQ,IAAI,WAAW,MAAM;CAC1C,IAAI,CAAC,QAAQ,QAAQ,IAAI,WAAW,QAAS,SAAS,OAAO,mBAAmB,CAAE;CAClF,OAAO;EAAE,QAAQ,GAAG,WAAW,OAAO;EAAK;CAAO;AACpD"}
|
package/build/TypeInfo.d.cts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TypeInfo.d.cts","names":[],"sources":["../src/TypeInfo.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;UAqBiB;EACf;EACA;EACA,SAAS;;EAET;;;;;;;;;;;;;;;;;;;iBAoBc,gBAAgB;;;;;;;;;iBA+DhB,gBAAgB,YAAY,uBAAuB"}
|
package/build/TypeInfo.d.mts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TypeInfo.d.mts","names":[],"sources":["../src/TypeInfo.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;UAqBiB;EACf;EACA;EACA,SAAS;;EAET;;;;;;;;;;;;;;;;;;;iBAoBc,gBAAgB;;;;;;;;;iBA+DhB,gBAAgB,YAAY,uBAAuB"}
|
package/build/TypeInfo.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TypeInfo.js","names":[],"sources":["../src/TypeInfo.ts"],"sourcesContent":["// Keep compatibility metadata a runtime leaf in both CJS and ESM builds.\nimport type { EntityMetadata } from \"./EntityMetadata.ts\";\n\n/**\n * Runtime proof that values can share scalar conversions.\n *\n * PostgreSQL compares projected SQL rows and chooses a common SQL type before Joist decodes them.\n * A compound uses one decoder per output column and retains an encoder for later comparisons and\n * coalesce fallbacks. TypeScript result types are erased, and equal SQL storage types do not imply\n * equal logical domains.\n *\n * I.e. Author.id and Book.author_id are compatible Author IDs despite having separate serdes, while\n * Book.id must not decode as an Author ID just because both use int4. Author.age and Author.age.sum()\n * both expose TypeScript numbers but produce int4 and int8 driver values. Enum, custom-mapper, and\n * JSON-schema domain tokens also prevent unrelated conversions from mixing.\n *\n * Compatibility requires exact equality of canonical `dbType`, `domain`, and `idMeta`. An absent\n * descriptor is unknown, not an identity codec. `idMeta` identifies scalar IDs only; arrays retain\n * their element domain separately so they cannot select a polymorphic IN component. Raw `sql<R>`\n * annotations supply no runtime evidence. This descriptor does not implement conversions.\n */\nexport interface TypeInfo {\n dbType: string;\n domain: unknown;\n idMeta?: EntityMetadata;\n /** Internal conversion proof, consistent for equal dbType/domain/idMeta; not another compatibility key. */\n arrayElementSafe?: boolean;\n}\n\n/**\n * Normalizes known PostgreSQL type synonyms without treating coercible types or user types as equal.\n * The output compatibility checks compare these names, so normalize only spellings of the same type.\n *\n * I.e. `integer` and `int` both mean `int4`; `integer[]` and `int4[]` also describe the same SQL type.\n * Keeping these spellings distinct would reject compatible outputs just because their serdes use\n * different names for the same representation.\n *\n * I.e. `int4` can be promoted to `int8`, but they are not synonyms: classic pg returns int4 as a number\n * and int8 as a string. Treating them as equal could admit a compound whose first operand's decoder\n * cannot handle the common SQL type. This function does not choose or apply a conversion.\n *\n * I.e. `citext` must stay distinct from `text`: they disagree on whether 'Alice' and 'alice' are equal,\n * which matters when a set operation compares rows. A user-defined `app.email` domain over text can\n * also impose constraints that text does not. Unknown names remain unchanged, including their schema\n * and quoting; neither coercibility nor a shared base type proves that their outputs are compatible.\n */\nexport function canonicalDbType(dbType: string): string {\n if (dbType.endsWith(\"[]\")) return `${canonicalDbType(dbType.slice(0, -2))}[]`;\n switch (dbType) {\n case \"smallint\":\n return \"int2\";\n case \"int\":\n case \"integer\":\n return \"int4\";\n case \"bigint\":\n return \"int8\";\n case \"decimal\":\n return \"numeric\";\n case \"real\":\n return \"float4\";\n case \"double precision\":\n return \"float8\";\n case \"boolean\":\n return \"bool\";\n case \"character varying\":\n return \"varchar\";\n case \"character\":\n return \"bpchar\";\n case \"timestamp without time zone\":\n return \"timestamp\";\n case \"timestamp with time zone\":\n return \"timestamptz\";\n case \"time without time zone\":\n return \"time\";\n case \"time with time zone\":\n return \"timetz\";\n default:\n return dbType;\n }\n}\n\nconst arrayDomains = new Map<unknown, Map<EntityMetadata | undefined, symbol>>();\n\n// Both classic pg and lazy binary reads decode these physical arrays, not an unparsed array string.\nconst arrayElementDbTypes = new Set([\n \"bool\",\n \"bytea\",\n \"int2\",\n \"int4\",\n \"int8\",\n \"float4\",\n \"float8\",\n \"numeric\",\n \"text\",\n \"varchar\",\n \"bpchar\",\n \"uuid\",\n \"json\",\n \"jsonb\",\n]);\n\n/**\n * Describes elementwise conversion only for known physical array parsers and stable domain conversion.\n *\n * I.e. `a.id.arrayAgg()` wraps Author's tag and `idMeta` in its domain token, but has no scalar\n * `idMeta` of its own. Repeated expressions share the token; IDs of subtypes with a shared tag do not.\n * Native enum/citext, date/time, and nested SQL arrays remain unknown. Numeric elements can be numbers\n * in classic pg and strings in lazy binary reads, so a scalar string-only mapper is not sufficient.\n */\nexport function arrayOutputType(outputType: TypeInfo | undefined): TypeInfo | undefined {\n if (!outputType?.arrayElementSafe || !arrayElementDbTypes.has(outputType.dbType)) return undefined;\n let domains = arrayDomains.get(outputType.domain);\n if (!domains) arrayDomains.set(outputType.domain, (domains = new Map()));\n let domain = domains.get(outputType.idMeta);\n if (!domain) domains.set(outputType.idMeta, (domain = Symbol(\"joist.arrayOutput\")));\n return { dbType: `${outputType.dbType}[]`, domain };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA8CA,SAAgB,gBAAgB,QAAwB;CACtD,IAAI,OAAO,SAAS,IAAI,GAAG,OAAO,GAAG,gBAAgB,OAAO,MAAM,GAAG,EAAE,CAAC,EAAE;CAC1E,QAAQ,QAAR;EACE,KAAK,YACH,OAAO;EACT,KAAK;EACL,KAAK,WACH,OAAO;EACT,KAAK,UACH,OAAO;EACT,KAAK,WACH,OAAO;EACT,KAAK,QACH,OAAO;EACT,KAAK,oBACH,OAAO;EACT,KAAK,WACH,OAAO;EACT,KAAK,qBACH,OAAO;EACT,KAAK,aACH,OAAO;EACT,KAAK,+BACH,OAAO;EACT,KAAK,4BACH,OAAO;EACT,KAAK,0BACH,OAAO;EACT,KAAK,uBACH,OAAO;EACT,SACE,OAAO;CACX;AACF;AAEA,MAAM,+BAAe,IAAI,IAAsD;AAG/E,MAAM,sCAAsB,IAAI,IAAI;CAClC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;;;;;;;;AAUD,SAAgB,gBAAgB,YAAwD;CACtF,IAAI,CAAC,YAAY,oBAAoB,CAAC,oBAAoB,IAAI,WAAW,MAAM,GAAG,OAAO,KAAA;CACzF,IAAI,UAAU,aAAa,IAAI,WAAW,MAAM;CAChD,IAAI,CAAC,SAAS,aAAa,IAAI,WAAW,QAAS,0BAAU,IAAI,IAAI,CAAE;CACvE,IAAI,SAAS,QAAQ,IAAI,WAAW,MAAM;CAC1C,IAAI,CAAC,QAAQ,QAAQ,IAAI,WAAW,QAAS,SAAS,OAAO,mBAAmB,CAAE;CAClF,OAAO;EAAE,QAAQ,GAAG,WAAW,OAAO;EAAK;CAAO;AACpD"}
|
package/build/columns.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"columns.cjs","names":[],"sources":["../src/columns.ts"],"sourcesContent":["// These must be erased imports: descriptors are loaded before entity metadata and relation classes.\nimport type { EntityMetadata } from \"./EntityMetadata.ts\";\nimport type { ScalarCodec } from \"./serde.ts\";\nimport type { TypeInfo } from \"./TypeInfo.ts\";\n\n/** A physical column owns one scalar codec, shared with every field binding for that column. */\nexport class Column {\n readonly insert: \"required\" | \"optional\" | \"never\";\n readonly update: boolean;\n /** Physical storage and SQL write policy, independent of domain field requiredness and defaults. */\n constructor(\n readonly columnName: string,\n readonly sqlNullable: boolean,\n readonly hasDefault: boolean,\n readonly isGenerated: boolean,\n /** ORM-maintained timestamps can be omitted by the SQL API as well. */\n readonly insertOptional: boolean,\n /** Polymorphic components are readable, but direct mutations remain unsupported. */\n readonly writable: boolean,\n readonly idMetadata: (() => EntityMetadata) | undefined,\n readonly codec: ScalarCodec,\n ) {\n const primaryKey = columnName === \"id\";\n this.insert =\n isGenerated || writable === false\n ? \"never\"\n : sqlNullable || hasDefault || insertOptional || (primaryKey && [\"int\", \"bigint\"].includes(codec.dbType))\n ? \"optional\"\n : \"required\";\n this.update = !primaryKey && !isGenerated && writable !== false;\n }\n\n get dbType(): string {\n return this.codec.dbType;\n }\n get isArray(): boolean {\n return this.codec.isArray;\n }\n get isNullableArray(): boolean {\n return this.codec.isArray && this.sqlNullable;\n }\n\n /** Resolve ID metadata only after all generated entity modules have initialized. */\n get outputType(): TypeInfo | undefined {\n const output = this.codec.outputType;\n if (!this.idMetadata) return output;\n // Scalar ID evidence must never be attached to an array domain or an unknown replacement codec.\n return output && !this.codec.isArray && !output.dbType.endsWith(\"[]\")\n ? { ...output, idMeta: this.idMetadata() }\n : undefined;\n }\n\n mapToDb(value: any): any {\n return this.codec.mapToDb(value);\n }\n mapToDbValue(value: unknown): unknown {\n return this.codec.mapToDbValue!(value);\n }\n mapFromDb(value: unknown): unknown {\n return this.codec.mapFromDb(value);\n }\n mapFromJsonAgg(value: any): any {\n return this.codec.mapFromJsonAgg(value);\n }\n}\n\nexport type ColumnDescriptors = Record<string, Column>;\n"],"mappings":";;;AAMA,IAAa,SAAb,MAAoB;CAKP;CACA;CACA;CACA;CAEA;CAEA;CACA;CACA;CAbX;CACA;;CAEA,YACE,YACA,aACA,YACA,aAEA,gBAEA,UACA,YACA,OACA;EAVS,KAAA,aAAA;EACA,KAAA,cAAA;EACA,KAAA,aAAA;EACA,KAAA,cAAA;EAEA,KAAA,iBAAA;EAEA,KAAA,WAAA;EACA,KAAA,aAAA;EACA,KAAA,QAAA;EAET,MAAM,aAAa,eAAe;EAClC,KAAK,SACH,eAAe,aAAa,QACxB,UACA,eAAe,cAAc,kBAAmB,cAAc,CAAC,OAAO,QAAQ,CAAC,CAAC,SAAS,MAAM,MAAM,IACnG,aACA;EACR,KAAK,SAAS,CAAC,cAAc,CAAC,eAAe,aAAa;CAC5D;CAEA,IAAI,SAAiB;EACnB,OAAO,KAAK,MAAM;CACpB;CACA,IAAI,UAAmB;EACrB,OAAO,KAAK,MAAM;CACpB;CACA,IAAI,kBAA2B;EAC7B,OAAO,KAAK,MAAM,WAAW,KAAK;CACpC;;CAGA,IAAI,aAAmC;EACrC,MAAM,SAAS,KAAK,MAAM;EAC1B,IAAI,CAAC,KAAK,YAAY,OAAO;EAE7B,OAAO,UAAU,CAAC,KAAK,MAAM,WAAW,CAAC,OAAO,OAAO,SAAS,IAAI,IAChE;GAAE,GAAG;GAAQ,QAAQ,KAAK,WAAW;EAAE,IACvC,KAAA;CACN;CAEA,QAAQ,OAAiB;EACvB,OAAO,KAAK,MAAM,QAAQ,KAAK;CACjC;CACA,aAAa,OAAyB;EACpC,OAAO,KAAK,MAAM,aAAc,KAAK;CACvC;CACA,UAAU,OAAyB;EACjC,OAAO,KAAK,MAAM,UAAU,KAAK;CACnC;CACA,eAAe,OAAiB;EAC9B,OAAO,KAAK,MAAM,eAAe,KAAK;CACxC;AACF"}
|
package/build/columns.d.cts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"columns.d.cts","names":[],"sources":["../src/columns.ts"],"mappings":";;;;;cAMa;WAKA;WACA;WACA;WACA;;WAEA;;WAEA;WACA,mBAAmB;WACnB,OAAO;WAbT;WACA;;EAET,YACW,oBACA,sBACA,qBACA,sBAEA;;EAAA,yBAEA;;EAAA,mBACA,mBAAmB,6BACnB,OAAO;MAYd;MAGA;MAGA;;MAKA,cAAc;EASlB,QAAQ;EAGR,aAAa;EAGb,UAAU;EAGV,eAAe;;KAKL,oBAAoB,eAAe"}
|
package/build/columns.d.mts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"columns.d.mts","names":[],"sources":["../src/columns.ts"],"mappings":";;;;;cAMa;WAKA;WACA;WACA;WACA;;WAEA;;WAEA;WACA,mBAAmB;WACnB,OAAO;WAbT;WACA;;EAET,YACW,oBACA,sBACA,qBACA,sBAEA;;EAAA,yBAEA;;EAAA,mBACA,mBAAmB,6BACnB,OAAO;MAYd;MAGA;MAGA;;MAKA,cAAc;EASlB,QAAQ;EAGR,aAAa;EAGb,UAAU;EAGV,eAAe;;KAKL,oBAAoB,eAAe"}
|
package/build/columns.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"columns.js","names":[],"sources":["../src/columns.ts"],"sourcesContent":["// These must be erased imports: descriptors are loaded before entity metadata and relation classes.\nimport type { EntityMetadata } from \"./EntityMetadata.ts\";\nimport type { ScalarCodec } from \"./serde.ts\";\nimport type { TypeInfo } from \"./TypeInfo.ts\";\n\n/** A physical column owns one scalar codec, shared with every field binding for that column. */\nexport class Column {\n readonly insert: \"required\" | \"optional\" | \"never\";\n readonly update: boolean;\n /** Physical storage and SQL write policy, independent of domain field requiredness and defaults. */\n constructor(\n readonly columnName: string,\n readonly sqlNullable: boolean,\n readonly hasDefault: boolean,\n readonly isGenerated: boolean,\n /** ORM-maintained timestamps can be omitted by the SQL API as well. */\n readonly insertOptional: boolean,\n /** Polymorphic components are readable, but direct mutations remain unsupported. */\n readonly writable: boolean,\n readonly idMetadata: (() => EntityMetadata) | undefined,\n readonly codec: ScalarCodec,\n ) {\n const primaryKey = columnName === \"id\";\n this.insert =\n isGenerated || writable === false\n ? \"never\"\n : sqlNullable || hasDefault || insertOptional || (primaryKey && [\"int\", \"bigint\"].includes(codec.dbType))\n ? \"optional\"\n : \"required\";\n this.update = !primaryKey && !isGenerated && writable !== false;\n }\n\n get dbType(): string {\n return this.codec.dbType;\n }\n get isArray(): boolean {\n return this.codec.isArray;\n }\n get isNullableArray(): boolean {\n return this.codec.isArray && this.sqlNullable;\n }\n\n /** Resolve ID metadata only after all generated entity modules have initialized. */\n get outputType(): TypeInfo | undefined {\n const output = this.codec.outputType;\n if (!this.idMetadata) return output;\n // Scalar ID evidence must never be attached to an array domain or an unknown replacement codec.\n return output && !this.codec.isArray && !output.dbType.endsWith(\"[]\")\n ? { ...output, idMeta: this.idMetadata() }\n : undefined;\n }\n\n mapToDb(value: any): any {\n return this.codec.mapToDb(value);\n }\n mapToDbValue(value: unknown): unknown {\n return this.codec.mapToDbValue!(value);\n }\n mapFromDb(value: unknown): unknown {\n return this.codec.mapFromDb(value);\n }\n mapFromJsonAgg(value: any): any {\n return this.codec.mapFromJsonAgg(value);\n }\n}\n\nexport type ColumnDescriptors = Record<string, Column>;\n"],"mappings":";;AAMA,IAAa,SAAb,MAAoB;CAKP;CACA;CACA;CACA;CAEA;CAEA;CACA;CACA;CAbX;CACA;;CAEA,YACE,YACA,aACA,YACA,aAEA,gBAEA,UACA,YACA,OACA;EAVS,KAAA,aAAA;EACA,KAAA,cAAA;EACA,KAAA,aAAA;EACA,KAAA,cAAA;EAEA,KAAA,iBAAA;EAEA,KAAA,WAAA;EACA,KAAA,aAAA;EACA,KAAA,QAAA;EAET,MAAM,aAAa,eAAe;EAClC,KAAK,SACH,eAAe,aAAa,QACxB,UACA,eAAe,cAAc,kBAAmB,cAAc,CAAC,OAAO,QAAQ,CAAC,CAAC,SAAS,MAAM,MAAM,IACnG,aACA;EACR,KAAK,SAAS,CAAC,cAAc,CAAC,eAAe,aAAa;CAC5D;CAEA,IAAI,SAAiB;EACnB,OAAO,KAAK,MAAM;CACpB;CACA,IAAI,UAAmB;EACrB,OAAO,KAAK,MAAM;CACpB;CACA,IAAI,kBAA2B;EAC7B,OAAO,KAAK,MAAM,WAAW,KAAK;CACpC;;CAGA,IAAI,aAAmC;EACrC,MAAM,SAAS,KAAK,MAAM;EAC1B,IAAI,CAAC,KAAK,YAAY,OAAO;EAE7B,OAAO,UAAU,CAAC,KAAK,MAAM,WAAW,CAAC,OAAO,OAAO,SAAS,IAAI,IAChE;GAAE,GAAG;GAAQ,QAAQ,KAAK,WAAW;EAAE,IACvC,KAAA;CACN;CAEA,QAAQ,OAAiB;EACvB,OAAO,KAAK,MAAM,QAAQ,KAAK;CACjC;CACA,aAAa,OAAyB;EACpC,OAAO,KAAK,MAAM,aAAc,KAAK;CACvC;CACA,UAAU,OAAyB;EACjC,OAAO,KAAK,MAAM,UAAU,KAAK;CACnC;CACA,eAAe,OAAiB;EAC9B,OAAO,KAAK,MAAM,eAAe,KAAK;CACxC;AACF"}
|
package/build/driverApi.cjs
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
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_drivers_EntityWriter = require("./drivers/EntityWriter.cjs");
|
|
6
|
-
//#region src/driverApi.ts
|
|
7
|
-
const driverApi = {
|
|
8
|
-
buildValuesCte: require("./dataloaders/findDataLoader.cjs").buildValuesCte,
|
|
9
|
-
generateOps: require_drivers_EntityWriter.generateOps,
|
|
10
|
-
buildCteSql: require_queries_find_buildFindQuery.buildCteSql,
|
|
11
|
-
getRuntimeConfig: require_runtimeConfig.getRuntimeConfig,
|
|
12
|
-
batched: require_utils.batched,
|
|
13
|
-
cleanSql: require_utils.cleanSql
|
|
14
|
-
};
|
|
15
|
-
//#endregion
|
|
16
|
-
exports.driverApi = driverApi;
|
|
17
|
-
|
|
18
|
-
//# sourceMappingURL=driverApi.cjs.map
|
package/build/driverApi.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"driverApi.cjs","names":[],"sources":["../src/driverApi.ts"],"sourcesContent":["import { buildValuesCte } from \"./dataloaders/findDataLoader.ts\";\nimport { type DeleteOp, type InsertOp, type UpdateOp, generateOps } from \"./drivers/EntityWriter.ts\";\nimport { buildCteSql } from \"./queries/find/buildFindQuery.ts\";\nimport { getRuntimeConfig } from \"./runtimeConfig.ts\";\nimport { batched, cleanSql } from \"./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,0DAAA,CAAA,CAAA;CACA,aAAA,6BAAA;CACA,aAAA,oCAAA;CACA,kBAAA,sBAAA;CACA,SAAA,cAAA;CACA,UAAA,cAAA;AACF"}
|
package/build/driverApi.d.cts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { batched, cleanSql } from "./utils.cjs";
|
|
2
|
-
import { DeleteOp, InsertOp, UpdateOp, generateOps } from "./drivers/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/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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"driverApi.d.cts","names":[],"sources":["../src/driverApi.ts"],"mappings":";;;;;;cAMa;;;;;;;;KASD;EACV,UAAU;EACV,UAAU;EACV,UAAU"}
|
package/build/driverApi.d.mts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { batched, cleanSql } from "./utils.mjs";
|
|
2
|
-
import { DeleteOp, InsertOp, UpdateOp, generateOps } from "./drivers/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/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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"driverApi.d.mts","names":[],"sources":["../src/driverApi.ts"],"mappings":";;;;;;cAMa;;;;;;;;KASD;EACV,UAAU;EACV,UAAU;EACV,UAAU"}
|
package/build/driverApi.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { batched, cleanSql } from "./utils.js";
|
|
2
|
-
import { getRuntimeConfig } from "./runtimeConfig.js";
|
|
3
|
-
import { buildCteSql } from "./queries/find/buildFindQuery.js";
|
|
4
|
-
import { generateOps } from "./drivers/EntityWriter.js";
|
|
5
|
-
import { buildValuesCte } from "./dataloaders/findDataLoader.js";
|
|
6
|
-
//#region src/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
|
package/build/driverApi.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"driverApi.js","names":[],"sources":["../src/driverApi.ts"],"sourcesContent":["import { buildValuesCte } from \"./dataloaders/findDataLoader.ts\";\nimport { type DeleteOp, type InsertOp, type UpdateOp, generateOps } from \"./drivers/EntityWriter.ts\";\nimport { buildCteSql } from \"./queries/find/buildFindQuery.ts\";\nimport { getRuntimeConfig } from \"./runtimeConfig.ts\";\nimport { batched, cleanSql } from \"./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/fieldSerde.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fieldSerde.cjs","names":["isEntity","getMetadata","maybeResolveReferenceToId","getConstructorFromTaggedId","groupBy","getBaseMeta"],"sources":["../src/fieldSerde.ts"],"sourcesContent":["import type { Column } from \"./columns.ts\";\nimport { getConstructorFromTaggedId } from \"./configure.ts\";\nimport type { InsertFixup } from \"./drivers/EntityWriter.ts\";\nimport { type Entity, isEntity } from \"./Entity.ts\";\nimport {\n type EntityMetadata,\n type Field,\n type PolymorphicField,\n type PolymorphicFieldComponent,\n type SerdeField,\n getBaseMeta,\n getMetadata,\n} from \"./EntityMetadata.ts\";\nimport { maybeResolveReferenceToId } from \"./keys.ts\";\nimport type { RowData } from \"./RowData.ts\";\nimport type { TimestampCodec } from \"./serde.ts\";\nimport { groupBy } from \"./utils.ts\";\n\nexport function hasSerde(field: Field): field is SerdeField {\n return !!field.serde;\n}\n\n/** Entity hydration and flush bindings; a polymorphic relationship spans several physical columns. */\nexport interface FieldSerde {\n columns: FieldColumn[];\n /** Decode one domain value from accessed cells; callers own entity assignment and caching. */\n fromRow(rowData: RowData, rowIndex: number): unknown;\n}\n\nexport interface TimestampSerde<T> extends FieldSerde {\n mapFromNow(now: Date): T;\n dbValue(data: any): any;\n}\n\n/** Binds a physical column to entity data without adding a second codec or storage declaration. */\nexport class FieldColumn {\n constructor(\n readonly fieldName: string,\n readonly column: Column,\n ) {}\n get codec() {\n return this.column.codec;\n }\n get insertOptional() {\n return this.column.insertOptional;\n }\n get writable() {\n return this.column.writable;\n }\n get insert() {\n return this.column.insert;\n }\n get update() {\n return this.column.update;\n }\n get idMetadata() {\n return this.column.idMetadata;\n }\n get columnName(): string {\n return this.column.columnName;\n }\n get dbType(): string {\n return this.column.dbType;\n }\n get isArray(): boolean {\n return this.column.isArray;\n }\n get isNullableArray(): boolean {\n return this.column.isNullableArray;\n }\n get sqlNullable(): boolean {\n return this.column.sqlNullable;\n }\n get hasDefault(): boolean {\n return this.column.hasDefault;\n }\n get isGenerated(): boolean {\n return this.column.isGenerated;\n }\n get outputType() {\n return this.column.outputType;\n }\n mapToDb(value: any): any {\n return this.column.mapToDb(value);\n }\n mapToDbValue(value: unknown): unknown {\n return this.column.mapToDbValue(value);\n }\n mapFromDb(value: unknown): unknown {\n return this.column.mapFromDb(value);\n }\n mapFromJsonAgg(value: any): any {\n return this.column.mapFromJsonAgg(value);\n }\n\n /** Defers FK writes whose new target must be inserted after this entity. */\n dbValue(data: any, entity: Entity, tableName: string, fixups: InsertFixup[] | undefined): any {\n const value = data[this.fieldName];\n if (\n this.column.idMetadata &&\n fixups &&\n isEntity(value) &&\n value.isNewEntity &&\n getMetadata(value).nonDeferredFkOrder &&\n getMetadata(entity).nonDeferredFkOrder &&\n getMetadata(value).nonDeferredFkOrder! >= getMetadata(entity).nonDeferredFkOrder!\n ) {\n fixups.push({ entity, tableName, column: this, value: this.mapToDbValue(maybeResolveReferenceToId(value)) });\n return null;\n }\n return this.mapToDbValue(value);\n }\n\n /** Reconstruct the driver's row representation, which can differ from write bindings for Date and JSON. */\n rowValue(data: any): any {\n return this.column.codec.mapToRow(data[this.fieldName]);\n }\n}\n\n/** Binds one entity field to its physical column. */\nexport class SimpleFieldSerde extends FieldColumn implements FieldSerde {\n readonly columns: FieldColumn[] = [this];\n /** Decode this field's physical column without changing entity data. */\n fromRow(rowData: RowData, rowIndex: number): unknown {\n return this.column.mapFromDb(rowData.get(rowIndex, this.column.columnName));\n }\n mapFromNow(now: Date): unknown {\n return (this.column.codec as TimestampCodec<unknown>).mapFromNow(now);\n }\n}\n\n/** A polymorphic field selects exactly one component while each physical column retains a scalar ID codec. */\nexport class PolymorphicKeySerde implements FieldSerde {\n readonly columns: PolymorphicFieldColumn[];\n constructor(\n readonly fieldName: string,\n components: PolymorphicFieldComponent[],\n ) {\n this.columns = components.map((component) => new PolymorphicFieldColumn(fieldName, component, components));\n }\n /** Select the first truthy component whose decoded ID is not nullish. */\n fromRow(rowData: RowData, rowIndex: number): unknown {\n let decoded: unknown;\n for (const column of this.columns) {\n const value = rowData.get(rowIndex, column.columnName);\n if (value) {\n decoded = column.mapFromDb(value);\n if (decoded != null) return decoded;\n }\n }\n return decoded;\n }\n}\n\n/** Shares domain components between relationship traversal and entity write selection. */\nexport function polymorphicField(\n fieldName: string,\n required: boolean,\n components: PolymorphicFieldComponent[],\n): PolymorphicField {\n return {\n kind: \"poly\",\n fieldName,\n fieldIdName: `${fieldName}Id`,\n required,\n components,\n serde: new PolymorphicKeySerde(fieldName, components),\n immutable: false,\n };\n}\n\n/** A domain relationship component references storage and only overrides a specialized domain target. */\nexport class PolyComponent implements PolymorphicFieldComponent {\n constructor(\n readonly column: Column,\n readonly otherFieldName: string,\n private readonly target?: () => EntityMetadata,\n ) {}\n get columnName(): string {\n return this.column.columnName;\n }\n get otherMetadata(): () => EntityMetadata {\n return this.target ?? this.column.idMetadata!;\n }\n}\n\n/** Selects a relationship component for entity writes only; direct SQL writes use its scalar column codec. */\nclass PolymorphicFieldColumn extends FieldColumn {\n constructor(\n fieldName: string,\n private readonly component: PolymorphicFieldComponent,\n private readonly components: PolymorphicFieldComponent[],\n ) {\n super(fieldName, component.column);\n }\n get otherMetadata() {\n return this.component.otherMetadata;\n }\n\n /** Preserve exact subtype selection when multiple components share a base type. */\n mapToDbValue(value: unknown): unknown {\n const id = maybeResolveReferenceToId(value as Parameters<typeof maybeResolveReferenceToId>[0]);\n const cstr = isEntity(value) ? getMetadata(value).cstr : id ? getConstructorFromTaggedId(id) : undefined;\n // If our poly has multiple components from the same base type, i.e.\n // `parent_small_publisher_id` and `parent_large_publisher_id`, then we\n // need slightly different logic...\n const hasMultipleComponentsWithSameBaseType = [\n ...groupBy(this.components, (component) => getBaseMeta(component.otherMetadata()).type).values(),\n ].some((group) => group.length > 1);\n const otherMeta = this.otherMetadata();\n // We'll have multiple columns, i.e. [parent_author_id, parent_book_id], and each column\n // will only return a value if the `id` matches its type, i.e. `parent_author_id=a:1` will\n // return 1, but `parent_book_id` will return null.\n const applies = hasMultipleComponentsWithSameBaseType\n ? cstr === otherMeta.cstr\n : cstr === otherMeta.cstr ||\n cstr === getBaseMeta(otherMeta).cstr ||\n otherMeta.subTypes.some((subTypeMeta) => cstr === subTypeMeta.cstr);\n return applies ? this.column.mapToDbValue(id) : undefined;\n }\n // Polymorphic writes historically do not schedule non-deferred FK fixups.\n dbValue(data: any): any {\n return this.mapToDbValue(data[this.fieldName]);\n }\n rowValue(data: any): any {\n return this.dbValue(data);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fieldSerde.d.cts","names":[],"sources":["../src/fieldSerde.ts"],"mappings":";;;;;;;;iBAkBgB,SAAS,OAAO,QAAQ,SAAS;;UAKhC;EACf,SAAS;;EAET,QAAQ,SAAS,SAAS;;UAGX,eAAe,WAAW;EACzC,WAAW,KAAK,OAAO;EACvB,QAAQ;;;cAIG;WAEA;WACA,QAAQ;EAFnB,YACW,mBACA,QAAQ;MAEf,SAFe;MAKf;MAGA;MAGA;MAGA;MAGA,qBAAU;MAGV;MAGA;MAGA;MAGA;MAGA;MAGA;MAGA;MAGA,cAxBU;EA2Bd,QAAQ;EAGR,aAAa;EAGb,UAAU;EAGV,eAAe;;EAKf,QAAQ,WAAW,QAAQ,QAAQ,mBAAmB,QAAQ;;EAkB9D,SAAS;;;cAME,yBAAyB,uBAAuB;WAClD,SAAS;;EAElB,QAAQ,SAAS,SAAS;EAG1B,WAAW,KAAK;;;cAML,+BAA+B;WAG/B;WAFF,SAAS;EAClB,YACW,mBACT,YAAY;;EAKd,QAAQ,SAAS,SAAS;;;iBAcZ,iBACd,mBACA,mBACA,YAAY,8BACX;;cAaU,yBAAyB;WAEzB,QAAQ;WACR;mBACQ;EAHnB,YACW,QAAQ,QACR,wBACQ,gBAAe;MAE9B;MAGA,uBAAuB;;;cAMvB,+BAA+B;mBAGhB;mBACA;EAHnB,YACE,mBACiB,WAAW,2BACX,YAAY;MAI3B,uBAAa;;EAKjB,aAAa;EAqBb,QAAQ;EAGR,SAAS"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fieldSerde.d.mts","names":[],"sources":["../src/fieldSerde.ts"],"mappings":";;;;;;;;iBAkBgB,SAAS,OAAO,QAAQ,SAAS;;UAKhC;EACf,SAAS;;EAET,QAAQ,SAAS,SAAS;;UAGX,eAAe,WAAW;EACzC,WAAW,KAAK,OAAO;EACvB,QAAQ;;;cAIG;WAEA;WACA,QAAQ;EAFnB,YACW,mBACA,QAAQ;MAEf,SAFe;MAKf;MAGA;MAGA;MAGA;MAGA,qBAAU;MAGV;MAGA;MAGA;MAGA;MAGA;MAGA;MAGA;MAGA,cAxBU;EA2Bd,QAAQ;EAGR,aAAa;EAGb,UAAU;EAGV,eAAe;;EAKf,QAAQ,WAAW,QAAQ,QAAQ,mBAAmB,QAAQ;;EAkB9D,SAAS;;;cAME,yBAAyB,uBAAuB;WAClD,SAAS;;EAElB,QAAQ,SAAS,SAAS;EAG1B,WAAW,KAAK;;;cAML,+BAA+B;WAG/B;WAFF,SAAS;EAClB,YACW,mBACT,YAAY;;EAKd,QAAQ,SAAS,SAAS;;;iBAcZ,iBACd,mBACA,mBACA,YAAY,8BACX;;cAaU,yBAAyB;WAEzB,QAAQ;WACR;mBACQ;EAHnB,YACW,QAAQ,QACR,wBACQ,gBAAe;MAE9B;MAGA,uBAAuB;;;cAMvB,+BAA+B;mBAGhB;mBACA;EAHnB,YACE,mBACiB,WAAW,2BACX,YAAY;MAI3B,uBAAa;;EAKjB,aAAa;EAqBb,QAAQ;EAGR,SAAS"}
|
package/build/fieldSerde.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fieldSerde.js","names":[],"sources":["../src/fieldSerde.ts"],"sourcesContent":["import type { Column } from \"./columns.ts\";\nimport { getConstructorFromTaggedId } from \"./configure.ts\";\nimport type { InsertFixup } from \"./drivers/EntityWriter.ts\";\nimport { type Entity, isEntity } from \"./Entity.ts\";\nimport {\n type EntityMetadata,\n type Field,\n type PolymorphicField,\n type PolymorphicFieldComponent,\n type SerdeField,\n getBaseMeta,\n getMetadata,\n} from \"./EntityMetadata.ts\";\nimport { maybeResolveReferenceToId } from \"./keys.ts\";\nimport type { RowData } from \"./RowData.ts\";\nimport type { TimestampCodec } from \"./serde.ts\";\nimport { groupBy } from \"./utils.ts\";\n\nexport function hasSerde(field: Field): field is SerdeField {\n return !!field.serde;\n}\n\n/** Entity hydration and flush bindings; a polymorphic relationship spans several physical columns. */\nexport interface FieldSerde {\n columns: FieldColumn[];\n /** Decode one domain value from accessed cells; callers own entity assignment and caching. */\n fromRow(rowData: RowData, rowIndex: number): unknown;\n}\n\nexport interface TimestampSerde<T> extends FieldSerde {\n mapFromNow(now: Date): T;\n dbValue(data: any): any;\n}\n\n/** Binds a physical column to entity data without adding a second codec or storage declaration. */\nexport class FieldColumn {\n constructor(\n readonly fieldName: string,\n readonly column: Column,\n ) {}\n get codec() {\n return this.column.codec;\n }\n get insertOptional() {\n return this.column.insertOptional;\n }\n get writable() {\n return this.column.writable;\n }\n get insert() {\n return this.column.insert;\n }\n get update() {\n return this.column.update;\n }\n get idMetadata() {\n return this.column.idMetadata;\n }\n get columnName(): string {\n return this.column.columnName;\n }\n get dbType(): string {\n return this.column.dbType;\n }\n get isArray(): boolean {\n return this.column.isArray;\n }\n get isNullableArray(): boolean {\n return this.column.isNullableArray;\n }\n get sqlNullable(): boolean {\n return this.column.sqlNullable;\n }\n get hasDefault(): boolean {\n return this.column.hasDefault;\n }\n get isGenerated(): boolean {\n return this.column.isGenerated;\n }\n get outputType() {\n return this.column.outputType;\n }\n mapToDb(value: any): any {\n return this.column.mapToDb(value);\n }\n mapToDbValue(value: unknown): unknown {\n return this.column.mapToDbValue(value);\n }\n mapFromDb(value: unknown): unknown {\n return this.column.mapFromDb(value);\n }\n mapFromJsonAgg(value: any): any {\n return this.column.mapFromJsonAgg(value);\n }\n\n /** Defers FK writes whose new target must be inserted after this entity. */\n dbValue(data: any, entity: Entity, tableName: string, fixups: InsertFixup[] | undefined): any {\n const value = data[this.fieldName];\n if (\n this.column.idMetadata &&\n fixups &&\n isEntity(value) &&\n value.isNewEntity &&\n getMetadata(value).nonDeferredFkOrder &&\n getMetadata(entity).nonDeferredFkOrder &&\n getMetadata(value).nonDeferredFkOrder! >= getMetadata(entity).nonDeferredFkOrder!\n ) {\n fixups.push({ entity, tableName, column: this, value: this.mapToDbValue(maybeResolveReferenceToId(value)) });\n return null;\n }\n return this.mapToDbValue(value);\n }\n\n /** Reconstruct the driver's row representation, which can differ from write bindings for Date and JSON. */\n rowValue(data: any): any {\n return this.column.codec.mapToRow(data[this.fieldName]);\n }\n}\n\n/** Binds one entity field to its physical column. */\nexport class SimpleFieldSerde extends FieldColumn implements FieldSerde {\n readonly columns: FieldColumn[] = [this];\n /** Decode this field's physical column without changing entity data. */\n fromRow(rowData: RowData, rowIndex: number): unknown {\n return this.column.mapFromDb(rowData.get(rowIndex, this.column.columnName));\n }\n mapFromNow(now: Date): unknown {\n return (this.column.codec as TimestampCodec<unknown>).mapFromNow(now);\n }\n}\n\n/** A polymorphic field selects exactly one component while each physical column retains a scalar ID codec. */\nexport class PolymorphicKeySerde implements FieldSerde {\n readonly columns: PolymorphicFieldColumn[];\n constructor(\n readonly fieldName: string,\n components: PolymorphicFieldComponent[],\n ) {\n this.columns = components.map((component) => new PolymorphicFieldColumn(fieldName, component, components));\n }\n /** Select the first truthy component whose decoded ID is not nullish. */\n fromRow(rowData: RowData, rowIndex: number): unknown {\n let decoded: unknown;\n for (const column of this.columns) {\n const value = rowData.get(rowIndex, column.columnName);\n if (value) {\n decoded = column.mapFromDb(value);\n if (decoded != null) return decoded;\n }\n }\n return decoded;\n }\n}\n\n/** Shares domain components between relationship traversal and entity write selection. */\nexport function polymorphicField(\n fieldName: string,\n required: boolean,\n components: PolymorphicFieldComponent[],\n): PolymorphicField {\n return {\n kind: \"poly\",\n fieldName,\n fieldIdName: `${fieldName}Id`,\n required,\n components,\n serde: new PolymorphicKeySerde(fieldName, components),\n immutable: false,\n };\n}\n\n/** A domain relationship component references storage and only overrides a specialized domain target. */\nexport class PolyComponent implements PolymorphicFieldComponent {\n constructor(\n readonly column: Column,\n readonly otherFieldName: string,\n private readonly target?: () => EntityMetadata,\n ) {}\n get columnName(): string {\n return this.column.columnName;\n }\n get otherMetadata(): () => EntityMetadata {\n return this.target ?? this.column.idMetadata!;\n }\n}\n\n/** Selects a relationship component for entity writes only; direct SQL writes use its scalar column codec. */\nclass PolymorphicFieldColumn extends FieldColumn {\n constructor(\n fieldName: string,\n private readonly component: PolymorphicFieldComponent,\n private readonly components: PolymorphicFieldComponent[],\n ) {\n super(fieldName, component.column);\n }\n get otherMetadata() {\n return this.component.otherMetadata;\n }\n\n /** Preserve exact subtype selection when multiple components share a base type. */\n mapToDbValue(value: unknown): unknown {\n const id = maybeResolveReferenceToId(value as Parameters<typeof maybeResolveReferenceToId>[0]);\n const cstr = isEntity(value) ? getMetadata(value).cstr : id ? getConstructorFromTaggedId(id) : undefined;\n // If our poly has multiple components from the same base type, i.e.\n // `parent_small_publisher_id` and `parent_large_publisher_id`, then we\n // need slightly different logic...\n const hasMultipleComponentsWithSameBaseType = [\n ...groupBy(this.components, (component) => getBaseMeta(component.otherMetadata()).type).values(),\n ].some((group) => group.length > 1);\n const otherMeta = this.otherMetadata();\n // We'll have multiple columns, i.e. [parent_author_id, parent_book_id], and each column\n // will only return a value if the `id` matches its type, i.e. `parent_author_id=a:1` will\n // return 1, but `parent_book_id` will return null.\n const applies = hasMultipleComponentsWithSameBaseType\n ? cstr === otherMeta.cstr\n : cstr === otherMeta.cstr ||\n cstr === getBaseMeta(otherMeta).cstr ||\n otherMeta.subTypes.some((subTypeMeta) => cstr === subTypeMeta.cstr);\n return applies ? this.column.mapToDbValue(id) : undefined;\n }\n // Polymorphic writes historically do not schedule non-deferred FK fixups.\n dbValue(data: any): any {\n return this.mapToDbValue(data[this.fieldName]);\n }\n rowValue(data: any): any {\n return this.dbValue(data);\n }\n}\n"],"mappings":"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"}
|
package/build/loadHints.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"loadHints.cjs","names":["getRelationFromMaybePolyKey"],"sources":["../src/loadHints.ts"],"sourcesContent":["import { type Entity } from \"./Entity.ts\";\nimport { type NormalizeHint } from \"./normalizeHints.ts\";\nimport { getRelationFromMaybePolyKey } from \"./reactiveHints.ts\";\nimport {\n type AsyncMethod,\n type Collection,\n type EnumCollection,\n type LoadedCollection,\n type LoadedEnumCollection,\n type LoadedMethod,\n type LoadedProperty,\n type LoadedReadOnlyCollection,\n type LoadedReference,\n type OneToOneReference,\n type Property,\n type ReadOnlyCollection,\n type Reference,\n type Relation,\n} from \"./relations/index.ts\";\nimport { type LoadedOneToOneReference } from \"./relations/OneToOneReference.ts\";\nimport { type OptsOf } from \"./typeMap.ts\";\nimport { type MaybePromise, type NullOrDefinedOr, fail } from \"./utils.ts\";\n\nconst deepLoad = Symbol();\ntype DeepLoadHint<T extends Entity> = NestedLoadHint<T> & { [deepLoad]: true };\n\n// Use any to correctly handle subtype/base type load hints.\n//\n// If a load hint is typed as `LoadHint<SmallPublisher, \"authors\">`, but the property\n// is actually `Publisher.authors`, if we do `P extends LoadedCollection<SmallPublisher, ...>`\n// the `SmallPublisher !== Publisher`, so the `authors` property doesn't match, and then\n// we drop the rest of the nested load hint.\n//\n// But if we check `P extends LoadedCollection<any, ...>` it works.\ntype MaybeBaseType = any;\n\n/** Marks a given `T[K]` field as the loaded/synchronous version of the collection. */\nexport type MarkLoaded<T extends Entity, P, UH = {}> =\n P extends EnumCollection<MaybeBaseType, infer E>\n ? LoadedEnumCollection<T, E>\n : P extends OneToOneReference<MaybeBaseType, infer U>\n ? LoadedOneToOneReference<T, Loaded<U, UH>>\n : P extends Reference<MaybeBaseType, infer U, infer N>\n ? LoadedReference<T, Loaded<U, UH>, N>\n : P extends Collection<MaybeBaseType, infer U>\n ? LoadedCollection<T, Loaded<U, UH>>\n : P extends ReadOnlyCollection<MaybeBaseType, infer U>\n ? LoadedReadOnlyCollection<T, Loaded<U, UH>>\n : P extends Property<MaybeBaseType, infer V>\n ? // prettier-ignore\n [V] extends [(infer U extends Entity) | undefined]\n ? LoadedProperty<T, Loaded<U, UH> | Exclude<V, U>>\n : V extends readonly (infer U extends Entity)[]\n ? LoadedProperty<T, Loaded<U, UH>[]>\n : LoadedProperty<T, V>\n : P extends AsyncMethod<T, infer A, infer V>\n ? LoadedMethod<T, A, V>\n : unknown;\n\n/** A version of MarkLoaded the uses `DeepLoadHint` for tests. */\ntype MarkDeepLoaded<T extends Entity, P> =\n P extends EnumCollection<MaybeBaseType, infer E>\n ? LoadedEnumCollection<T, E>\n : P extends OneToOneReference<MaybeBaseType, infer U>\n ? LoadedOneToOneReference<T, Loaded<U, DeepLoadHint<U>>>\n : P extends Reference<MaybeBaseType, infer U, infer N>\n ? LoadedReference<T, Loaded<U, DeepLoadHint<U>>, N>\n : P extends Collection<MaybeBaseType, infer U>\n ? LoadedCollection<T, Loaded<U, DeepLoadHint<U>>>\n : P extends ReadOnlyCollection<MaybeBaseType, infer U>\n ? LoadedReadOnlyCollection<T, Loaded<U, DeepLoadHint<U>>>\n : P extends Property<MaybeBaseType, infer V>\n ? // prettier-ignore\n [V] extends [(infer U extends Entity) | undefined]\n ? LoadedProperty<T, Loaded<U, DeepLoadHint<U>> | Exclude<V, U>>\n : V extends readonly (infer U extends Entity)[]\n ? LoadedProperty<T, Loaded<U, DeepLoadHint<U>>[]>\n : LoadedProperty<T, V>\n : P extends AsyncMethod<T, infer A, infer V>\n ? LoadedMethod<T, A, V>\n : unknown;\n\n/**\n * A helper type for `New` that marks every `Reference` and `LoadedCollection` in `T` as loaded.\n *\n * We also look in opts `O` for the \"`U`\" type, i.e. the next level up/down in the graph,\n * because the call site's opts may be using an also-marked loaded parent/child as an opt,\n * so this will infer the type of that parent/child and use that for the `U` type.\n *\n * This means things like `entity.parent.get.grandParent.get` will work on the resulting\n * type.\n *\n * Note that this is also purposefully broken out of `New` because of some weirdness\n * around type narrowing that wasn't working when inlined into `New`.\n */\ntype MaybeUseOptsType<T extends Entity, O, K extends keyof T & keyof O> =\n O[K] extends NullOrDefinedOr<infer OK>\n ? OK extends Entity\n ? T[K] extends OneToOneReference<T, infer U>\n ? LoadedOneToOneReference<T, U>\n : T[K] extends Reference<T, infer U, infer N>\n ? LoadedReference<T, OK, N>\n : never\n : OK extends Array<infer OU>\n ? OU extends Entity\n ? T[K] extends Collection<T, infer U>\n ? LoadedCollection<T, OU>\n : never\n : T[K]\n : T[K]\n : never;\n\n/**\n * Marks all references/collections of `T` as loaded, i.e. for newly instantiated entities where\n * we know there are no already-existing rows with fk's to this new entity in the database.\n *\n * `O` is the generic from the call site so that if the caller passes `{ author: SomeLoadedAuthor }`,\n * we'll prefer that type, as it might have more nested load hints that we can't otherwise assume.\n */\nexport type New<T extends Entity, O extends OptsOf<T> = OptsOf<T>> = T & {\n // K will be `keyof T` and `keyof O` for codegen'd relations, but custom relations\n // line `hasOneThrough` and `hasOneDerived` will not pass `keyof O` and so use the\n // `: MarkLoaded`.\n //\n // Note that the safest thing is to probably make this `: unknown` instead so that\n // custom relations are not marked loaded, b/c they will very likely require a `.load`\n // to work. However, we have some tests that currently expect `author.image.get` to work\n // on a new author, so keeping the `MarkLoaded` behavior for now.\n [K in keyof T]: K extends keyof O ? MaybeUseOptsType<T, O, K> : MarkLoaded<T, T[K]>;\n};\n\n/**\n * Marks all references/collections of `T` as deeply loaded, which is only useful for\n * tests where we can have \"the whole object graph\" in-memory.\n */\nexport type DeepNew<T extends Entity> = Loaded<T, DeepLoadHint<T>>;\n\n/** Detects whether an entity is newly created, and so we can treat all the relations as loaded. */\nexport function isNew<T extends Entity>(e: T): e is New<T> {\n return e.isNewEntity;\n}\n\n/**\n * All the loadable fields, i.e. relations or lazy-loaded/async properties, in an entity.\n *\n * We use a mapped type (instead of a code-generated type) so that we can pick up custom\n * fields that have be added to the entity classes, i.e. `Author.numberOfBooks2` async\n * properties.\n */\nexport type Loadable<T extends Entity> = {\n -readonly [K in keyof T as LoadableValue<T[K]> extends never ? never : K]: LoadableValue<T[K]>;\n};\n\n/**\n * Given an entity field/value, return the loadable entity.\n *\n * I.e. `Author.books` as a Reference or Collection, return `Book`.\n *\n * Note that we usually return entities, but for AsyncProperties it could be\n * a calculated primitive value like number or string.\n */\nexport type LoadableValue<V> =\n V extends EnumCollection<any, infer E>\n ? E\n : V extends Reference<any, infer U, any>\n ? U\n : V extends Collection<any, infer U>\n ? U\n : V extends ReadOnlyCollection<any, infer U>\n ? U\n : V extends AsyncMethod<any, any, infer V>\n ? V\n : V extends Property<any, infer P>\n ? // If the Property returns `Comment | undefined`, then we want to return `Comment`\n // prettier-ignore\n P extends (infer U extends Entity) | undefined ? U : P\n : never;\n\n/**\n * A load hint of a single key, multiple keys, or nested keys and sub-hints.\n *\n * Load hints are different from reactive hints in that load hints include only references,\n * collections, and async properties to preload (like `Book.author` or `Author.books`), and\n * do not include any primitive fields (like `Author.firstName`).\n */\nexport type LoadHint<T extends Entity> =\n | (keyof Loadable<T> & string)\n | ReadonlyArray<keyof Loadable<T> & string>\n | NestedLoadHint<T>;\n\nexport type NestedLoadHint<T extends Entity> = {\n // Don't filter out entity-loadable keys, because we need to support `{ numberOfBooks2: {} }`\n [K in keyof Loadable<T>]?: Loadable<T>[K] extends infer U extends Entity ? LoadHint<U> : {};\n};\n\n/** Given an entity `T` that is being populated with hints `H`, marks the `H` attributes as populated. */\nexport type Loaded<T extends Entity, H> = T & {\n [K in keyof T & keyof NormalizeHint<H>]: H extends DeepLoadHint<T>\n ? MarkDeepLoaded<T, T[K]>\n : MarkLoaded<T, T[K], NormalizeHint<H>[K]>;\n};\n\n/** Recursively checks if the relations from a load hint are loaded on an entity. */\nexport function isLoaded<T extends Entity, H extends LoadHint<T>>(entity: T, hint: H): entity is Loaded<T, H> {\n if (typeof hint === \"string\") {\n return (entity as any)[hint].isLoaded;\n } else if (Array.isArray(hint)) {\n for (const key of hint as string[]) {\n if (!(entity as any)[key].isLoaded) return false;\n }\n return true;\n } else if (typeof hint === \"object\") {\n for (const entry of Object.entries(hint as object)) {\n const [key, nestedHint] = entry;\n const relation = getRelationFromMaybePolyKey(entity, key);\n if (!relation || typeof relation.load !== \"function\") continue;\n if (relation.isLoaded) {\n const result = relation.get;\n if (Array.isArray(result)) {\n for (const entity of result) {\n if (!isLoaded(entity, nestedHint)) return false;\n }\n } else if (result && !isLoaded(result, nestedHint)) {\n return false;\n }\n } else {\n return false;\n }\n }\n return true;\n } else {\n throw new Error(`Unexpected hint ${hint}`);\n }\n}\n\n/**\n * Recursively checks if a relation-only populate hint is loaded on an entity.\n *\n * Unlike `isLoaded`, this returns `false` for non-loadable/primitive leaves instead of ignoring them, because\n * `ReactiveField.load` calls `em.populate` with load hints converted from reactive hints, i.e. `{ firstName: {} }`.\n * Treating those primitive leaves as loaded would let `EntityManager.populate` skip the batchloader path and change\n * reactive recalculation ordering, so the populate fast-path only applies to true relation populate hints.\n */\nexport function isLoadedForPopulate<T extends Entity, H extends LoadHint<T>>(\n entity: T,\n hint: H,\n): entity is Loaded<T, H> {\n if (typeof hint === \"string\") {\n const relation = getRelationFromMaybePolyKey(entity, hint);\n return !!relation && typeof relation.load === \"function\" && relation.isLoaded;\n } else if (Array.isArray(hint)) {\n for (const key of hint as string[]) {\n if (!isLoadedForPopulate(entity, key as H)) return false;\n }\n return true;\n } else if (typeof hint === \"object\") {\n for (const entry of Object.entries(hint as object)) {\n const [key, nestedHint] = entry;\n const relation = getRelationFromMaybePolyKey(entity, key);\n if (!relation || typeof relation.load !== \"function\" || !relation.isLoaded) return false;\n const result = relation.get;\n if (Array.isArray(result)) {\n for (const entity of result) {\n if (!isLoadedForPopulate(entity, nestedHint as LoadHint<typeof entity>)) return false;\n }\n } else if (result && !isLoadedForPopulate(result, nestedHint as LoadHint<typeof result>)) {\n return false;\n }\n }\n return true;\n } else {\n throw new Error(`Unexpected hint ${hint}`);\n }\n}\n\nexport function maybePopulateThen<T extends Entity, H extends LoadHint<T>, R>(\n entity: T,\n hint: H,\n fn: (loaded: Loaded<T, H>) => R,\n): MaybePromise<R> {\n return isLoaded(entity, hint) ? fn(entity) : (entity as any).populate(hint).then(fn);\n}\n\n/**\n * Runtime checks that `entity` has `hint` loaded, and type guards it as a `Loaded<T, hint>`.\n *\n * Similar to `ensureLoaded`, although `ensureLoaded` returns its value.\n */\nexport function assertLoaded<T extends Entity, const H extends LoadHint<T>>(\n entity: T,\n hint: H,\n): asserts entity is Loaded<T, H> {\n if (!isLoaded(entity, hint)) fail(`${entity.id} is not loaded for ${JSON.stringify(hint)}`);\n}\n\n/**\n * Runtime checks that `entity` has `hint` loaded, and returns it as a `Loaded<T, entity>`.\n *\n * Similar to `assertLoaded`, although `assertLoaded` is a boolean type guard.\n */\nexport function ensureLoaded<T extends Entity, const H extends LoadHint<T>>(entity: T, hint: H): Loaded<T, H> {\n assertLoaded<T, H>(entity, hint);\n return entity;\n}\n\n/**\n * Unsafe type check for `entity` to `hint`, *without* a runtime type check.\n *\n * You should only use this if you're extremely sure that entity has hint loaded.\n */\nexport function unsafeLoaded<T extends Entity, const H extends LoadHint<T>>(entity: T, hint: H): Loaded<T, H> {\n return entity as Loaded<T, H>;\n}\n\n/** From any `Relations` field in `T`, i.e. for loader hints. */\nexport type RelationsIn<T extends Entity> = SubType<T, Relation<any, any>>;\n\n// https://medium.com/dailyjs/typescript-create-a-condition-based-subset-types-9d902cea5b8c\ntype SubType<T, C> = Pick<T, { [K in keyof T]: T[K] extends C ? K : never }[keyof T]>;\n"],"mappings":";;;;;;;;;;AA0IA,SAAgB,MAAwB,GAAmB;CACzD,OAAO,EAAE;AACX;;AA+DA,SAAgB,SAAkD,QAAW,MAAiC;CAC5G,IAAI,OAAO,SAAS,UAClB,OAAQ,OAAe,KAAK,CAAC;MACxB,IAAI,MAAM,QAAQ,IAAI,GAAG;EAC9B,KAAK,MAAM,OAAO,MAChB,IAAI,CAAE,OAAe,IAAI,CAAC,UAAU,OAAO;EAE7C,OAAO;CACT,OAAO,IAAI,OAAO,SAAS,UAAU;EACnC,KAAK,MAAM,SAAS,OAAO,QAAQ,IAAc,GAAG;GAClD,MAAM,CAAC,KAAK,cAAc;GAC1B,MAAM,WAAWA,sBAAAA,4BAA4B,QAAQ,GAAG;GACxD,IAAI,CAAC,YAAY,OAAO,SAAS,SAAS,YAAY;GACtD,IAAI,SAAS,UAAU;IACrB,MAAM,SAAS,SAAS;IACxB,IAAI,MAAM,QAAQ,MAAM,GACjB;UAAA,MAAM,UAAU,QACnB,IAAI,CAAC,SAAS,QAAQ,UAAU,GAAG,OAAO;IAAA,OAEvC,IAAI,UAAU,CAAC,SAAS,QAAQ,UAAU,GAC/C,OAAO;GAEX,OACE,OAAO;EAEX;EACA,OAAO;CACT,OACE,MAAM,IAAI,MAAM,mBAAmB,MAAM;AAE7C;;;;;;;;;AAUA,SAAgB,oBACd,QACA,MACwB;CACxB,IAAI,OAAO,SAAS,UAAU;EAC5B,MAAM,WAAWA,sBAAAA,4BAA4B,QAAQ,IAAI;EACzD,OAAO,CAAC,CAAC,YAAY,OAAO,SAAS,SAAS,cAAc,SAAS;CACvE,OAAO,IAAI,MAAM,QAAQ,IAAI,GAAG;EAC9B,KAAK,MAAM,OAAO,MAChB,IAAI,CAAC,oBAAoB,QAAQ,GAAQ,GAAG,OAAO;EAErD,OAAO;CACT,OAAO,IAAI,OAAO,SAAS,UAAU;EACnC,KAAK,MAAM,SAAS,OAAO,QAAQ,IAAc,GAAG;GAClD,MAAM,CAAC,KAAK,cAAc;GAC1B,MAAM,WAAWA,sBAAAA,4BAA4B,QAAQ,GAAG;GACxD,IAAI,CAAC,YAAY,OAAO,SAAS,SAAS,cAAc,CAAC,SAAS,UAAU,OAAO;GACnF,MAAM,SAAS,SAAS;GACxB,IAAI,MAAM,QAAQ,MAAM,GACjB;SAAA,MAAM,UAAU,QACnB,IAAI,CAAC,oBAAoB,QAAQ,UAAqC,GAAG,OAAO;GAAA,OAE7E,IAAI,UAAU,CAAC,oBAAoB,QAAQ,UAAqC,GACrF,OAAO;EAEX;EACA,OAAO;CACT,OACE,MAAM,IAAI,MAAM,mBAAmB,MAAM;AAE7C;AAEA,SAAgB,kBACd,QACA,MACA,IACiB;CACjB,OAAO,SAAS,QAAQ,IAAI,IAAI,GAAG,MAAM,IAAK,OAAe,SAAS,IAAI,CAAC,CAAC,KAAK,EAAE;AACrF;;;;;;AAOA,SAAgB,aACd,QACA,MACgC;CAChC,IAAI,CAAC,SAAS,QAAQ,IAAI,GAAG,cAAA,KAAK,GAAG,OAAO,GAAG,qBAAqB,KAAK,UAAU,IAAI,GAAG;AAC5F;;;;;;AAOA,SAAgB,aAA4D,QAAW,MAAuB;CAC5G,aAAmB,QAAQ,IAAI;CAC/B,OAAO;AACT;;;;;;AAOA,SAAgB,aAA4D,QAAW,MAAuB;CAC5G,OAAO;AACT"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"loadHints.d.cts","names":[],"sources":["../src/loadHints.ts"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"loadHints.d.mts","names":[],"sources":["../src/loadHints.ts"],"mappings":";;;;;;;;;;;;;;cAuBM;KACD,aAAa,UAAU,UAAU,eAAe;GAAQ;;KAUxD;;KAGO,WAAW,UAAU,QAAQ,GAAG,WAC1C,UAAU,eAAe,qBAAqB,KAC1C,qBAAqB,GAAG,KACxB,UAAU,kBAAkB,qBAAqB,KAC/C,wBAAwB,GAAG,OAAO,GAAG,OACrC,UAAU,UAAU,qBAAqB,SAAS,KAChD,gBAAgB,GAAG,OAAO,GAAG,KAAK,KAClC,UAAU,WAAW,qBAAqB,KACxC,iBAAiB,GAAG,OAAO,GAAG,OAC9B,UAAU,mBAAmB,qBAAqB,KAChD,yBAAyB,GAAG,OAAO,GAAG,OACtC,UAAU,SAAS,qBAAqB,MAErC,mBAAmB,UAAU,uBACxC,eAAe,GAAG,OAAO,GAAG,MAAM,QAAQ,GAAG,MAC7C,0BAA0B,UAAU,YACpC,eAAe,GAAG,OAAO,GAAG,SAC5B,eAAe,GAAG,KACR,UAAU,YAAY,SAAS,SAAS,KACtC,aAAa,GAAG,GAAG;;KAIhC,eAAe,UAAU,QAAQ,KACpC,UAAU,eAAe,qBAAqB,KAC1C,qBAAqB,GAAG,KACxB,UAAU,kBAAkB,qBAAqB,KAC/C,wBAAwB,GAAG,OAAO,GAAG,aAAa,OAClD,UAAU,UAAU,qBAAqB,SAAS,KAChD,gBAAgB,GAAG,OAAO,GAAG,aAAa,KAAK,KAC/C,UAAU,WAAW,qBAAqB,KACxC,iBAAiB,GAAG,OAAO,GAAG,aAAa,OAC3C,UAAU,mBAAmB,qBAAqB,KAChD,yBAAyB,GAAG,OAAO,GAAG,aAAa,OACnD,UAAU,SAAS,qBAAqB,MAErC,mBAAmB,UAAU,uBACxC,eAAe,GAAG,OAAO,GAAG,aAAa,MAAM,QAAQ,GAAG,MAC1D,0BAA0B,UAAU,YACpC,eAAe,GAAG,OAAO,GAAG,aAAa,SACzC,eAAe,GAAG,KACR,UAAU,YAAY,SAAS,SAAS,KACtC,aAAa,GAAG,GAAG;;;;;;;;;;;;;;KAgBhC,iBAAiB,UAAU,QAAQ,GAAG,gBAAgB,UAAU,KACnE,EAAE,WAAW,sBAAsB,MAC/B,WAAW,SACT,EAAE,WAAW,kBAAkB,SAAS,KACtC,wBAAwB,GAAG,KAC3B,EAAE,WAAW,UAAU,SAAS,SAAS,KACvC,gBAAgB,GAAG,IAAI,aAE3B,WAAW,YAAY,MACrB,WAAW,SACT,EAAE,WAAW,WAAW,SAAS,KAC/B,iBAAiB,GAAG,cAEtB,EAAE,KACJ,EAAE;;;;;;;;KAUA,IAAI,UAAU,QAAQ,UAAU,OAAO,KAAK,OAAO,MAAM,OASlE,WAAW,IAAI,gBAAgB,IAAI,iBAAiB,GAAG,GAAG,KAAK,WAAW,GAAG,EAAE;;;;;KAOtE,QAAQ,UAAU,UAAU,OAAO,GAAG,aAAa;;iBAG/C,MAAM,UAAU,QAAQ,GAAG,IAAI,KAAK,IAAI;;;;;;;;KAW5C,SAAS,UAAU,uBAClB,WAAW,KAAK,cAAc,EAAE,4BAA4B,IAAI,cAAc,EAAE;;;;;;;;;KAWjF,cAAc,KACxB,UAAU,0BAA0B,KAChC,IACA,UAAU,qBAAqB,UAC7B,IACA,UAAU,sBAAsB,KAC9B,IACA,UAAU,8BAA8B,KACtC,IACA,UAAU,4BAA4B,KACpC,IACA,UAAU,oBAAoB,KAG5B,iBAAiB,UAAU,sBAAsB,IAAI;;;;;;;;KAUzD,SAAS,UAAU,iBACpB,SAAS,eAChB,oBAAoB,SAAS,eAC7B,eAAe;KAEP,eAAe,UAAU,aAElC,WAAW,SAAS,MAAM,SAAS,GAAG,kBAAiB,UAAU,UAAS,SAAS;;KAI1E,OAAO,UAAU,QAAQ,KAAK,OACvC,WAAW,UAAU,cAAc,KAAK,UAAU,aAAa,KAC5D,eAAe,GAAG,EAAE,MACpB,WAAW,GAAG,EAAE,IAAI,cAAc,GAAG;;iBAI3B,SAAS,UAAU,QAAQ,UAAU,SAAS,IAAI,QAAQ,GAAG,MAAM,IAAI,UAAU,OAAO,GAAG;;;;;;;;;iBAwC3F,oBAAoB,UAAU,QAAQ,UAAU,SAAS,IACvE,QAAQ,GACR,MAAM,IACL,UAAU,OAAO,GAAG;iBA6BP,kBAAkB,UAAU,QAAQ,UAAU,SAAS,IAAI,GACzE,QAAQ,GACR,MAAM,GACN,KAAK,QAAQ,OAAO,GAAG,OAAO,IAC7B,aAAa;;;;;;iBASA,aAAa,UAAU,cAAc,UAAU,SAAS,IACtE,QAAQ,GACR,MAAM,YACG,UAAU,OAAO,GAAG;;;;;;iBASf,aAAa,UAAU,cAAc,UAAU,SAAS,IAAI,QAAQ,GAAG,MAAM,IAAI,OAAO,GAAG;;;;;;iBAU3F,aAAa,UAAU,cAAc,UAAU,SAAS,IAAI,QAAQ,GAAG,MAAM,IAAI,OAAO,GAAG;;KAK/F,YAAY,UAAU,UAAU,QAAQ,GAAG;KAGlD,QAAQ,GAAG,KAAK,KAAK,MAAM,WAAW,IAAI,EAAE,WAAW,IAAI,mBAAkB"}
|
package/build/loadHints.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"loadHints.js","names":[],"sources":["../src/loadHints.ts"],"sourcesContent":["import { type Entity } from \"./Entity.ts\";\nimport { type NormalizeHint } from \"./normalizeHints.ts\";\nimport { getRelationFromMaybePolyKey } from \"./reactiveHints.ts\";\nimport {\n type AsyncMethod,\n type Collection,\n type EnumCollection,\n type LoadedCollection,\n type LoadedEnumCollection,\n type LoadedMethod,\n type LoadedProperty,\n type LoadedReadOnlyCollection,\n type LoadedReference,\n type OneToOneReference,\n type Property,\n type ReadOnlyCollection,\n type Reference,\n type Relation,\n} from \"./relations/index.ts\";\nimport { type LoadedOneToOneReference } from \"./relations/OneToOneReference.ts\";\nimport { type OptsOf } from \"./typeMap.ts\";\nimport { type MaybePromise, type NullOrDefinedOr, fail } from \"./utils.ts\";\n\nconst deepLoad = Symbol();\ntype DeepLoadHint<T extends Entity> = NestedLoadHint<T> & { [deepLoad]: true };\n\n// Use any to correctly handle subtype/base type load hints.\n//\n// If a load hint is typed as `LoadHint<SmallPublisher, \"authors\">`, but the property\n// is actually `Publisher.authors`, if we do `P extends LoadedCollection<SmallPublisher, ...>`\n// the `SmallPublisher !== Publisher`, so the `authors` property doesn't match, and then\n// we drop the rest of the nested load hint.\n//\n// But if we check `P extends LoadedCollection<any, ...>` it works.\ntype MaybeBaseType = any;\n\n/** Marks a given `T[K]` field as the loaded/synchronous version of the collection. */\nexport type MarkLoaded<T extends Entity, P, UH = {}> =\n P extends EnumCollection<MaybeBaseType, infer E>\n ? LoadedEnumCollection<T, E>\n : P extends OneToOneReference<MaybeBaseType, infer U>\n ? LoadedOneToOneReference<T, Loaded<U, UH>>\n : P extends Reference<MaybeBaseType, infer U, infer N>\n ? LoadedReference<T, Loaded<U, UH>, N>\n : P extends Collection<MaybeBaseType, infer U>\n ? LoadedCollection<T, Loaded<U, UH>>\n : P extends ReadOnlyCollection<MaybeBaseType, infer U>\n ? LoadedReadOnlyCollection<T, Loaded<U, UH>>\n : P extends Property<MaybeBaseType, infer V>\n ? // prettier-ignore\n [V] extends [(infer U extends Entity) | undefined]\n ? LoadedProperty<T, Loaded<U, UH> | Exclude<V, U>>\n : V extends readonly (infer U extends Entity)[]\n ? LoadedProperty<T, Loaded<U, UH>[]>\n : LoadedProperty<T, V>\n : P extends AsyncMethod<T, infer A, infer V>\n ? LoadedMethod<T, A, V>\n : unknown;\n\n/** A version of MarkLoaded the uses `DeepLoadHint` for tests. */\ntype MarkDeepLoaded<T extends Entity, P> =\n P extends EnumCollection<MaybeBaseType, infer E>\n ? LoadedEnumCollection<T, E>\n : P extends OneToOneReference<MaybeBaseType, infer U>\n ? LoadedOneToOneReference<T, Loaded<U, DeepLoadHint<U>>>\n : P extends Reference<MaybeBaseType, infer U, infer N>\n ? LoadedReference<T, Loaded<U, DeepLoadHint<U>>, N>\n : P extends Collection<MaybeBaseType, infer U>\n ? LoadedCollection<T, Loaded<U, DeepLoadHint<U>>>\n : P extends ReadOnlyCollection<MaybeBaseType, infer U>\n ? LoadedReadOnlyCollection<T, Loaded<U, DeepLoadHint<U>>>\n : P extends Property<MaybeBaseType, infer V>\n ? // prettier-ignore\n [V] extends [(infer U extends Entity) | undefined]\n ? LoadedProperty<T, Loaded<U, DeepLoadHint<U>> | Exclude<V, U>>\n : V extends readonly (infer U extends Entity)[]\n ? LoadedProperty<T, Loaded<U, DeepLoadHint<U>>[]>\n : LoadedProperty<T, V>\n : P extends AsyncMethod<T, infer A, infer V>\n ? LoadedMethod<T, A, V>\n : unknown;\n\n/**\n * A helper type for `New` that marks every `Reference` and `LoadedCollection` in `T` as loaded.\n *\n * We also look in opts `O` for the \"`U`\" type, i.e. the next level up/down in the graph,\n * because the call site's opts may be using an also-marked loaded parent/child as an opt,\n * so this will infer the type of that parent/child and use that for the `U` type.\n *\n * This means things like `entity.parent.get.grandParent.get` will work on the resulting\n * type.\n *\n * Note that this is also purposefully broken out of `New` because of some weirdness\n * around type narrowing that wasn't working when inlined into `New`.\n */\ntype MaybeUseOptsType<T extends Entity, O, K extends keyof T & keyof O> =\n O[K] extends NullOrDefinedOr<infer OK>\n ? OK extends Entity\n ? T[K] extends OneToOneReference<T, infer U>\n ? LoadedOneToOneReference<T, U>\n : T[K] extends Reference<T, infer U, infer N>\n ? LoadedReference<T, OK, N>\n : never\n : OK extends Array<infer OU>\n ? OU extends Entity\n ? T[K] extends Collection<T, infer U>\n ? LoadedCollection<T, OU>\n : never\n : T[K]\n : T[K]\n : never;\n\n/**\n * Marks all references/collections of `T` as loaded, i.e. for newly instantiated entities where\n * we know there are no already-existing rows with fk's to this new entity in the database.\n *\n * `O` is the generic from the call site so that if the caller passes `{ author: SomeLoadedAuthor }`,\n * we'll prefer that type, as it might have more nested load hints that we can't otherwise assume.\n */\nexport type New<T extends Entity, O extends OptsOf<T> = OptsOf<T>> = T & {\n // K will be `keyof T` and `keyof O` for codegen'd relations, but custom relations\n // line `hasOneThrough` and `hasOneDerived` will not pass `keyof O` and so use the\n // `: MarkLoaded`.\n //\n // Note that the safest thing is to probably make this `: unknown` instead so that\n // custom relations are not marked loaded, b/c they will very likely require a `.load`\n // to work. However, we have some tests that currently expect `author.image.get` to work\n // on a new author, so keeping the `MarkLoaded` behavior for now.\n [K in keyof T]: K extends keyof O ? MaybeUseOptsType<T, O, K> : MarkLoaded<T, T[K]>;\n};\n\n/**\n * Marks all references/collections of `T` as deeply loaded, which is only useful for\n * tests where we can have \"the whole object graph\" in-memory.\n */\nexport type DeepNew<T extends Entity> = Loaded<T, DeepLoadHint<T>>;\n\n/** Detects whether an entity is newly created, and so we can treat all the relations as loaded. */\nexport function isNew<T extends Entity>(e: T): e is New<T> {\n return e.isNewEntity;\n}\n\n/**\n * All the loadable fields, i.e. relations or lazy-loaded/async properties, in an entity.\n *\n * We use a mapped type (instead of a code-generated type) so that we can pick up custom\n * fields that have be added to the entity classes, i.e. `Author.numberOfBooks2` async\n * properties.\n */\nexport type Loadable<T extends Entity> = {\n -readonly [K in keyof T as LoadableValue<T[K]> extends never ? never : K]: LoadableValue<T[K]>;\n};\n\n/**\n * Given an entity field/value, return the loadable entity.\n *\n * I.e. `Author.books` as a Reference or Collection, return `Book`.\n *\n * Note that we usually return entities, but for AsyncProperties it could be\n * a calculated primitive value like number or string.\n */\nexport type LoadableValue<V> =\n V extends EnumCollection<any, infer E>\n ? E\n : V extends Reference<any, infer U, any>\n ? U\n : V extends Collection<any, infer U>\n ? U\n : V extends ReadOnlyCollection<any, infer U>\n ? U\n : V extends AsyncMethod<any, any, infer V>\n ? V\n : V extends Property<any, infer P>\n ? // If the Property returns `Comment | undefined`, then we want to return `Comment`\n // prettier-ignore\n P extends (infer U extends Entity) | undefined ? U : P\n : never;\n\n/**\n * A load hint of a single key, multiple keys, or nested keys and sub-hints.\n *\n * Load hints are different from reactive hints in that load hints include only references,\n * collections, and async properties to preload (like `Book.author` or `Author.books`), and\n * do not include any primitive fields (like `Author.firstName`).\n */\nexport type LoadHint<T extends Entity> =\n | (keyof Loadable<T> & string)\n | ReadonlyArray<keyof Loadable<T> & string>\n | NestedLoadHint<T>;\n\nexport type NestedLoadHint<T extends Entity> = {\n // Don't filter out entity-loadable keys, because we need to support `{ numberOfBooks2: {} }`\n [K in keyof Loadable<T>]?: Loadable<T>[K] extends infer U extends Entity ? LoadHint<U> : {};\n};\n\n/** Given an entity `T` that is being populated with hints `H`, marks the `H` attributes as populated. */\nexport type Loaded<T extends Entity, H> = T & {\n [K in keyof T & keyof NormalizeHint<H>]: H extends DeepLoadHint<T>\n ? MarkDeepLoaded<T, T[K]>\n : MarkLoaded<T, T[K], NormalizeHint<H>[K]>;\n};\n\n/** Recursively checks if the relations from a load hint are loaded on an entity. */\nexport function isLoaded<T extends Entity, H extends LoadHint<T>>(entity: T, hint: H): entity is Loaded<T, H> {\n if (typeof hint === \"string\") {\n return (entity as any)[hint].isLoaded;\n } else if (Array.isArray(hint)) {\n for (const key of hint as string[]) {\n if (!(entity as any)[key].isLoaded) return false;\n }\n return true;\n } else if (typeof hint === \"object\") {\n for (const entry of Object.entries(hint as object)) {\n const [key, nestedHint] = entry;\n const relation = getRelationFromMaybePolyKey(entity, key);\n if (!relation || typeof relation.load !== \"function\") continue;\n if (relation.isLoaded) {\n const result = relation.get;\n if (Array.isArray(result)) {\n for (const entity of result) {\n if (!isLoaded(entity, nestedHint)) return false;\n }\n } else if (result && !isLoaded(result, nestedHint)) {\n return false;\n }\n } else {\n return false;\n }\n }\n return true;\n } else {\n throw new Error(`Unexpected hint ${hint}`);\n }\n}\n\n/**\n * Recursively checks if a relation-only populate hint is loaded on an entity.\n *\n * Unlike `isLoaded`, this returns `false` for non-loadable/primitive leaves instead of ignoring them, because\n * `ReactiveField.load` calls `em.populate` with load hints converted from reactive hints, i.e. `{ firstName: {} }`.\n * Treating those primitive leaves as loaded would let `EntityManager.populate` skip the batchloader path and change\n * reactive recalculation ordering, so the populate fast-path only applies to true relation populate hints.\n */\nexport function isLoadedForPopulate<T extends Entity, H extends LoadHint<T>>(\n entity: T,\n hint: H,\n): entity is Loaded<T, H> {\n if (typeof hint === \"string\") {\n const relation = getRelationFromMaybePolyKey(entity, hint);\n return !!relation && typeof relation.load === \"function\" && relation.isLoaded;\n } else if (Array.isArray(hint)) {\n for (const key of hint as string[]) {\n if (!isLoadedForPopulate(entity, key as H)) return false;\n }\n return true;\n } else if (typeof hint === \"object\") {\n for (const entry of Object.entries(hint as object)) {\n const [key, nestedHint] = entry;\n const relation = getRelationFromMaybePolyKey(entity, key);\n if (!relation || typeof relation.load !== \"function\" || !relation.isLoaded) return false;\n const result = relation.get;\n if (Array.isArray(result)) {\n for (const entity of result) {\n if (!isLoadedForPopulate(entity, nestedHint as LoadHint<typeof entity>)) return false;\n }\n } else if (result && !isLoadedForPopulate(result, nestedHint as LoadHint<typeof result>)) {\n return false;\n }\n }\n return true;\n } else {\n throw new Error(`Unexpected hint ${hint}`);\n }\n}\n\nexport function maybePopulateThen<T extends Entity, H extends LoadHint<T>, R>(\n entity: T,\n hint: H,\n fn: (loaded: Loaded<T, H>) => R,\n): MaybePromise<R> {\n return isLoaded(entity, hint) ? fn(entity) : (entity as any).populate(hint).then(fn);\n}\n\n/**\n * Runtime checks that `entity` has `hint` loaded, and type guards it as a `Loaded<T, hint>`.\n *\n * Similar to `ensureLoaded`, although `ensureLoaded` returns its value.\n */\nexport function assertLoaded<T extends Entity, const H extends LoadHint<T>>(\n entity: T,\n hint: H,\n): asserts entity is Loaded<T, H> {\n if (!isLoaded(entity, hint)) fail(`${entity.id} is not loaded for ${JSON.stringify(hint)}`);\n}\n\n/**\n * Runtime checks that `entity` has `hint` loaded, and returns it as a `Loaded<T, entity>`.\n *\n * Similar to `assertLoaded`, although `assertLoaded` is a boolean type guard.\n */\nexport function ensureLoaded<T extends Entity, const H extends LoadHint<T>>(entity: T, hint: H): Loaded<T, H> {\n assertLoaded<T, H>(entity, hint);\n return entity;\n}\n\n/**\n * Unsafe type check for `entity` to `hint`, *without* a runtime type check.\n *\n * You should only use this if you're extremely sure that entity has hint loaded.\n */\nexport function unsafeLoaded<T extends Entity, const H extends LoadHint<T>>(entity: T, hint: H): Loaded<T, H> {\n return entity as Loaded<T, H>;\n}\n\n/** From any `Relations` field in `T`, i.e. for loader hints. */\nexport type RelationsIn<T extends Entity> = SubType<T, Relation<any, any>>;\n\n// https://medium.com/dailyjs/typescript-create-a-condition-based-subset-types-9d902cea5b8c\ntype SubType<T, C> = Pick<T, { [K in keyof T]: T[K] extends C ? K : never }[keyof T]>;\n"],"mappings":";;;;;;;;;AA0IA,SAAgB,MAAwB,GAAmB;CACzD,OAAO,EAAE;AACX;;AA+DA,SAAgB,SAAkD,QAAW,MAAiC;CAC5G,IAAI,OAAO,SAAS,UAClB,OAAQ,OAAe,KAAK,CAAC;MACxB,IAAI,MAAM,QAAQ,IAAI,GAAG;EAC9B,KAAK,MAAM,OAAO,MAChB,IAAI,CAAE,OAAe,IAAI,CAAC,UAAU,OAAO;EAE7C,OAAO;CACT,OAAO,IAAI,OAAO,SAAS,UAAU;EACnC,KAAK,MAAM,SAAS,OAAO,QAAQ,IAAc,GAAG;GAClD,MAAM,CAAC,KAAK,cAAc;GAC1B,MAAM,WAAW,4BAA4B,QAAQ,GAAG;GACxD,IAAI,CAAC,YAAY,OAAO,SAAS,SAAS,YAAY;GACtD,IAAI,SAAS,UAAU;IACrB,MAAM,SAAS,SAAS;IACxB,IAAI,MAAM,QAAQ,MAAM,GACjB;UAAA,MAAM,UAAU,QACnB,IAAI,CAAC,SAAS,QAAQ,UAAU,GAAG,OAAO;IAAA,OAEvC,IAAI,UAAU,CAAC,SAAS,QAAQ,UAAU,GAC/C,OAAO;GAEX,OACE,OAAO;EAEX;EACA,OAAO;CACT,OACE,MAAM,IAAI,MAAM,mBAAmB,MAAM;AAE7C;;;;;;;;;AAUA,SAAgB,oBACd,QACA,MACwB;CACxB,IAAI,OAAO,SAAS,UAAU;EAC5B,MAAM,WAAW,4BAA4B,QAAQ,IAAI;EACzD,OAAO,CAAC,CAAC,YAAY,OAAO,SAAS,SAAS,cAAc,SAAS;CACvE,OAAO,IAAI,MAAM,QAAQ,IAAI,GAAG;EAC9B,KAAK,MAAM,OAAO,MAChB,IAAI,CAAC,oBAAoB,QAAQ,GAAQ,GAAG,OAAO;EAErD,OAAO;CACT,OAAO,IAAI,OAAO,SAAS,UAAU;EACnC,KAAK,MAAM,SAAS,OAAO,QAAQ,IAAc,GAAG;GAClD,MAAM,CAAC,KAAK,cAAc;GAC1B,MAAM,WAAW,4BAA4B,QAAQ,GAAG;GACxD,IAAI,CAAC,YAAY,OAAO,SAAS,SAAS,cAAc,CAAC,SAAS,UAAU,OAAO;GACnF,MAAM,SAAS,SAAS;GACxB,IAAI,MAAM,QAAQ,MAAM,GACjB;SAAA,MAAM,UAAU,QACnB,IAAI,CAAC,oBAAoB,QAAQ,UAAqC,GAAG,OAAO;GAAA,OAE7E,IAAI,UAAU,CAAC,oBAAoB,QAAQ,UAAqC,GACrF,OAAO;EAEX;EACA,OAAO;CACT,OACE,MAAM,IAAI,MAAM,mBAAmB,MAAM;AAE7C;AAEA,SAAgB,kBACd,QACA,MACA,IACiB;CACjB,OAAO,SAAS,QAAQ,IAAI,IAAI,GAAG,MAAM,IAAK,OAAe,SAAS,IAAI,CAAC,CAAC,KAAK,EAAE;AACrF;;;;;;AAOA,SAAgB,aACd,QACA,MACgC;CAChC,IAAI,CAAC,SAAS,QAAQ,IAAI,GAAG,KAAK,GAAG,OAAO,GAAG,qBAAqB,KAAK,UAAU,IAAI,GAAG;AAC5F;;;;;;AAOA,SAAgB,aAA4D,QAAW,MAAuB;CAC5G,aAAmB,QAAQ,IAAI;CAC/B,OAAO;AACT;;;;;;AAOA,SAAgB,aAA4D,QAAW,MAAuB;CAC5G,OAAO;AACT"}
|