joist-core 2.3.0-next.97 → 2.3.0-next.99
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/BaseEntity.cjs.map +1 -1
- package/build/BaseEntity.js.map +1 -1
- package/build/Entity.cjs.map +1 -1
- package/build/Entity.js.map +1 -1
- package/build/EntityManager.cjs +45 -46
- package/build/EntityManager.cjs.map +1 -1
- package/build/EntityManager.d.cts +7 -7
- package/build/EntityManager.d.cts.map +1 -1
- package/build/EntityManager.d.mts +7 -7
- package/build/EntityManager.d.mts.map +1 -1
- package/build/EntityManager.js +27 -28
- package/build/EntityManager.js.map +1 -1
- package/build/EntityMetadata.cjs +0 -2
- package/build/EntityMetadata.cjs.map +1 -1
- package/build/EntityMetadata.d.cts +3 -3
- package/build/EntityMetadata.d.mts +3 -3
- package/build/EntityMetadata.js +0 -2
- package/build/EntityMetadata.js.map +1 -1
- package/build/IndexManager.cjs +1 -1
- package/build/IndexManager.cjs.map +1 -1
- package/build/IndexManager.js +1 -1
- package/build/IndexManager.js.map +1 -1
- package/build/InstanceData.cjs.map +1 -1
- package/build/InstanceData.js.map +1 -1
- package/build/PluginManager.cjs +0 -1
- package/build/PluginManager.cjs.map +1 -1
- package/build/PluginManager.d.cts +1 -1
- package/build/PluginManager.d.mts +1 -1
- package/build/PluginManager.js +0 -1
- package/build/PluginManager.js.map +1 -1
- package/build/batchloaders/enumCollectionBatchLoader.cjs +1 -1
- package/build/batchloaders/enumCollectionBatchLoader.cjs.map +1 -1
- package/build/batchloaders/enumCollectionBatchLoader.d.cts +1 -1
- package/build/batchloaders/enumCollectionBatchLoader.d.mts +1 -1
- package/build/batchloaders/enumCollectionBatchLoader.js +1 -1
- package/build/batchloaders/enumCollectionBatchLoader.js.map +1 -1
- package/build/batchloaders/loadBatchLoader.cjs +3 -4
- package/build/batchloaders/loadBatchLoader.cjs.map +1 -1
- package/build/batchloaders/loadBatchLoader.d.cts +1 -1
- package/build/batchloaders/loadBatchLoader.d.mts +1 -1
- package/build/batchloaders/loadBatchLoader.js +2 -3
- package/build/batchloaders/loadBatchLoader.js.map +1 -1
- package/build/batchloaders/manyToManyBatchLoader.cjs +1 -1
- package/build/batchloaders/manyToManyBatchLoader.cjs.map +1 -1
- package/build/batchloaders/manyToManyBatchLoader.d.cts +1 -1
- package/build/batchloaders/manyToManyBatchLoader.d.mts +1 -1
- package/build/batchloaders/manyToManyBatchLoader.js +1 -1
- package/build/batchloaders/manyToManyBatchLoader.js.map +1 -1
- package/build/batchloaders/oneToManyBatchLoader.cjs +1 -1
- package/build/batchloaders/oneToManyBatchLoader.cjs.map +1 -1
- package/build/batchloaders/oneToManyBatchLoader.js +1 -1
- package/build/batchloaders/oneToManyBatchLoader.js.map +1 -1
- package/build/batchloaders/oneToOneBatchLoader.cjs +1 -1
- package/build/batchloaders/oneToOneBatchLoader.cjs.map +1 -1
- package/build/batchloaders/oneToOneBatchLoader.js +1 -1
- package/build/batchloaders/oneToOneBatchLoader.js.map +1 -1
- package/build/batchloaders/populateBatchLoader.cjs +11 -12
- package/build/batchloaders/populateBatchLoader.cjs.map +1 -1
- package/build/batchloaders/populateBatchLoader.d.cts +1 -1
- package/build/batchloaders/populateBatchLoader.d.mts +1 -1
- package/build/batchloaders/populateBatchLoader.js +7 -8
- package/build/batchloaders/populateBatchLoader.js.map +1 -1
- package/build/batchloaders/recursiveChildrenBatchLoader.cjs +2 -2
- package/build/batchloaders/recursiveChildrenBatchLoader.cjs.map +1 -1
- package/build/batchloaders/recursiveChildrenBatchLoader.js +2 -2
- package/build/batchloaders/recursiveChildrenBatchLoader.js.map +1 -1
- package/build/batchloaders/recursiveM2mBatchLoader.cjs +2 -2
- package/build/batchloaders/recursiveM2mBatchLoader.cjs.map +1 -1
- package/build/batchloaders/recursiveM2mBatchLoader.js +2 -2
- package/build/batchloaders/recursiveM2mBatchLoader.js.map +1 -1
- package/build/batchloaders/recursiveParentsBatchLoader.cjs +2 -2
- package/build/batchloaders/recursiveParentsBatchLoader.cjs.map +1 -1
- package/build/batchloaders/recursiveParentsBatchLoader.js +2 -2
- package/build/batchloaders/recursiveParentsBatchLoader.js.map +1 -1
- package/build/changes.cjs +2 -3
- package/build/changes.cjs.map +1 -1
- package/build/changes.js +2 -3
- package/build/changes.js.map +1 -1
- package/build/config.cjs +3 -3
- package/build/config.cjs.map +1 -1
- package/build/config.d.cts +2 -2
- package/build/config.d.mts +2 -2
- package/build/config.js +1 -1
- package/build/config.js.map +1 -1
- package/build/configure.cjs +10 -10
- package/build/configure.cjs.map +1 -1
- package/build/configure.js +5 -5
- package/build/configure.js.map +1 -1
- package/build/dataloaders/fastWhereFilterHash.cjs +8 -8
- package/build/dataloaders/fastWhereFilterHash.cjs.map +1 -1
- package/build/dataloaders/fastWhereFilterHash.d.cts.map +1 -1
- package/build/dataloaders/fastWhereFilterHash.d.mts.map +1 -1
- package/build/dataloaders/fastWhereFilterHash.js +3 -3
- package/build/dataloaders/fastWhereFilterHash.js.map +1 -1
- package/build/dataloaders/findByUniqueDataLoader.cjs.map +1 -1
- package/build/dataloaders/findByUniqueDataLoader.d.cts.map +1 -1
- package/build/dataloaders/findByUniqueDataLoader.d.mts.map +1 -1
- package/build/dataloaders/findByUniqueDataLoader.js.map +1 -1
- package/build/dataloaders/findCountDataLoader.cjs +2 -2
- package/build/dataloaders/findCountDataLoader.cjs.map +1 -1
- package/build/dataloaders/findCountDataLoader.js +1 -1
- package/build/dataloaders/findCountDataLoader.js.map +1 -1
- package/build/dataloaders/findDataLoader.cjs +6 -6
- package/build/dataloaders/findDataLoader.cjs.map +1 -1
- package/build/dataloaders/findDataLoader.d.cts +1 -1
- package/build/dataloaders/findDataLoader.d.mts +1 -1
- package/build/dataloaders/findDataLoader.js +3 -3
- package/build/dataloaders/findDataLoader.js.map +1 -1
- package/build/dataloaders/findIdsDataLoader.cjs +3 -3
- package/build/dataloaders/findIdsDataLoader.cjs.map +1 -1
- package/build/dataloaders/findIdsDataLoader.js +2 -2
- package/build/dataloaders/findIdsDataLoader.js.map +1 -1
- package/build/dataloaders/findOrCreateDataLoader.cjs +1 -1
- package/build/dataloaders/findOrCreateDataLoader.cjs.map +1 -1
- package/build/dataloaders/findOrCreateDataLoader.d.cts.map +1 -1
- package/build/dataloaders/findOrCreateDataLoader.d.mts.map +1 -1
- package/build/dataloaders/findOrCreateDataLoader.js +1 -1
- package/build/dataloaders/findOrCreateDataLoader.js.map +1 -1
- package/build/dataloaders/findPaginatedDataLoader.cjs +6 -6
- package/build/dataloaders/findPaginatedDataLoader.cjs.map +1 -1
- package/build/dataloaders/findPaginatedDataLoader.d.cts +1 -1
- package/build/dataloaders/findPaginatedDataLoader.d.mts +1 -1
- package/build/dataloaders/findPaginatedDataLoader.js +3 -3
- package/build/dataloaders/findPaginatedDataLoader.js.map +1 -1
- package/build/dataloaders/lensDataLoader.cjs +3 -3
- package/build/dataloaders/lensDataLoader.cjs.map +1 -1
- package/build/dataloaders/lensDataLoader.d.cts.map +1 -1
- package/build/dataloaders/lensDataLoader.d.mts.map +1 -1
- package/build/dataloaders/lensDataLoader.js +2 -2
- package/build/dataloaders/lensDataLoader.js.map +1 -1
- package/build/dataloaders/manyToManyFindDataLoader.cjs +1 -1
- package/build/dataloaders/manyToManyFindDataLoader.cjs.map +1 -1
- package/build/dataloaders/manyToManyFindDataLoader.d.cts.map +1 -1
- package/build/dataloaders/manyToManyFindDataLoader.d.mts.map +1 -1
- package/build/dataloaders/manyToManyFindDataLoader.js +1 -1
- package/build/dataloaders/manyToManyFindDataLoader.js.map +1 -1
- package/build/dataloaders/oneToManyFindDataLoader.cjs +1 -1
- package/build/dataloaders/oneToManyFindDataLoader.cjs.map +1 -1
- package/build/dataloaders/oneToManyFindDataLoader.d.cts.map +1 -1
- package/build/dataloaders/oneToManyFindDataLoader.d.mts.map +1 -1
- package/build/dataloaders/oneToManyFindDataLoader.js +1 -1
- package/build/dataloaders/oneToManyFindDataLoader.js.map +1 -1
- package/build/defaults.cjs +5 -5
- package/build/defaults.cjs.map +1 -1
- package/build/defaults.d.cts +1 -1
- package/build/defaults.d.cts.map +1 -1
- package/build/defaults.d.mts +1 -1
- package/build/defaults.d.mts.map +1 -1
- package/build/defaults.js +4 -4
- package/build/defaults.js.map +1 -1
- package/build/drivers/Driver.cjs +0 -1
- package/build/drivers/Driver.d.cts +1 -1
- package/build/drivers/Driver.d.mts +1 -1
- package/build/drivers/Driver.js +0 -1
- package/build/drivers/EntityWriter.cjs +6 -7
- package/build/drivers/EntityWriter.cjs.map +1 -1
- package/build/drivers/EntityWriter.d.cts +1 -1
- package/build/drivers/EntityWriter.d.mts +1 -1
- package/build/drivers/EntityWriter.js +2 -3
- package/build/drivers/EntityWriter.js.map +1 -1
- package/build/drivers/IdAssigner.cjs +0 -1
- package/build/drivers/IdAssigner.cjs.map +1 -1
- package/build/drivers/IdAssigner.d.cts +1 -1
- package/build/drivers/IdAssigner.d.mts +1 -1
- package/build/drivers/IdAssigner.js +0 -1
- package/build/drivers/IdAssigner.js.map +1 -1
- package/build/drivers/driverApi.cjs +19 -0
- package/build/drivers/driverApi.cjs.map +1 -0
- package/build/drivers/driverApi.d.cts +22 -0
- package/build/drivers/driverApi.d.cts.map +1 -0
- package/build/drivers/driverApi.d.mts +22 -0
- package/build/drivers/driverApi.d.mts.map +1 -0
- package/build/drivers/driverApi.js +18 -0
- package/build/drivers/driverApi.js.map +1 -0
- package/build/fields.cjs +3 -3
- package/build/fields.cjs.map +1 -1
- package/build/fields.js +2 -2
- package/build/fields.js.map +1 -1
- package/build/{FlushLock.cjs → flush/FlushLock.cjs} +1 -1
- package/build/flush/FlushLock.cjs.map +1 -0
- package/build/{FlushLock.d.cts → flush/FlushLock.d.cts} +1 -1
- package/build/flush/FlushLock.d.cts.map +1 -0
- package/build/{FlushLock.d.mts → flush/FlushLock.d.mts} +1 -1
- package/build/flush/FlushLock.d.mts.map +1 -0
- package/build/{FlushLock.js → flush/FlushLock.js} +1 -1
- package/build/flush/FlushLock.js.map +1 -0
- package/build/{JoinRows.cjs → flush/JoinRows.cjs} +5 -8
- package/build/flush/JoinRows.cjs.map +1 -0
- package/build/{JoinRows.d.cts → flush/JoinRows.d.cts} +5 -5
- package/build/flush/JoinRows.d.cts.map +1 -0
- package/build/{JoinRows.d.mts → flush/JoinRows.d.mts} +5 -5
- package/build/flush/JoinRows.d.mts.map +1 -0
- package/build/{JoinRows.js → flush/JoinRows.js} +5 -8
- package/build/flush/JoinRows.js.map +1 -0
- package/build/{PendingChanges.cjs → flush/PendingChanges.cjs} +0 -1
- package/build/{PendingChanges.d.cts → flush/PendingChanges.d.cts} +2 -2
- package/build/flush/PendingChanges.d.cts.map +1 -0
- package/build/{PendingChanges.d.mts → flush/PendingChanges.d.mts} +2 -2
- package/build/flush/PendingChanges.d.mts.map +1 -0
- package/build/flush/PendingChanges.js +1 -0
- package/build/{Todo.cjs → flush/Todo.cjs} +4 -6
- package/build/flush/Todo.cjs.map +1 -0
- package/build/{Todo.d.cts → flush/Todo.d.cts} +3 -3
- package/build/flush/Todo.d.cts.map +1 -0
- package/build/{Todo.d.mts → flush/Todo.d.mts} +3 -3
- package/build/flush/Todo.d.mts.map +1 -0
- package/build/{Todo.js → flush/Todo.js} +4 -6
- package/build/flush/Todo.js.map +1 -0
- package/build/getProperties.cjs.map +1 -1
- package/build/getProperties.js.map +1 -1
- package/build/index.cjs +100 -100
- package/build/index.cjs.map +1 -1
- package/build/index.d.cts +15 -15
- package/build/index.d.mts +15 -15
- package/build/index.js +42 -42
- package/build/index.js.map +1 -1
- package/build/json.cjs +4 -4
- package/build/json.cjs.map +1 -1
- package/build/json.js +3 -3
- package/build/json.js.map +1 -1
- package/build/keys.cjs +1 -1
- package/build/keys.cjs.map +1 -1
- package/build/keys.js +1 -1
- package/build/keys.js.map +1 -1
- package/build/{HintTree.cjs → loading/HintTree.cjs} +2 -5
- package/build/loading/HintTree.cjs.map +1 -0
- package/build/{HintTree.d.cts → loading/HintTree.d.cts} +3 -3
- package/build/loading/HintTree.d.cts.map +1 -0
- package/build/{HintTree.d.mts → loading/HintTree.d.mts} +3 -3
- package/build/loading/HintTree.d.mts.map +1 -0
- package/build/{HintTree.js → loading/HintTree.js} +2 -5
- package/build/loading/HintTree.js.map +1 -0
- package/build/{IsLoadedCache.cjs → loading/IsLoadedCache.cjs} +2 -3
- package/build/loading/IsLoadedCache.cjs.map +1 -0
- package/build/{IsLoadedCache.d.cts → loading/IsLoadedCache.d.cts} +2 -2
- package/build/loading/IsLoadedCache.d.cts.map +1 -0
- package/build/{IsLoadedCache.d.mts → loading/IsLoadedCache.d.mts} +2 -2
- package/build/loading/IsLoadedCache.d.mts.map +1 -0
- package/build/{IsLoadedCache.js → loading/IsLoadedCache.js} +2 -3
- package/build/{IsLoadedCache.cjs.map → loading/IsLoadedCache.js.map} +1 -1
- package/build/{loadHints.cjs → loading/loadHints.cjs} +6 -11
- package/build/loading/loadHints.cjs.map +1 -0
- package/build/{loadHints.d.cts → loading/loadHints.d.cts} +14 -14
- package/build/loading/loadHints.d.cts.map +1 -0
- package/build/{loadHints.d.mts → loading/loadHints.d.mts} +14 -14
- package/build/loading/loadHints.d.mts.map +1 -0
- package/build/{loadHints.js → loading/loadHints.js} +3 -8
- package/build/loading/loadHints.js.map +1 -0
- package/build/{loadLens.cjs → loading/loadLens.cjs} +8 -9
- package/build/loading/loadLens.cjs.map +1 -0
- package/build/{loadLens.d.cts → loading/loadLens.d.cts} +3 -3
- package/build/loading/loadLens.d.cts.map +1 -0
- package/build/{loadLens.d.mts → loading/loadLens.d.mts} +3 -3
- package/build/loading/loadLens.d.mts.map +1 -0
- package/build/{loadLens.js → loading/loadLens.js} +8 -9
- package/build/loading/loadLens.js.map +1 -0
- package/build/{withLoaded.cjs → loading/withLoaded.cjs} +12 -13
- package/build/loading/withLoaded.cjs.map +1 -0
- package/build/{withLoaded.d.cts → loading/withLoaded.d.cts} +9 -9
- package/build/loading/withLoaded.d.cts.map +1 -0
- package/build/{withLoaded.d.mts → loading/withLoaded.d.mts} +9 -9
- package/build/loading/withLoaded.d.mts.map +1 -0
- package/build/{withLoaded.js → loading/withLoaded.js} +10 -11
- package/build/loading/withLoaded.js.map +1 -0
- package/build/logging/FactoryLogger.cjs.map +1 -1
- package/build/logging/FactoryLogger.d.cts.map +1 -1
- package/build/logging/FactoryLogger.d.mts.map +1 -1
- package/build/logging/FactoryLogger.js.map +1 -1
- package/build/logging/FieldLogger.cjs.map +1 -1
- package/build/logging/FieldLogger.d.cts.map +1 -1
- package/build/logging/FieldLogger.d.mts.map +1 -1
- package/build/logging/FieldLogger.js.map +1 -1
- package/build/logging/ReactionLogger.cjs +0 -2
- package/build/logging/ReactionLogger.cjs.map +1 -1
- package/build/logging/ReactionLogger.d.cts +2 -2
- package/build/logging/ReactionLogger.d.cts.map +1 -1
- package/build/logging/ReactionLogger.d.mts +2 -2
- package/build/logging/ReactionLogger.d.mts.map +1 -1
- package/build/logging/ReactionLogger.js +0 -2
- package/build/logging/ReactionLogger.js.map +1 -1
- package/build/newEntity.cjs.map +1 -1
- package/build/newEntity.js.map +1 -1
- package/build/newTestInstance.cjs +3 -3
- package/build/newTestInstance.cjs.map +1 -1
- package/build/newTestInstance.d.cts +1 -1
- package/build/newTestInstance.d.cts.map +1 -1
- package/build/newTestInstance.d.mts +1 -1
- package/build/newTestInstance.d.mts.map +1 -1
- package/build/newTestInstance.js +2 -2
- package/build/newTestInstance.js.map +1 -1
- package/build/normalizeHints.cjs +0 -2
- package/build/normalizeHints.cjs.map +1 -1
- package/build/normalizeHints.d.cts +2 -2
- package/build/normalizeHints.d.mts +2 -2
- package/build/normalizeHints.js +0 -2
- package/build/normalizeHints.js.map +1 -1
- package/build/nowUTC.cjs +2 -2
- package/build/nowUTC.cjs.map +1 -1
- package/build/nowUTC.d.cts +1 -1
- package/build/nowUTC.d.mts +1 -1
- package/build/nowUTC.js +1 -1
- package/build/nowUTC.js.map +1 -1
- package/build/plugins/ImmutableEntitiesPlugin.cjs.map +1 -1
- package/build/plugins/ImmutableEntitiesPlugin.js.map +1 -1
- package/build/plugins/PreloadPlugin.cjs +0 -2
- package/build/plugins/PreloadPlugin.d.cts +2 -2
- package/build/plugins/PreloadPlugin.d.mts +2 -2
- package/build/plugins/PreloadPlugin.js +0 -2
- package/build/preloading/JsonAggregatePreloader.cjs +1 -4
- package/build/preloading/JsonAggregatePreloader.cjs.map +1 -1
- package/build/preloading/JsonAggregatePreloader.d.cts +2 -2
- package/build/preloading/JsonAggregatePreloader.d.cts.map +1 -1
- package/build/preloading/JsonAggregatePreloader.d.mts +2 -2
- package/build/preloading/JsonAggregatePreloader.d.mts.map +1 -1
- package/build/preloading/JsonAggregatePreloader.js +1 -4
- package/build/preloading/JsonAggregatePreloader.js.map +1 -1
- package/build/preloading/canPreload.cjs.map +1 -1
- package/build/preloading/canPreload.js.map +1 -1
- package/build/preloading/partitionHint.cjs +2 -3
- package/build/preloading/partitionHint.cjs.map +1 -1
- package/build/preloading/partitionHint.d.cts +1 -1
- package/build/preloading/partitionHint.d.mts +1 -1
- package/build/preloading/partitionHint.js +2 -3
- package/build/preloading/partitionHint.js.map +1 -1
- package/build/queries/ConditionBuilder.cjs.map +1 -1
- package/build/queries/ConditionBuilder.d.cts +1 -1
- package/build/queries/ConditionBuilder.d.mts +1 -1
- package/build/queries/ConditionBuilder.js.map +1 -1
- package/build/queries/conditions.cjs.map +1 -1
- package/build/queries/conditions.js.map +1 -1
- package/build/queries/entityQueryUtils.cjs.map +1 -1
- package/build/queries/entityQueryUtils.js.map +1 -1
- package/build/queries/find/Aliases.cjs +1 -1
- package/build/queries/find/Aliases.cjs.map +1 -1
- package/build/queries/find/Aliases.d.cts.map +1 -1
- package/build/queries/find/Aliases.d.mts.map +1 -1
- package/build/queries/find/Aliases.js +1 -1
- package/build/queries/find/Aliases.js.map +1 -1
- package/build/queries/find/DeferredAlias.cjs.map +1 -1
- package/build/queries/find/DeferredAlias.js.map +1 -1
- package/build/queries/find/EntityFilter.cjs.map +1 -1
- package/build/queries/find/EntityFilter.js.map +1 -1
- package/build/queries/find/EntityGraphQLFilter.cjs.map +1 -1
- package/build/queries/find/EntityGraphQLFilter.js.map +1 -1
- package/build/queries/find/QueryParser.cjs +2 -2
- package/build/queries/find/QueryParser.cjs.map +1 -1
- package/build/queries/find/QueryParser.collectionJoins.cjs.map +1 -1
- package/build/queries/find/QueryParser.collectionJoins.js.map +1 -1
- package/build/queries/find/QueryParser.d.cts.map +1 -1
- package/build/queries/find/QueryParser.d.mts.map +1 -1
- package/build/queries/find/QueryParser.js +2 -2
- package/build/queries/find/QueryParser.js.map +1 -1
- package/build/queries/find/QueryParser.pruning.cjs.map +1 -1
- package/build/queries/find/QueryParser.pruning.js.map +1 -1
- package/build/queries/find/QueryVisitor.cjs.map +1 -1
- package/build/queries/find/QueryVisitor.js.map +1 -1
- package/build/queries/find/buildFindQuery.cjs.map +1 -1
- package/build/queries/find/buildFindQuery.js.map +1 -1
- package/build/queries/find/scopes.cjs.map +1 -1
- package/build/queries/find/scopes.d.cts +1 -1
- package/build/queries/find/scopes.d.mts +1 -1
- package/build/queries/find/scopes.js.map +1 -1
- package/build/queries/parsedConditions.cjs.map +1 -1
- package/build/queries/parsedConditions.js.map +1 -1
- package/build/queries/renderConditions.cjs.map +1 -1
- package/build/queries/renderConditions.js.map +1 -1
- package/build/queries/skipCondition.cjs.map +1 -1
- package/build/queries/skipCondition.js.map +1 -1
- package/build/queries/sql/AliasAssigner.cjs.map +1 -1
- package/build/queries/sql/AliasAssigner.js.map +1 -1
- package/build/queries/sql/Expr.cjs +2 -2
- package/build/queries/sql/Expr.cjs.map +1 -1
- package/build/queries/sql/Expr.d.cts +1 -1
- package/build/queries/sql/Expr.d.mts +1 -1
- package/build/queries/sql/Expr.js +1 -1
- package/build/queries/sql/Expr.js.map +1 -1
- package/build/queries/sql/Tables.cjs +1 -1
- package/build/queries/sql/Tables.cjs.map +1 -1
- package/build/queries/sql/Tables.d.cts.map +1 -1
- package/build/queries/sql/Tables.d.mts.map +1 -1
- package/build/queries/sql/Tables.js +1 -1
- package/build/queries/sql/Tables.js.map +1 -1
- package/build/queries/sql/execute.cjs +1 -1
- package/build/queries/sql/execute.cjs.map +1 -1
- package/build/queries/sql/execute.js +1 -1
- package/build/queries/sql/execute.js.map +1 -1
- package/build/queries/sql/expressions/arrayAgg.cjs.map +1 -1
- package/build/queries/sql/expressions/arrayAgg.js.map +1 -1
- package/build/queries/sql/expressions/case.cjs.map +1 -1
- package/build/queries/sql/expressions/case.js.map +1 -1
- package/build/queries/sql/expressions/coalesce.cjs.map +1 -1
- package/build/queries/sql/expressions/coalesce.js.map +1 -1
- package/build/queries/sql/expressions/codecs.cjs +2 -2
- package/build/queries/sql/expressions/codecs.cjs.map +1 -1
- package/build/queries/sql/expressions/codecs.js +1 -1
- package/build/queries/sql/expressions/codecs.js.map +1 -1
- package/build/queries/sql/expressions/expression.cjs.map +1 -1
- package/build/queries/sql/expressions/expression.d.cts.map +1 -1
- package/build/queries/sql/expressions/expression.d.mts.map +1 -1
- package/build/queries/sql/expressions/expression.js.map +1 -1
- package/build/queries/sql/expressions/greatest.cjs.map +1 -1
- package/build/queries/sql/expressions/greatest.js.map +1 -1
- package/build/queries/sql/expressions/least.cjs.map +1 -1
- package/build/queries/sql/expressions/least.js.map +1 -1
- package/build/queries/sql/expressions/nullIf.cjs.map +1 -1
- package/build/queries/sql/expressions/nullIf.js.map +1 -1
- package/build/queries/sql/expressions/parseExpression.cjs.map +1 -1
- package/build/queries/sql/expressions/parseExpression.js.map +1 -1
- package/build/queries/sql/expressions/types.d.cts.map +1 -1
- package/build/queries/sql/expressions/types.d.mts.map +1 -1
- package/build/queries/sql/query.cjs +1 -1
- package/build/queries/sql/query.cjs.map +1 -1
- package/build/queries/sql/query.d.cts +1 -1
- package/build/queries/sql/query.d.mts +1 -1
- package/build/queries/sql/query.js +1 -1
- package/build/queries/sql/query.js.map +1 -1
- package/build/{unnest.cjs → queries/unnest.cjs} +1 -2
- package/build/queries/unnest.cjs.map +1 -0
- package/build/{unnest.d.cts → queries/unnest.d.cts} +3 -3
- package/build/queries/unnest.d.cts.map +1 -0
- package/build/{unnest.d.mts → queries/unnest.d.mts} +3 -3
- package/build/queries/unnest.d.mts.map +1 -0
- package/build/{unnest.js → queries/unnest.js} +1 -2
- package/build/queries/unnest.js.map +1 -0
- package/build/queries/valueFilters.cjs.map +1 -1
- package/build/queries/valueFilters.d.cts +1 -1
- package/build/queries/valueFilters.d.cts.map +1 -1
- package/build/queries/valueFilters.d.mts +1 -1
- package/build/queries/valueFilters.d.mts.map +1 -1
- package/build/queries/valueFilters.js.map +1 -1
- package/build/{ReactionsManager.cjs → reactivity/ReactionsManager.cjs} +8 -10
- package/build/reactivity/ReactionsManager.cjs.map +1 -0
- package/build/{ReactionsManager.d.cts → reactivity/ReactionsManager.d.cts} +5 -6
- package/build/reactivity/ReactionsManager.d.cts.map +1 -0
- package/build/{ReactionsManager.d.mts → reactivity/ReactionsManager.d.mts} +5 -6
- package/build/reactivity/ReactionsManager.d.mts.map +1 -0
- package/build/{ReactionsManager.js → reactivity/ReactionsManager.js} +6 -8
- package/build/reactivity/ReactionsManager.js.map +1 -0
- package/build/{reactiveHints.cjs → reactivity/reactiveHints.cjs} +12 -16
- package/build/reactivity/reactiveHints.cjs.map +1 -0
- package/build/{reactiveHints.d.cts → reactivity/reactiveHints.d.cts} +17 -17
- package/build/reactivity/reactiveHints.d.cts.map +1 -0
- package/build/{reactiveHints.d.mts → reactivity/reactiveHints.d.mts} +17 -17
- package/build/reactivity/reactiveHints.d.mts.map +1 -0
- package/build/{reactiveHints.js → reactivity/reactiveHints.js} +12 -16
- package/build/reactivity/reactiveHints.js.map +1 -0
- package/build/relations/AbstractRelationImpl.cjs.map +1 -1
- package/build/relations/AbstractRelationImpl.js.map +1 -1
- package/build/relations/AsyncProperty.cjs.map +1 -1
- package/build/relations/AsyncProperty.js.map +1 -1
- package/build/relations/AsyncReactiveField.cjs +6 -6
- package/build/relations/AsyncReactiveField.cjs.map +1 -1
- package/build/relations/AsyncReactiveField.d.cts +1 -1
- package/build/relations/AsyncReactiveField.d.mts +1 -1
- package/build/relations/AsyncReactiveField.js +4 -4
- package/build/relations/AsyncReactiveField.js.map +1 -1
- package/build/relations/Collection.cjs +1 -1
- package/build/relations/Collection.cjs.map +1 -1
- package/build/relations/Collection.js +1 -1
- package/build/relations/Collection.js.map +1 -1
- package/build/relations/CustomCollection.cjs.map +1 -1
- package/build/relations/CustomCollection.d.cts +1 -1
- package/build/relations/CustomCollection.d.mts +1 -1
- package/build/relations/CustomCollection.js.map +1 -1
- package/build/relations/CustomReference.cjs +1 -1
- package/build/relations/CustomReference.cjs.map +1 -1
- package/build/relations/CustomReference.d.cts +1 -1
- package/build/relations/CustomReference.d.mts +1 -1
- package/build/relations/CustomReference.js +1 -1
- package/build/relations/CustomReference.js.map +1 -1
- package/build/relations/EnumCollection.cjs.map +1 -1
- package/build/relations/EnumCollection.d.cts +1 -1
- package/build/relations/EnumCollection.d.mts +1 -1
- package/build/relations/EnumCollection.js.map +1 -1
- package/build/relations/LazyField.cjs +4 -4
- package/build/relations/LazyField.cjs.map +1 -1
- package/build/relations/LazyField.js +4 -4
- package/build/relations/LazyField.js.map +1 -1
- package/build/relations/ManyToManyCollection.cjs +3 -3
- package/build/relations/ManyToManyCollection.cjs.map +1 -1
- package/build/relations/ManyToManyCollection.js +3 -3
- package/build/relations/ManyToManyCollection.js.map +1 -1
- package/build/relations/ManyToManyLargeCollection.cjs +3 -3
- package/build/relations/ManyToManyLargeCollection.cjs.map +1 -1
- package/build/relations/ManyToManyLargeCollection.js +3 -3
- package/build/relations/ManyToManyLargeCollection.js.map +1 -1
- package/build/relations/ManyToOneReference.cjs +4 -4
- package/build/relations/ManyToOneReference.cjs.map +1 -1
- package/build/relations/ManyToOneReference.js +4 -4
- package/build/relations/ManyToOneReference.js.map +1 -1
- package/build/relations/OneToManyCollection.cjs +1 -2
- package/build/relations/OneToManyCollection.cjs.map +1 -1
- package/build/relations/OneToManyCollection.d.cts +1 -1
- package/build/relations/OneToManyCollection.d.mts +1 -1
- package/build/relations/OneToManyCollection.js +1 -2
- package/build/relations/OneToManyCollection.js.map +1 -1
- package/build/relations/OneToManyLargeCollection.cjs +1 -1
- package/build/relations/OneToManyLargeCollection.cjs.map +1 -1
- package/build/relations/OneToManyLargeCollection.js +1 -1
- package/build/relations/OneToManyLargeCollection.js.map +1 -1
- package/build/relations/OneToOneReference.cjs +5 -5
- package/build/relations/OneToOneReference.cjs.map +1 -1
- package/build/relations/OneToOneReference.js +5 -5
- package/build/relations/OneToOneReference.js.map +1 -1
- package/build/relations/PolymorphicReference.cjs +3 -3
- package/build/relations/PolymorphicReference.cjs.map +1 -1
- package/build/relations/PolymorphicReference.js +3 -3
- package/build/relations/PolymorphicReference.js.map +1 -1
- package/build/relations/ReactiveField.cjs +5 -6
- package/build/relations/ReactiveField.cjs.map +1 -1
- package/build/relations/ReactiveField.d.cts +2 -2
- package/build/relations/ReactiveField.d.mts +2 -2
- package/build/relations/ReactiveField.js +3 -4
- package/build/relations/ReactiveField.js.map +1 -1
- package/build/relations/ReactiveGetter.cjs +0 -1
- package/build/relations/ReactiveGetter.cjs.map +1 -1
- package/build/relations/ReactiveGetter.d.cts +1 -1
- package/build/relations/ReactiveGetter.d.mts +1 -1
- package/build/relations/ReactiveGetter.js +0 -1
- package/build/relations/ReactiveGetter.js.map +1 -1
- package/build/relations/ReactiveManyToMany.cjs +5 -6
- package/build/relations/ReactiveManyToMany.cjs.map +1 -1
- package/build/relations/ReactiveManyToMany.d.cts +2 -2
- package/build/relations/ReactiveManyToMany.d.cts.map +1 -1
- package/build/relations/ReactiveManyToMany.d.mts +2 -2
- package/build/relations/ReactiveManyToMany.d.mts.map +1 -1
- package/build/relations/ReactiveManyToMany.js +3 -4
- package/build/relations/ReactiveManyToMany.js.map +1 -1
- package/build/relations/ReactiveManyToManyOtherSide.cjs +1 -3
- package/build/relations/ReactiveManyToManyOtherSide.cjs.map +1 -1
- package/build/relations/ReactiveManyToManyOtherSide.d.cts +2 -2
- package/build/relations/ReactiveManyToManyOtherSide.d.mts +2 -2
- package/build/relations/ReactiveManyToManyOtherSide.js +1 -3
- package/build/relations/ReactiveManyToManyOtherSide.js.map +1 -1
- package/build/relations/ReactiveReference.cjs +8 -9
- package/build/relations/ReactiveReference.cjs.map +1 -1
- package/build/relations/ReactiveReference.d.cts +2 -2
- package/build/relations/ReactiveReference.d.cts.map +1 -1
- package/build/relations/ReactiveReference.d.mts +2 -2
- package/build/relations/ReactiveReference.d.mts.map +1 -1
- package/build/relations/ReactiveReference.js +6 -7
- package/build/relations/ReactiveReference.js.map +1 -1
- package/build/relations/ReadOnlyCollection.cjs.map +1 -1
- package/build/relations/ReadOnlyCollection.js.map +1 -1
- package/build/relations/RecursiveCollection.cjs +3 -4
- package/build/relations/RecursiveCollection.cjs.map +1 -1
- package/build/relations/RecursiveCollection.d.cts +1 -1
- package/build/relations/RecursiveCollection.d.mts +1 -1
- package/build/relations/RecursiveCollection.js +3 -4
- package/build/relations/RecursiveCollection.js.map +1 -1
- package/build/relations/RecursiveCycleError.cjs.map +1 -1
- package/build/relations/RecursiveCycleError.js.map +1 -1
- package/build/relations/Reference.cjs +1 -1
- package/build/relations/Reference.cjs.map +1 -1
- package/build/relations/Reference.js +1 -1
- package/build/relations/Reference.js.map +1 -1
- package/build/relations/Relation.cjs.map +1 -1
- package/build/relations/Relation.js.map +1 -1
- package/build/relations/hasAsyncMethod.cjs +2 -2
- package/build/relations/hasAsyncMethod.cjs.map +1 -1
- package/build/relations/hasAsyncMethod.d.cts +1 -1
- package/build/relations/hasAsyncMethod.d.mts +1 -1
- package/build/relations/hasAsyncMethod.js +1 -1
- package/build/relations/hasAsyncMethod.js.map +1 -1
- package/build/relations/hasManyDerived.cjs +3 -3
- package/build/relations/hasManyDerived.cjs.map +1 -1
- package/build/relations/hasManyDerived.d.cts +1 -1
- package/build/relations/hasManyDerived.d.mts +1 -1
- package/build/relations/hasManyDerived.js +2 -2
- package/build/relations/hasManyDerived.js.map +1 -1
- package/build/relations/hasManyThrough.cjs +6 -6
- package/build/relations/hasManyThrough.cjs.map +1 -1
- package/build/relations/hasManyThrough.d.cts +1 -1
- package/build/relations/hasManyThrough.d.mts +1 -1
- package/build/relations/hasManyThrough.js +2 -2
- package/build/relations/hasManyThrough.js.map +1 -1
- package/build/relations/hasOneDerived.cjs +3 -3
- package/build/relations/hasOneDerived.cjs.map +1 -1
- package/build/relations/hasOneDerived.d.cts +1 -1
- package/build/relations/hasOneDerived.d.mts +1 -1
- package/build/relations/hasOneDerived.js +2 -2
- package/build/relations/hasOneDerived.js.map +1 -1
- package/build/relations/hasOneThrough.cjs +7 -7
- package/build/relations/hasOneThrough.cjs.map +1 -1
- package/build/relations/hasOneThrough.d.cts +1 -1
- package/build/relations/hasOneThrough.d.mts +1 -1
- package/build/relations/hasOneThrough.js +2 -2
- package/build/relations/hasOneThrough.js.map +1 -1
- package/build/relations/hasProperty.cjs +4 -4
- package/build/relations/hasProperty.cjs.map +1 -1
- package/build/relations/hasProperty.d.cts +2 -2
- package/build/relations/hasProperty.d.mts +2 -2
- package/build/relations/hasProperty.js +2 -2
- package/build/relations/hasProperty.js.map +1 -1
- package/build/relations/index.cjs +10 -10
- package/build/relations/index.js +10 -10
- package/build/relations/isCascadeDelete.cjs.map +1 -1
- package/build/relations/isCascadeDelete.js.map +1 -1
- package/build/resurrection.cjs.map +1 -1
- package/build/resurrection.js.map +1 -1
- package/build/rules.cjs +3 -4
- package/build/rules.cjs.map +1 -1
- package/build/rules.d.cts +1 -1
- package/build/rules.d.mts +1 -1
- package/build/rules.js +3 -4
- package/build/rules.js.map +1 -1
- package/build/runtimeConfig.cjs.map +1 -1
- package/build/runtimeConfig.js.map +1 -1
- package/build/{TypeInfo.cjs → serde/TypeInfo.cjs} +1 -1
- package/build/serde/TypeInfo.cjs.map +1 -0
- package/build/{TypeInfo.d.cts → serde/TypeInfo.d.cts} +2 -2
- package/build/serde/TypeInfo.d.cts.map +1 -0
- package/build/{TypeInfo.d.mts → serde/TypeInfo.d.mts} +2 -2
- package/build/serde/TypeInfo.d.mts.map +1 -0
- package/build/{TypeInfo.js → serde/TypeInfo.js} +1 -1
- package/build/serde/TypeInfo.js.map +1 -0
- package/build/{columns.cjs → serde/columns.cjs} +1 -1
- package/build/serde/columns.cjs.map +1 -0
- package/build/{columns.d.cts → serde/columns.d.cts} +2 -2
- package/build/serde/columns.d.cts.map +1 -0
- package/build/{columns.d.mts → serde/columns.d.mts} +2 -2
- package/build/serde/columns.d.mts.map +1 -0
- package/build/{columns.js → serde/columns.js} +1 -1
- package/build/serde/columns.js.map +1 -0
- package/build/{fieldSerde.cjs → serde/fieldSerde.cjs} +6 -6
- package/build/serde/fieldSerde.cjs.map +1 -0
- package/build/{fieldSerde.d.cts → serde/fieldSerde.d.cts} +5 -5
- package/build/serde/fieldSerde.d.cts.map +1 -0
- package/build/{fieldSerde.d.mts → serde/fieldSerde.d.mts} +5 -5
- package/build/serde/fieldSerde.d.mts.map +1 -0
- package/build/{fieldSerde.js → serde/fieldSerde.js} +6 -6
- package/build/serde/fieldSerde.js.map +1 -0
- package/build/{serde.cjs → serde/serde.cjs} +25 -26
- package/build/serde/serde.cjs.map +1 -0
- package/build/{serde.d.cts → serde/serde.d.cts} +1 -1
- package/build/serde/serde.d.cts.map +1 -0
- package/build/{serde.d.mts → serde/serde.d.mts} +1 -1
- package/build/serde/serde.d.mts.map +1 -0
- package/build/{serde.js → serde/serde.js} +4 -5
- package/build/serde/serde.js.map +1 -0
- package/build/{temporal.cjs → serde/temporal.cjs} +1 -1
- package/build/serde/temporal.cjs.map +1 -0
- package/build/{temporal.d.cts → serde/temporal.d.cts} +1 -1
- package/build/serde/temporal.d.cts.map +1 -0
- package/build/{temporal.d.mts → serde/temporal.d.mts} +1 -1
- package/build/serde/temporal.d.mts.map +1 -0
- package/build/{temporal.js → serde/temporal.js} +1 -1
- package/build/serde/temporal.js.map +1 -0
- package/build/{temporalMappers.cjs → serde/temporalMappers.cjs} +4 -5
- package/build/serde/temporalMappers.cjs.map +1 -0
- package/build/{temporalMappers.d.cts → serde/temporalMappers.d.cts} +1 -1
- package/build/serde/temporalMappers.d.cts.map +1 -0
- package/build/{temporalMappers.d.mts → serde/temporalMappers.d.mts} +1 -1
- package/build/serde/temporalMappers.d.mts.map +1 -0
- package/build/{temporalMappers.js → serde/temporalMappers.js} +2 -3
- package/build/serde/temporalMappers.js.map +1 -0
- package/build/upsert.cjs +1 -1
- package/build/upsert.cjs.map +1 -1
- package/build/upsert.d.cts.map +1 -1
- package/build/upsert.d.mts.map +1 -1
- package/build/upsert.js +1 -1
- package/build/upsert.js.map +1 -1
- package/build/utils.cjs +0 -1
- package/build/utils.cjs.map +1 -1
- package/build/utils.d.cts +1 -1
- package/build/utils.d.mts +1 -1
- package/build/utils.js +0 -1
- package/build/utils.js.map +1 -1
- package/package.json +2 -2
- package/build/FlushLock.cjs.map +0 -1
- package/build/FlushLock.d.cts.map +0 -1
- package/build/FlushLock.d.mts.map +0 -1
- package/build/FlushLock.js.map +0 -1
- package/build/HintTree.cjs.map +0 -1
- package/build/HintTree.d.cts.map +0 -1
- package/build/HintTree.d.mts.map +0 -1
- package/build/HintTree.js.map +0 -1
- package/build/IsLoadedCache.d.cts.map +0 -1
- package/build/IsLoadedCache.d.mts.map +0 -1
- package/build/IsLoadedCache.js.map +0 -1
- package/build/JoinRows.cjs.map +0 -1
- package/build/JoinRows.d.cts.map +0 -1
- package/build/JoinRows.d.mts.map +0 -1
- package/build/JoinRows.js.map +0 -1
- package/build/PendingChanges.d.cts.map +0 -1
- package/build/PendingChanges.d.mts.map +0 -1
- package/build/PendingChanges.js +0 -2
- package/build/ReactionsManager.cjs.map +0 -1
- package/build/ReactionsManager.d.cts.map +0 -1
- package/build/ReactionsManager.d.mts.map +0 -1
- package/build/ReactionsManager.js.map +0 -1
- package/build/Todo.cjs.map +0 -1
- package/build/Todo.d.cts.map +0 -1
- package/build/Todo.d.mts.map +0 -1
- package/build/Todo.js.map +0 -1
- package/build/TypeInfo.cjs.map +0 -1
- package/build/TypeInfo.d.cts.map +0 -1
- package/build/TypeInfo.d.mts.map +0 -1
- package/build/TypeInfo.js.map +0 -1
- package/build/columns.cjs.map +0 -1
- package/build/columns.d.cts.map +0 -1
- package/build/columns.d.mts.map +0 -1
- package/build/columns.js.map +0 -1
- package/build/driverApi.cjs +0 -18
- package/build/driverApi.cjs.map +0 -1
- package/build/driverApi.d.cts +0 -22
- package/build/driverApi.d.cts.map +0 -1
- package/build/driverApi.d.mts +0 -22
- package/build/driverApi.d.mts.map +0 -1
- package/build/driverApi.js +0 -18
- package/build/driverApi.js.map +0 -1
- package/build/fieldSerde.cjs.map +0 -1
- package/build/fieldSerde.d.cts.map +0 -1
- package/build/fieldSerde.d.mts.map +0 -1
- package/build/fieldSerde.js.map +0 -1
- package/build/loadHints.cjs.map +0 -1
- package/build/loadHints.d.cts.map +0 -1
- package/build/loadHints.d.mts.map +0 -1
- package/build/loadHints.js.map +0 -1
- package/build/loadLens.cjs.map +0 -1
- package/build/loadLens.d.cts.map +0 -1
- package/build/loadLens.d.mts.map +0 -1
- package/build/loadLens.js.map +0 -1
- package/build/reactiveHints.cjs.map +0 -1
- package/build/reactiveHints.d.cts.map +0 -1
- package/build/reactiveHints.d.mts.map +0 -1
- package/build/reactiveHints.js.map +0 -1
- package/build/serde.cjs.map +0 -1
- package/build/serde.d.cts.map +0 -1
- package/build/serde.d.mts.map +0 -1
- package/build/serde.js.map +0 -1
- package/build/temporal.cjs.map +0 -1
- package/build/temporal.d.cts.map +0 -1
- package/build/temporal.d.mts.map +0 -1
- package/build/temporal.js.map +0 -1
- package/build/temporalMappers.cjs.map +0 -1
- package/build/temporalMappers.d.cts.map +0 -1
- package/build/temporalMappers.d.mts.map +0 -1
- package/build/temporalMappers.js.map +0 -1
- package/build/unnest.cjs.map +0 -1
- package/build/unnest.d.cts.map +0 -1
- package/build/unnest.d.mts.map +0 -1
- package/build/unnest.js.map +0 -1
- package/build/withLoaded.cjs.map +0 -1
- package/build/withLoaded.d.cts.map +0 -1
- package/build/withLoaded.d.mts.map +0 -1
- package/build/withLoaded.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lensDataLoader.cjs","names":["abbreviation","getMetadata","mapPathsToTarget","getBaseMeta","deTagIds","groupBy","tagId"],"sources":["../../src/dataloaders/lensDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\n\nimport { type Entity } from \"../Entity.ts\";\nimport { type EntityManager, type MaybeAbstractEntityConstructor, type TaggedId } from \"../EntityManager.ts\";\nimport {\n type EntityMetadata,\n type ManyToOneField,\n type OneToManyField,\n type OneToOneField,\n getBaseMeta,\n getMetadata,\n} from \"../EntityMetadata.ts\";\nimport { deTagIds, tagId } from \"../keys.ts\";\nimport { mapPathsToTarget } from \"../loadLens.ts\";\nimport {\n type ParsedFindQuery,\n type ParsedOrderBy,\n type ParsedTable,\n addTablePerClassJoinsAndClassTag,\n maybeAddOrderBy,\n} from \"../queries/find/QueryParser.ts\";\nimport type { ColumnCondition } from \"../queries/parsedConditions.ts\";\nimport { abbreviation, groupBy } from \"../utils.ts\";\n\nexport const lensOperation = \"lens\";\n\n/**\n * Loads lens paths via SQL.\n *\n * I.e. instead of loading `author.load(a => a.books.reviews)` by pulling all\n * Books into memory, we do a join from the Author to BookReviews.\n */\nexport function lensDataLoader<T extends Entity>(\n em: EntityManager,\n type: MaybeAbstractEntityConstructor<T>,\n startIsArray: boolean,\n paths: string[],\n): DataLoader<TaggedId, T | T[]> {\n // Batch lens loads by type + path to avoid N+1s\n const batchKey = `${type.name}-${paths.join(\"/\")}`;\n return em.getLoader(lensOperation, batchKey, async (sourceIds) => {\n const aliases: Record<string, number> = {};\n function getAlias(tableName: string): string {\n const abbrev = abbreviation(tableName);\n const i = aliases[abbrev] || 0;\n aliases[abbrev] = i + 1;\n return i === 0 ? abbrev : `${abbrev}${i}`;\n }\n\n // br.load(br => br.book.author)\n // select br.id as __source_id, a.*\n // from authors a\n // join books b ON b.author_id = a.id\n // join book_reviews br ON br.book_id = br.id\n // where br.id in (keys)\n // source=BR, target=Author, fields=books,bookReviews\n\n // a.load(a => a.books.reviews)\n // select b.author_id as __source_id, br.*\n // from book_reviews br\n // join books b on b.id = br.book_id\n // where b.author_id in (keys)\n\n const source = getMetadata(type);\n // Walk source -> paths -> the target, and return the target -> source fields\n const [target, fields] = mapPathsToTarget(source, paths);\n let resultIsArray = startIsArray;\n\n const alias = getAlias(target.tableName);\n const selects = [`\"${alias}\".*`];\n const tables: ParsedTable[] = [{ alias, join: \"primary\", table: target.tableName }];\n const conditions: ColumnCondition[] = [];\n const orderBys: ParsedOrderBy[] = [];\n const query: ParsedFindQuery = { selects, tables, condition: { kind: \"exp\", op: \"and\", conditions }, orderBys };\n addTablePerClassJoinsAndClassTag(query, target, alias, true);\n maybeAddOrderBy(query, target, alias);\n\n function maybeAddNotSoftDeleted(other: EntityMetadata, alias: string): void {\n const { deletedAt } = getBaseMeta(other).timestampFields ?? {};\n if (deletedAt) {\n const column = other.allFields[deletedAt].serde?.columns[0]!;\n conditions.push({\n kind: \"column\",\n alias,\n column: column.columnName,\n dbType: column.dbType,\n cond: { kind: \"is-null\" },\n });\n }\n }\n\n let lastAlias = alias;\n fields.forEach(([, field], i) => {\n const isLast = i === fields.length - 1;\n switch (field.kind) {\n case \"o2o\":\n case \"o2m\": {\n // This is `Publisher.authors` and we want to join in the authors table,\n // so get the `Author.publisher` field to know the column name\n const other = field.otherMetadata();\n const m2o = other.allFields[field.otherFieldName] as ManyToOneField;\n const alias = getAlias(other.tableName);\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.${m2o.serde.columns[0].columnName}`,\n col2: `${lastAlias}.id`,\n });\n maybeAddNotSoftDeleted(other, alias);\n if (isLast) {\n selects.push(`\"${alias}\".id as __source_id`);\n conditions.push({\n kind: \"column\",\n alias,\n column: \"id\",\n dbType: other.idDbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n }\n lastAlias = alias;\n break;\n }\n case \"m2o\": {\n // This is `Book.author` and we want to join in the authors table\n const other = field.otherMetadata();\n const otherField = other.fields[field.otherFieldName] as OneToManyField | OneToOneField;\n const alias = getAlias(other.tableName);\n if (!isLast) {\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.id`,\n col2: `${lastAlias}.${field.serde.columns[0].columnName}`,\n });\n maybeAddNotSoftDeleted(other, alias);\n } else {\n selects.push(`\"${lastAlias}\".${field.serde.columns[0].columnName} as __source_id`);\n conditions.push({\n kind: \"column\",\n alias: lastAlias,\n column: field.serde.columns[0].columnName,\n dbType: field.serde.columns[0].dbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n // Need to add filter for soft-deleted...\n }\n resultIsArray = otherField.kind === \"o2o\" ? resultIsArray : true;\n lastAlias = alias;\n break;\n }\n case \"m2m\": {\n // This is `Book.tags` and we want to join through the m2m table\n const other = field.otherMetadata();\n const alias = getAlias(other.tableName);\n tables.push({\n alias: `${alias}_m2m`,\n join: \"inner\",\n table: field.joinTableName,\n col1: `${alias}_m2m.${field.columnNames[0]}`,\n col2: `${lastAlias}.id`,\n });\n // If this is the last table, we could skip this join like we do for m2os\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.id`,\n col2: `${alias}_m2m.${field.columnNames[1]}`,\n });\n maybeAddNotSoftDeleted(other, alias);\n if (isLast) {\n selects.push(`\"${alias}\".id as __source_id`);\n conditions.push({\n kind: \"column\",\n alias,\n column: \"id\",\n dbType: other.idDbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n }\n resultIsArray = true;\n lastAlias = alias;\n break;\n }\n default:\n throw new Error(\"Unsupported field kind: \" + field.kind);\n }\n });\n\n // Get back `__source_id, target.*`\n const rows = await em[\"executeFind\"](target, lensOperation, query, {});\n\n // Group the target entities (i.e. BookReview) by the source id we reached them from.\n const entitiesBySourceId = new Map(\n [...groupBy(rows, (row) => row[\"__source_id\"]).entries()].map(([sourceId, rows]) => {\n // We may technically re-hydrate the same entity twice if it was reached\n // via multiple sources, but that should be fine/get deduped by hydrate.\n return [tagId(source, sourceId), em.hydrate(target.cstr, rows)];\n }),\n );\n\n // Re-order the output by the batched input\n return sourceIds.map((id) => {\n const result = entitiesBySourceId.get(id);\n return resultIsArray ? [...new Set(result ?? [])] : result?.[0];\n });\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lensDataLoader.cjs","names":["abbreviation","getMetadata","mapPathsToTarget","getBaseMeta","deTagIds","groupBy","tagId"],"sources":["../../src/dataloaders/lensDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\nimport { type Entity } from \"src/Entity.ts\";\nimport { type EntityManager, type MaybeAbstractEntityConstructor, type TaggedId } from \"src/EntityManager.ts\";\nimport {\n type EntityMetadata,\n type ManyToOneField,\n type OneToManyField,\n type OneToOneField,\n getBaseMeta,\n getMetadata,\n} from \"src/EntityMetadata.ts\";\nimport { deTagIds, tagId } from \"src/keys.ts\";\nimport { mapPathsToTarget } from \"src/loading/loadLens.ts\";\nimport {\n type ParsedFindQuery,\n type ParsedOrderBy,\n type ParsedTable,\n addTablePerClassJoinsAndClassTag,\n maybeAddOrderBy,\n} from \"src/queries/find/QueryParser.ts\";\nimport type { ColumnCondition } from \"src/queries/parsedConditions.ts\";\nimport { abbreviation, groupBy } from \"src/utils.ts\";\n\nexport const lensOperation = \"lens\";\n\n/**\n * Loads lens paths via SQL.\n *\n * I.e. instead of loading `author.load(a => a.books.reviews)` by pulling all\n * Books into memory, we do a join from the Author to BookReviews.\n */\nexport function lensDataLoader<T extends Entity>(\n em: EntityManager,\n type: MaybeAbstractEntityConstructor<T>,\n startIsArray: boolean,\n paths: string[],\n): DataLoader<TaggedId, T | T[]> {\n // Batch lens loads by type + path to avoid N+1s\n const batchKey = `${type.name}-${paths.join(\"/\")}`;\n return em.getLoader(lensOperation, batchKey, async (sourceIds) => {\n const aliases: Record<string, number> = {};\n function getAlias(tableName: string): string {\n const abbrev = abbreviation(tableName);\n const i = aliases[abbrev] || 0;\n aliases[abbrev] = i + 1;\n return i === 0 ? abbrev : `${abbrev}${i}`;\n }\n\n // br.load(br => br.book.author)\n // select br.id as __source_id, a.*\n // from authors a\n // join books b ON b.author_id = a.id\n // join book_reviews br ON br.book_id = br.id\n // where br.id in (keys)\n // source=BR, target=Author, fields=books,bookReviews\n\n // a.load(a => a.books.reviews)\n // select b.author_id as __source_id, br.*\n // from book_reviews br\n // join books b on b.id = br.book_id\n // where b.author_id in (keys)\n\n const source = getMetadata(type);\n // Walk source -> paths -> the target, and return the target -> source fields\n const [target, fields] = mapPathsToTarget(source, paths);\n let resultIsArray = startIsArray;\n\n const alias = getAlias(target.tableName);\n const selects = [`\"${alias}\".*`];\n const tables: ParsedTable[] = [{ alias, join: \"primary\", table: target.tableName }];\n const conditions: ColumnCondition[] = [];\n const orderBys: ParsedOrderBy[] = [];\n const query: ParsedFindQuery = { selects, tables, condition: { kind: \"exp\", op: \"and\", conditions }, orderBys };\n addTablePerClassJoinsAndClassTag(query, target, alias, true);\n maybeAddOrderBy(query, target, alias);\n\n function maybeAddNotSoftDeleted(other: EntityMetadata, alias: string): void {\n const { deletedAt } = getBaseMeta(other).timestampFields ?? {};\n if (deletedAt) {\n const column = other.allFields[deletedAt].serde?.columns[0]!;\n conditions.push({\n kind: \"column\",\n alias,\n column: column.columnName,\n dbType: column.dbType,\n cond: { kind: \"is-null\" },\n });\n }\n }\n\n let lastAlias = alias;\n fields.forEach(([, field], i) => {\n const isLast = i === fields.length - 1;\n switch (field.kind) {\n case \"o2o\":\n case \"o2m\": {\n // This is `Publisher.authors` and we want to join in the authors table,\n // so get the `Author.publisher` field to know the column name\n const other = field.otherMetadata();\n const m2o = other.allFields[field.otherFieldName] as ManyToOneField;\n const alias = getAlias(other.tableName);\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.${m2o.serde.columns[0].columnName}`,\n col2: `${lastAlias}.id`,\n });\n maybeAddNotSoftDeleted(other, alias);\n if (isLast) {\n selects.push(`\"${alias}\".id as __source_id`);\n conditions.push({\n kind: \"column\",\n alias,\n column: \"id\",\n dbType: other.idDbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n }\n lastAlias = alias;\n break;\n }\n case \"m2o\": {\n // This is `Book.author` and we want to join in the authors table\n const other = field.otherMetadata();\n const otherField = other.fields[field.otherFieldName] as OneToManyField | OneToOneField;\n const alias = getAlias(other.tableName);\n if (!isLast) {\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.id`,\n col2: `${lastAlias}.${field.serde.columns[0].columnName}`,\n });\n maybeAddNotSoftDeleted(other, alias);\n } else {\n selects.push(`\"${lastAlias}\".${field.serde.columns[0].columnName} as __source_id`);\n conditions.push({\n kind: \"column\",\n alias: lastAlias,\n column: field.serde.columns[0].columnName,\n dbType: field.serde.columns[0].dbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n // Need to add filter for soft-deleted...\n }\n resultIsArray = otherField.kind === \"o2o\" ? resultIsArray : true;\n lastAlias = alias;\n break;\n }\n case \"m2m\": {\n // This is `Book.tags` and we want to join through the m2m table\n const other = field.otherMetadata();\n const alias = getAlias(other.tableName);\n tables.push({\n alias: `${alias}_m2m`,\n join: \"inner\",\n table: field.joinTableName,\n col1: `${alias}_m2m.${field.columnNames[0]}`,\n col2: `${lastAlias}.id`,\n });\n // If this is the last table, we could skip this join like we do for m2os\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.id`,\n col2: `${alias}_m2m.${field.columnNames[1]}`,\n });\n maybeAddNotSoftDeleted(other, alias);\n if (isLast) {\n selects.push(`\"${alias}\".id as __source_id`);\n conditions.push({\n kind: \"column\",\n alias,\n column: \"id\",\n dbType: other.idDbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n }\n resultIsArray = true;\n lastAlias = alias;\n break;\n }\n default:\n throw new Error(\"Unsupported field kind: \" + field.kind);\n }\n });\n\n // Get back `__source_id, target.*`\n const rows = await em[\"executeFind\"](target, lensOperation, query, {});\n\n // Group the target entities (i.e. BookReview) by the source id we reached them from.\n const entitiesBySourceId = new Map(\n [...groupBy(rows, (row) => row[\"__source_id\"]).entries()].map(([sourceId, rows]) => {\n // We may technically re-hydrate the same entity twice if it was reached\n // via multiple sources, but that should be fine/get deduped by hydrate.\n return [tagId(source, sourceId), em.hydrate(target.cstr, rows)];\n }),\n );\n\n // Re-order the output by the batched input\n return sourceIds.map((id) => {\n const result = entitiesBySourceId.get(id);\n return resultIsArray ? [...new Set(result ?? [])] : result?.[0];\n });\n });\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lensDataLoader.d.cts","names":[],"sources":["../../src/dataloaders/lensDataLoader.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"lensDataLoader.d.cts","names":[],"sources":["../../src/dataloaders/lensDataLoader.ts"],"mappings":";;;;cAuBa;;;;;;;iBAQG,eAAe,UAAU,QACvC,IAAI,eACJ,MAAM,+BAA+B,IACrC,uBACA,kBACC,WAAW,UAAU,IAAI"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lensDataLoader.d.mts","names":[],"sources":["../../src/dataloaders/lensDataLoader.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"lensDataLoader.d.mts","names":[],"sources":["../../src/dataloaders/lensDataLoader.ts"],"mappings":";;;;cAuBa;;;;;;;iBAQG,eAAe,UAAU,QACvC,IAAI,eACJ,MAAM,+BAA+B,IACrC,uBACA,kBACC,WAAW,UAAU,IAAI"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { deTagIds, tagId } from "../keys.js";
|
|
1
2
|
import { addTablePerClassJoinsAndClassTag, maybeAddOrderBy } from "../queries/find/QueryParser.js";
|
|
2
3
|
import { abbreviation, groupBy } from "../utils.js";
|
|
3
|
-
import { deTagIds, tagId } from "../keys.js";
|
|
4
4
|
import { getBaseMeta, getMetadata } from "../EntityMetadata.js";
|
|
5
|
-
import { mapPathsToTarget } from "../loadLens.js";
|
|
5
|
+
import { mapPathsToTarget } from "../loading/loadLens.js";
|
|
6
6
|
import "../EntityManager.js";
|
|
7
7
|
import "../Entity.js";
|
|
8
8
|
//#region src/dataloaders/lensDataLoader.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lensDataLoader.js","names":[],"sources":["../../src/dataloaders/lensDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\n\nimport { type Entity } from \"../Entity.ts\";\nimport { type EntityManager, type MaybeAbstractEntityConstructor, type TaggedId } from \"../EntityManager.ts\";\nimport {\n type EntityMetadata,\n type ManyToOneField,\n type OneToManyField,\n type OneToOneField,\n getBaseMeta,\n getMetadata,\n} from \"../EntityMetadata.ts\";\nimport { deTagIds, tagId } from \"../keys.ts\";\nimport { mapPathsToTarget } from \"../loadLens.ts\";\nimport {\n type ParsedFindQuery,\n type ParsedOrderBy,\n type ParsedTable,\n addTablePerClassJoinsAndClassTag,\n maybeAddOrderBy,\n} from \"../queries/find/QueryParser.ts\";\nimport type { ColumnCondition } from \"../queries/parsedConditions.ts\";\nimport { abbreviation, groupBy } from \"../utils.ts\";\n\nexport const lensOperation = \"lens\";\n\n/**\n * Loads lens paths via SQL.\n *\n * I.e. instead of loading `author.load(a => a.books.reviews)` by pulling all\n * Books into memory, we do a join from the Author to BookReviews.\n */\nexport function lensDataLoader<T extends Entity>(\n em: EntityManager,\n type: MaybeAbstractEntityConstructor<T>,\n startIsArray: boolean,\n paths: string[],\n): DataLoader<TaggedId, T | T[]> {\n // Batch lens loads by type + path to avoid N+1s\n const batchKey = `${type.name}-${paths.join(\"/\")}`;\n return em.getLoader(lensOperation, batchKey, async (sourceIds) => {\n const aliases: Record<string, number> = {};\n function getAlias(tableName: string): string {\n const abbrev = abbreviation(tableName);\n const i = aliases[abbrev] || 0;\n aliases[abbrev] = i + 1;\n return i === 0 ? abbrev : `${abbrev}${i}`;\n }\n\n // br.load(br => br.book.author)\n // select br.id as __source_id, a.*\n // from authors a\n // join books b ON b.author_id = a.id\n // join book_reviews br ON br.book_id = br.id\n // where br.id in (keys)\n // source=BR, target=Author, fields=books,bookReviews\n\n // a.load(a => a.books.reviews)\n // select b.author_id as __source_id, br.*\n // from book_reviews br\n // join books b on b.id = br.book_id\n // where b.author_id in (keys)\n\n const source = getMetadata(type);\n // Walk source -> paths -> the target, and return the target -> source fields\n const [target, fields] = mapPathsToTarget(source, paths);\n let resultIsArray = startIsArray;\n\n const alias = getAlias(target.tableName);\n const selects = [`\"${alias}\".*`];\n const tables: ParsedTable[] = [{ alias, join: \"primary\", table: target.tableName }];\n const conditions: ColumnCondition[] = [];\n const orderBys: ParsedOrderBy[] = [];\n const query: ParsedFindQuery = { selects, tables, condition: { kind: \"exp\", op: \"and\", conditions }, orderBys };\n addTablePerClassJoinsAndClassTag(query, target, alias, true);\n maybeAddOrderBy(query, target, alias);\n\n function maybeAddNotSoftDeleted(other: EntityMetadata, alias: string): void {\n const { deletedAt } = getBaseMeta(other).timestampFields ?? {};\n if (deletedAt) {\n const column = other.allFields[deletedAt].serde?.columns[0]!;\n conditions.push({\n kind: \"column\",\n alias,\n column: column.columnName,\n dbType: column.dbType,\n cond: { kind: \"is-null\" },\n });\n }\n }\n\n let lastAlias = alias;\n fields.forEach(([, field], i) => {\n const isLast = i === fields.length - 1;\n switch (field.kind) {\n case \"o2o\":\n case \"o2m\": {\n // This is `Publisher.authors` and we want to join in the authors table,\n // so get the `Author.publisher` field to know the column name\n const other = field.otherMetadata();\n const m2o = other.allFields[field.otherFieldName] as ManyToOneField;\n const alias = getAlias(other.tableName);\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.${m2o.serde.columns[0].columnName}`,\n col2: `${lastAlias}.id`,\n });\n maybeAddNotSoftDeleted(other, alias);\n if (isLast) {\n selects.push(`\"${alias}\".id as __source_id`);\n conditions.push({\n kind: \"column\",\n alias,\n column: \"id\",\n dbType: other.idDbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n }\n lastAlias = alias;\n break;\n }\n case \"m2o\": {\n // This is `Book.author` and we want to join in the authors table\n const other = field.otherMetadata();\n const otherField = other.fields[field.otherFieldName] as OneToManyField | OneToOneField;\n const alias = getAlias(other.tableName);\n if (!isLast) {\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.id`,\n col2: `${lastAlias}.${field.serde.columns[0].columnName}`,\n });\n maybeAddNotSoftDeleted(other, alias);\n } else {\n selects.push(`\"${lastAlias}\".${field.serde.columns[0].columnName} as __source_id`);\n conditions.push({\n kind: \"column\",\n alias: lastAlias,\n column: field.serde.columns[0].columnName,\n dbType: field.serde.columns[0].dbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n // Need to add filter for soft-deleted...\n }\n resultIsArray = otherField.kind === \"o2o\" ? resultIsArray : true;\n lastAlias = alias;\n break;\n }\n case \"m2m\": {\n // This is `Book.tags` and we want to join through the m2m table\n const other = field.otherMetadata();\n const alias = getAlias(other.tableName);\n tables.push({\n alias: `${alias}_m2m`,\n join: \"inner\",\n table: field.joinTableName,\n col1: `${alias}_m2m.${field.columnNames[0]}`,\n col2: `${lastAlias}.id`,\n });\n // If this is the last table, we could skip this join like we do for m2os\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.id`,\n col2: `${alias}_m2m.${field.columnNames[1]}`,\n });\n maybeAddNotSoftDeleted(other, alias);\n if (isLast) {\n selects.push(`\"${alias}\".id as __source_id`);\n conditions.push({\n kind: \"column\",\n alias,\n column: \"id\",\n dbType: other.idDbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n }\n resultIsArray = true;\n lastAlias = alias;\n break;\n }\n default:\n throw new Error(\"Unsupported field kind: \" + field.kind);\n }\n });\n\n // Get back `__source_id, target.*`\n const rows = await em[\"executeFind\"](target, lensOperation, query, {});\n\n // Group the target entities (i.e. BookReview) by the source id we reached them from.\n const entitiesBySourceId = new Map(\n [...groupBy(rows, (row) => row[\"__source_id\"]).entries()].map(([sourceId, rows]) => {\n // We may technically re-hydrate the same entity twice if it was reached\n // via multiple sources, but that should be fine/get deduped by hydrate.\n return [tagId(source, sourceId), em.hydrate(target.cstr, rows)];\n }),\n );\n\n // Re-order the output by the batched input\n return sourceIds.map((id) => {\n const result = entitiesBySourceId.get(id);\n return resultIsArray ? [...new Set(result ?? [])] : result?.[0];\n });\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lensDataLoader.js","names":[],"sources":["../../src/dataloaders/lensDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\nimport { type Entity } from \"src/Entity.ts\";\nimport { type EntityManager, type MaybeAbstractEntityConstructor, type TaggedId } from \"src/EntityManager.ts\";\nimport {\n type EntityMetadata,\n type ManyToOneField,\n type OneToManyField,\n type OneToOneField,\n getBaseMeta,\n getMetadata,\n} from \"src/EntityMetadata.ts\";\nimport { deTagIds, tagId } from \"src/keys.ts\";\nimport { mapPathsToTarget } from \"src/loading/loadLens.ts\";\nimport {\n type ParsedFindQuery,\n type ParsedOrderBy,\n type ParsedTable,\n addTablePerClassJoinsAndClassTag,\n maybeAddOrderBy,\n} from \"src/queries/find/QueryParser.ts\";\nimport type { ColumnCondition } from \"src/queries/parsedConditions.ts\";\nimport { abbreviation, groupBy } from \"src/utils.ts\";\n\nexport const lensOperation = \"lens\";\n\n/**\n * Loads lens paths via SQL.\n *\n * I.e. instead of loading `author.load(a => a.books.reviews)` by pulling all\n * Books into memory, we do a join from the Author to BookReviews.\n */\nexport function lensDataLoader<T extends Entity>(\n em: EntityManager,\n type: MaybeAbstractEntityConstructor<T>,\n startIsArray: boolean,\n paths: string[],\n): DataLoader<TaggedId, T | T[]> {\n // Batch lens loads by type + path to avoid N+1s\n const batchKey = `${type.name}-${paths.join(\"/\")}`;\n return em.getLoader(lensOperation, batchKey, async (sourceIds) => {\n const aliases: Record<string, number> = {};\n function getAlias(tableName: string): string {\n const abbrev = abbreviation(tableName);\n const i = aliases[abbrev] || 0;\n aliases[abbrev] = i + 1;\n return i === 0 ? abbrev : `${abbrev}${i}`;\n }\n\n // br.load(br => br.book.author)\n // select br.id as __source_id, a.*\n // from authors a\n // join books b ON b.author_id = a.id\n // join book_reviews br ON br.book_id = br.id\n // where br.id in (keys)\n // source=BR, target=Author, fields=books,bookReviews\n\n // a.load(a => a.books.reviews)\n // select b.author_id as __source_id, br.*\n // from book_reviews br\n // join books b on b.id = br.book_id\n // where b.author_id in (keys)\n\n const source = getMetadata(type);\n // Walk source -> paths -> the target, and return the target -> source fields\n const [target, fields] = mapPathsToTarget(source, paths);\n let resultIsArray = startIsArray;\n\n const alias = getAlias(target.tableName);\n const selects = [`\"${alias}\".*`];\n const tables: ParsedTable[] = [{ alias, join: \"primary\", table: target.tableName }];\n const conditions: ColumnCondition[] = [];\n const orderBys: ParsedOrderBy[] = [];\n const query: ParsedFindQuery = { selects, tables, condition: { kind: \"exp\", op: \"and\", conditions }, orderBys };\n addTablePerClassJoinsAndClassTag(query, target, alias, true);\n maybeAddOrderBy(query, target, alias);\n\n function maybeAddNotSoftDeleted(other: EntityMetadata, alias: string): void {\n const { deletedAt } = getBaseMeta(other).timestampFields ?? {};\n if (deletedAt) {\n const column = other.allFields[deletedAt].serde?.columns[0]!;\n conditions.push({\n kind: \"column\",\n alias,\n column: column.columnName,\n dbType: column.dbType,\n cond: { kind: \"is-null\" },\n });\n }\n }\n\n let lastAlias = alias;\n fields.forEach(([, field], i) => {\n const isLast = i === fields.length - 1;\n switch (field.kind) {\n case \"o2o\":\n case \"o2m\": {\n // This is `Publisher.authors` and we want to join in the authors table,\n // so get the `Author.publisher` field to know the column name\n const other = field.otherMetadata();\n const m2o = other.allFields[field.otherFieldName] as ManyToOneField;\n const alias = getAlias(other.tableName);\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.${m2o.serde.columns[0].columnName}`,\n col2: `${lastAlias}.id`,\n });\n maybeAddNotSoftDeleted(other, alias);\n if (isLast) {\n selects.push(`\"${alias}\".id as __source_id`);\n conditions.push({\n kind: \"column\",\n alias,\n column: \"id\",\n dbType: other.idDbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n }\n lastAlias = alias;\n break;\n }\n case \"m2o\": {\n // This is `Book.author` and we want to join in the authors table\n const other = field.otherMetadata();\n const otherField = other.fields[field.otherFieldName] as OneToManyField | OneToOneField;\n const alias = getAlias(other.tableName);\n if (!isLast) {\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.id`,\n col2: `${lastAlias}.${field.serde.columns[0].columnName}`,\n });\n maybeAddNotSoftDeleted(other, alias);\n } else {\n selects.push(`\"${lastAlias}\".${field.serde.columns[0].columnName} as __source_id`);\n conditions.push({\n kind: \"column\",\n alias: lastAlias,\n column: field.serde.columns[0].columnName,\n dbType: field.serde.columns[0].dbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n // Need to add filter for soft-deleted...\n }\n resultIsArray = otherField.kind === \"o2o\" ? resultIsArray : true;\n lastAlias = alias;\n break;\n }\n case \"m2m\": {\n // This is `Book.tags` and we want to join through the m2m table\n const other = field.otherMetadata();\n const alias = getAlias(other.tableName);\n tables.push({\n alias: `${alias}_m2m`,\n join: \"inner\",\n table: field.joinTableName,\n col1: `${alias}_m2m.${field.columnNames[0]}`,\n col2: `${lastAlias}.id`,\n });\n // If this is the last table, we could skip this join like we do for m2os\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.id`,\n col2: `${alias}_m2m.${field.columnNames[1]}`,\n });\n maybeAddNotSoftDeleted(other, alias);\n if (isLast) {\n selects.push(`\"${alias}\".id as __source_id`);\n conditions.push({\n kind: \"column\",\n alias,\n column: \"id\",\n dbType: other.idDbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n }\n resultIsArray = true;\n lastAlias = alias;\n break;\n }\n default:\n throw new Error(\"Unsupported field kind: \" + field.kind);\n }\n });\n\n // Get back `__source_id, target.*`\n const rows = await em[\"executeFind\"](target, lensOperation, query, {});\n\n // Group the target entities (i.e. BookReview) by the source id we reached them from.\n const entitiesBySourceId = new Map(\n [...groupBy(rows, (row) => row[\"__source_id\"]).entries()].map(([sourceId, rows]) => {\n // We may technically re-hydrate the same entity twice if it was reached\n // via multiple sources, but that should be fine/get deduped by hydrate.\n return [tagId(source, sourceId), em.hydrate(target.cstr, rows)];\n }),\n );\n\n // Re-order the output by the batched input\n return sourceIds.map((id) => {\n const result = entitiesBySourceId.get(id);\n return resultIsArray ? [...new Set(result ?? [])] : result?.[0];\n });\n });\n}\n"],"mappings":";;;;;;;;AAuBA,MAAa,gBAAgB;;;;;;;AAQ7B,SAAgB,eACd,IACA,MACA,cACA,OAC+B;CAE/B,MAAM,WAAW,GAAG,KAAK,KAAK,GAAG,MAAM,KAAK,GAAG;CAC/C,OAAO,GAAG,UAAU,eAAe,UAAU,OAAO,cAAc;EAChE,MAAM,UAAkC,CAAC;EACzC,SAAS,SAAS,WAA2B;GAC3C,MAAM,SAAS,aAAa,SAAS;GACrC,MAAM,IAAI,QAAQ,WAAW;GAC7B,QAAQ,UAAU,IAAI;GACtB,OAAO,MAAM,IAAI,SAAS,GAAG,SAAS;EACxC;EAgBA,MAAM,SAAS,YAAY,IAAI;EAE/B,MAAM,CAAC,QAAQ,UAAU,iBAAiB,QAAQ,KAAK;EACvD,IAAI,gBAAgB;EAEpB,MAAM,QAAQ,SAAS,OAAO,SAAS;EACvC,MAAM,UAAU,CAAC,IAAI,MAAM,IAAI;EAC/B,MAAM,SAAwB,CAAC;GAAE;GAAO,MAAM;GAAW,OAAO,OAAO;EAAU,CAAC;EAClF,MAAM,aAAgC,CAAC;EAEvC,MAAM,QAAyB;GAAE;GAAS;GAAQ,WAAW;IAAE,MAAM;IAAO,IAAI;IAAO;GAAW;GAAG,UAAA,CAAO;EAAE;EAC9G,iCAAiC,OAAO,QAAQ,OAAO,IAAI;EAC3D,gBAAgB,OAAO,QAAQ,KAAK;EAEpC,SAAS,uBAAuB,OAAuB,OAAqB;GAC1E,MAAM,EAAE,cAAc,YAAY,KAAK,CAAC,CAAC,mBAAmB,CAAC;GAC7D,IAAI,WAAW;IACb,MAAM,SAAS,MAAM,UAAU,UAAU,CAAC,OAAO,QAAQ;IACzD,WAAW,KAAK;KACd,MAAM;KACN;KACA,QAAQ,OAAO;KACf,QAAQ,OAAO;KACf,MAAM,EAAE,MAAM,UAAU;IAC1B,CAAC;GACH;EACF;EAEA,IAAI,YAAY;EAChB,OAAO,SAAS,GAAG,QAAQ,MAAM;GAC/B,MAAM,SAAS,MAAM,OAAO,SAAS;GACrC,QAAQ,MAAM,MAAd;IACE,KAAK;IACL,KAAK,OAAO;KAGV,MAAM,QAAQ,MAAM,cAAc;KAClC,MAAM,MAAM,MAAM,UAAU,MAAM;KAClC,MAAM,QAAQ,SAAS,MAAM,SAAS;KACtC,OAAO,KAAK;MACV;MACA,MAAM;MACN,OAAO,MAAM;MACb,MAAM,GAAG,MAAM,GAAG,IAAI,MAAM,QAAQ,EAAE,CAAC;MACvC,MAAM,GAAG,UAAU;KACrB,CAAC;KACD,uBAAuB,OAAO,KAAK;KACnC,IAAI,QAAQ;MACV,QAAQ,KAAK,IAAI,MAAM,oBAAoB;MAC3C,WAAW,KAAK;OACd,MAAM;OACN;OACA,QAAQ;OACR,QAAQ,MAAM;OACd,MAAM;QAAE,MAAM;QAAM,OAAO,SAAS,QAAQ,SAAS;OAAE;MACzD,CAAC;KACH;KACA,YAAY;KACZ;IACF;IACA,KAAK,OAAO;KAEV,MAAM,QAAQ,MAAM,cAAc;KAClC,MAAM,aAAa,MAAM,OAAO,MAAM;KACtC,MAAM,QAAQ,SAAS,MAAM,SAAS;KACtC,IAAI,CAAC,QAAQ;MACX,OAAO,KAAK;OACV;OACA,MAAM;OACN,OAAO,MAAM;OACb,MAAM,GAAG,MAAM;OACf,MAAM,GAAG,UAAU,GAAG,MAAM,MAAM,QAAQ,EAAE,CAAC;MAC/C,CAAC;MACD,uBAAuB,OAAO,KAAK;KACrC,OAAO;MACL,QAAQ,KAAK,IAAI,UAAU,IAAI,MAAM,MAAM,QAAQ,EAAE,CAAC,WAAW,gBAAgB;MACjF,WAAW,KAAK;OACd,MAAM;OACN,OAAO;OACP,QAAQ,MAAM,MAAM,QAAQ,EAAE,CAAC;OAC/B,QAAQ,MAAM,MAAM,QAAQ,EAAE,CAAC;OAC/B,MAAM;QAAE,MAAM;QAAM,OAAO,SAAS,QAAQ,SAAS;OAAE;MACzD,CAAC;KAEH;KACA,gBAAgB,WAAW,SAAS,QAAQ,gBAAgB;KAC5D,YAAY;KACZ;IACF;IACA,KAAK,OAAO;KAEV,MAAM,QAAQ,MAAM,cAAc;KAClC,MAAM,QAAQ,SAAS,MAAM,SAAS;KACtC,OAAO,KAAK;MACV,OAAO,GAAG,MAAM;MAChB,MAAM;MACN,OAAO,MAAM;MACb,MAAM,GAAG,MAAM,OAAO,MAAM,YAAY;MACxC,MAAM,GAAG,UAAU;KACrB,CAAC;KAED,OAAO,KAAK;MACV;MACA,MAAM;MACN,OAAO,MAAM;MACb,MAAM,GAAG,MAAM;MACf,MAAM,GAAG,MAAM,OAAO,MAAM,YAAY;KAC1C,CAAC;KACD,uBAAuB,OAAO,KAAK;KACnC,IAAI,QAAQ;MACV,QAAQ,KAAK,IAAI,MAAM,oBAAoB;MAC3C,WAAW,KAAK;OACd,MAAM;OACN;OACA,QAAQ;OACR,QAAQ,MAAM;OACd,MAAM;QAAE,MAAM;QAAM,OAAO,SAAS,QAAQ,SAAS;OAAE;MACzD,CAAC;KACH;KACA,gBAAgB;KAChB,YAAY;KACZ;IACF;IACA,SACE,MAAM,IAAI,MAAM,6BAA6B,MAAM,IAAI;GAC3D;EACF,CAAC;EAGD,MAAM,OAAO,MAAM,GAAG,cAAc,CAAC,QAAQ,eAAe,OAAO,CAAC,CAAC;EAGrE,MAAM,qBAAqB,IAAI,IAC7B,CAAC,GAAG,QAAQ,OAAO,QAAQ,IAAI,cAAc,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,UAAU;GAGlF,OAAO,CAAC,MAAM,QAAQ,QAAQ,GAAG,GAAG,QAAQ,OAAO,MAAM,IAAI,CAAC;EAChE,CAAC,CACH;EAGA,OAAO,UAAU,KAAK,OAAO;GAC3B,MAAM,SAAS,mBAAmB,IAAI,EAAE;GACxC,OAAO,gBAAgB,CAAC,GAAG,IAAI,IAAI,UAAU,CAAC,CAAC,CAAC,IAAI,SAAS;EAC/D,CAAC;CACH,CAAC;AACH"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_utils = require("../utils.cjs");
|
|
3
2
|
const require_keys = require("../keys.cjs");
|
|
3
|
+
const require_utils = require("../utils.cjs");
|
|
4
4
|
//#region src/dataloaders/manyToManyFindDataLoader.ts
|
|
5
5
|
const manyToManyFindOperation = "m2m-find";
|
|
6
6
|
/** Batches m2m.find/include calls (i.e. that don't fully load the m2m relation). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manyToManyFindDataLoader.cjs","names":["abbreviation","keyToNumber","tagId"],"sources":["../../src/dataloaders/manyToManyFindDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\
|
|
1
|
+
{"version":3,"file":"manyToManyFindDataLoader.cjs","names":["abbreviation","keyToNumber","tagId"],"sources":["../../src/dataloaders/manyToManyFindDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\nimport type { Entity } from \"src/Entity.ts\";\nimport type { EntityManager } from \"src/EntityManager.ts\";\nimport { keyToNumber, tagId } from \"src/keys.ts\";\nimport type { ParsedFindQuery } from \"src/queries/find/QueryParser.ts\";\nimport type { ManyToManyCollection } from \"src/relations/ManyToManyCollection.ts\";\nimport type { ManyToManyLargeCollection } from \"src/relations/ManyToManyLargeCollection.ts\";\nimport { abbreviation } from \"src/utils.ts\";\n\nexport const manyToManyFindOperation = \"m2m-find\";\n\n/** Batches m2m.find/include calls (i.e. that don't fully load the m2m relation). */\nexport function manyToManyFindDataLoader<T extends Entity, U extends Entity>(\n em: EntityManager,\n collection: ManyToManyCollection<T, U> | ManyToManyLargeCollection<T, U>,\n): DataLoader<string, boolean> {\n return em.getLoader(manyToManyFindOperation, collection.joinTableName, (keys) => load(collection, keys));\n}\n\nasync function load<T extends Entity, U extends Entity>(\n collection: ManyToManyCollection<T, U> | ManyToManyLargeCollection<T, U>,\n keys: ReadonlyArray<string>,\n): Promise<boolean[]> {\n const { joinTableName } = collection;\n const { em } = collection.entity;\n\n const alias = abbreviation(joinTableName);\n const query: ParsedFindQuery = {\n selects: [`\"${alias}\".*`],\n tables: [{ alias, join: \"primary\", table: joinTableName }],\n // Or together `where (tag_id = X and book_id = Y)` or `(book_id = B and tag_id = A)`\n condition: {\n kind: \"exp\",\n op: \"or\",\n conditions: keys.map((key) => {\n const [one, two] = key.split(\",\");\n const [columnOne, idOne] = one.split(\"=\");\n const [columnTwo, idTwo] = two.split(\"=\");\n // Pick the right meta i.e. tag_id --> TagMeta or book_id --> BookMeta\n const [meta1, meta2] =\n collection.columnName === columnOne\n ? [collection.meta, collection.otherMeta]\n : [collection.otherMeta, collection.meta];\n return {\n kind: \"exp\",\n op: \"and\",\n conditions: [\n {\n kind: \"column\",\n alias,\n column: columnOne,\n dbType: meta1.idDbType,\n cond: { kind: \"eq\", value: keyToNumber(meta1, idOne) },\n },\n {\n kind: \"column\",\n alias,\n column: columnTwo,\n dbType: meta2.idDbType,\n cond: { kind: \"eq\", value: keyToNumber(meta2, idTwo) },\n },\n ],\n };\n }),\n },\n // Id-less join tables have no surrogate id to order by, so order by the FK columns instead.\n orderBys: collection.hasJoinTableId\n ? [{ alias, column: \"id\", order: \"ASC\" }]\n : [\n { alias, column: collection.columnName, order: \"ASC\" },\n { alias, column: collection.otherColumnName, order: \"ASC\" },\n ],\n };\n\n const rows = await em[\"executeFind\"](collection.otherMeta, manyToManyFindOperation, query, {});\n\n const column1 = collection.columnName;\n const column2 = collection.otherColumnName;\n const meta1 = collection.meta;\n const meta2 = collection.otherMeta;\n\n // Because keys might come from either side of the m2m relationship, build\n // a list of both `foo_id=2,bar_id=3` and `bar_id=3,foo_id=2` to make the\n // final return value just a map of `Set.has`.\n const found = new Set(\n rows.flatMap((dbRow) => {\n const a = `${column1}=${tagId(meta1, dbRow[column1] as number)}`;\n const b = `${column2}=${tagId(meta2, dbRow[column2] as number)}`;\n return [`${a},${b}`, `${b},${a}`];\n }),\n );\n\n return keys.map((key) => found.has(key));\n}\n"],"mappings":";;;;AASA,MAAa,0BAA0B;;AAGvC,SAAgB,yBACd,IACA,YAC6B;CAC7B,OAAO,GAAG,UAAU,yBAAyB,WAAW,gBAAgB,SAAS,KAAK,YAAY,IAAI,CAAC;AACzG;AAEA,eAAe,KACb,YACA,MACoB;CACpB,MAAM,EAAE,kBAAkB;CAC1B,MAAM,EAAE,OAAO,WAAW;CAE1B,MAAM,QAAQA,cAAAA,aAAa,aAAa;CACxC,MAAM,QAAyB;EAC7B,SAAS,CAAC,IAAI,MAAM,IAAI;EACxB,QAAQ,CAAC;GAAE;GAAO,MAAM;GAAW,OAAO;EAAc,CAAC;EAEzD,WAAW;GACT,MAAM;GACN,IAAI;GACJ,YAAY,KAAK,KAAK,QAAQ;IAC5B,MAAM,CAAC,KAAK,OAAO,IAAI,MAAM,GAAG;IAChC,MAAM,CAAC,WAAW,SAAS,IAAI,MAAM,GAAG;IACxC,MAAM,CAAC,WAAW,SAAS,IAAI,MAAM,GAAG;IAExC,MAAM,CAAC,OAAO,SACZ,WAAW,eAAe,YACtB,CAAC,WAAW,MAAM,WAAW,SAAS,IACtC,CAAC,WAAW,WAAW,WAAW,IAAI;IAC5C,OAAO;KACL,MAAM;KACN,IAAI;KACJ,YAAY,CACV;MACE,MAAM;MACN;MACA,QAAQ;MACR,QAAQ,MAAM;MACd,MAAM;OAAE,MAAM;OAAM,OAAOC,aAAAA,YAAY,OAAO,KAAK;MAAE;KACvD,GACA;MACE,MAAM;MACN;MACA,QAAQ;MACR,QAAQ,MAAM;MACd,MAAM;OAAE,MAAM;OAAM,OAAOA,aAAAA,YAAY,OAAO,KAAK;MAAE;KACvD,CACF;IACF;GACF,CAAC;EACH;EAEA,UAAU,WAAW,iBACjB,CAAC;GAAE;GAAO,QAAQ;GAAM,OAAO;EAAM,CAAC,IACtC,CACE;GAAE;GAAO,QAAQ,WAAW;GAAY,OAAO;EAAM,GACrD;GAAE;GAAO,QAAQ,WAAW;GAAiB,OAAO;EAAM,CAC5D;CACN;CAEA,MAAM,OAAO,MAAM,GAAG,cAAc,CAAC,WAAW,WAAW,yBAAyB,OAAO,CAAC,CAAC;CAE7F,MAAM,UAAU,WAAW;CAC3B,MAAM,UAAU,WAAW;CAC3B,MAAM,QAAQ,WAAW;CACzB,MAAM,QAAQ,WAAW;CAKzB,MAAM,QAAQ,IAAI,IAChB,KAAK,SAAS,UAAU;EACtB,MAAM,IAAI,GAAG,QAAQ,GAAGC,aAAAA,MAAM,OAAO,MAAM,QAAkB;EAC7D,MAAM,IAAI,GAAG,QAAQ,GAAGA,aAAAA,MAAM,OAAO,MAAM,QAAkB;EAC7D,OAAO,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,EAAE,GAAG,GAAG;CAClC,CAAC,CACH;CAEA,OAAO,KAAK,KAAK,QAAQ,MAAM,IAAI,GAAG,CAAC;AACzC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manyToManyFindDataLoader.d.cts","names":[],"sources":["../../src/dataloaders/manyToManyFindDataLoader.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"manyToManyFindDataLoader.d.cts","names":[],"sources":["../../src/dataloaders/manyToManyFindDataLoader.ts"],"mappings":";;;;;;cASa;;iBAGG,yBAAyB,UAAU,QAAQ,UAAU,QACnE,IAAI,eACJ,YAAY,qBAAqB,GAAG,KAAK,0BAA0B,GAAG,KACrE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manyToManyFindDataLoader.d.mts","names":[],"sources":["../../src/dataloaders/manyToManyFindDataLoader.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"manyToManyFindDataLoader.d.mts","names":[],"sources":["../../src/dataloaders/manyToManyFindDataLoader.ts"],"mappings":";;;;;;cASa;;iBAGG,yBAAyB,UAAU,QAAQ,UAAU,QACnE,IAAI,eACJ,YAAY,qBAAqB,GAAG,KAAK,0BAA0B,GAAG,KACrE"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { abbreviation } from "../utils.js";
|
|
2
1
|
import { keyToNumber, tagId } from "../keys.js";
|
|
2
|
+
import { abbreviation } from "../utils.js";
|
|
3
3
|
//#region src/dataloaders/manyToManyFindDataLoader.ts
|
|
4
4
|
const manyToManyFindOperation = "m2m-find";
|
|
5
5
|
/** Batches m2m.find/include calls (i.e. that don't fully load the m2m relation). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manyToManyFindDataLoader.js","names":[],"sources":["../../src/dataloaders/manyToManyFindDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\
|
|
1
|
+
{"version":3,"file":"manyToManyFindDataLoader.js","names":[],"sources":["../../src/dataloaders/manyToManyFindDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\nimport type { Entity } from \"src/Entity.ts\";\nimport type { EntityManager } from \"src/EntityManager.ts\";\nimport { keyToNumber, tagId } from \"src/keys.ts\";\nimport type { ParsedFindQuery } from \"src/queries/find/QueryParser.ts\";\nimport type { ManyToManyCollection } from \"src/relations/ManyToManyCollection.ts\";\nimport type { ManyToManyLargeCollection } from \"src/relations/ManyToManyLargeCollection.ts\";\nimport { abbreviation } from \"src/utils.ts\";\n\nexport const manyToManyFindOperation = \"m2m-find\";\n\n/** Batches m2m.find/include calls (i.e. that don't fully load the m2m relation). */\nexport function manyToManyFindDataLoader<T extends Entity, U extends Entity>(\n em: EntityManager,\n collection: ManyToManyCollection<T, U> | ManyToManyLargeCollection<T, U>,\n): DataLoader<string, boolean> {\n return em.getLoader(manyToManyFindOperation, collection.joinTableName, (keys) => load(collection, keys));\n}\n\nasync function load<T extends Entity, U extends Entity>(\n collection: ManyToManyCollection<T, U> | ManyToManyLargeCollection<T, U>,\n keys: ReadonlyArray<string>,\n): Promise<boolean[]> {\n const { joinTableName } = collection;\n const { em } = collection.entity;\n\n const alias = abbreviation(joinTableName);\n const query: ParsedFindQuery = {\n selects: [`\"${alias}\".*`],\n tables: [{ alias, join: \"primary\", table: joinTableName }],\n // Or together `where (tag_id = X and book_id = Y)` or `(book_id = B and tag_id = A)`\n condition: {\n kind: \"exp\",\n op: \"or\",\n conditions: keys.map((key) => {\n const [one, two] = key.split(\",\");\n const [columnOne, idOne] = one.split(\"=\");\n const [columnTwo, idTwo] = two.split(\"=\");\n // Pick the right meta i.e. tag_id --> TagMeta or book_id --> BookMeta\n const [meta1, meta2] =\n collection.columnName === columnOne\n ? [collection.meta, collection.otherMeta]\n : [collection.otherMeta, collection.meta];\n return {\n kind: \"exp\",\n op: \"and\",\n conditions: [\n {\n kind: \"column\",\n alias,\n column: columnOne,\n dbType: meta1.idDbType,\n cond: { kind: \"eq\", value: keyToNumber(meta1, idOne) },\n },\n {\n kind: \"column\",\n alias,\n column: columnTwo,\n dbType: meta2.idDbType,\n cond: { kind: \"eq\", value: keyToNumber(meta2, idTwo) },\n },\n ],\n };\n }),\n },\n // Id-less join tables have no surrogate id to order by, so order by the FK columns instead.\n orderBys: collection.hasJoinTableId\n ? [{ alias, column: \"id\", order: \"ASC\" }]\n : [\n { alias, column: collection.columnName, order: \"ASC\" },\n { alias, column: collection.otherColumnName, order: \"ASC\" },\n ],\n };\n\n const rows = await em[\"executeFind\"](collection.otherMeta, manyToManyFindOperation, query, {});\n\n const column1 = collection.columnName;\n const column2 = collection.otherColumnName;\n const meta1 = collection.meta;\n const meta2 = collection.otherMeta;\n\n // Because keys might come from either side of the m2m relationship, build\n // a list of both `foo_id=2,bar_id=3` and `bar_id=3,foo_id=2` to make the\n // final return value just a map of `Set.has`.\n const found = new Set(\n rows.flatMap((dbRow) => {\n const a = `${column1}=${tagId(meta1, dbRow[column1] as number)}`;\n const b = `${column2}=${tagId(meta2, dbRow[column2] as number)}`;\n return [`${a},${b}`, `${b},${a}`];\n }),\n );\n\n return keys.map((key) => found.has(key));\n}\n"],"mappings":";;;AASA,MAAa,0BAA0B;;AAGvC,SAAgB,yBACd,IACA,YAC6B;CAC7B,OAAO,GAAG,UAAU,yBAAyB,WAAW,gBAAgB,SAAS,KAAK,YAAY,IAAI,CAAC;AACzG;AAEA,eAAe,KACb,YACA,MACoB;CACpB,MAAM,EAAE,kBAAkB;CAC1B,MAAM,EAAE,OAAO,WAAW;CAE1B,MAAM,QAAQ,aAAa,aAAa;CACxC,MAAM,QAAyB;EAC7B,SAAS,CAAC,IAAI,MAAM,IAAI;EACxB,QAAQ,CAAC;GAAE;GAAO,MAAM;GAAW,OAAO;EAAc,CAAC;EAEzD,WAAW;GACT,MAAM;GACN,IAAI;GACJ,YAAY,KAAK,KAAK,QAAQ;IAC5B,MAAM,CAAC,KAAK,OAAO,IAAI,MAAM,GAAG;IAChC,MAAM,CAAC,WAAW,SAAS,IAAI,MAAM,GAAG;IACxC,MAAM,CAAC,WAAW,SAAS,IAAI,MAAM,GAAG;IAExC,MAAM,CAAC,OAAO,SACZ,WAAW,eAAe,YACtB,CAAC,WAAW,MAAM,WAAW,SAAS,IACtC,CAAC,WAAW,WAAW,WAAW,IAAI;IAC5C,OAAO;KACL,MAAM;KACN,IAAI;KACJ,YAAY,CACV;MACE,MAAM;MACN;MACA,QAAQ;MACR,QAAQ,MAAM;MACd,MAAM;OAAE,MAAM;OAAM,OAAO,YAAY,OAAO,KAAK;MAAE;KACvD,GACA;MACE,MAAM;MACN;MACA,QAAQ;MACR,QAAQ,MAAM;MACd,MAAM;OAAE,MAAM;OAAM,OAAO,YAAY,OAAO,KAAK;MAAE;KACvD,CACF;IACF;GACF,CAAC;EACH;EAEA,UAAU,WAAW,iBACjB,CAAC;GAAE;GAAO,QAAQ;GAAM,OAAO;EAAM,CAAC,IACtC,CACE;GAAE;GAAO,QAAQ,WAAW;GAAY,OAAO;EAAM,GACrD;GAAE;GAAO,QAAQ,WAAW;GAAiB,OAAO;EAAM,CAC5D;CACN;CAEA,MAAM,OAAO,MAAM,GAAG,cAAc,CAAC,WAAW,WAAW,yBAAyB,OAAO,CAAC,CAAC;CAE7F,MAAM,UAAU,WAAW;CAC3B,MAAM,UAAU,WAAW;CAC3B,MAAM,QAAQ,WAAW;CACzB,MAAM,QAAQ,WAAW;CAKzB,MAAM,QAAQ,IAAI,IAChB,KAAK,SAAS,UAAU;EACtB,MAAM,IAAI,GAAG,QAAQ,GAAG,MAAM,OAAO,MAAM,QAAkB;EAC7D,MAAM,IAAI,GAAG,QAAQ,GAAG,MAAM,OAAO,MAAM,QAAkB;EAC7D,OAAO,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,EAAE,GAAG,GAAG;CAClC,CAAC,CACH;CAEA,OAAO,KAAK,KAAK,QAAQ,MAAM,IAAI,GAAG,CAAC;AACzC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_keys = require("../keys.cjs");
|
|
2
3
|
const require_queries_find_QueryParser = require("../queries/find/QueryParser.cjs");
|
|
3
4
|
const require_utils = require("../utils.cjs");
|
|
4
|
-
const require_keys = require("../keys.cjs");
|
|
5
5
|
//#region src/dataloaders/oneToManyFindDataLoader.ts
|
|
6
6
|
const oneToManyFindOperation = "o2m-find";
|
|
7
7
|
/** Batches o2m.find/include calls (i.e. that don't fully load the o2m relation). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oneToManyFindDataLoader.cjs","names":["abbreviation","keyToNumber"],"sources":["../../src/dataloaders/oneToManyFindDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\
|
|
1
|
+
{"version":3,"file":"oneToManyFindDataLoader.cjs","names":["abbreviation","keyToNumber"],"sources":["../../src/dataloaders/oneToManyFindDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\nimport type { Entity } from \"src/Entity.ts\";\nimport type { EntityManager } from \"src/EntityManager.ts\";\nimport { keyToNumber } from \"src/keys.ts\";\nimport { type ParsedFindQuery, addTablePerClassJoinsAndClassTag } from \"src/queries/find/QueryParser.ts\";\nimport type { OneToManyCollection } from \"src/relations/OneToManyCollection.ts\";\nimport type { OneToManyLargeCollection } from \"src/relations/OneToManyLargeCollection.ts\";\nimport { abbreviation } from \"src/utils.ts\";\n\nexport const oneToManyFindOperation = \"o2m-find\";\n\n/** Batches o2m.find/include calls (i.e. that don't fully load the o2m relation). */\nexport function oneToManyFindDataLoader<T extends Entity, U extends Entity>(\n em: EntityManager,\n collection: OneToManyCollection<T, U> | OneToManyLargeCollection<T, U>,\n): DataLoader<string, U | undefined> {\n const { meta } = collection;\n const batchKey = `${meta.tableName}-${collection.fieldName}`;\n return em.getLoader(oneToManyFindOperation, batchKey, async (keys) => {\n const { em } = collection.entity;\n\n const meta = collection.otherMeta;\n const alias = abbreviation(meta.tableName);\n const query: ParsedFindQuery = {\n selects: [`\"${alias}\".*`],\n tables: [{ alias, join: \"primary\", table: meta.tableName }],\n // Or together `where (id = X and book_id = Y)`\n condition: {\n kind: \"exp\",\n op: \"or\",\n conditions: keys.map((key) => {\n const [one, two] = key.split(\",\");\n // columnOne is the `id=`, so is really the \"other\" side of the o2m\n const [columnOne, idOne] = one.split(\"=\");\n const [columnTwo, idTwo] = two.split(\"=\");\n const [meta1, meta2] = [collection.otherMeta, collection.meta];\n // Pick the right meta i.e. tag_id --> TagMeta or book_id --> BookMeta\n return {\n kind: \"exp\",\n op: \"and\",\n conditions: [\n {\n kind: \"column\",\n alias,\n column: columnOne,\n dbType: meta1.idDbType,\n cond: { kind: \"eq\", value: keyToNumber(meta1, idOne) },\n },\n {\n kind: \"column\",\n alias,\n column: columnTwo,\n dbType: meta2.idDbType,\n cond: { kind: \"eq\", value: keyToNumber(meta2, idTwo) },\n },\n ],\n };\n }),\n },\n orderBys: [{ alias, column: \"id\", order: \"ASC\" }],\n };\n\n addTablePerClassJoinsAndClassTag(query, meta, alias, true);\n // Skip maybeAddOrderBy b/c we're only returning 1 result\n // maybeAddNotSoftDeleted(conditions, meta, alias, \"include\");\n\n const rows = await em[\"executeFind\"](collection.otherMeta, oneToManyFindOperation, query, {});\n em.hydrate(collection.otherMeta.cstr, rows);\n\n // Decode `id=b:1,author_id=a:1`\n return keys.map((k) => {\n const [otherKey, parentKey] = k.split(\",\");\n const [, otherId] = otherKey.split(\"=\");\n const [, parentId] = parentKey.split(\"=\");\n const other = em.getEntity(otherId) as U;\n // We have may fetched `other` for a different parent in our batch\n const isMine = (other as any)?.[collection.otherFieldName].id === parentId;\n return isMine ? other : undefined;\n });\n });\n}\n"],"mappings":";;;;;AASA,MAAa,yBAAyB;;AAGtC,SAAgB,wBACd,IACA,YACmC;CACnC,MAAM,EAAE,SAAS;CACjB,MAAM,WAAW,GAAG,KAAK,UAAU,GAAG,WAAW;CACjD,OAAO,GAAG,UAAU,wBAAwB,UAAU,OAAO,SAAS;EACpE,MAAM,EAAE,OAAO,WAAW;EAE1B,MAAM,OAAO,WAAW;EACxB,MAAM,QAAQA,cAAAA,aAAa,KAAK,SAAS;EACzC,MAAM,QAAyB;GAC7B,SAAS,CAAC,IAAI,MAAM,IAAI;GACxB,QAAQ,CAAC;IAAE;IAAO,MAAM;IAAW,OAAO,KAAK;GAAU,CAAC;GAE1D,WAAW;IACT,MAAM;IACN,IAAI;IACJ,YAAY,KAAK,KAAK,QAAQ;KAC5B,MAAM,CAAC,KAAK,OAAO,IAAI,MAAM,GAAG;KAEhC,MAAM,CAAC,WAAW,SAAS,IAAI,MAAM,GAAG;KACxC,MAAM,CAAC,WAAW,SAAS,IAAI,MAAM,GAAG;KACxC,MAAM,CAAC,OAAO,SAAS,CAAC,WAAW,WAAW,WAAW,IAAI;KAE7D,OAAO;MACL,MAAM;MACN,IAAI;MACJ,YAAY,CACV;OACE,MAAM;OACN;OACA,QAAQ;OACR,QAAQ,MAAM;OACd,MAAM;QAAE,MAAM;QAAM,OAAOC,aAAAA,YAAY,OAAO,KAAK;OAAE;MACvD,GACA;OACE,MAAM;OACN;OACA,QAAQ;OACR,QAAQ,MAAM;OACd,MAAM;QAAE,MAAM;QAAM,OAAOA,aAAAA,YAAY,OAAO,KAAK;OAAE;MACvD,CACF;KACF;IACF,CAAC;GACH;GACA,UAAU,CAAC;IAAE;IAAO,QAAQ;IAAM,OAAO;GAAM,CAAC;EAClD;EAEA,iCAAA,iCAAiC,OAAO,MAAM,OAAO,IAAI;EAIzD,MAAM,OAAO,MAAM,GAAG,cAAc,CAAC,WAAW,WAAW,wBAAwB,OAAO,CAAC,CAAC;EAC5F,GAAG,QAAQ,WAAW,UAAU,MAAM,IAAI;EAG1C,OAAO,KAAK,KAAK,MAAM;GACrB,MAAM,CAAC,UAAU,aAAa,EAAE,MAAM,GAAG;GACzC,MAAM,GAAG,WAAW,SAAS,MAAM,GAAG;GACtC,MAAM,GAAG,YAAY,UAAU,MAAM,GAAG;GACxC,MAAM,QAAQ,GAAG,UAAU,OAAO;GAGlC,OADgB,QAAgB,WAAW,eAAe,CAAC,OAAO,WAClD,QAAQ,KAAA;EAC1B,CAAC;CACH,CAAC;AACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oneToManyFindDataLoader.d.cts","names":[],"sources":["../../src/dataloaders/oneToManyFindDataLoader.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"oneToManyFindDataLoader.d.cts","names":[],"sources":["../../src/dataloaders/oneToManyFindDataLoader.ts"],"mappings":";;;;;;cASa;;iBAGG,wBAAwB,UAAU,QAAQ,UAAU,QAClE,IAAI,eACJ,YAAY,oBAAoB,GAAG,KAAK,yBAAyB,GAAG,KACnE,mBAAmB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oneToManyFindDataLoader.d.mts","names":[],"sources":["../../src/dataloaders/oneToManyFindDataLoader.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"oneToManyFindDataLoader.d.mts","names":[],"sources":["../../src/dataloaders/oneToManyFindDataLoader.ts"],"mappings":";;;;;;cASa;;iBAGG,wBAAwB,UAAU,QAAQ,UAAU,QAClE,IAAI,eACJ,YAAY,oBAAoB,GAAG,KAAK,yBAAyB,GAAG,KACnE,mBAAmB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { keyToNumber } from "../keys.js";
|
|
1
2
|
import { addTablePerClassJoinsAndClassTag } from "../queries/find/QueryParser.js";
|
|
2
3
|
import { abbreviation } from "../utils.js";
|
|
3
|
-
import { keyToNumber } from "../keys.js";
|
|
4
4
|
//#region src/dataloaders/oneToManyFindDataLoader.ts
|
|
5
5
|
const oneToManyFindOperation = "o2m-find";
|
|
6
6
|
/** Batches o2m.find/include calls (i.e. that don't fully load the o2m relation). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oneToManyFindDataLoader.js","names":[],"sources":["../../src/dataloaders/oneToManyFindDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\
|
|
1
|
+
{"version":3,"file":"oneToManyFindDataLoader.js","names":[],"sources":["../../src/dataloaders/oneToManyFindDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\nimport type { Entity } from \"src/Entity.ts\";\nimport type { EntityManager } from \"src/EntityManager.ts\";\nimport { keyToNumber } from \"src/keys.ts\";\nimport { type ParsedFindQuery, addTablePerClassJoinsAndClassTag } from \"src/queries/find/QueryParser.ts\";\nimport type { OneToManyCollection } from \"src/relations/OneToManyCollection.ts\";\nimport type { OneToManyLargeCollection } from \"src/relations/OneToManyLargeCollection.ts\";\nimport { abbreviation } from \"src/utils.ts\";\n\nexport const oneToManyFindOperation = \"o2m-find\";\n\n/** Batches o2m.find/include calls (i.e. that don't fully load the o2m relation). */\nexport function oneToManyFindDataLoader<T extends Entity, U extends Entity>(\n em: EntityManager,\n collection: OneToManyCollection<T, U> | OneToManyLargeCollection<T, U>,\n): DataLoader<string, U | undefined> {\n const { meta } = collection;\n const batchKey = `${meta.tableName}-${collection.fieldName}`;\n return em.getLoader(oneToManyFindOperation, batchKey, async (keys) => {\n const { em } = collection.entity;\n\n const meta = collection.otherMeta;\n const alias = abbreviation(meta.tableName);\n const query: ParsedFindQuery = {\n selects: [`\"${alias}\".*`],\n tables: [{ alias, join: \"primary\", table: meta.tableName }],\n // Or together `where (id = X and book_id = Y)`\n condition: {\n kind: \"exp\",\n op: \"or\",\n conditions: keys.map((key) => {\n const [one, two] = key.split(\",\");\n // columnOne is the `id=`, so is really the \"other\" side of the o2m\n const [columnOne, idOne] = one.split(\"=\");\n const [columnTwo, idTwo] = two.split(\"=\");\n const [meta1, meta2] = [collection.otherMeta, collection.meta];\n // Pick the right meta i.e. tag_id --> TagMeta or book_id --> BookMeta\n return {\n kind: \"exp\",\n op: \"and\",\n conditions: [\n {\n kind: \"column\",\n alias,\n column: columnOne,\n dbType: meta1.idDbType,\n cond: { kind: \"eq\", value: keyToNumber(meta1, idOne) },\n },\n {\n kind: \"column\",\n alias,\n column: columnTwo,\n dbType: meta2.idDbType,\n cond: { kind: \"eq\", value: keyToNumber(meta2, idTwo) },\n },\n ],\n };\n }),\n },\n orderBys: [{ alias, column: \"id\", order: \"ASC\" }],\n };\n\n addTablePerClassJoinsAndClassTag(query, meta, alias, true);\n // Skip maybeAddOrderBy b/c we're only returning 1 result\n // maybeAddNotSoftDeleted(conditions, meta, alias, \"include\");\n\n const rows = await em[\"executeFind\"](collection.otherMeta, oneToManyFindOperation, query, {});\n em.hydrate(collection.otherMeta.cstr, rows);\n\n // Decode `id=b:1,author_id=a:1`\n return keys.map((k) => {\n const [otherKey, parentKey] = k.split(\",\");\n const [, otherId] = otherKey.split(\"=\");\n const [, parentId] = parentKey.split(\"=\");\n const other = em.getEntity(otherId) as U;\n // We have may fetched `other` for a different parent in our batch\n const isMine = (other as any)?.[collection.otherFieldName].id === parentId;\n return isMine ? other : undefined;\n });\n });\n}\n"],"mappings":";;;;AASA,MAAa,yBAAyB;;AAGtC,SAAgB,wBACd,IACA,YACmC;CACnC,MAAM,EAAE,SAAS;CACjB,MAAM,WAAW,GAAG,KAAK,UAAU,GAAG,WAAW;CACjD,OAAO,GAAG,UAAU,wBAAwB,UAAU,OAAO,SAAS;EACpE,MAAM,EAAE,OAAO,WAAW;EAE1B,MAAM,OAAO,WAAW;EACxB,MAAM,QAAQ,aAAa,KAAK,SAAS;EACzC,MAAM,QAAyB;GAC7B,SAAS,CAAC,IAAI,MAAM,IAAI;GACxB,QAAQ,CAAC;IAAE;IAAO,MAAM;IAAW,OAAO,KAAK;GAAU,CAAC;GAE1D,WAAW;IACT,MAAM;IACN,IAAI;IACJ,YAAY,KAAK,KAAK,QAAQ;KAC5B,MAAM,CAAC,KAAK,OAAO,IAAI,MAAM,GAAG;KAEhC,MAAM,CAAC,WAAW,SAAS,IAAI,MAAM,GAAG;KACxC,MAAM,CAAC,WAAW,SAAS,IAAI,MAAM,GAAG;KACxC,MAAM,CAAC,OAAO,SAAS,CAAC,WAAW,WAAW,WAAW,IAAI;KAE7D,OAAO;MACL,MAAM;MACN,IAAI;MACJ,YAAY,CACV;OACE,MAAM;OACN;OACA,QAAQ;OACR,QAAQ,MAAM;OACd,MAAM;QAAE,MAAM;QAAM,OAAO,YAAY,OAAO,KAAK;OAAE;MACvD,GACA;OACE,MAAM;OACN;OACA,QAAQ;OACR,QAAQ,MAAM;OACd,MAAM;QAAE,MAAM;QAAM,OAAO,YAAY,OAAO,KAAK;OAAE;MACvD,CACF;KACF;IACF,CAAC;GACH;GACA,UAAU,CAAC;IAAE;IAAO,QAAQ;IAAM,OAAO;GAAM,CAAC;EAClD;EAEA,iCAAiC,OAAO,MAAM,OAAO,IAAI;EAIzD,MAAM,OAAO,MAAM,GAAG,cAAc,CAAC,WAAW,WAAW,wBAAwB,OAAO,CAAC,CAAC;EAC5F,GAAG,QAAQ,WAAW,UAAU,MAAM,IAAI;EAG1C,OAAO,KAAK,KAAK,MAAM;GACrB,MAAM,CAAC,UAAU,aAAa,EAAE,MAAM,GAAG;GACzC,MAAM,GAAG,WAAW,SAAS,MAAM,GAAG;GACtC,MAAM,GAAG,YAAY,UAAU,MAAM,GAAG;GACxC,MAAM,QAAQ,GAAG,UAAU,OAAO;GAGlC,OADgB,QAAgB,WAAW,eAAe,CAAC,OAAO,WAClD,QAAQ,KAAA;EAC1B,CAAC;CACH,CAAC;AACH"}
|
package/build/defaults.cjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_normalizeHints = require("./normalizeHints.cjs");
|
|
3
|
+
const require_reactivity_reactiveHints = require("./reactivity/reactiveHints.cjs");
|
|
2
4
|
const require_fields = require("./fields.cjs");
|
|
3
|
-
const require_trusted = require("./trusted.cjs");
|
|
4
5
|
const require_relations_Reference = require("./relations/Reference.cjs");
|
|
5
|
-
const require_reactiveHints = require("./reactiveHints.cjs");
|
|
6
|
-
const require_normalizeHints = require("./normalizeHints.cjs");
|
|
7
|
-
const require_utils = require("./utils.cjs");
|
|
8
6
|
require("./relations/index.cjs");
|
|
7
|
+
const require_utils = require("./utils.cjs");
|
|
9
8
|
const require_EntityMetadata = require("./EntityMetadata.cjs");
|
|
9
|
+
const require_trusted = require("./trusted.cjs");
|
|
10
10
|
require("./Entity.cjs");
|
|
11
11
|
const require_BaseEntity = require("./BaseEntity.cjs");
|
|
12
12
|
let joist_utils = require("joist-utils");
|
|
@@ -108,7 +108,7 @@ var AsyncDefault = class {
|
|
|
108
108
|
}
|
|
109
109
|
/** For the given `entity`, returns what the default value should be. */
|
|
110
110
|
getValue(entity, ctx) {
|
|
111
|
-
this.#loadHint ??=
|
|
111
|
+
this.#loadHint ??= require_reactivity_reactiveHints.convertToLoadHint(require_EntityMetadata.getMetadata(entity), this.fieldHint);
|
|
112
112
|
return entity.em.populate(entity, this.#loadHint).then((loaded) => this.fn(loaded, ctx));
|
|
113
113
|
}
|
|
114
114
|
deps(meta) {
|
package/build/defaults.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.cjs","names":["getBaseAndSelfMetas","runInTrustedContext","getMetadata","getInstanceData","isLoadedReference","#loadHint","convertToLoadHint","#deps","normalizeHint","#deferreds","fail","Deferred"],"sources":["../src/defaults.ts"],"sourcesContent":["import { Deferred } from \"joist-utils\";\n\nimport { getInstanceData } from \"./BaseEntity.ts\";\nimport { type Entity } from \"./Entity.ts\";\nimport {\n type EntityMetadata,\n type EnumField,\n type Field,\n type PrimitiveField,\n getBaseAndSelfMetas,\n getMetadata,\n} from \"./EntityMetadata.ts\";\nimport { setField } from \"./fields.ts\";\nimport { normalizeHint } from \"./normalizeHints.ts\";\nimport { type ReactiveHint, convertToLoadHint } from \"./reactiveHints.ts\";\nimport { isLoadedReference } from \"./relations/index.ts\";\nimport { runInTrustedContext } from \"./trusted.ts\";\nimport { fail, failIfAnyRejected } from \"./utils.ts\";\n\nexport function hasDefaultValue(meta: EntityMetadata, fieldName: string): boolean {\n return getBaseAndSelfMetas(meta).some(\n (m) => fieldName in m.config.__data.syncDefaults || fieldName in m.config.__data.asyncDefaults,\n );\n}\n\n/** Run the sync defaults for `entity`. */\nexport function setSyncDefaults(entity: Entity): void {\n return runInTrustedContext(() => {\n const meta = getMetadata(entity);\n // Allow subtypes to override base setDefaults\n const syncDefaults: Record<string, any> = getBaseAndSelfMetas(meta).reduce(\n (acc, m) => ({ ...acc, ...m.config.__data.syncDefaults }),\n {},\n );\n for (const [fieldName, maybeFn] of Object.entries(syncDefaults)) {\n const field = meta.allFields[fieldName];\n // Use allFields in case a subtype sets a default for one of its base fields\n if (\n (field.kind === \"primitive\" || field.kind === \"enum\") &&\n (field as PrimitiveField | EnumField).derived === \"async\"\n ) {\n // If this is an AsyncReactiveField, we want to push in a default, but setOpts is called\n // from the codegen constructor, so the user-defined `hasAsyncReactiveField` fields will\n // not have been initialized yet (i.e. `entity[field]` will be undefined and not yet an\n // `instanceof AsyncReactiveField`). Thankfully we can just use setField.\n const value = maybeFn instanceof Function ? maybeFn(entity) : maybeFn;\n setField(entity, fieldName, value);\n } else if (!isRelation(field)) {\n const hasBeenSet = fieldName in getInstanceData(entity).data;\n if (!hasBeenSet) {\n const value = maybeFn instanceof Function ? maybeFn(entity) : maybeFn;\n // If the value is undefined, leave it unset, so that a default invoked during\n // the constructor being called (before any other opts are set) can be called\n // again during `em.flush` and get an opportunity to observe other fields.\n if (value !== undefined) {\n (entity as any)[fieldName] = value;\n }\n }\n } else {\n const value = (entity as any)[fieldName];\n if (isLoadedReference(value) && !value.isSet && !value.hasBeenSet) {\n // A sync default usually would never be for a reference, because reference defaults usually\n // require a field hint (so would be async) to get \"the other entity\". However, something like:\n // `config.setDefault(\"original\", (self) => self);` is technically valid.\n value.set(maybeFn instanceof Function ? maybeFn(entity) : maybeFn);\n }\n }\n }\n });\n}\n\n/** Runs the async defaults for all inserted entities in `todos`. */\nexport async function setAsyncDefaults(\n suppressedTypeErrors: Error[],\n ctx: unknown,\n // We want this to be per-subtype, so that a subtype can have its own default, and we still invoke\n // the subtype `setOnEntities(...all subtype entities...)` and `setOnEntities(...any base types...)`\n // as bulk calls.\n insertsBySubType: Map<EntityMetadata, Entity[]>,\n): Promise<void> {\n return runInTrustedContext(async () => {\n const dt = new DependencyTracker(insertsBySubType);\n const results = await Promise.allSettled(\n [...insertsBySubType.entries()].flatMap(([meta, inserts]) => {\n // configure will have copy/pasted base defaults into our config, so we can loop over it directly\n return Object.values(meta.config.__data.asyncDefaults).map((df) =>\n df.setOnEntities(ctx, dt, suppressedTypeErrors, meta, inserts),\n );\n }),\n );\n failIfAnyRejected(results);\n });\n}\n\n/** Sets async defaults *synchronously*, only safe for factories with `DeepNew` entities. */\nexport function setAsyncDefaultsSynchronously(ctx: unknown, entity: Entity): void {\n return runInTrustedContext(() => {\n // configure will have copy/pasted base defaults into our config, so we can loop over it directly\n for (const df of Object.values(getMetadata(entity).config.__data.asyncDefaults)) {\n df.setOnFactoryEntity(ctx, entity);\n }\n });\n}\n\n/** Wraps the hint + lambda of an async `setDefault`. */\nexport class AsyncDefault<T extends Entity> {\n readonly fieldName: string;\n readonly fieldHint: ReactiveHint<T>;\n readonly fn: (entity: any, ctx: any) => any;\n #loadHint: any;\n // We can't calc this until post-boot because it requires following metadata\n #deps: DefaultDependency[] | undefined;\n\n constructor(fieldName: string, fieldHint: ReactiveHint<T>, fn: (entity: T, ctx: any) => any) {\n this.fieldName = fieldName;\n this.fieldHint = fieldHint;\n this.fn = fn;\n }\n\n /** Given a list of inserts of the same type/subtype, set ourselves on each of them. */\n async setOnEntities(\n ctx: any,\n dt: DependencyTracker,\n suppressedTypeErrors: Error[],\n baseMetadata: EntityMetadata,\n inserts: T[],\n ): Promise<any> {\n try {\n // Ensure our dependencies have been set\n // (...and only wait on dependencies that are actively being calculated)\n const deps = this.deps(baseMetadata).filter((dep) => dt.hasMaybePending(dep.meta));\n if (deps.length > 0) {\n // console.log(\n // \"WAITING ON\",\n // deps.map((dep) => `${dep.meta.type}.${dep.fieldName}`),\n // `FOR ${baseMetadata.type}.${this.fieldName}`,\n // );\n // deps promises shouldn't reject, so we should be fine w/o allSettled here\n await Promise.all(deps.map((dep) => dt.getDeferred(dep.meta, dep.fieldName).promise));\n }\n\n // Run our default for all entities, use allSettled to avoid leaving lambdas running if one fails\n const results = await Promise.allSettled(\n inserts\n .map(async (entity) => {\n if (!isRelation(baseMetadata.allFields[this.fieldName])) {\n const hasBeenSet = this.fieldName in getInstanceData(entity).data;\n if (!hasBeenSet) {\n const value = await this.getValue(entity, ctx);\n if (value !== undefined) {\n (entity as any)[this.fieldName] = value;\n }\n }\n } else {\n const value = (entity as any)[this.fieldName];\n if (isLoadedReference(value) && !value.isSet && !value.hasBeenSet) {\n const val = await this.getValue(entity, ctx);\n if (val !== undefined) {\n value.set(val);\n }\n }\n }\n })\n .map((promise) =>\n promise.catch((reason) => {\n // If we NPE-d because a required field wasn't set, hold on to this and\n // let the validation failures reject the `em.flush` instead of us\n if (reason instanceof TypeError) {\n suppressedTypeErrors.push(reason);\n } else {\n throw reason;\n }\n }),\n ),\n );\n failIfAnyRejected(results);\n } finally {\n // Mark ourselves as complete (from a `finally` just in case our `setDefault`\n // blows up, we don't forever block the other defaults waiting on us).\n // console.log(`FINISHED ${baseMetadata.type}.${this.fieldName}`);\n dt.getDeferred(baseMetadata, this.fieldName).resolve();\n }\n }\n\n setOnFactoryEntity(ctx: unknown, entity: T): void {\n // If the lambda uses the `async` keyword, it definitely makes a promise, so don't invoke it\n // from a synchronous factory call.\n if (this.fn.constructor.name === \"AsyncFunction\") return;\n const value = (entity as any)[this.fieldName];\n try {\n if (value === undefined || (isLoadedReference(value) && !value.isSet)) {\n const val = this.fn(entity, ctx);\n // Even though we checked `async () => ...` above, a lambda could still return a Promise\n if (val instanceof Promise) {\n throw new Error(\n `Use the \\`async\\` keyword for the setDefault \"${this.fieldName}\" function that returns a Promise`,\n );\n } else if (val === undefined) {\n // If val is undefined, let the setDefault get invoked again later\n } else {\n if (isLoadedReference(value)) {\n value.set(val);\n } else {\n (entity as any)[this.fieldName] = val;\n }\n }\n }\n } catch (e) {\n // It's likely common to get NPEs/TypeErrors from speculatively executing defaults\n // pre-em.flush, i.e. we don't have the DependencyTracker/etc infra here, the lambdas\n // could do a `book.author.get.name` and NPE on the `author.get.name`. So instead just\n // suppress errors and assume `em.flush` will try again.\n // ...we need to add a NotLoadedError\n // if (!(e instanceof TypeError || e instanceof NotL)) {\n // throw e;\n // }\n }\n }\n\n /** For the given `entity`, returns what the default value should be. */\n private getValue(entity: T, ctx: any): Promise<any> {\n // We can't convert this until now, since it requires the `metadata`\n this.#loadHint ??= convertToLoadHint(getMetadata(entity), this.fieldHint);\n return entity.em.populate(entity, this.#loadHint).then((loaded) => this.fn(loaded, ctx));\n }\n\n // Calc once and cache\n private deps(meta: EntityMetadata): DefaultDependency[] {\n return (this.#deps ??= getDefaultDependencies(meta, this.fieldName, this.fieldHint));\n }\n}\n\ntype DefaultDependency = {\n meta: EntityMetadata;\n fieldName: string;\n};\n\n/**\n * Given a `meta` and a nested field hint, return the meta+field tuples included within the hint.\n *\n * I.e. passing `{ author: { firstName: {}, publisher: \"name\" } }` would return `[[Author, \"firstName\"],\n * [Publisher, \"name\"]]`.\n */\nexport function getDefaultDependencies<T extends Entity>(\n baseMeta: EntityMetadata<T>,\n baseFieldName: string,\n baseHint: ReactiveHint<T>,\n): DefaultDependency[] {\n // Ensure the hint is an `{ ... }`\n const deps: DefaultDependency[] = [];\n const todo: [meta: EntityMetadata, hint: ReactiveHint<any>][] = [[baseMeta, normalizeHint(baseHint)]];\n while (todo.length !== 0) {\n const [meta, hint] = todo.pop()!;\n for (const [fieldName, nestedHint] of Object.entries(hint)) {\n const field = meta.allFields[fieldName];\n // Super naive circular dependency detection\n const isSameField = meta === baseMeta && fieldName === baseFieldName;\n if (isSameField) continue;\n // If this is an invalid hint, just ignore it, and assume someone else will fail on it\n if (!field) continue;\n switch (field.kind) {\n case \"enum\":\n case \"primitive\":\n if (field.default === \"config\" && fieldName in meta.config.__data.asyncDefaults) {\n deps.push({ meta, fieldName });\n }\n break;\n case \"m2o\":\n if (field.default === \"config\" && fieldName in meta.config.__data.asyncDefaults) {\n deps.push({ meta, fieldName });\n }\n if (nestedHint) {\n todo.push([field.otherMetadata(), normalizeHint(nestedHint)]);\n }\n break;\n case \"o2o\":\n case \"o2m\":\n case \"m2m\":\n if (nestedHint) {\n todo.push([field.otherMetadata(), normalizeHint(nestedHint)]);\n }\n break;\n }\n }\n }\n return deps;\n}\n\n/**\n * This tracks cross-default dependencies that are active within a single `em.flush` loop.\n *\n * I.e. this is not a static \"the Author.firstName in general depends on Publisher.whatever\",\n * it tracks that we're actively inserting 10 new `Author` instances, and their `firstName`\n * default needs to wait until the `Publisher.whatever` fields have their async default\n * calculated.\n *\n * Really this is just a smaller wrapper around a map of `Deferred`s.\n */\nclass DependencyTracker {\n // Create a map \"entityType -> fieldName -> deferred\"\n #deferreds = new Map<string, Map<string, Deferred<void>>>();\n\n constructor(insertsBySubType: Map<EntityMetadata, Entity[]>) {\n // Seed it with any entities that we're actively inserting (as any dependencies to\n // entities that aren't even having `setDefault` called can be skipped)\n for (const meta of [...insertsBySubType.keys()]) {\n this.#deferreds.set(meta.type, new Map());\n }\n }\n\n hasMaybePending(meta: EntityMetadata): boolean {\n return this.#deferreds.has(meta.type) ?? false;\n }\n\n getDeferred(meta: EntityMetadata, fieldName: string): Deferred<void> {\n const map = this.#deferreds.get(meta.type) ?? fail(`No deferred check necessary for ${meta.type}.${fieldName}`);\n let deferred = map.get(fieldName);\n if (!deferred) {\n deferred = new Deferred();\n map.set(fieldName, deferred);\n }\n return deferred;\n }\n}\n\nfunction isRelation(field: Field): boolean {\n return field.kind !== \"primitive\" && field.kind !== \"enum\";\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"defaults.cjs","names":["getBaseAndSelfMetas","runInTrustedContext","getMetadata","getInstanceData","isLoadedReference","#loadHint","convertToLoadHint","#deps","normalizeHint","#deferreds","fail","Deferred"],"sources":["../src/defaults.ts"],"sourcesContent":["import { Deferred } from \"joist-utils\";\nimport { getInstanceData } from \"src/BaseEntity.ts\";\nimport { type Entity } from \"src/Entity.ts\";\nimport {\n type EntityMetadata,\n type EnumField,\n type Field,\n type PrimitiveField,\n getBaseAndSelfMetas,\n getMetadata,\n} from \"src/EntityMetadata.ts\";\nimport { setField } from \"src/fields.ts\";\nimport { normalizeHint } from \"src/normalizeHints.ts\";\nimport { type ReactiveHint, convertToLoadHint } from \"src/reactivity/reactiveHints.ts\";\nimport { isLoadedReference } from \"src/relations/index.ts\";\nimport { runInTrustedContext } from \"src/trusted.ts\";\nimport { fail, failIfAnyRejected } from \"src/utils.ts\";\n\nexport function hasDefaultValue(meta: EntityMetadata, fieldName: string): boolean {\n return getBaseAndSelfMetas(meta).some(\n (m) => fieldName in m.config.__data.syncDefaults || fieldName in m.config.__data.asyncDefaults,\n );\n}\n\n/** Run the sync defaults for `entity`. */\nexport function setSyncDefaults(entity: Entity): void {\n return runInTrustedContext(() => {\n const meta = getMetadata(entity);\n // Allow subtypes to override base setDefaults\n const syncDefaults: Record<string, any> = getBaseAndSelfMetas(meta).reduce(\n (acc, m) => ({ ...acc, ...m.config.__data.syncDefaults }),\n {},\n );\n for (const [fieldName, maybeFn] of Object.entries(syncDefaults)) {\n const field = meta.allFields[fieldName];\n // Use allFields in case a subtype sets a default for one of its base fields\n if (\n (field.kind === \"primitive\" || field.kind === \"enum\") &&\n (field as PrimitiveField | EnumField).derived === \"async\"\n ) {\n // If this is an AsyncReactiveField, we want to push in a default, but setOpts is called\n // from the codegen constructor, so the user-defined `hasAsyncReactiveField` fields will\n // not have been initialized yet (i.e. `entity[field]` will be undefined and not yet an\n // `instanceof AsyncReactiveField`). Thankfully we can just use setField.\n const value = maybeFn instanceof Function ? maybeFn(entity) : maybeFn;\n setField(entity, fieldName, value);\n } else if (!isRelation(field)) {\n const hasBeenSet = fieldName in getInstanceData(entity).data;\n if (!hasBeenSet) {\n const value = maybeFn instanceof Function ? maybeFn(entity) : maybeFn;\n // If the value is undefined, leave it unset, so that a default invoked during\n // the constructor being called (before any other opts are set) can be called\n // again during `em.flush` and get an opportunity to observe other fields.\n if (value !== undefined) {\n (entity as any)[fieldName] = value;\n }\n }\n } else {\n const value = (entity as any)[fieldName];\n if (isLoadedReference(value) && !value.isSet && !value.hasBeenSet) {\n // A sync default usually would never be for a reference, because reference defaults usually\n // require a field hint (so would be async) to get \"the other entity\". However, something like:\n // `config.setDefault(\"original\", (self) => self);` is technically valid.\n value.set(maybeFn instanceof Function ? maybeFn(entity) : maybeFn);\n }\n }\n }\n });\n}\n\n/** Runs the async defaults for all inserted entities in `todos`. */\nexport async function setAsyncDefaults(\n suppressedTypeErrors: Error[],\n ctx: unknown,\n // We want this to be per-subtype, so that a subtype can have its own default, and we still invoke\n // the subtype `setOnEntities(...all subtype entities...)` and `setOnEntities(...any base types...)`\n // as bulk calls.\n insertsBySubType: Map<EntityMetadata, Entity[]>,\n): Promise<void> {\n return runInTrustedContext(async () => {\n const dt = new DependencyTracker(insertsBySubType);\n const results = await Promise.allSettled(\n [...insertsBySubType.entries()].flatMap(([meta, inserts]) => {\n // configure will have copy/pasted base defaults into our config, so we can loop over it directly\n return Object.values(meta.config.__data.asyncDefaults).map((df) =>\n df.setOnEntities(ctx, dt, suppressedTypeErrors, meta, inserts),\n );\n }),\n );\n failIfAnyRejected(results);\n });\n}\n\n/** Sets async defaults *synchronously*, only safe for factories with `DeepNew` entities. */\nexport function setAsyncDefaultsSynchronously(ctx: unknown, entity: Entity): void {\n return runInTrustedContext(() => {\n // configure will have copy/pasted base defaults into our config, so we can loop over it directly\n for (const df of Object.values(getMetadata(entity).config.__data.asyncDefaults)) {\n df.setOnFactoryEntity(ctx, entity);\n }\n });\n}\n\n/** Wraps the hint + lambda of an async `setDefault`. */\nexport class AsyncDefault<T extends Entity> {\n readonly fieldName: string;\n readonly fieldHint: ReactiveHint<T>;\n readonly fn: (entity: any, ctx: any) => any;\n #loadHint: any;\n // We can't calc this until post-boot because it requires following metadata\n #deps: DefaultDependency[] | undefined;\n\n constructor(fieldName: string, fieldHint: ReactiveHint<T>, fn: (entity: T, ctx: any) => any) {\n this.fieldName = fieldName;\n this.fieldHint = fieldHint;\n this.fn = fn;\n }\n\n /** Given a list of inserts of the same type/subtype, set ourselves on each of them. */\n async setOnEntities(\n ctx: any,\n dt: DependencyTracker,\n suppressedTypeErrors: Error[],\n baseMetadata: EntityMetadata,\n inserts: T[],\n ): Promise<any> {\n try {\n // Ensure our dependencies have been set\n // (...and only wait on dependencies that are actively being calculated)\n const deps = this.deps(baseMetadata).filter((dep) => dt.hasMaybePending(dep.meta));\n if (deps.length > 0) {\n // console.log(\n // \"WAITING ON\",\n // deps.map((dep) => `${dep.meta.type}.${dep.fieldName}`),\n // `FOR ${baseMetadata.type}.${this.fieldName}`,\n // );\n // deps promises shouldn't reject, so we should be fine w/o allSettled here\n await Promise.all(deps.map((dep) => dt.getDeferred(dep.meta, dep.fieldName).promise));\n }\n\n // Run our default for all entities, use allSettled to avoid leaving lambdas running if one fails\n const results = await Promise.allSettled(\n inserts\n .map(async (entity) => {\n if (!isRelation(baseMetadata.allFields[this.fieldName])) {\n const hasBeenSet = this.fieldName in getInstanceData(entity).data;\n if (!hasBeenSet) {\n const value = await this.getValue(entity, ctx);\n if (value !== undefined) {\n (entity as any)[this.fieldName] = value;\n }\n }\n } else {\n const value = (entity as any)[this.fieldName];\n if (isLoadedReference(value) && !value.isSet && !value.hasBeenSet) {\n const val = await this.getValue(entity, ctx);\n if (val !== undefined) {\n value.set(val);\n }\n }\n }\n })\n .map((promise) =>\n promise.catch((reason) => {\n // If we NPE-d because a required field wasn't set, hold on to this and\n // let the validation failures reject the `em.flush` instead of us\n if (reason instanceof TypeError) {\n suppressedTypeErrors.push(reason);\n } else {\n throw reason;\n }\n }),\n ),\n );\n failIfAnyRejected(results);\n } finally {\n // Mark ourselves as complete (from a `finally` just in case our `setDefault`\n // blows up, we don't forever block the other defaults waiting on us).\n // console.log(`FINISHED ${baseMetadata.type}.${this.fieldName}`);\n dt.getDeferred(baseMetadata, this.fieldName).resolve();\n }\n }\n\n setOnFactoryEntity(ctx: unknown, entity: T): void {\n // If the lambda uses the `async` keyword, it definitely makes a promise, so don't invoke it\n // from a synchronous factory call.\n if (this.fn.constructor.name === \"AsyncFunction\") return;\n const value = (entity as any)[this.fieldName];\n try {\n if (value === undefined || (isLoadedReference(value) && !value.isSet)) {\n const val = this.fn(entity, ctx);\n // Even though we checked `async () => ...` above, a lambda could still return a Promise\n if (val instanceof Promise) {\n throw new Error(\n `Use the \\`async\\` keyword for the setDefault \"${this.fieldName}\" function that returns a Promise`,\n );\n } else if (val === undefined) {\n // If val is undefined, let the setDefault get invoked again later\n } else {\n if (isLoadedReference(value)) {\n value.set(val);\n } else {\n (entity as any)[this.fieldName] = val;\n }\n }\n }\n } catch (e) {\n // It's likely common to get NPEs/TypeErrors from speculatively executing defaults\n // pre-em.flush, i.e. we don't have the DependencyTracker/etc infra here, the lambdas\n // could do a `book.author.get.name` and NPE on the `author.get.name`. So instead just\n // suppress errors and assume `em.flush` will try again.\n // ...we need to add a NotLoadedError\n // if (!(e instanceof TypeError || e instanceof NotL)) {\n // throw e;\n // }\n }\n }\n\n /** For the given `entity`, returns what the default value should be. */\n private getValue(entity: T, ctx: any): Promise<any> {\n // We can't convert this until now, since it requires the `metadata`\n this.#loadHint ??= convertToLoadHint(getMetadata(entity), this.fieldHint);\n return entity.em.populate(entity, this.#loadHint).then((loaded) => this.fn(loaded, ctx));\n }\n\n // Calc once and cache\n private deps(meta: EntityMetadata): DefaultDependency[] {\n return (this.#deps ??= getDefaultDependencies(meta, this.fieldName, this.fieldHint));\n }\n}\n\ntype DefaultDependency = {\n meta: EntityMetadata;\n fieldName: string;\n};\n\n/**\n * Given a `meta` and a nested field hint, return the meta+field tuples included within the hint.\n *\n * I.e. passing `{ author: { firstName: {}, publisher: \"name\" } }` would return `[[Author, \"firstName\"],\n * [Publisher, \"name\"]]`.\n */\nexport function getDefaultDependencies<T extends Entity>(\n baseMeta: EntityMetadata<T>,\n baseFieldName: string,\n baseHint: ReactiveHint<T>,\n): DefaultDependency[] {\n // Ensure the hint is an `{ ... }`\n const deps: DefaultDependency[] = [];\n const todo: [meta: EntityMetadata, hint: ReactiveHint<any>][] = [[baseMeta, normalizeHint(baseHint)]];\n while (todo.length !== 0) {\n const [meta, hint] = todo.pop()!;\n for (const [fieldName, nestedHint] of Object.entries(hint)) {\n const field = meta.allFields[fieldName];\n // Super naive circular dependency detection\n const isSameField = meta === baseMeta && fieldName === baseFieldName;\n if (isSameField) continue;\n // If this is an invalid hint, just ignore it, and assume someone else will fail on it\n if (!field) continue;\n switch (field.kind) {\n case \"enum\":\n case \"primitive\":\n if (field.default === \"config\" && fieldName in meta.config.__data.asyncDefaults) {\n deps.push({ meta, fieldName });\n }\n break;\n case \"m2o\":\n if (field.default === \"config\" && fieldName in meta.config.__data.asyncDefaults) {\n deps.push({ meta, fieldName });\n }\n if (nestedHint) {\n todo.push([field.otherMetadata(), normalizeHint(nestedHint)]);\n }\n break;\n case \"o2o\":\n case \"o2m\":\n case \"m2m\":\n if (nestedHint) {\n todo.push([field.otherMetadata(), normalizeHint(nestedHint)]);\n }\n break;\n }\n }\n }\n return deps;\n}\n\n/**\n * This tracks cross-default dependencies that are active within a single `em.flush` loop.\n *\n * I.e. this is not a static \"the Author.firstName in general depends on Publisher.whatever\",\n * it tracks that we're actively inserting 10 new `Author` instances, and their `firstName`\n * default needs to wait until the `Publisher.whatever` fields have their async default\n * calculated.\n *\n * Really this is just a smaller wrapper around a map of `Deferred`s.\n */\nclass DependencyTracker {\n // Create a map \"entityType -> fieldName -> deferred\"\n #deferreds = new Map<string, Map<string, Deferred<void>>>();\n\n constructor(insertsBySubType: Map<EntityMetadata, Entity[]>) {\n // Seed it with any entities that we're actively inserting (as any dependencies to\n // entities that aren't even having `setDefault` called can be skipped)\n for (const meta of [...insertsBySubType.keys()]) {\n this.#deferreds.set(meta.type, new Map());\n }\n }\n\n hasMaybePending(meta: EntityMetadata): boolean {\n return this.#deferreds.has(meta.type) ?? false;\n }\n\n getDeferred(meta: EntityMetadata, fieldName: string): Deferred<void> {\n const map = this.#deferreds.get(meta.type) ?? fail(`No deferred check necessary for ${meta.type}.${fieldName}`);\n let deferred = map.get(fieldName);\n if (!deferred) {\n deferred = new Deferred();\n map.set(fieldName, deferred);\n }\n return deferred;\n }\n}\n\nfunction isRelation(field: Field): boolean {\n return field.kind !== \"primitive\" && field.kind !== \"enum\";\n}\n"],"mappings":"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"}
|
package/build/defaults.d.cts
CHANGED
package/build/defaults.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.d.cts","names":[],"sources":["../src/defaults.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"defaults.d.cts","names":[],"sources":["../src/defaults.ts"],"mappings":";;;;;iBAkBgB,gBAAgB,MAAM,gBAAgB;;iBAOtC,gBAAgB,QAAQ;;iBA8ClB,iBACpB,sBAAsB,SACtB,cAIA,kBAAkB,IAAI,gBAAgB,YACrC;;iBAgBa,8BAA8B,cAAc,QAAQ;;cAUvD,aAAa,UAAU;;WACzB;WACA,WAAW,aAAa;WACxB,KAAK,aAAa;EAK3B,YAAY,mBAAmB,WAAW,aAAa,IAAI,KAAK,QAAQ,GAAG;;EAOrE,cACJ,UACA,IAAI,mBACJ,sBAAsB,SACtB,cAAc,gBACd,SAAS,MACR;EA0DH,mBAAmB,cAAc,QAAQ;;UAoCjC;UAOA;;KAKL;EACH,MAAM;EACN;;;;;;;;iBASc,uBAAuB,UAAU,QAC/C,UAAU,eAAe,IACzB,uBACA,UAAU,aAAa,KACtB;;;;;;;;;;;cAmDG;;EAIJ,YAAY,kBAAkB,IAAI,gBAAgB;EAQlD,gBAAgB,MAAM;EAItB,YAAY,MAAM,gBAAgB,oBAAoB"}
|
package/build/defaults.d.mts
CHANGED
package/build/defaults.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.d.mts","names":[],"sources":["../src/defaults.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"defaults.d.mts","names":[],"sources":["../src/defaults.ts"],"mappings":";;;;;iBAkBgB,gBAAgB,MAAM,gBAAgB;;iBAOtC,gBAAgB,QAAQ;;iBA8ClB,iBACpB,sBAAsB,SACtB,cAIA,kBAAkB,IAAI,gBAAgB,YACrC;;iBAgBa,8BAA8B,cAAc,QAAQ;;cAUvD,aAAa,UAAU;;WACzB;WACA,WAAW,aAAa;WACxB,KAAK,aAAa;EAK3B,YAAY,mBAAmB,WAAW,aAAa,IAAI,KAAK,QAAQ,GAAG;;EAOrE,cACJ,UACA,IAAI,mBACJ,sBAAsB,SACtB,cAAc,gBACd,SAAS,MACR;EA0DH,mBAAmB,cAAc,QAAQ;;UAoCjC;UAOA;;KAKL;EACH,MAAM;EACN;;;;;;;;iBASc,uBAAuB,UAAU,QAC/C,UAAU,eAAe,IACzB,uBACA,UAAU,aAAa,KACtB;;;;;;;;;;;cAmDG;;EAIJ,YAAY,kBAAkB,IAAI,gBAAgB;EAQlD,gBAAgB,MAAM;EAItB,YAAY,MAAM,gBAAgB,oBAAoB"}
|
package/build/defaults.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import { normalizeHint } from "./normalizeHints.js";
|
|
2
|
+
import { convertToLoadHint } from "./reactivity/reactiveHints.js";
|
|
1
3
|
import { setField } from "./fields.js";
|
|
2
|
-
import { runInTrustedContext } from "./trusted.js";
|
|
3
4
|
import { isLoadedReference } from "./relations/Reference.js";
|
|
4
|
-
import { convertToLoadHint } from "./reactiveHints.js";
|
|
5
|
-
import { normalizeHint } from "./normalizeHints.js";
|
|
6
|
-
import { fail, failIfAnyRejected } from "./utils.js";
|
|
7
5
|
import "./relations/index.js";
|
|
6
|
+
import { fail, failIfAnyRejected } from "./utils.js";
|
|
8
7
|
import { getBaseAndSelfMetas, getMetadata } from "./EntityMetadata.js";
|
|
8
|
+
import { runInTrustedContext } from "./trusted.js";
|
|
9
9
|
import "./Entity.js";
|
|
10
10
|
import { getInstanceData } from "./BaseEntity.js";
|
|
11
11
|
import { Deferred } from "joist-utils";
|
package/build/defaults.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.js","names":["#loadHint","#deps","#deferreds"],"sources":["../src/defaults.ts"],"sourcesContent":["import { Deferred } from \"joist-utils\";\n\nimport { getInstanceData } from \"./BaseEntity.ts\";\nimport { type Entity } from \"./Entity.ts\";\nimport {\n type EntityMetadata,\n type EnumField,\n type Field,\n type PrimitiveField,\n getBaseAndSelfMetas,\n getMetadata,\n} from \"./EntityMetadata.ts\";\nimport { setField } from \"./fields.ts\";\nimport { normalizeHint } from \"./normalizeHints.ts\";\nimport { type ReactiveHint, convertToLoadHint } from \"./reactiveHints.ts\";\nimport { isLoadedReference } from \"./relations/index.ts\";\nimport { runInTrustedContext } from \"./trusted.ts\";\nimport { fail, failIfAnyRejected } from \"./utils.ts\";\n\nexport function hasDefaultValue(meta: EntityMetadata, fieldName: string): boolean {\n return getBaseAndSelfMetas(meta).some(\n (m) => fieldName in m.config.__data.syncDefaults || fieldName in m.config.__data.asyncDefaults,\n );\n}\n\n/** Run the sync defaults for `entity`. */\nexport function setSyncDefaults(entity: Entity): void {\n return runInTrustedContext(() => {\n const meta = getMetadata(entity);\n // Allow subtypes to override base setDefaults\n const syncDefaults: Record<string, any> = getBaseAndSelfMetas(meta).reduce(\n (acc, m) => ({ ...acc, ...m.config.__data.syncDefaults }),\n {},\n );\n for (const [fieldName, maybeFn] of Object.entries(syncDefaults)) {\n const field = meta.allFields[fieldName];\n // Use allFields in case a subtype sets a default for one of its base fields\n if (\n (field.kind === \"primitive\" || field.kind === \"enum\") &&\n (field as PrimitiveField | EnumField).derived === \"async\"\n ) {\n // If this is an AsyncReactiveField, we want to push in a default, but setOpts is called\n // from the codegen constructor, so the user-defined `hasAsyncReactiveField` fields will\n // not have been initialized yet (i.e. `entity[field]` will be undefined and not yet an\n // `instanceof AsyncReactiveField`). Thankfully we can just use setField.\n const value = maybeFn instanceof Function ? maybeFn(entity) : maybeFn;\n setField(entity, fieldName, value);\n } else if (!isRelation(field)) {\n const hasBeenSet = fieldName in getInstanceData(entity).data;\n if (!hasBeenSet) {\n const value = maybeFn instanceof Function ? maybeFn(entity) : maybeFn;\n // If the value is undefined, leave it unset, so that a default invoked during\n // the constructor being called (before any other opts are set) can be called\n // again during `em.flush` and get an opportunity to observe other fields.\n if (value !== undefined) {\n (entity as any)[fieldName] = value;\n }\n }\n } else {\n const value = (entity as any)[fieldName];\n if (isLoadedReference(value) && !value.isSet && !value.hasBeenSet) {\n // A sync default usually would never be for a reference, because reference defaults usually\n // require a field hint (so would be async) to get \"the other entity\". However, something like:\n // `config.setDefault(\"original\", (self) => self);` is technically valid.\n value.set(maybeFn instanceof Function ? maybeFn(entity) : maybeFn);\n }\n }\n }\n });\n}\n\n/** Runs the async defaults for all inserted entities in `todos`. */\nexport async function setAsyncDefaults(\n suppressedTypeErrors: Error[],\n ctx: unknown,\n // We want this to be per-subtype, so that a subtype can have its own default, and we still invoke\n // the subtype `setOnEntities(...all subtype entities...)` and `setOnEntities(...any base types...)`\n // as bulk calls.\n insertsBySubType: Map<EntityMetadata, Entity[]>,\n): Promise<void> {\n return runInTrustedContext(async () => {\n const dt = new DependencyTracker(insertsBySubType);\n const results = await Promise.allSettled(\n [...insertsBySubType.entries()].flatMap(([meta, inserts]) => {\n // configure will have copy/pasted base defaults into our config, so we can loop over it directly\n return Object.values(meta.config.__data.asyncDefaults).map((df) =>\n df.setOnEntities(ctx, dt, suppressedTypeErrors, meta, inserts),\n );\n }),\n );\n failIfAnyRejected(results);\n });\n}\n\n/** Sets async defaults *synchronously*, only safe for factories with `DeepNew` entities. */\nexport function setAsyncDefaultsSynchronously(ctx: unknown, entity: Entity): void {\n return runInTrustedContext(() => {\n // configure will have copy/pasted base defaults into our config, so we can loop over it directly\n for (const df of Object.values(getMetadata(entity).config.__data.asyncDefaults)) {\n df.setOnFactoryEntity(ctx, entity);\n }\n });\n}\n\n/** Wraps the hint + lambda of an async `setDefault`. */\nexport class AsyncDefault<T extends Entity> {\n readonly fieldName: string;\n readonly fieldHint: ReactiveHint<T>;\n readonly fn: (entity: any, ctx: any) => any;\n #loadHint: any;\n // We can't calc this until post-boot because it requires following metadata\n #deps: DefaultDependency[] | undefined;\n\n constructor(fieldName: string, fieldHint: ReactiveHint<T>, fn: (entity: T, ctx: any) => any) {\n this.fieldName = fieldName;\n this.fieldHint = fieldHint;\n this.fn = fn;\n }\n\n /** Given a list of inserts of the same type/subtype, set ourselves on each of them. */\n async setOnEntities(\n ctx: any,\n dt: DependencyTracker,\n suppressedTypeErrors: Error[],\n baseMetadata: EntityMetadata,\n inserts: T[],\n ): Promise<any> {\n try {\n // Ensure our dependencies have been set\n // (...and only wait on dependencies that are actively being calculated)\n const deps = this.deps(baseMetadata).filter((dep) => dt.hasMaybePending(dep.meta));\n if (deps.length > 0) {\n // console.log(\n // \"WAITING ON\",\n // deps.map((dep) => `${dep.meta.type}.${dep.fieldName}`),\n // `FOR ${baseMetadata.type}.${this.fieldName}`,\n // );\n // deps promises shouldn't reject, so we should be fine w/o allSettled here\n await Promise.all(deps.map((dep) => dt.getDeferred(dep.meta, dep.fieldName).promise));\n }\n\n // Run our default for all entities, use allSettled to avoid leaving lambdas running if one fails\n const results = await Promise.allSettled(\n inserts\n .map(async (entity) => {\n if (!isRelation(baseMetadata.allFields[this.fieldName])) {\n const hasBeenSet = this.fieldName in getInstanceData(entity).data;\n if (!hasBeenSet) {\n const value = await this.getValue(entity, ctx);\n if (value !== undefined) {\n (entity as any)[this.fieldName] = value;\n }\n }\n } else {\n const value = (entity as any)[this.fieldName];\n if (isLoadedReference(value) && !value.isSet && !value.hasBeenSet) {\n const val = await this.getValue(entity, ctx);\n if (val !== undefined) {\n value.set(val);\n }\n }\n }\n })\n .map((promise) =>\n promise.catch((reason) => {\n // If we NPE-d because a required field wasn't set, hold on to this and\n // let the validation failures reject the `em.flush` instead of us\n if (reason instanceof TypeError) {\n suppressedTypeErrors.push(reason);\n } else {\n throw reason;\n }\n }),\n ),\n );\n failIfAnyRejected(results);\n } finally {\n // Mark ourselves as complete (from a `finally` just in case our `setDefault`\n // blows up, we don't forever block the other defaults waiting on us).\n // console.log(`FINISHED ${baseMetadata.type}.${this.fieldName}`);\n dt.getDeferred(baseMetadata, this.fieldName).resolve();\n }\n }\n\n setOnFactoryEntity(ctx: unknown, entity: T): void {\n // If the lambda uses the `async` keyword, it definitely makes a promise, so don't invoke it\n // from a synchronous factory call.\n if (this.fn.constructor.name === \"AsyncFunction\") return;\n const value = (entity as any)[this.fieldName];\n try {\n if (value === undefined || (isLoadedReference(value) && !value.isSet)) {\n const val = this.fn(entity, ctx);\n // Even though we checked `async () => ...` above, a lambda could still return a Promise\n if (val instanceof Promise) {\n throw new Error(\n `Use the \\`async\\` keyword for the setDefault \"${this.fieldName}\" function that returns a Promise`,\n );\n } else if (val === undefined) {\n // If val is undefined, let the setDefault get invoked again later\n } else {\n if (isLoadedReference(value)) {\n value.set(val);\n } else {\n (entity as any)[this.fieldName] = val;\n }\n }\n }\n } catch (e) {\n // It's likely common to get NPEs/TypeErrors from speculatively executing defaults\n // pre-em.flush, i.e. we don't have the DependencyTracker/etc infra here, the lambdas\n // could do a `book.author.get.name` and NPE on the `author.get.name`. So instead just\n // suppress errors and assume `em.flush` will try again.\n // ...we need to add a NotLoadedError\n // if (!(e instanceof TypeError || e instanceof NotL)) {\n // throw e;\n // }\n }\n }\n\n /** For the given `entity`, returns what the default value should be. */\n private getValue(entity: T, ctx: any): Promise<any> {\n // We can't convert this until now, since it requires the `metadata`\n this.#loadHint ??= convertToLoadHint(getMetadata(entity), this.fieldHint);\n return entity.em.populate(entity, this.#loadHint).then((loaded) => this.fn(loaded, ctx));\n }\n\n // Calc once and cache\n private deps(meta: EntityMetadata): DefaultDependency[] {\n return (this.#deps ??= getDefaultDependencies(meta, this.fieldName, this.fieldHint));\n }\n}\n\ntype DefaultDependency = {\n meta: EntityMetadata;\n fieldName: string;\n};\n\n/**\n * Given a `meta` and a nested field hint, return the meta+field tuples included within the hint.\n *\n * I.e. passing `{ author: { firstName: {}, publisher: \"name\" } }` would return `[[Author, \"firstName\"],\n * [Publisher, \"name\"]]`.\n */\nexport function getDefaultDependencies<T extends Entity>(\n baseMeta: EntityMetadata<T>,\n baseFieldName: string,\n baseHint: ReactiveHint<T>,\n): DefaultDependency[] {\n // Ensure the hint is an `{ ... }`\n const deps: DefaultDependency[] = [];\n const todo: [meta: EntityMetadata, hint: ReactiveHint<any>][] = [[baseMeta, normalizeHint(baseHint)]];\n while (todo.length !== 0) {\n const [meta, hint] = todo.pop()!;\n for (const [fieldName, nestedHint] of Object.entries(hint)) {\n const field = meta.allFields[fieldName];\n // Super naive circular dependency detection\n const isSameField = meta === baseMeta && fieldName === baseFieldName;\n if (isSameField) continue;\n // If this is an invalid hint, just ignore it, and assume someone else will fail on it\n if (!field) continue;\n switch (field.kind) {\n case \"enum\":\n case \"primitive\":\n if (field.default === \"config\" && fieldName in meta.config.__data.asyncDefaults) {\n deps.push({ meta, fieldName });\n }\n break;\n case \"m2o\":\n if (field.default === \"config\" && fieldName in meta.config.__data.asyncDefaults) {\n deps.push({ meta, fieldName });\n }\n if (nestedHint) {\n todo.push([field.otherMetadata(), normalizeHint(nestedHint)]);\n }\n break;\n case \"o2o\":\n case \"o2m\":\n case \"m2m\":\n if (nestedHint) {\n todo.push([field.otherMetadata(), normalizeHint(nestedHint)]);\n }\n break;\n }\n }\n }\n return deps;\n}\n\n/**\n * This tracks cross-default dependencies that are active within a single `em.flush` loop.\n *\n * I.e. this is not a static \"the Author.firstName in general depends on Publisher.whatever\",\n * it tracks that we're actively inserting 10 new `Author` instances, and their `firstName`\n * default needs to wait until the `Publisher.whatever` fields have their async default\n * calculated.\n *\n * Really this is just a smaller wrapper around a map of `Deferred`s.\n */\nclass DependencyTracker {\n // Create a map \"entityType -> fieldName -> deferred\"\n #deferreds = new Map<string, Map<string, Deferred<void>>>();\n\n constructor(insertsBySubType: Map<EntityMetadata, Entity[]>) {\n // Seed it with any entities that we're actively inserting (as any dependencies to\n // entities that aren't even having `setDefault` called can be skipped)\n for (const meta of [...insertsBySubType.keys()]) {\n this.#deferreds.set(meta.type, new Map());\n }\n }\n\n hasMaybePending(meta: EntityMetadata): boolean {\n return this.#deferreds.has(meta.type) ?? false;\n }\n\n getDeferred(meta: EntityMetadata, fieldName: string): Deferred<void> {\n const map = this.#deferreds.get(meta.type) ?? fail(`No deferred check necessary for ${meta.type}.${fieldName}`);\n let deferred = map.get(fieldName);\n if (!deferred) {\n deferred = new Deferred();\n map.set(fieldName, deferred);\n }\n return deferred;\n }\n}\n\nfunction isRelation(field: Field): boolean {\n return field.kind !== \"primitive\" && field.kind !== \"enum\";\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"defaults.js","names":["#loadHint","#deps","#deferreds"],"sources":["../src/defaults.ts"],"sourcesContent":["import { Deferred } from \"joist-utils\";\nimport { getInstanceData } from \"src/BaseEntity.ts\";\nimport { type Entity } from \"src/Entity.ts\";\nimport {\n type EntityMetadata,\n type EnumField,\n type Field,\n type PrimitiveField,\n getBaseAndSelfMetas,\n getMetadata,\n} from \"src/EntityMetadata.ts\";\nimport { setField } from \"src/fields.ts\";\nimport { normalizeHint } from \"src/normalizeHints.ts\";\nimport { type ReactiveHint, convertToLoadHint } from \"src/reactivity/reactiveHints.ts\";\nimport { isLoadedReference } from \"src/relations/index.ts\";\nimport { runInTrustedContext } from \"src/trusted.ts\";\nimport { fail, failIfAnyRejected } from \"src/utils.ts\";\n\nexport function hasDefaultValue(meta: EntityMetadata, fieldName: string): boolean {\n return getBaseAndSelfMetas(meta).some(\n (m) => fieldName in m.config.__data.syncDefaults || fieldName in m.config.__data.asyncDefaults,\n );\n}\n\n/** Run the sync defaults for `entity`. */\nexport function setSyncDefaults(entity: Entity): void {\n return runInTrustedContext(() => {\n const meta = getMetadata(entity);\n // Allow subtypes to override base setDefaults\n const syncDefaults: Record<string, any> = getBaseAndSelfMetas(meta).reduce(\n (acc, m) => ({ ...acc, ...m.config.__data.syncDefaults }),\n {},\n );\n for (const [fieldName, maybeFn] of Object.entries(syncDefaults)) {\n const field = meta.allFields[fieldName];\n // Use allFields in case a subtype sets a default for one of its base fields\n if (\n (field.kind === \"primitive\" || field.kind === \"enum\") &&\n (field as PrimitiveField | EnumField).derived === \"async\"\n ) {\n // If this is an AsyncReactiveField, we want to push in a default, but setOpts is called\n // from the codegen constructor, so the user-defined `hasAsyncReactiveField` fields will\n // not have been initialized yet (i.e. `entity[field]` will be undefined and not yet an\n // `instanceof AsyncReactiveField`). Thankfully we can just use setField.\n const value = maybeFn instanceof Function ? maybeFn(entity) : maybeFn;\n setField(entity, fieldName, value);\n } else if (!isRelation(field)) {\n const hasBeenSet = fieldName in getInstanceData(entity).data;\n if (!hasBeenSet) {\n const value = maybeFn instanceof Function ? maybeFn(entity) : maybeFn;\n // If the value is undefined, leave it unset, so that a default invoked during\n // the constructor being called (before any other opts are set) can be called\n // again during `em.flush` and get an opportunity to observe other fields.\n if (value !== undefined) {\n (entity as any)[fieldName] = value;\n }\n }\n } else {\n const value = (entity as any)[fieldName];\n if (isLoadedReference(value) && !value.isSet && !value.hasBeenSet) {\n // A sync default usually would never be for a reference, because reference defaults usually\n // require a field hint (so would be async) to get \"the other entity\". However, something like:\n // `config.setDefault(\"original\", (self) => self);` is technically valid.\n value.set(maybeFn instanceof Function ? maybeFn(entity) : maybeFn);\n }\n }\n }\n });\n}\n\n/** Runs the async defaults for all inserted entities in `todos`. */\nexport async function setAsyncDefaults(\n suppressedTypeErrors: Error[],\n ctx: unknown,\n // We want this to be per-subtype, so that a subtype can have its own default, and we still invoke\n // the subtype `setOnEntities(...all subtype entities...)` and `setOnEntities(...any base types...)`\n // as bulk calls.\n insertsBySubType: Map<EntityMetadata, Entity[]>,\n): Promise<void> {\n return runInTrustedContext(async () => {\n const dt = new DependencyTracker(insertsBySubType);\n const results = await Promise.allSettled(\n [...insertsBySubType.entries()].flatMap(([meta, inserts]) => {\n // configure will have copy/pasted base defaults into our config, so we can loop over it directly\n return Object.values(meta.config.__data.asyncDefaults).map((df) =>\n df.setOnEntities(ctx, dt, suppressedTypeErrors, meta, inserts),\n );\n }),\n );\n failIfAnyRejected(results);\n });\n}\n\n/** Sets async defaults *synchronously*, only safe for factories with `DeepNew` entities. */\nexport function setAsyncDefaultsSynchronously(ctx: unknown, entity: Entity): void {\n return runInTrustedContext(() => {\n // configure will have copy/pasted base defaults into our config, so we can loop over it directly\n for (const df of Object.values(getMetadata(entity).config.__data.asyncDefaults)) {\n df.setOnFactoryEntity(ctx, entity);\n }\n });\n}\n\n/** Wraps the hint + lambda of an async `setDefault`. */\nexport class AsyncDefault<T extends Entity> {\n readonly fieldName: string;\n readonly fieldHint: ReactiveHint<T>;\n readonly fn: (entity: any, ctx: any) => any;\n #loadHint: any;\n // We can't calc this until post-boot because it requires following metadata\n #deps: DefaultDependency[] | undefined;\n\n constructor(fieldName: string, fieldHint: ReactiveHint<T>, fn: (entity: T, ctx: any) => any) {\n this.fieldName = fieldName;\n this.fieldHint = fieldHint;\n this.fn = fn;\n }\n\n /** Given a list of inserts of the same type/subtype, set ourselves on each of them. */\n async setOnEntities(\n ctx: any,\n dt: DependencyTracker,\n suppressedTypeErrors: Error[],\n baseMetadata: EntityMetadata,\n inserts: T[],\n ): Promise<any> {\n try {\n // Ensure our dependencies have been set\n // (...and only wait on dependencies that are actively being calculated)\n const deps = this.deps(baseMetadata).filter((dep) => dt.hasMaybePending(dep.meta));\n if (deps.length > 0) {\n // console.log(\n // \"WAITING ON\",\n // deps.map((dep) => `${dep.meta.type}.${dep.fieldName}`),\n // `FOR ${baseMetadata.type}.${this.fieldName}`,\n // );\n // deps promises shouldn't reject, so we should be fine w/o allSettled here\n await Promise.all(deps.map((dep) => dt.getDeferred(dep.meta, dep.fieldName).promise));\n }\n\n // Run our default for all entities, use allSettled to avoid leaving lambdas running if one fails\n const results = await Promise.allSettled(\n inserts\n .map(async (entity) => {\n if (!isRelation(baseMetadata.allFields[this.fieldName])) {\n const hasBeenSet = this.fieldName in getInstanceData(entity).data;\n if (!hasBeenSet) {\n const value = await this.getValue(entity, ctx);\n if (value !== undefined) {\n (entity as any)[this.fieldName] = value;\n }\n }\n } else {\n const value = (entity as any)[this.fieldName];\n if (isLoadedReference(value) && !value.isSet && !value.hasBeenSet) {\n const val = await this.getValue(entity, ctx);\n if (val !== undefined) {\n value.set(val);\n }\n }\n }\n })\n .map((promise) =>\n promise.catch((reason) => {\n // If we NPE-d because a required field wasn't set, hold on to this and\n // let the validation failures reject the `em.flush` instead of us\n if (reason instanceof TypeError) {\n suppressedTypeErrors.push(reason);\n } else {\n throw reason;\n }\n }),\n ),\n );\n failIfAnyRejected(results);\n } finally {\n // Mark ourselves as complete (from a `finally` just in case our `setDefault`\n // blows up, we don't forever block the other defaults waiting on us).\n // console.log(`FINISHED ${baseMetadata.type}.${this.fieldName}`);\n dt.getDeferred(baseMetadata, this.fieldName).resolve();\n }\n }\n\n setOnFactoryEntity(ctx: unknown, entity: T): void {\n // If the lambda uses the `async` keyword, it definitely makes a promise, so don't invoke it\n // from a synchronous factory call.\n if (this.fn.constructor.name === \"AsyncFunction\") return;\n const value = (entity as any)[this.fieldName];\n try {\n if (value === undefined || (isLoadedReference(value) && !value.isSet)) {\n const val = this.fn(entity, ctx);\n // Even though we checked `async () => ...` above, a lambda could still return a Promise\n if (val instanceof Promise) {\n throw new Error(\n `Use the \\`async\\` keyword for the setDefault \"${this.fieldName}\" function that returns a Promise`,\n );\n } else if (val === undefined) {\n // If val is undefined, let the setDefault get invoked again later\n } else {\n if (isLoadedReference(value)) {\n value.set(val);\n } else {\n (entity as any)[this.fieldName] = val;\n }\n }\n }\n } catch (e) {\n // It's likely common to get NPEs/TypeErrors from speculatively executing defaults\n // pre-em.flush, i.e. we don't have the DependencyTracker/etc infra here, the lambdas\n // could do a `book.author.get.name` and NPE on the `author.get.name`. So instead just\n // suppress errors and assume `em.flush` will try again.\n // ...we need to add a NotLoadedError\n // if (!(e instanceof TypeError || e instanceof NotL)) {\n // throw e;\n // }\n }\n }\n\n /** For the given `entity`, returns what the default value should be. */\n private getValue(entity: T, ctx: any): Promise<any> {\n // We can't convert this until now, since it requires the `metadata`\n this.#loadHint ??= convertToLoadHint(getMetadata(entity), this.fieldHint);\n return entity.em.populate(entity, this.#loadHint).then((loaded) => this.fn(loaded, ctx));\n }\n\n // Calc once and cache\n private deps(meta: EntityMetadata): DefaultDependency[] {\n return (this.#deps ??= getDefaultDependencies(meta, this.fieldName, this.fieldHint));\n }\n}\n\ntype DefaultDependency = {\n meta: EntityMetadata;\n fieldName: string;\n};\n\n/**\n * Given a `meta` and a nested field hint, return the meta+field tuples included within the hint.\n *\n * I.e. passing `{ author: { firstName: {}, publisher: \"name\" } }` would return `[[Author, \"firstName\"],\n * [Publisher, \"name\"]]`.\n */\nexport function getDefaultDependencies<T extends Entity>(\n baseMeta: EntityMetadata<T>,\n baseFieldName: string,\n baseHint: ReactiveHint<T>,\n): DefaultDependency[] {\n // Ensure the hint is an `{ ... }`\n const deps: DefaultDependency[] = [];\n const todo: [meta: EntityMetadata, hint: ReactiveHint<any>][] = [[baseMeta, normalizeHint(baseHint)]];\n while (todo.length !== 0) {\n const [meta, hint] = todo.pop()!;\n for (const [fieldName, nestedHint] of Object.entries(hint)) {\n const field = meta.allFields[fieldName];\n // Super naive circular dependency detection\n const isSameField = meta === baseMeta && fieldName === baseFieldName;\n if (isSameField) continue;\n // If this is an invalid hint, just ignore it, and assume someone else will fail on it\n if (!field) continue;\n switch (field.kind) {\n case \"enum\":\n case \"primitive\":\n if (field.default === \"config\" && fieldName in meta.config.__data.asyncDefaults) {\n deps.push({ meta, fieldName });\n }\n break;\n case \"m2o\":\n if (field.default === \"config\" && fieldName in meta.config.__data.asyncDefaults) {\n deps.push({ meta, fieldName });\n }\n if (nestedHint) {\n todo.push([field.otherMetadata(), normalizeHint(nestedHint)]);\n }\n break;\n case \"o2o\":\n case \"o2m\":\n case \"m2m\":\n if (nestedHint) {\n todo.push([field.otherMetadata(), normalizeHint(nestedHint)]);\n }\n break;\n }\n }\n }\n return deps;\n}\n\n/**\n * This tracks cross-default dependencies that are active within a single `em.flush` loop.\n *\n * I.e. this is not a static \"the Author.firstName in general depends on Publisher.whatever\",\n * it tracks that we're actively inserting 10 new `Author` instances, and their `firstName`\n * default needs to wait until the `Publisher.whatever` fields have their async default\n * calculated.\n *\n * Really this is just a smaller wrapper around a map of `Deferred`s.\n */\nclass DependencyTracker {\n // Create a map \"entityType -> fieldName -> deferred\"\n #deferreds = new Map<string, Map<string, Deferred<void>>>();\n\n constructor(insertsBySubType: Map<EntityMetadata, Entity[]>) {\n // Seed it with any entities that we're actively inserting (as any dependencies to\n // entities that aren't even having `setDefault` called can be skipped)\n for (const meta of [...insertsBySubType.keys()]) {\n this.#deferreds.set(meta.type, new Map());\n }\n }\n\n hasMaybePending(meta: EntityMetadata): boolean {\n return this.#deferreds.has(meta.type) ?? false;\n }\n\n getDeferred(meta: EntityMetadata, fieldName: string): Deferred<void> {\n const map = this.#deferreds.get(meta.type) ?? fail(`No deferred check necessary for ${meta.type}.${fieldName}`);\n let deferred = map.get(fieldName);\n if (!deferred) {\n deferred = new Deferred();\n map.set(fieldName, deferred);\n }\n return deferred;\n }\n}\n\nfunction isRelation(field: Field): boolean {\n return field.kind !== \"primitive\" && field.kind !== \"enum\";\n}\n"],"mappings":"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"}
|
package/build/drivers/Driver.cjs
CHANGED