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":"JsonAggregatePreloader.cjs","names":["partitionHint","AliasAssigner","getTables","kqDot","kq","canPreload","ConditionBuilder","fail","keyToNumber","keyToTaggedId","getMetadataForField","getMetadata","getEmInternalApi"],"sources":["../../src/preloading/JsonAggregatePreloader.ts"],"sourcesContent":["import { type Entity } from \"../Entity.ts\";\nimport { getEmInternalApi } from \"../EntityManager.ts\";\nimport { type EntityMetadata, type ManyToManyEnumField, getMetadata, getMetadataForField } from \"../EntityMetadata.ts\";\nimport { type EntityOrId, type HintNode } from \"../HintTree.ts\";\nimport { type ManyToManyLike } from \"../JoinRows.ts\";\nimport { keyToNumber, keyToTaggedId } from \"../keys.ts\";\nimport { type LoadHint, type NestedLoadHint } from \"../loadHints.ts\";\nimport { type JoinResult, type PreloadHydrator, type PreloadPlugin } from \"../plugins/PreloadPlugin.ts\";\nimport { ConditionBuilder } from \"../queries/ConditionBuilder.ts\";\nimport { type JoinTable, type LateralJoinTable, type ParsedFindQuery, getTables } from \"../queries/find/QueryParser.ts\";\nimport { AliasAssigner } from \"../queries/sql/AliasAssigner.ts\";\nimport { kq, kqDot } from \"../queries/sql/keywords.ts\";\nimport { type RowData } from \"../RowData.ts\";\nimport { fail } from \"../utils.ts\";\nimport { canPreload } from \"./canPreload.ts\";\nimport { partitionHint } from \"./partitionHint.ts\";\n\n/**\n * A PreloadPlugin implementation that uses `CROSS LATERAL JOIN` and `json_aggregate`\n * to preload/reduce a subtree of data while still being a single row of data.\n */\nexport class JsonAggregatePreloader implements PreloadPlugin {\n partitionHint(\n meta: EntityMetadata | undefined,\n hint: LoadHint<any>,\n ): [NestedLoadHint<any> | undefined, NestedLoadHint<any> | undefined] {\n return partitionHint(meta, hint);\n }\n\n addPreloading<T extends Entity>(\n meta: EntityMetadata,\n root: HintNode<T>,\n query: ParsedFindQuery,\n ): PreloadHydrator | undefined {\n const assigner = new AliasAssigner(query);\n\n // Get the existing primary alias\n const alias = getTables(query)[0].alias;\n const joins = calcLateralJoins(assigner, { tree: root, alias, meta }, root, alias, meta);\n // If there are no sql-based preload in the hints, just return\n if (joins.length === 0) return undefined;\n\n // Include the aggregate `_b1._ as _prequel`, `_c._ as _randomComment`\n for (const { alias, relationAlias, join } of joins) {\n query.selects.push({\n sql: `${kqDot(alias, \"_\")} as ${kq(relationAlias)}`,\n aliases: [alias],\n bindings: [],\n });\n query.tables.push(join);\n }\n\n return (rows, entities) => {\n for (let i = 0; i < entities.length; i++) {\n const parent = entities[i];\n for (const { relationAlias, hydrator } of joins) {\n hydrator(parent, parent, readRowValue(rows, i, relationAlias) ?? []);\n }\n }\n };\n }\n\n getPreloadJoins<T extends Entity>(meta: EntityMetadata, root: HintNode<T>, query: ParsedFindQuery): JoinResult[] {\n const assigner = new AliasAssigner(query);\n\n // Get the existing primary alias\n const alias = getTables(query)[0].alias;\n const joins = calcLateralJoins(assigner, { tree: root, alias, meta }, root, alias, meta);\n // If there are no sql-based preload in the hints, just return\n\n // Adapt our json aggregate joins to the higher-level JoinResult\n return joins.map((join) => {\n return {\n selects: [{ value: kqDot(join.alias, \"_\"), as: join.relationAlias }],\n join: join.join,\n hydrator: (rows, entities) => {\n for (let i = 0; i < entities.length; i++) {\n const parent = entities[i];\n join.hydrator(parent, parent, readRowValue(rows, i, join.relationAlias) ?? []);\n }\n },\n };\n });\n }\n}\n\n/** Decodes an array-of-arrays of children entries, and stores them the `parent`'s relation. */\ntype AggregateJsonHydrator = (root: Entity, parent: Entity, arrays: unknown[][]) => void;\n\n/**\n * For a given hint tree `hint`, finds all SQL-able relations and preloads them.\n *\n * Specifically we use `json_agg` & `json_build_array` to `CROSS LATERAL JOIN`\n * children/grand children back as arbitrarily-deeply nested arrays, and then\n * stash the results in the `EntityManager` `joinLoadedRelations` cache, which\n * each join-instrumented relation will check before making its SQL calls.\n *\n * https://sqlfum.pt/?n=60&indent=2&spaces=1&simplify=1&align=0&case=lower&sql=c2VsZWN0IGEuaWQsIGIuXyBhcyBiLCBjMS5fIGFzIGMxLCBhMS5fIGFzIGExIGZyb20gYXV0aG9ycyBhIGNyb3NzIGpvaW4gbGF0ZXJhbCAoIHNlbGVjdCBqc29uX2FnZyhqc29uX2J1aWxkX2FycmF5KGIuaWQsIGIudGl0bGUsIGIuIm9yZGVyIiwgYi5kZWxldGVkX2F0LCBiLmNyZWF0ZWRfYXQsIGIudXBkYXRlZF9hdCwgYi5hdXRob3JfaWQsIGJyLl8pKSBhcyBfIGZyb20gYm9va3MgYiBjcm9zcyBqb2luIGxhdGVyYWwgKCBzZWxlY3QganNvbl9hZ2coanNvbl9idWlsZF9hcnJheShici5pZCwgYnIucmF0aW5nLCBici5pc19wdWJsaWMsIGJyLmlzX3Rlc3QsIGJyLmNyZWF0ZWRfYXQsIGJyLnVwZGF0ZWRfYXQsIGJyLmJvb2tfaWQsIGMuXykpIGFzIF8gZnJvbSBib29rX3Jldmlld3MgYnIgY3Jvc3Mgam9pbiBsYXRlcmFsICggc2VsZWN0IGpzb25fYWdnKGpzb25fYnVpbGRfYXJyYXkoYy5pZCwgYy50ZXh0LCBjLmNyZWF0ZWRfYXQsIGMudXBkYXRlZF9hdCwgYy51c2VyX2lkLCBjLnBhcmVudF9hdXRob3JfaWQsIGMucGFyZW50X2Jvb2tfaWQsIGMucGFyZW50X2Jvb2tfcmV2aWV3X2lkLCBjLnBhcmVudF9wdWJsaXNoZXJfaWQpKSBhcyBfIGZyb20gY29tbWVudHMgYyB3aGVyZSBjLnBhcmVudF9ib29rX3Jldmlld19pZCA9IGJyLmlkICkgYyB3aGVyZSBici5ib29rX2lkID0gYi5pZCApIGJyIHdoZXJlIGIuYXV0aG9yX2lkID0gYS5pZCApIGIgY3Jvc3Mgam9pbiBsYXRlcmFsICggc2VsZWN0IGpzb25fYWdnKGpzb25fYnVpbGRfYXJyYXkoYzEuaWQsIGMxLnRleHQsIGMxLmNyZWF0ZWRfYXQsIGMxLnVwZGF0ZWRfYXQsIGMxLnVzZXJfaWQsIGMxLnBhcmVudF9hdXRob3JfaWQsIGMxLnBhcmVudF9ib29rX2lkLCBjMS5wYXJlbnRfYm9va19yZXZpZXdfaWQsIGMxLnBhcmVudF9wdWJsaXNoZXJfaWQpKSBhcyBfIGZyb20gY29tbWVudHMgYzEgd2hlcmUgYzEucGFyZW50X2F1dGhvcl9pZCA9IGEuaWQgKSBjMSBjcm9zcyBqb2luIGxhdGVyYWwgKCBzZWxlY3QganNvbl9hZ2coanNvbl9idWlsZF9hcnJheShhMS5pZCwgYTEuZmlyc3RfbmFtZSwgYTEubGFzdF9uYW1lLCBhMS5zc24sIGExLmluaXRpYWxzLCBhMS5udW1iZXJfb2ZfYm9va3MsIGExLmJvb2tfY29tbWVudHMsIGExLmlzX3BvcHVsYXIsIGExLmFnZSwgYTEuZ3JhZHVhdGVkLCBhMS5uaWNrX25hbWVzLCBhMS53YXNfZXZlcl9wb3B1bGFyLCBhMS5hZGRyZXNzLCBhMS5idXNpbmVzc19hZGRyZXNzLCBhMS5xdW90ZXMsIGExLm51bWJlcl9vZl9hdG9tcywgYTEuZGVsZXRlZF9hdCwgYTEubnVtYmVyX29mX3B1YmxpY19yZXZpZXdzLCBhMS4ibnVtYmVyT2ZQdWJsaWNSZXZpZXdzMiIsIGExLnRhZ3Nfb2ZfYWxsX2Jvb2tzLCBhMS5jcmVhdGVkX2F0LCBhMS51cGRhdGVkX2F0LCBhMS5mYXZvcml0ZV9zaGFwZSwgYTEuZmF2b3JpdGVfY29sb3JzLCBhMS5tZW50b3JfaWQsIGExLmN1cnJlbnRfZHJhZnRfYm9va19pZCwgYTEuZmF2b3JpdGVfYm9va19pZCwgYTEucHVibGlzaGVyX2lkKSkgYXMgXyBmcm9tIGF1dGhvcnMgYTEgd2hlcmUgYTEuaWQgPSBhLm1lbnRvcl9pZCApIGExIHdoZXJlIGEuaWQgPSAxOw%3D%3D\n */\n\n/**\n * Given a `parent` like Author, and a hint of `{ books: ..., comments: ... }`, create `CROSS JOIN LATERAL`s\n * that will pull in the `books` & `comments` children.\n */\nfunction calcLateralJoins<I extends EntityOrId>(\n assigner: AliasAssigner,\n root: { tree: HintNode<I>; alias: string; meta: EntityMetadata },\n tree: HintNode<I>,\n parentAlias: string,\n parentMeta: EntityMetadata,\n pathPrefix: string = \"\",\n): AggregateJoinResult[] {\n const results: AggregateJoinResult[] = [];\n\n // Join in SQL-able hints from parent\n Object.entries(tree.hints).forEach(([key, subTree]) => {\n const field = parentMeta.allFields[key];\n // AsyncProperties don't have fields, which is fine, skip for now...\n if (field && canPreload(parentMeta, field)) {\n // Enum m2ms have no \"other\" entity to join/hydrate; just aggregate the join table's enum ids.\n if (field.kind === \"m2mEnum\") {\n results.push(calcEnumLateralJoin(assigner, root, subTree, parentAlias, field, key, pathPrefix));\n return;\n }\n const otherMeta = field.otherMetadata();\n const otherField = otherMeta.allFields[field.otherFieldName];\n\n // Short table alias for column refs inside the subquery, e.g. `_b1`\n const otherAlias = `_${assigner.getAlias(otherMeta.tableName)}`;\n // Readable path-based column alias for the outer AS clause, e.g. `_books_reviews`\n const pathKey = key.toLowerCase();\n const relationAlias = `_${assigner.getLiteralAlias(`${pathPrefix}${pathKey}`)}`;\n\n // Do the recursion up-front, so we can work it into our own join/hydrator\n const subJoins = calcLateralJoins(assigner, root, subTree, otherAlias, otherMeta, `${pathPrefix}${pathKey}_`);\n\n // Get all fields with serdes and flatten out the columns, skipping `lazy` columns (fetched on-demand)\n const columns = Object.values(otherMeta.allFields)\n .filter((f) => f.serde && !(f.kind === \"primitive\" && f.lazy))\n .flatMap((f) => f.serde!.columns);\n const selects = [\n ...columns.map((c) => kqDot(otherAlias, c.columnName)),\n // We eventually need to handle parent types/subtypes here...\n // Combine any grandchilden\n ...subJoins.map((sb) => kqDot(sb.alias, \"_\")),\n ];\n\n const aliasMaybeSuffix = kq(`${parentAlias}${field.aliasSuffix}`);\n\n const cb = new ConditionBuilder();\n let m2mTable: JoinTable | undefined;\n let m2mAlias: string | undefined;\n if (otherField.kind === \"m2o\") {\n cb.addRawCondition({\n aliases: [otherAlias, parentAlias],\n condition: `${kqDot(otherAlias, otherField.serde.columns[0].columnName)} = ${kqDot(parentAlias, \"id\")}`,\n pruneable: true,\n });\n } else if (otherField.kind === \"poly\") {\n // Get the component that points to us\n // const comp = otherField.components.find((c) => getAllMetas(parentMeta).some((m) => m.cstr === c.otherMetadata().cstr)) ??\n const comp =\n otherField.components.find((c) => parentMeta.cstr === c.otherMetadata().cstr) ??\n fail(`No component found for ${field.fieldName} -> ${otherField.fieldName}`);\n cb.addRawCondition({\n aliases: [otherAlias, parentAlias],\n condition: `${kqDot(otherAlias, comp.columnName)} = ${kqDot(parentAlias, \"id\")}`,\n pruneable: true,\n });\n } else if (otherField.kind === \"o2m\" || otherField.kind === \"lo2m\") {\n cb.addRawCondition({\n aliases: [otherAlias, aliasMaybeSuffix],\n condition: `${kqDot(otherAlias, \"id\")} = ${aliasMaybeSuffix}.${kq(field.serde!.columns[0].columnName)}`,\n pruneable: true,\n });\n } else if (otherField.kind === \"o2o\") {\n cb.addRawCondition({\n aliases: [otherAlias, aliasMaybeSuffix],\n condition: `${kqDot(otherAlias, \"id\")} = ${aliasMaybeSuffix}.${kq(field.serde!.columns[0].columnName)}`,\n pruneable: true,\n });\n } else if (otherField.kind === \"m2m\") {\n m2mAlias = assigner.getAlias(otherField.joinTableName);\n // Get the m2m row's id to track in JoinRows; id-less tables have no surrogate id.\n if (otherField.hasJoinTableId) selects.unshift(kqDot(m2mAlias, \"id\"));\n m2mTable = {\n join: \"inner\",\n table: otherField.joinTableName,\n alias: m2mAlias,\n col1: kqDot(parentAlias, \"id\"),\n col2: kqDot(m2mAlias, otherField.columnNames[1]),\n };\n cb.addRawCondition({\n aliases: [m2mAlias, otherAlias],\n condition: `${kqDot(m2mAlias, otherField.columnNames[0])} = ${kqDot(otherAlias, \"id\")}`,\n pruneable: true,\n });\n } else {\n throw new Error(`Unsupported otherField.kind ${otherField.kind}`);\n }\n\n const needsSubSelect = subTree.entities.size !== root.tree.entities.size;\n if (needsSubSelect) {\n cb.addRawCondition({\n aliases: [root.alias],\n condition: `${kqDot(root.alias, \"id\")} = ANY(?)`,\n bindings: [\n [...subTree.entities]\n .filter((e) => typeof e === \"string\" || !e.isNewEntity)\n .map((e) => keyToNumber(root.meta, typeof e === \"string\" ? e : e.id)),\n ],\n pruneable: true,\n });\n }\n\n // For m2m, order by the join-row's id so preloaded results match the order the lazy batch\n // loader returns (which orders by join-row id). Id-less join tables have no surrogate id,\n // so order by the other entity's FK column (matching the lazy loader & getOthers). Otherwise,\n // order by the target entity's id.\n const orderBy =\n otherField.kind === \"m2m\" && !otherField.hasJoinTableId\n ? `${kq(m2mAlias!)}.${kq(otherField.columnNames[0])}`\n : `${kq(m2mAlias ?? otherAlias)}.id`;\n\n const join: LateralJoinTable = {\n join: \"lateral\",\n alias: otherAlias,\n // Do we need to say which alias we're coming from, to avoid having it pruned?\n // ...maybe not because preloading is always on the primary table?\n fromAlias: \"unset\",\n table: otherMeta.tableName,\n query: {\n selects: [`json_agg(json_build_array(${selects.join(\", \")}) order by ${orderBy}) as _`],\n tables: [\n { join: \"primary\", table: otherMeta.tableName, alias: otherAlias },\n ...(m2mTable ? [m2mTable] : []),\n ...subJoins.map((sj) => sj.join),\n ],\n condition: cb.toExpressionFilter(),\n orderBys: [],\n },\n };\n\n // Pre-compute column names so we don't re-read them per entity\n const columnNames = columns.map((c) => c.columnName);\n // If we've snuck the m2m row id into the json array, ignore it (id-less tables have no id)\n const m2mOffset = field.kind === \"m2m\" && field.hasJoinTableId ? 1 : 0;\n\n const hydrator: AggregateJsonHydrator = (root, parent, arrays) => {\n const { em } = root;\n\n // If we had overlapping load hints, i.e. `author.books` for [a1, a2] and `author.comments` for [a1], and\n // we're processing the arrays of comments, but for a root author like `a2` that didn't ask for our load\n // hint, then skip it to keep the relation unloaded.\n if (subTree.entitiesKind === \"instances\" && !subTree.entities.has(root as any)) return;\n if (subTree.entitiesKind === \"ids\" && !subTree.entities.has(root.idTagged as any)) return;\n\n // We get back an array of [[1, title], [2, title], [3, title]]\n const children = arrays.map((array) => {\n const taggedId = keyToTaggedId(otherMeta, array[m2mOffset] as any)!;\n const row: Record<string, any> = {};\n for (let i = 0; i < columns.length; i++) {\n row[columnNames[i]] = columns[i].mapFromJsonAgg(array[m2mOffset + i]);\n }\n const entity =\n em.findExistingInstance<Entity>(taggedId) ??\n (em.hydrate(otherMeta.cstr, [row], { overwriteExisting: false }) as Entity[])[0];\n // Tell the internal JoinRow booking-keeping about this m2m row\n if (field.kind === \"m2m\") {\n // TODO This `addExisting` needs to be pulled up, out of the `arrays.map`, so we can do a `loadRows`-ish\n // call that passes all now-known m2m rows into JoinRows as a single list, so that it can mark any\n // deleted-from-under-us m2m rows as deleted.\n const m2m = (parent as any)[key];\n getEmInternalApi(em)\n .joinRows(m2m)\n .addPreloadedRow(m2m, field.hasJoinTableId ? (array[0] as any) : undefined, parent, entity);\n }\n // Within each child, look for grandchildren\n subJoins.forEach((sub, i) => {\n // array[i] could be null if there are no grandchildren, but still call `sub` to\n // process it so that we store the empty array into the em.joinLoadedRelations, to\n // avoid the relation.load method later doing a SQL for rows we know are not there.\n sub.hydrator(root, entity, (array[m2mOffset + columns.length + i] as any) ?? []);\n });\n return entity;\n });\n // Cache the entities so `.load`s will see them\n getEmInternalApi(em).setPreloadedRelation(parent.idTagged, key, children);\n };\n\n results.push({ alias: otherAlias, relationAlias, join, hydrator });\n }\n });\n\n return results;\n}\n\n/**\n * Builds the `CROSS JOIN LATERAL` that aggregates an enum-m2m join table (e.g. `publisher_logo_colors`)\n * into a json array of enum ids, e.g. `[[1], [3]]` (or `[[1, id], [3, id]]` for id-ful join tables).\n */\nfunction calcEnumLateralJoin<I extends EntityOrId>(\n assigner: AliasAssigner,\n root: { tree: HintNode<I>; alias: string; meta: EntityMetadata },\n subTree: HintNode<I>,\n parentAlias: string,\n field: ManyToManyEnumField,\n key: string,\n pathPrefix: string,\n): AggregateJoinResult {\n const [entityColumn, enumColumn] = field.columnNames;\n const jtAlias = `_${assigner.getAlias(field.joinTableName)}`;\n const relationAlias = `_${assigner.getLiteralAlias(`${pathPrefix}${key.toLowerCase()}`)}`;\n\n const parts = [kqDot(jtAlias, enumColumn)];\n if (field.hasJoinTableId) parts.push(kqDot(jtAlias, \"id\"));\n\n const cb = new ConditionBuilder();\n cb.addRawCondition({\n aliases: [jtAlias, parentAlias],\n condition: `${kqDot(jtAlias, entityColumn)} = ${kqDot(parentAlias, \"id\")}`,\n pruneable: true,\n });\n\n const needsSubSelect = subTree.entities.size !== root.tree.entities.size;\n if (needsSubSelect) {\n cb.addRawCondition({\n aliases: [root.alias],\n condition: `${kqDot(root.alias, \"id\")} = ANY(?)`,\n bindings: [\n [...subTree.entities]\n .filter((e) => typeof e === \"string\" || !e.isNewEntity)\n .map((e) => keyToNumber(root.meta, typeof e === \"string\" ? e : e.id)),\n ],\n pruneable: true,\n });\n }\n\n const orderBy = `${kq(jtAlias)}.${kq(field.hasJoinTableId ? \"id\" : enumColumn)}`;\n const join: LateralJoinTable = {\n join: \"lateral\",\n alias: jtAlias,\n fromAlias: \"unset\",\n table: field.joinTableName,\n query: {\n selects: [`json_agg(json_build_array(${parts.join(\", \")}) order by ${orderBy}) as _`],\n tables: [{ join: \"primary\", table: field.joinTableName, alias: jtAlias }],\n condition: cb.toExpressionFilter(),\n orderBys: [],\n },\n };\n\n const hydrator: AggregateJsonHydrator = (root, parent, arrays) => {\n const { em } = root;\n if (subTree.entitiesKind === \"instances\" && !subTree.entities.has(root as any)) return;\n if (subTree.entitiesKind === \"ids\" && !subTree.entities.has(root.idTagged as any)) return;\n const like: ManyToManyLike = {\n entity: parent,\n joinTableName: field.joinTableName,\n columnName: entityColumn,\n otherColumnName: enumColumn,\n fieldName: key,\n meta: getMetadataForField(getMetadata(parent), key),\n otherEnum: field.enumDetailType,\n hasJoinTableId: field.hasJoinTableId,\n };\n const api = getEmInternalApi(em);\n const joinRows = api.joinRows(like);\n const codes: any[] = [];\n for (const array of arrays) {\n const enumId = array[0] as number;\n joinRows.addPreloadedRow(like, field.hasJoinTableId ? (array[1] as number) : undefined, parent, enumId);\n codes.push(field.enumDetailType.findById(enumId)!.code);\n }\n api.setPreloadedRelation(parent.idTagged, key, codes);\n };\n\n return { alias: jtAlias, relationAlias, join, hydrator };\n}\n\n/** A preload-loadable join for a given child, with potentially grand-child joins contained within it. */\ntype AggregateJoinResult = {\n /** The short table alias used for column references inside the subquery, e.g. `_b1`. */\n alias: string;\n /** The readable relation-name alias used in the outer `AS` clause, e.g. `_prequel`. */\n relationAlias: string;\n /** The SQL for this child's lateral join, which itself might have recursive lateral joins. */\n join: LateralJoinTable;\n /** The hydrator for this child's lateral join, which itself might recursively hydrator subjoins. */\n hydrator: AggregateJsonHydrator;\n};\n\n/** Reads one column from either classic POJO rows or a lazy `RowData` result. */\nfunction readRowValue(rows: any[] | RowData, rowIndex: number, columnName: string): any {\n return Array.isArray(rows) ? rows[rowIndex][columnName] : rows.get(rowIndex, columnName);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"JsonAggregatePreloader.cjs","names":["partitionHint","AliasAssigner","getTables","kqDot","kq","canPreload","ConditionBuilder","fail","keyToNumber","keyToTaggedId","getMetadataForField","getMetadata","getEmInternalApi"],"sources":["../../src/preloading/JsonAggregatePreloader.ts"],"sourcesContent":["import { type Entity } from \"src/Entity.ts\";\nimport { getEmInternalApi } from \"src/EntityManager.ts\";\nimport { type EntityMetadata, type ManyToManyEnumField, getMetadata, getMetadataForField } from \"src/EntityMetadata.ts\";\nimport type { ManyToManyLike } from \"src/flush/JoinRows.ts\";\nimport { keyToNumber, keyToTaggedId } from \"src/keys.ts\";\nimport type { EntityOrId, HintNode } from \"src/loading/HintTree.ts\";\nimport type { LoadHint, NestedLoadHint } from \"src/loading/loadHints.ts\";\nimport { type JoinResult, type PreloadHydrator, type PreloadPlugin } from \"src/plugins/PreloadPlugin.ts\";\nimport { canPreload } from \"src/preloading/canPreload.ts\";\nimport { partitionHint } from \"src/preloading/partitionHint.ts\";\nimport { ConditionBuilder } from \"src/queries/ConditionBuilder.ts\";\nimport {\n type JoinTable,\n type LateralJoinTable,\n type ParsedFindQuery,\n getTables,\n} from \"src/queries/find/QueryParser.ts\";\nimport { AliasAssigner } from \"src/queries/sql/AliasAssigner.ts\";\nimport { kq, kqDot } from \"src/queries/sql/keywords.ts\";\nimport { type RowData } from \"src/RowData.ts\";\nimport { fail } from \"src/utils.ts\";\n\n/**\n * A PreloadPlugin implementation that uses `CROSS LATERAL JOIN` and `json_aggregate`\n * to preload/reduce a subtree of data while still being a single row of data.\n */\nexport class JsonAggregatePreloader implements PreloadPlugin {\n partitionHint(\n meta: EntityMetadata | undefined,\n hint: LoadHint<any>,\n ): [NestedLoadHint<any> | undefined, NestedLoadHint<any> | undefined] {\n return partitionHint(meta, hint);\n }\n\n addPreloading<T extends Entity>(\n meta: EntityMetadata,\n root: HintNode<T>,\n query: ParsedFindQuery,\n ): PreloadHydrator | undefined {\n const assigner = new AliasAssigner(query);\n\n // Get the existing primary alias\n const alias = getTables(query)[0].alias;\n const joins = calcLateralJoins(assigner, { tree: root, alias, meta }, root, alias, meta);\n // If there are no sql-based preload in the hints, just return\n if (joins.length === 0) return undefined;\n\n // Include the aggregate `_b1._ as _prequel`, `_c._ as _randomComment`\n for (const { alias, relationAlias, join } of joins) {\n query.selects.push({\n sql: `${kqDot(alias, \"_\")} as ${kq(relationAlias)}`,\n aliases: [alias],\n bindings: [],\n });\n query.tables.push(join);\n }\n\n return (rows, entities) => {\n for (let i = 0; i < entities.length; i++) {\n const parent = entities[i];\n for (const { relationAlias, hydrator } of joins) {\n hydrator(parent, parent, readRowValue(rows, i, relationAlias) ?? []);\n }\n }\n };\n }\n\n getPreloadJoins<T extends Entity>(meta: EntityMetadata, root: HintNode<T>, query: ParsedFindQuery): JoinResult[] {\n const assigner = new AliasAssigner(query);\n\n // Get the existing primary alias\n const alias = getTables(query)[0].alias;\n const joins = calcLateralJoins(assigner, { tree: root, alias, meta }, root, alias, meta);\n // If there are no sql-based preload in the hints, just return\n\n // Adapt our json aggregate joins to the higher-level JoinResult\n return joins.map((join) => {\n return {\n selects: [{ value: kqDot(join.alias, \"_\"), as: join.relationAlias }],\n join: join.join,\n hydrator: (rows, entities) => {\n for (let i = 0; i < entities.length; i++) {\n const parent = entities[i];\n join.hydrator(parent, parent, readRowValue(rows, i, join.relationAlias) ?? []);\n }\n },\n };\n });\n }\n}\n\n/** Decodes an array-of-arrays of children entries, and stores them the `parent`'s relation. */\ntype AggregateJsonHydrator = (root: Entity, parent: Entity, arrays: unknown[][]) => void;\n\n/**\n * For a given hint tree `hint`, finds all SQL-able relations and preloads them.\n *\n * Specifically we use `json_agg` & `json_build_array` to `CROSS LATERAL JOIN`\n * children/grand children back as arbitrarily-deeply nested arrays, and then\n * stash the results in the `EntityManager` `joinLoadedRelations` cache, which\n * each join-instrumented relation will check before making its SQL calls.\n *\n * https://sqlfum.pt/?n=60&indent=2&spaces=1&simplify=1&align=0&case=lower&sql=c2VsZWN0IGEuaWQsIGIuXyBhcyBiLCBjMS5fIGFzIGMxLCBhMS5fIGFzIGExIGZyb20gYXV0aG9ycyBhIGNyb3NzIGpvaW4gbGF0ZXJhbCAoIHNlbGVjdCBqc29uX2FnZyhqc29uX2J1aWxkX2FycmF5KGIuaWQsIGIudGl0bGUsIGIuIm9yZGVyIiwgYi5kZWxldGVkX2F0LCBiLmNyZWF0ZWRfYXQsIGIudXBkYXRlZF9hdCwgYi5hdXRob3JfaWQsIGJyLl8pKSBhcyBfIGZyb20gYm9va3MgYiBjcm9zcyBqb2luIGxhdGVyYWwgKCBzZWxlY3QganNvbl9hZ2coanNvbl9idWlsZF9hcnJheShici5pZCwgYnIucmF0aW5nLCBici5pc19wdWJsaWMsIGJyLmlzX3Rlc3QsIGJyLmNyZWF0ZWRfYXQsIGJyLnVwZGF0ZWRfYXQsIGJyLmJvb2tfaWQsIGMuXykpIGFzIF8gZnJvbSBib29rX3Jldmlld3MgYnIgY3Jvc3Mgam9pbiBsYXRlcmFsICggc2VsZWN0IGpzb25fYWdnKGpzb25fYnVpbGRfYXJyYXkoYy5pZCwgYy50ZXh0LCBjLmNyZWF0ZWRfYXQsIGMudXBkYXRlZF9hdCwgYy51c2VyX2lkLCBjLnBhcmVudF9hdXRob3JfaWQsIGMucGFyZW50X2Jvb2tfaWQsIGMucGFyZW50X2Jvb2tfcmV2aWV3X2lkLCBjLnBhcmVudF9wdWJsaXNoZXJfaWQpKSBhcyBfIGZyb20gY29tbWVudHMgYyB3aGVyZSBjLnBhcmVudF9ib29rX3Jldmlld19pZCA9IGJyLmlkICkgYyB3aGVyZSBici5ib29rX2lkID0gYi5pZCApIGJyIHdoZXJlIGIuYXV0aG9yX2lkID0gYS5pZCApIGIgY3Jvc3Mgam9pbiBsYXRlcmFsICggc2VsZWN0IGpzb25fYWdnKGpzb25fYnVpbGRfYXJyYXkoYzEuaWQsIGMxLnRleHQsIGMxLmNyZWF0ZWRfYXQsIGMxLnVwZGF0ZWRfYXQsIGMxLnVzZXJfaWQsIGMxLnBhcmVudF9hdXRob3JfaWQsIGMxLnBhcmVudF9ib29rX2lkLCBjMS5wYXJlbnRfYm9va19yZXZpZXdfaWQsIGMxLnBhcmVudF9wdWJsaXNoZXJfaWQpKSBhcyBfIGZyb20gY29tbWVudHMgYzEgd2hlcmUgYzEucGFyZW50X2F1dGhvcl9pZCA9IGEuaWQgKSBjMSBjcm9zcyBqb2luIGxhdGVyYWwgKCBzZWxlY3QganNvbl9hZ2coanNvbl9idWlsZF9hcnJheShhMS5pZCwgYTEuZmlyc3RfbmFtZSwgYTEubGFzdF9uYW1lLCBhMS5zc24sIGExLmluaXRpYWxzLCBhMS5udW1iZXJfb2ZfYm9va3MsIGExLmJvb2tfY29tbWVudHMsIGExLmlzX3BvcHVsYXIsIGExLmFnZSwgYTEuZ3JhZHVhdGVkLCBhMS5uaWNrX25hbWVzLCBhMS53YXNfZXZlcl9wb3B1bGFyLCBhMS5hZGRyZXNzLCBhMS5idXNpbmVzc19hZGRyZXNzLCBhMS5xdW90ZXMsIGExLm51bWJlcl9vZl9hdG9tcywgYTEuZGVsZXRlZF9hdCwgYTEubnVtYmVyX29mX3B1YmxpY19yZXZpZXdzLCBhMS4ibnVtYmVyT2ZQdWJsaWNSZXZpZXdzMiIsIGExLnRhZ3Nfb2ZfYWxsX2Jvb2tzLCBhMS5jcmVhdGVkX2F0LCBhMS51cGRhdGVkX2F0LCBhMS5mYXZvcml0ZV9zaGFwZSwgYTEuZmF2b3JpdGVfY29sb3JzLCBhMS5tZW50b3JfaWQsIGExLmN1cnJlbnRfZHJhZnRfYm9va19pZCwgYTEuZmF2b3JpdGVfYm9va19pZCwgYTEucHVibGlzaGVyX2lkKSkgYXMgXyBmcm9tIGF1dGhvcnMgYTEgd2hlcmUgYTEuaWQgPSBhLm1lbnRvcl9pZCApIGExIHdoZXJlIGEuaWQgPSAxOw%3D%3D\n */\n\n/**\n * Given a `parent` like Author, and a hint of `{ books: ..., comments: ... }`, create `CROSS JOIN LATERAL`s\n * that will pull in the `books` & `comments` children.\n */\nfunction calcLateralJoins<I extends EntityOrId>(\n assigner: AliasAssigner,\n root: { tree: HintNode<I>; alias: string; meta: EntityMetadata },\n tree: HintNode<I>,\n parentAlias: string,\n parentMeta: EntityMetadata,\n pathPrefix: string = \"\",\n): AggregateJoinResult[] {\n const results: AggregateJoinResult[] = [];\n\n // Join in SQL-able hints from parent\n Object.entries(tree.hints).forEach(([key, subTree]) => {\n const field = parentMeta.allFields[key];\n // AsyncProperties don't have fields, which is fine, skip for now...\n if (field && canPreload(parentMeta, field)) {\n // Enum m2ms have no \"other\" entity to join/hydrate; just aggregate the join table's enum ids.\n if (field.kind === \"m2mEnum\") {\n results.push(calcEnumLateralJoin(assigner, root, subTree, parentAlias, field, key, pathPrefix));\n return;\n }\n const otherMeta = field.otherMetadata();\n const otherField = otherMeta.allFields[field.otherFieldName];\n\n // Short table alias for column refs inside the subquery, e.g. `_b1`\n const otherAlias = `_${assigner.getAlias(otherMeta.tableName)}`;\n // Readable path-based column alias for the outer AS clause, e.g. `_books_reviews`\n const pathKey = key.toLowerCase();\n const relationAlias = `_${assigner.getLiteralAlias(`${pathPrefix}${pathKey}`)}`;\n\n // Do the recursion up-front, so we can work it into our own join/hydrator\n const subJoins = calcLateralJoins(assigner, root, subTree, otherAlias, otherMeta, `${pathPrefix}${pathKey}_`);\n\n // Get all fields with serdes and flatten out the columns, skipping `lazy` columns (fetched on-demand)\n const columns = Object.values(otherMeta.allFields)\n .filter((f) => f.serde && !(f.kind === \"primitive\" && f.lazy))\n .flatMap((f) => f.serde!.columns);\n const selects = [\n ...columns.map((c) => kqDot(otherAlias, c.columnName)),\n // We eventually need to handle parent types/subtypes here...\n // Combine any grandchilden\n ...subJoins.map((sb) => kqDot(sb.alias, \"_\")),\n ];\n\n const aliasMaybeSuffix = kq(`${parentAlias}${field.aliasSuffix}`);\n\n const cb = new ConditionBuilder();\n let m2mTable: JoinTable | undefined;\n let m2mAlias: string | undefined;\n if (otherField.kind === \"m2o\") {\n cb.addRawCondition({\n aliases: [otherAlias, parentAlias],\n condition: `${kqDot(otherAlias, otherField.serde.columns[0].columnName)} = ${kqDot(parentAlias, \"id\")}`,\n pruneable: true,\n });\n } else if (otherField.kind === \"poly\") {\n // Get the component that points to us\n // const comp = otherField.components.find((c) => getAllMetas(parentMeta).some((m) => m.cstr === c.otherMetadata().cstr)) ??\n const comp =\n otherField.components.find((c) => parentMeta.cstr === c.otherMetadata().cstr) ??\n fail(`No component found for ${field.fieldName} -> ${otherField.fieldName}`);\n cb.addRawCondition({\n aliases: [otherAlias, parentAlias],\n condition: `${kqDot(otherAlias, comp.columnName)} = ${kqDot(parentAlias, \"id\")}`,\n pruneable: true,\n });\n } else if (otherField.kind === \"o2m\" || otherField.kind === \"lo2m\") {\n cb.addRawCondition({\n aliases: [otherAlias, aliasMaybeSuffix],\n condition: `${kqDot(otherAlias, \"id\")} = ${aliasMaybeSuffix}.${kq(field.serde!.columns[0].columnName)}`,\n pruneable: true,\n });\n } else if (otherField.kind === \"o2o\") {\n cb.addRawCondition({\n aliases: [otherAlias, aliasMaybeSuffix],\n condition: `${kqDot(otherAlias, \"id\")} = ${aliasMaybeSuffix}.${kq(field.serde!.columns[0].columnName)}`,\n pruneable: true,\n });\n } else if (otherField.kind === \"m2m\") {\n m2mAlias = assigner.getAlias(otherField.joinTableName);\n // Get the m2m row's id to track in JoinRows; id-less tables have no surrogate id.\n if (otherField.hasJoinTableId) selects.unshift(kqDot(m2mAlias, \"id\"));\n m2mTable = {\n join: \"inner\",\n table: otherField.joinTableName,\n alias: m2mAlias,\n col1: kqDot(parentAlias, \"id\"),\n col2: kqDot(m2mAlias, otherField.columnNames[1]),\n };\n cb.addRawCondition({\n aliases: [m2mAlias, otherAlias],\n condition: `${kqDot(m2mAlias, otherField.columnNames[0])} = ${kqDot(otherAlias, \"id\")}`,\n pruneable: true,\n });\n } else {\n throw new Error(`Unsupported otherField.kind ${otherField.kind}`);\n }\n\n const needsSubSelect = subTree.entities.size !== root.tree.entities.size;\n if (needsSubSelect) {\n cb.addRawCondition({\n aliases: [root.alias],\n condition: `${kqDot(root.alias, \"id\")} = ANY(?)`,\n bindings: [\n [...subTree.entities]\n .filter((e) => typeof e === \"string\" || !e.isNewEntity)\n .map((e) => keyToNumber(root.meta, typeof e === \"string\" ? e : e.id)),\n ],\n pruneable: true,\n });\n }\n\n // For m2m, order by the join-row's id so preloaded results match the order the lazy batch\n // loader returns (which orders by join-row id). Id-less join tables have no surrogate id,\n // so order by the other entity's FK column (matching the lazy loader & getOthers). Otherwise,\n // order by the target entity's id.\n const orderBy =\n otherField.kind === \"m2m\" && !otherField.hasJoinTableId\n ? `${kq(m2mAlias!)}.${kq(otherField.columnNames[0])}`\n : `${kq(m2mAlias ?? otherAlias)}.id`;\n\n const join: LateralJoinTable = {\n join: \"lateral\",\n alias: otherAlias,\n // Do we need to say which alias we're coming from, to avoid having it pruned?\n // ...maybe not because preloading is always on the primary table?\n fromAlias: \"unset\",\n table: otherMeta.tableName,\n query: {\n selects: [`json_agg(json_build_array(${selects.join(\", \")}) order by ${orderBy}) as _`],\n tables: [\n { join: \"primary\", table: otherMeta.tableName, alias: otherAlias },\n ...(m2mTable ? [m2mTable] : []),\n ...subJoins.map((sj) => sj.join),\n ],\n condition: cb.toExpressionFilter(),\n orderBys: [],\n },\n };\n\n // Pre-compute column names so we don't re-read them per entity\n const columnNames = columns.map((c) => c.columnName);\n // If we've snuck the m2m row id into the json array, ignore it (id-less tables have no id)\n const m2mOffset = field.kind === \"m2m\" && field.hasJoinTableId ? 1 : 0;\n\n const hydrator: AggregateJsonHydrator = (root, parent, arrays) => {\n const { em } = root;\n\n // If we had overlapping load hints, i.e. `author.books` for [a1, a2] and `author.comments` for [a1], and\n // we're processing the arrays of comments, but for a root author like `a2` that didn't ask for our load\n // hint, then skip it to keep the relation unloaded.\n if (subTree.entitiesKind === \"instances\" && !subTree.entities.has(root as any)) return;\n if (subTree.entitiesKind === \"ids\" && !subTree.entities.has(root.idTagged as any)) return;\n\n // We get back an array of [[1, title], [2, title], [3, title]]\n const children = arrays.map((array) => {\n const taggedId = keyToTaggedId(otherMeta, array[m2mOffset] as any)!;\n const row: Record<string, any> = {};\n for (let i = 0; i < columns.length; i++) {\n row[columnNames[i]] = columns[i].mapFromJsonAgg(array[m2mOffset + i]);\n }\n const entity =\n em.findExistingInstance<Entity>(taggedId) ??\n (em.hydrate(otherMeta.cstr, [row], { overwriteExisting: false }) as Entity[])[0];\n // Tell the internal JoinRow booking-keeping about this m2m row\n if (field.kind === \"m2m\") {\n // TODO This `addExisting` needs to be pulled up, out of the `arrays.map`, so we can do a `loadRows`-ish\n // call that passes all now-known m2m rows into JoinRows as a single list, so that it can mark any\n // deleted-from-under-us m2m rows as deleted.\n const m2m = (parent as any)[key];\n getEmInternalApi(em)\n .joinRows(m2m)\n .addPreloadedRow(m2m, field.hasJoinTableId ? (array[0] as any) : undefined, parent, entity);\n }\n // Within each child, look for grandchildren\n subJoins.forEach((sub, i) => {\n // array[i] could be null if there are no grandchildren, but still call `sub` to\n // process it so that we store the empty array into the em.joinLoadedRelations, to\n // avoid the relation.load method later doing a SQL for rows we know are not there.\n sub.hydrator(root, entity, (array[m2mOffset + columns.length + i] as any) ?? []);\n });\n return entity;\n });\n // Cache the entities so `.load`s will see them\n getEmInternalApi(em).setPreloadedRelation(parent.idTagged, key, children);\n };\n\n results.push({ alias: otherAlias, relationAlias, join, hydrator });\n }\n });\n\n return results;\n}\n\n/**\n * Builds the `CROSS JOIN LATERAL` that aggregates an enum-m2m join table (e.g. `publisher_logo_colors`)\n * into a json array of enum ids, e.g. `[[1], [3]]` (or `[[1, id], [3, id]]` for id-ful join tables).\n */\nfunction calcEnumLateralJoin<I extends EntityOrId>(\n assigner: AliasAssigner,\n root: { tree: HintNode<I>; alias: string; meta: EntityMetadata },\n subTree: HintNode<I>,\n parentAlias: string,\n field: ManyToManyEnumField,\n key: string,\n pathPrefix: string,\n): AggregateJoinResult {\n const [entityColumn, enumColumn] = field.columnNames;\n const jtAlias = `_${assigner.getAlias(field.joinTableName)}`;\n const relationAlias = `_${assigner.getLiteralAlias(`${pathPrefix}${key.toLowerCase()}`)}`;\n\n const parts = [kqDot(jtAlias, enumColumn)];\n if (field.hasJoinTableId) parts.push(kqDot(jtAlias, \"id\"));\n\n const cb = new ConditionBuilder();\n cb.addRawCondition({\n aliases: [jtAlias, parentAlias],\n condition: `${kqDot(jtAlias, entityColumn)} = ${kqDot(parentAlias, \"id\")}`,\n pruneable: true,\n });\n\n const needsSubSelect = subTree.entities.size !== root.tree.entities.size;\n if (needsSubSelect) {\n cb.addRawCondition({\n aliases: [root.alias],\n condition: `${kqDot(root.alias, \"id\")} = ANY(?)`,\n bindings: [\n [...subTree.entities]\n .filter((e) => typeof e === \"string\" || !e.isNewEntity)\n .map((e) => keyToNumber(root.meta, typeof e === \"string\" ? e : e.id)),\n ],\n pruneable: true,\n });\n }\n\n const orderBy = `${kq(jtAlias)}.${kq(field.hasJoinTableId ? \"id\" : enumColumn)}`;\n const join: LateralJoinTable = {\n join: \"lateral\",\n alias: jtAlias,\n fromAlias: \"unset\",\n table: field.joinTableName,\n query: {\n selects: [`json_agg(json_build_array(${parts.join(\", \")}) order by ${orderBy}) as _`],\n tables: [{ join: \"primary\", table: field.joinTableName, alias: jtAlias }],\n condition: cb.toExpressionFilter(),\n orderBys: [],\n },\n };\n\n const hydrator: AggregateJsonHydrator = (root, parent, arrays) => {\n const { em } = root;\n if (subTree.entitiesKind === \"instances\" && !subTree.entities.has(root as any)) return;\n if (subTree.entitiesKind === \"ids\" && !subTree.entities.has(root.idTagged as any)) return;\n const like: ManyToManyLike = {\n entity: parent,\n joinTableName: field.joinTableName,\n columnName: entityColumn,\n otherColumnName: enumColumn,\n fieldName: key,\n meta: getMetadataForField(getMetadata(parent), key),\n otherEnum: field.enumDetailType,\n hasJoinTableId: field.hasJoinTableId,\n };\n const api = getEmInternalApi(em);\n const joinRows = api.joinRows(like);\n const codes: any[] = [];\n for (const array of arrays) {\n const enumId = array[0] as number;\n joinRows.addPreloadedRow(like, field.hasJoinTableId ? (array[1] as number) : undefined, parent, enumId);\n codes.push(field.enumDetailType.findById(enumId)!.code);\n }\n api.setPreloadedRelation(parent.idTagged, key, codes);\n };\n\n return { alias: jtAlias, relationAlias, join, hydrator };\n}\n\n/** A preload-loadable join for a given child, with potentially grand-child joins contained within it. */\ntype AggregateJoinResult = {\n /** The short table alias used for column references inside the subquery, e.g. `_b1`. */\n alias: string;\n /** The readable relation-name alias used in the outer `AS` clause, e.g. `_prequel`. */\n relationAlias: string;\n /** The SQL for this child's lateral join, which itself might have recursive lateral joins. */\n join: LateralJoinTable;\n /** The hydrator for this child's lateral join, which itself might recursively hydrator subjoins. */\n hydrator: AggregateJsonHydrator;\n};\n\n/** Reads one column from either classic POJO rows or a lazy `RowData` result. */\nfunction readRowValue(rows: any[] | RowData, rowIndex: number, columnName: string): any {\n return Array.isArray(rows) ? rows[rowIndex][columnName] : rows.get(rowIndex, columnName);\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ParsedFindQuery } from "../queries/find/QueryParser.cjs";
|
|
2
|
-
import { LoadHint, NestedLoadHint } from "../loadHints.cjs";
|
|
2
|
+
import { LoadHint, NestedLoadHint } from "../loading/loadHints.cjs";
|
|
3
3
|
import { EntityMetadata } from "../EntityMetadata.cjs";
|
|
4
|
-
import { HintNode } from "../HintTree.cjs";
|
|
4
|
+
import { HintNode } from "../loading/HintTree.cjs";
|
|
5
5
|
import { JoinResult, PreloadHydrator, PreloadPlugin } from "../plugins/PreloadPlugin.cjs";
|
|
6
6
|
import { Entity } from "../Entity.cjs";
|
|
7
7
|
//#region src/preloading/JsonAggregatePreloader.d.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JsonAggregatePreloader.d.cts","names":[],"sources":["../../src/preloading/JsonAggregatePreloader.ts"],"mappings":";;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"JsonAggregatePreloader.d.cts","names":[],"sources":["../../src/preloading/JsonAggregatePreloader.ts"],"mappings":";;;;;;;;;;;cA0Ba,kCAAkC;EAC7C,cACE,MAAM,4BACN,MAAM,iBACJ,iCAAiC;EAIrC,cAAc,UAAU,QACtB,MAAM,gBACN,MAAM,SAAS,IACf,OAAO,kBACN;EA6BH,gBAAgB,UAAU,QAAQ,MAAM,gBAAgB,MAAM,SAAS,IAAI,OAAO,kBAAkB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ParsedFindQuery } from "../queries/find/QueryParser.mjs";
|
|
2
|
-
import { LoadHint, NestedLoadHint } from "../loadHints.mjs";
|
|
2
|
+
import { LoadHint, NestedLoadHint } from "../loading/loadHints.mjs";
|
|
3
3
|
import { EntityMetadata } from "../EntityMetadata.mjs";
|
|
4
|
-
import { HintNode } from "../HintTree.mjs";
|
|
4
|
+
import { HintNode } from "../loading/HintTree.mjs";
|
|
5
5
|
import { JoinResult, PreloadHydrator, PreloadPlugin } from "../plugins/PreloadPlugin.mjs";
|
|
6
6
|
import { Entity } from "../Entity.mjs";
|
|
7
7
|
//#region src/preloading/JsonAggregatePreloader.d.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JsonAggregatePreloader.d.mts","names":[],"sources":["../../src/preloading/JsonAggregatePreloader.ts"],"mappings":";;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"JsonAggregatePreloader.d.mts","names":[],"sources":["../../src/preloading/JsonAggregatePreloader.ts"],"mappings":";;;;;;;;;;;cA0Ba,kCAAkC;EAC7C,cACE,MAAM,4BACN,MAAM,iBACJ,iCAAiC;EAIrC,cAAc,UAAU,QACtB,MAAM,gBACN,MAAM,SAAS,IACf,OAAO,kBACN;EA6BH,gBAAgB,UAAU,QAAQ,MAAM,gBAAgB,MAAM,SAAS,IAAI,OAAO,kBAAkB"}
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
import "../
|
|
1
|
+
import { keyToNumber, keyToTaggedId } from "../keys.js";
|
|
2
2
|
import { kq, kqDot } from "../queries/sql/keywords.js";
|
|
3
3
|
import { ConditionBuilder } from "../queries/ConditionBuilder.js";
|
|
4
4
|
import { getTables } from "../queries/find/QueryParser.js";
|
|
5
|
-
import "../loadHints.js";
|
|
6
5
|
import { fail } from "../utils.js";
|
|
7
|
-
import { keyToNumber, keyToTaggedId } from "../keys.js";
|
|
8
6
|
import { getMetadata, getMetadataForField } from "../EntityMetadata.js";
|
|
9
7
|
import { canPreload } from "./canPreload.js";
|
|
10
8
|
import { partitionHint } from "./partitionHint.js";
|
|
11
9
|
import { AliasAssigner } from "../queries/sql/AliasAssigner.js";
|
|
12
|
-
import "../HintTree.js";
|
|
13
10
|
import "../plugins/PreloadPlugin.js";
|
|
14
11
|
import { getEmInternalApi } from "../EntityManager.js";
|
|
15
12
|
import "../Entity.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JsonAggregatePreloader.js","names":[],"sources":["../../src/preloading/JsonAggregatePreloader.ts"],"sourcesContent":["import { type Entity } from \"../Entity.ts\";\nimport { getEmInternalApi } from \"../EntityManager.ts\";\nimport { type EntityMetadata, type ManyToManyEnumField, getMetadata, getMetadataForField } from \"../EntityMetadata.ts\";\nimport { type EntityOrId, type HintNode } from \"../HintTree.ts\";\nimport { type ManyToManyLike } from \"../JoinRows.ts\";\nimport { keyToNumber, keyToTaggedId } from \"../keys.ts\";\nimport { type LoadHint, type NestedLoadHint } from \"../loadHints.ts\";\nimport { type JoinResult, type PreloadHydrator, type PreloadPlugin } from \"../plugins/PreloadPlugin.ts\";\nimport { ConditionBuilder } from \"../queries/ConditionBuilder.ts\";\nimport { type JoinTable, type LateralJoinTable, type ParsedFindQuery, getTables } from \"../queries/find/QueryParser.ts\";\nimport { AliasAssigner } from \"../queries/sql/AliasAssigner.ts\";\nimport { kq, kqDot } from \"../queries/sql/keywords.ts\";\nimport { type RowData } from \"../RowData.ts\";\nimport { fail } from \"../utils.ts\";\nimport { canPreload } from \"./canPreload.ts\";\nimport { partitionHint } from \"./partitionHint.ts\";\n\n/**\n * A PreloadPlugin implementation that uses `CROSS LATERAL JOIN` and `json_aggregate`\n * to preload/reduce a subtree of data while still being a single row of data.\n */\nexport class JsonAggregatePreloader implements PreloadPlugin {\n partitionHint(\n meta: EntityMetadata | undefined,\n hint: LoadHint<any>,\n ): [NestedLoadHint<any> | undefined, NestedLoadHint<any> | undefined] {\n return partitionHint(meta, hint);\n }\n\n addPreloading<T extends Entity>(\n meta: EntityMetadata,\n root: HintNode<T>,\n query: ParsedFindQuery,\n ): PreloadHydrator | undefined {\n const assigner = new AliasAssigner(query);\n\n // Get the existing primary alias\n const alias = getTables(query)[0].alias;\n const joins = calcLateralJoins(assigner, { tree: root, alias, meta }, root, alias, meta);\n // If there are no sql-based preload in the hints, just return\n if (joins.length === 0) return undefined;\n\n // Include the aggregate `_b1._ as _prequel`, `_c._ as _randomComment`\n for (const { alias, relationAlias, join } of joins) {\n query.selects.push({\n sql: `${kqDot(alias, \"_\")} as ${kq(relationAlias)}`,\n aliases: [alias],\n bindings: [],\n });\n query.tables.push(join);\n }\n\n return (rows, entities) => {\n for (let i = 0; i < entities.length; i++) {\n const parent = entities[i];\n for (const { relationAlias, hydrator } of joins) {\n hydrator(parent, parent, readRowValue(rows, i, relationAlias) ?? []);\n }\n }\n };\n }\n\n getPreloadJoins<T extends Entity>(meta: EntityMetadata, root: HintNode<T>, query: ParsedFindQuery): JoinResult[] {\n const assigner = new AliasAssigner(query);\n\n // Get the existing primary alias\n const alias = getTables(query)[0].alias;\n const joins = calcLateralJoins(assigner, { tree: root, alias, meta }, root, alias, meta);\n // If there are no sql-based preload in the hints, just return\n\n // Adapt our json aggregate joins to the higher-level JoinResult\n return joins.map((join) => {\n return {\n selects: [{ value: kqDot(join.alias, \"_\"), as: join.relationAlias }],\n join: join.join,\n hydrator: (rows, entities) => {\n for (let i = 0; i < entities.length; i++) {\n const parent = entities[i];\n join.hydrator(parent, parent, readRowValue(rows, i, join.relationAlias) ?? []);\n }\n },\n };\n });\n }\n}\n\n/** Decodes an array-of-arrays of children entries, and stores them the `parent`'s relation. */\ntype AggregateJsonHydrator = (root: Entity, parent: Entity, arrays: unknown[][]) => void;\n\n/**\n * For a given hint tree `hint`, finds all SQL-able relations and preloads them.\n *\n * Specifically we use `json_agg` & `json_build_array` to `CROSS LATERAL JOIN`\n * children/grand children back as arbitrarily-deeply nested arrays, and then\n * stash the results in the `EntityManager` `joinLoadedRelations` cache, which\n * each join-instrumented relation will check before making its SQL calls.\n *\n * https://sqlfum.pt/?n=60&indent=2&spaces=1&simplify=1&align=0&case=lower&sql=c2VsZWN0IGEuaWQsIGIuXyBhcyBiLCBjMS5fIGFzIGMxLCBhMS5fIGFzIGExIGZyb20gYXV0aG9ycyBhIGNyb3NzIGpvaW4gbGF0ZXJhbCAoIHNlbGVjdCBqc29uX2FnZyhqc29uX2J1aWxkX2FycmF5KGIuaWQsIGIudGl0bGUsIGIuIm9yZGVyIiwgYi5kZWxldGVkX2F0LCBiLmNyZWF0ZWRfYXQsIGIudXBkYXRlZF9hdCwgYi5hdXRob3JfaWQsIGJyLl8pKSBhcyBfIGZyb20gYm9va3MgYiBjcm9zcyBqb2luIGxhdGVyYWwgKCBzZWxlY3QganNvbl9hZ2coanNvbl9idWlsZF9hcnJheShici5pZCwgYnIucmF0aW5nLCBici5pc19wdWJsaWMsIGJyLmlzX3Rlc3QsIGJyLmNyZWF0ZWRfYXQsIGJyLnVwZGF0ZWRfYXQsIGJyLmJvb2tfaWQsIGMuXykpIGFzIF8gZnJvbSBib29rX3Jldmlld3MgYnIgY3Jvc3Mgam9pbiBsYXRlcmFsICggc2VsZWN0IGpzb25fYWdnKGpzb25fYnVpbGRfYXJyYXkoYy5pZCwgYy50ZXh0LCBjLmNyZWF0ZWRfYXQsIGMudXBkYXRlZF9hdCwgYy51c2VyX2lkLCBjLnBhcmVudF9hdXRob3JfaWQsIGMucGFyZW50X2Jvb2tfaWQsIGMucGFyZW50X2Jvb2tfcmV2aWV3X2lkLCBjLnBhcmVudF9wdWJsaXNoZXJfaWQpKSBhcyBfIGZyb20gY29tbWVudHMgYyB3aGVyZSBjLnBhcmVudF9ib29rX3Jldmlld19pZCA9IGJyLmlkICkgYyB3aGVyZSBici5ib29rX2lkID0gYi5pZCApIGJyIHdoZXJlIGIuYXV0aG9yX2lkID0gYS5pZCApIGIgY3Jvc3Mgam9pbiBsYXRlcmFsICggc2VsZWN0IGpzb25fYWdnKGpzb25fYnVpbGRfYXJyYXkoYzEuaWQsIGMxLnRleHQsIGMxLmNyZWF0ZWRfYXQsIGMxLnVwZGF0ZWRfYXQsIGMxLnVzZXJfaWQsIGMxLnBhcmVudF9hdXRob3JfaWQsIGMxLnBhcmVudF9ib29rX2lkLCBjMS5wYXJlbnRfYm9va19yZXZpZXdfaWQsIGMxLnBhcmVudF9wdWJsaXNoZXJfaWQpKSBhcyBfIGZyb20gY29tbWVudHMgYzEgd2hlcmUgYzEucGFyZW50X2F1dGhvcl9pZCA9IGEuaWQgKSBjMSBjcm9zcyBqb2luIGxhdGVyYWwgKCBzZWxlY3QganNvbl9hZ2coanNvbl9idWlsZF9hcnJheShhMS5pZCwgYTEuZmlyc3RfbmFtZSwgYTEubGFzdF9uYW1lLCBhMS5zc24sIGExLmluaXRpYWxzLCBhMS5udW1iZXJfb2ZfYm9va3MsIGExLmJvb2tfY29tbWVudHMsIGExLmlzX3BvcHVsYXIsIGExLmFnZSwgYTEuZ3JhZHVhdGVkLCBhMS5uaWNrX25hbWVzLCBhMS53YXNfZXZlcl9wb3B1bGFyLCBhMS5hZGRyZXNzLCBhMS5idXNpbmVzc19hZGRyZXNzLCBhMS5xdW90ZXMsIGExLm51bWJlcl9vZl9hdG9tcywgYTEuZGVsZXRlZF9hdCwgYTEubnVtYmVyX29mX3B1YmxpY19yZXZpZXdzLCBhMS4ibnVtYmVyT2ZQdWJsaWNSZXZpZXdzMiIsIGExLnRhZ3Nfb2ZfYWxsX2Jvb2tzLCBhMS5jcmVhdGVkX2F0LCBhMS51cGRhdGVkX2F0LCBhMS5mYXZvcml0ZV9zaGFwZSwgYTEuZmF2b3JpdGVfY29sb3JzLCBhMS5tZW50b3JfaWQsIGExLmN1cnJlbnRfZHJhZnRfYm9va19pZCwgYTEuZmF2b3JpdGVfYm9va19pZCwgYTEucHVibGlzaGVyX2lkKSkgYXMgXyBmcm9tIGF1dGhvcnMgYTEgd2hlcmUgYTEuaWQgPSBhLm1lbnRvcl9pZCApIGExIHdoZXJlIGEuaWQgPSAxOw%3D%3D\n */\n\n/**\n * Given a `parent` like Author, and a hint of `{ books: ..., comments: ... }`, create `CROSS JOIN LATERAL`s\n * that will pull in the `books` & `comments` children.\n */\nfunction calcLateralJoins<I extends EntityOrId>(\n assigner: AliasAssigner,\n root: { tree: HintNode<I>; alias: string; meta: EntityMetadata },\n tree: HintNode<I>,\n parentAlias: string,\n parentMeta: EntityMetadata,\n pathPrefix: string = \"\",\n): AggregateJoinResult[] {\n const results: AggregateJoinResult[] = [];\n\n // Join in SQL-able hints from parent\n Object.entries(tree.hints).forEach(([key, subTree]) => {\n const field = parentMeta.allFields[key];\n // AsyncProperties don't have fields, which is fine, skip for now...\n if (field && canPreload(parentMeta, field)) {\n // Enum m2ms have no \"other\" entity to join/hydrate; just aggregate the join table's enum ids.\n if (field.kind === \"m2mEnum\") {\n results.push(calcEnumLateralJoin(assigner, root, subTree, parentAlias, field, key, pathPrefix));\n return;\n }\n const otherMeta = field.otherMetadata();\n const otherField = otherMeta.allFields[field.otherFieldName];\n\n // Short table alias for column refs inside the subquery, e.g. `_b1`\n const otherAlias = `_${assigner.getAlias(otherMeta.tableName)}`;\n // Readable path-based column alias for the outer AS clause, e.g. `_books_reviews`\n const pathKey = key.toLowerCase();\n const relationAlias = `_${assigner.getLiteralAlias(`${pathPrefix}${pathKey}`)}`;\n\n // Do the recursion up-front, so we can work it into our own join/hydrator\n const subJoins = calcLateralJoins(assigner, root, subTree, otherAlias, otherMeta, `${pathPrefix}${pathKey}_`);\n\n // Get all fields with serdes and flatten out the columns, skipping `lazy` columns (fetched on-demand)\n const columns = Object.values(otherMeta.allFields)\n .filter((f) => f.serde && !(f.kind === \"primitive\" && f.lazy))\n .flatMap((f) => f.serde!.columns);\n const selects = [\n ...columns.map((c) => kqDot(otherAlias, c.columnName)),\n // We eventually need to handle parent types/subtypes here...\n // Combine any grandchilden\n ...subJoins.map((sb) => kqDot(sb.alias, \"_\")),\n ];\n\n const aliasMaybeSuffix = kq(`${parentAlias}${field.aliasSuffix}`);\n\n const cb = new ConditionBuilder();\n let m2mTable: JoinTable | undefined;\n let m2mAlias: string | undefined;\n if (otherField.kind === \"m2o\") {\n cb.addRawCondition({\n aliases: [otherAlias, parentAlias],\n condition: `${kqDot(otherAlias, otherField.serde.columns[0].columnName)} = ${kqDot(parentAlias, \"id\")}`,\n pruneable: true,\n });\n } else if (otherField.kind === \"poly\") {\n // Get the component that points to us\n // const comp = otherField.components.find((c) => getAllMetas(parentMeta).some((m) => m.cstr === c.otherMetadata().cstr)) ??\n const comp =\n otherField.components.find((c) => parentMeta.cstr === c.otherMetadata().cstr) ??\n fail(`No component found for ${field.fieldName} -> ${otherField.fieldName}`);\n cb.addRawCondition({\n aliases: [otherAlias, parentAlias],\n condition: `${kqDot(otherAlias, comp.columnName)} = ${kqDot(parentAlias, \"id\")}`,\n pruneable: true,\n });\n } else if (otherField.kind === \"o2m\" || otherField.kind === \"lo2m\") {\n cb.addRawCondition({\n aliases: [otherAlias, aliasMaybeSuffix],\n condition: `${kqDot(otherAlias, \"id\")} = ${aliasMaybeSuffix}.${kq(field.serde!.columns[0].columnName)}`,\n pruneable: true,\n });\n } else if (otherField.kind === \"o2o\") {\n cb.addRawCondition({\n aliases: [otherAlias, aliasMaybeSuffix],\n condition: `${kqDot(otherAlias, \"id\")} = ${aliasMaybeSuffix}.${kq(field.serde!.columns[0].columnName)}`,\n pruneable: true,\n });\n } else if (otherField.kind === \"m2m\") {\n m2mAlias = assigner.getAlias(otherField.joinTableName);\n // Get the m2m row's id to track in JoinRows; id-less tables have no surrogate id.\n if (otherField.hasJoinTableId) selects.unshift(kqDot(m2mAlias, \"id\"));\n m2mTable = {\n join: \"inner\",\n table: otherField.joinTableName,\n alias: m2mAlias,\n col1: kqDot(parentAlias, \"id\"),\n col2: kqDot(m2mAlias, otherField.columnNames[1]),\n };\n cb.addRawCondition({\n aliases: [m2mAlias, otherAlias],\n condition: `${kqDot(m2mAlias, otherField.columnNames[0])} = ${kqDot(otherAlias, \"id\")}`,\n pruneable: true,\n });\n } else {\n throw new Error(`Unsupported otherField.kind ${otherField.kind}`);\n }\n\n const needsSubSelect = subTree.entities.size !== root.tree.entities.size;\n if (needsSubSelect) {\n cb.addRawCondition({\n aliases: [root.alias],\n condition: `${kqDot(root.alias, \"id\")} = ANY(?)`,\n bindings: [\n [...subTree.entities]\n .filter((e) => typeof e === \"string\" || !e.isNewEntity)\n .map((e) => keyToNumber(root.meta, typeof e === \"string\" ? e : e.id)),\n ],\n pruneable: true,\n });\n }\n\n // For m2m, order by the join-row's id so preloaded results match the order the lazy batch\n // loader returns (which orders by join-row id). Id-less join tables have no surrogate id,\n // so order by the other entity's FK column (matching the lazy loader & getOthers). Otherwise,\n // order by the target entity's id.\n const orderBy =\n otherField.kind === \"m2m\" && !otherField.hasJoinTableId\n ? `${kq(m2mAlias!)}.${kq(otherField.columnNames[0])}`\n : `${kq(m2mAlias ?? otherAlias)}.id`;\n\n const join: LateralJoinTable = {\n join: \"lateral\",\n alias: otherAlias,\n // Do we need to say which alias we're coming from, to avoid having it pruned?\n // ...maybe not because preloading is always on the primary table?\n fromAlias: \"unset\",\n table: otherMeta.tableName,\n query: {\n selects: [`json_agg(json_build_array(${selects.join(\", \")}) order by ${orderBy}) as _`],\n tables: [\n { join: \"primary\", table: otherMeta.tableName, alias: otherAlias },\n ...(m2mTable ? [m2mTable] : []),\n ...subJoins.map((sj) => sj.join),\n ],\n condition: cb.toExpressionFilter(),\n orderBys: [],\n },\n };\n\n // Pre-compute column names so we don't re-read them per entity\n const columnNames = columns.map((c) => c.columnName);\n // If we've snuck the m2m row id into the json array, ignore it (id-less tables have no id)\n const m2mOffset = field.kind === \"m2m\" && field.hasJoinTableId ? 1 : 0;\n\n const hydrator: AggregateJsonHydrator = (root, parent, arrays) => {\n const { em } = root;\n\n // If we had overlapping load hints, i.e. `author.books` for [a1, a2] and `author.comments` for [a1], and\n // we're processing the arrays of comments, but for a root author like `a2` that didn't ask for our load\n // hint, then skip it to keep the relation unloaded.\n if (subTree.entitiesKind === \"instances\" && !subTree.entities.has(root as any)) return;\n if (subTree.entitiesKind === \"ids\" && !subTree.entities.has(root.idTagged as any)) return;\n\n // We get back an array of [[1, title], [2, title], [3, title]]\n const children = arrays.map((array) => {\n const taggedId = keyToTaggedId(otherMeta, array[m2mOffset] as any)!;\n const row: Record<string, any> = {};\n for (let i = 0; i < columns.length; i++) {\n row[columnNames[i]] = columns[i].mapFromJsonAgg(array[m2mOffset + i]);\n }\n const entity =\n em.findExistingInstance<Entity>(taggedId) ??\n (em.hydrate(otherMeta.cstr, [row], { overwriteExisting: false }) as Entity[])[0];\n // Tell the internal JoinRow booking-keeping about this m2m row\n if (field.kind === \"m2m\") {\n // TODO This `addExisting` needs to be pulled up, out of the `arrays.map`, so we can do a `loadRows`-ish\n // call that passes all now-known m2m rows into JoinRows as a single list, so that it can mark any\n // deleted-from-under-us m2m rows as deleted.\n const m2m = (parent as any)[key];\n getEmInternalApi(em)\n .joinRows(m2m)\n .addPreloadedRow(m2m, field.hasJoinTableId ? (array[0] as any) : undefined, parent, entity);\n }\n // Within each child, look for grandchildren\n subJoins.forEach((sub, i) => {\n // array[i] could be null if there are no grandchildren, but still call `sub` to\n // process it so that we store the empty array into the em.joinLoadedRelations, to\n // avoid the relation.load method later doing a SQL for rows we know are not there.\n sub.hydrator(root, entity, (array[m2mOffset + columns.length + i] as any) ?? []);\n });\n return entity;\n });\n // Cache the entities so `.load`s will see them\n getEmInternalApi(em).setPreloadedRelation(parent.idTagged, key, children);\n };\n\n results.push({ alias: otherAlias, relationAlias, join, hydrator });\n }\n });\n\n return results;\n}\n\n/**\n * Builds the `CROSS JOIN LATERAL` that aggregates an enum-m2m join table (e.g. `publisher_logo_colors`)\n * into a json array of enum ids, e.g. `[[1], [3]]` (or `[[1, id], [3, id]]` for id-ful join tables).\n */\nfunction calcEnumLateralJoin<I extends EntityOrId>(\n assigner: AliasAssigner,\n root: { tree: HintNode<I>; alias: string; meta: EntityMetadata },\n subTree: HintNode<I>,\n parentAlias: string,\n field: ManyToManyEnumField,\n key: string,\n pathPrefix: string,\n): AggregateJoinResult {\n const [entityColumn, enumColumn] = field.columnNames;\n const jtAlias = `_${assigner.getAlias(field.joinTableName)}`;\n const relationAlias = `_${assigner.getLiteralAlias(`${pathPrefix}${key.toLowerCase()}`)}`;\n\n const parts = [kqDot(jtAlias, enumColumn)];\n if (field.hasJoinTableId) parts.push(kqDot(jtAlias, \"id\"));\n\n const cb = new ConditionBuilder();\n cb.addRawCondition({\n aliases: [jtAlias, parentAlias],\n condition: `${kqDot(jtAlias, entityColumn)} = ${kqDot(parentAlias, \"id\")}`,\n pruneable: true,\n });\n\n const needsSubSelect = subTree.entities.size !== root.tree.entities.size;\n if (needsSubSelect) {\n cb.addRawCondition({\n aliases: [root.alias],\n condition: `${kqDot(root.alias, \"id\")} = ANY(?)`,\n bindings: [\n [...subTree.entities]\n .filter((e) => typeof e === \"string\" || !e.isNewEntity)\n .map((e) => keyToNumber(root.meta, typeof e === \"string\" ? e : e.id)),\n ],\n pruneable: true,\n });\n }\n\n const orderBy = `${kq(jtAlias)}.${kq(field.hasJoinTableId ? \"id\" : enumColumn)}`;\n const join: LateralJoinTable = {\n join: \"lateral\",\n alias: jtAlias,\n fromAlias: \"unset\",\n table: field.joinTableName,\n query: {\n selects: [`json_agg(json_build_array(${parts.join(\", \")}) order by ${orderBy}) as _`],\n tables: [{ join: \"primary\", table: field.joinTableName, alias: jtAlias }],\n condition: cb.toExpressionFilter(),\n orderBys: [],\n },\n };\n\n const hydrator: AggregateJsonHydrator = (root, parent, arrays) => {\n const { em } = root;\n if (subTree.entitiesKind === \"instances\" && !subTree.entities.has(root as any)) return;\n if (subTree.entitiesKind === \"ids\" && !subTree.entities.has(root.idTagged as any)) return;\n const like: ManyToManyLike = {\n entity: parent,\n joinTableName: field.joinTableName,\n columnName: entityColumn,\n otherColumnName: enumColumn,\n fieldName: key,\n meta: getMetadataForField(getMetadata(parent), key),\n otherEnum: field.enumDetailType,\n hasJoinTableId: field.hasJoinTableId,\n };\n const api = getEmInternalApi(em);\n const joinRows = api.joinRows(like);\n const codes: any[] = [];\n for (const array of arrays) {\n const enumId = array[0] as number;\n joinRows.addPreloadedRow(like, field.hasJoinTableId ? (array[1] as number) : undefined, parent, enumId);\n codes.push(field.enumDetailType.findById(enumId)!.code);\n }\n api.setPreloadedRelation(parent.idTagged, key, codes);\n };\n\n return { alias: jtAlias, relationAlias, join, hydrator };\n}\n\n/** A preload-loadable join for a given child, with potentially grand-child joins contained within it. */\ntype AggregateJoinResult = {\n /** The short table alias used for column references inside the subquery, e.g. `_b1`. */\n alias: string;\n /** The readable relation-name alias used in the outer `AS` clause, e.g. `_prequel`. */\n relationAlias: string;\n /** The SQL for this child's lateral join, which itself might have recursive lateral joins. */\n join: LateralJoinTable;\n /** The hydrator for this child's lateral join, which itself might recursively hydrator subjoins. */\n hydrator: AggregateJsonHydrator;\n};\n\n/** Reads one column from either classic POJO rows or a lazy `RowData` result. */\nfunction readRowValue(rows: any[] | RowData, rowIndex: number, columnName: string): any {\n return Array.isArray(rows) ? rows[rowIndex][columnName] : rows.get(rowIndex, columnName);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"JsonAggregatePreloader.js","names":[],"sources":["../../src/preloading/JsonAggregatePreloader.ts"],"sourcesContent":["import { type Entity } from \"src/Entity.ts\";\nimport { getEmInternalApi } from \"src/EntityManager.ts\";\nimport { type EntityMetadata, type ManyToManyEnumField, getMetadata, getMetadataForField } from \"src/EntityMetadata.ts\";\nimport type { ManyToManyLike } from \"src/flush/JoinRows.ts\";\nimport { keyToNumber, keyToTaggedId } from \"src/keys.ts\";\nimport type { EntityOrId, HintNode } from \"src/loading/HintTree.ts\";\nimport type { LoadHint, NestedLoadHint } from \"src/loading/loadHints.ts\";\nimport { type JoinResult, type PreloadHydrator, type PreloadPlugin } from \"src/plugins/PreloadPlugin.ts\";\nimport { canPreload } from \"src/preloading/canPreload.ts\";\nimport { partitionHint } from \"src/preloading/partitionHint.ts\";\nimport { ConditionBuilder } from \"src/queries/ConditionBuilder.ts\";\nimport {\n type JoinTable,\n type LateralJoinTable,\n type ParsedFindQuery,\n getTables,\n} from \"src/queries/find/QueryParser.ts\";\nimport { AliasAssigner } from \"src/queries/sql/AliasAssigner.ts\";\nimport { kq, kqDot } from \"src/queries/sql/keywords.ts\";\nimport { type RowData } from \"src/RowData.ts\";\nimport { fail } from \"src/utils.ts\";\n\n/**\n * A PreloadPlugin implementation that uses `CROSS LATERAL JOIN` and `json_aggregate`\n * to preload/reduce a subtree of data while still being a single row of data.\n */\nexport class JsonAggregatePreloader implements PreloadPlugin {\n partitionHint(\n meta: EntityMetadata | undefined,\n hint: LoadHint<any>,\n ): [NestedLoadHint<any> | undefined, NestedLoadHint<any> | undefined] {\n return partitionHint(meta, hint);\n }\n\n addPreloading<T extends Entity>(\n meta: EntityMetadata,\n root: HintNode<T>,\n query: ParsedFindQuery,\n ): PreloadHydrator | undefined {\n const assigner = new AliasAssigner(query);\n\n // Get the existing primary alias\n const alias = getTables(query)[0].alias;\n const joins = calcLateralJoins(assigner, { tree: root, alias, meta }, root, alias, meta);\n // If there are no sql-based preload in the hints, just return\n if (joins.length === 0) return undefined;\n\n // Include the aggregate `_b1._ as _prequel`, `_c._ as _randomComment`\n for (const { alias, relationAlias, join } of joins) {\n query.selects.push({\n sql: `${kqDot(alias, \"_\")} as ${kq(relationAlias)}`,\n aliases: [alias],\n bindings: [],\n });\n query.tables.push(join);\n }\n\n return (rows, entities) => {\n for (let i = 0; i < entities.length; i++) {\n const parent = entities[i];\n for (const { relationAlias, hydrator } of joins) {\n hydrator(parent, parent, readRowValue(rows, i, relationAlias) ?? []);\n }\n }\n };\n }\n\n getPreloadJoins<T extends Entity>(meta: EntityMetadata, root: HintNode<T>, query: ParsedFindQuery): JoinResult[] {\n const assigner = new AliasAssigner(query);\n\n // Get the existing primary alias\n const alias = getTables(query)[0].alias;\n const joins = calcLateralJoins(assigner, { tree: root, alias, meta }, root, alias, meta);\n // If there are no sql-based preload in the hints, just return\n\n // Adapt our json aggregate joins to the higher-level JoinResult\n return joins.map((join) => {\n return {\n selects: [{ value: kqDot(join.alias, \"_\"), as: join.relationAlias }],\n join: join.join,\n hydrator: (rows, entities) => {\n for (let i = 0; i < entities.length; i++) {\n const parent = entities[i];\n join.hydrator(parent, parent, readRowValue(rows, i, join.relationAlias) ?? []);\n }\n },\n };\n });\n }\n}\n\n/** Decodes an array-of-arrays of children entries, and stores them the `parent`'s relation. */\ntype AggregateJsonHydrator = (root: Entity, parent: Entity, arrays: unknown[][]) => void;\n\n/**\n * For a given hint tree `hint`, finds all SQL-able relations and preloads them.\n *\n * Specifically we use `json_agg` & `json_build_array` to `CROSS LATERAL JOIN`\n * children/grand children back as arbitrarily-deeply nested arrays, and then\n * stash the results in the `EntityManager` `joinLoadedRelations` cache, which\n * each join-instrumented relation will check before making its SQL calls.\n *\n * https://sqlfum.pt/?n=60&indent=2&spaces=1&simplify=1&align=0&case=lower&sql=c2VsZWN0IGEuaWQsIGIuXyBhcyBiLCBjMS5fIGFzIGMxLCBhMS5fIGFzIGExIGZyb20gYXV0aG9ycyBhIGNyb3NzIGpvaW4gbGF0ZXJhbCAoIHNlbGVjdCBqc29uX2FnZyhqc29uX2J1aWxkX2FycmF5KGIuaWQsIGIudGl0bGUsIGIuIm9yZGVyIiwgYi5kZWxldGVkX2F0LCBiLmNyZWF0ZWRfYXQsIGIudXBkYXRlZF9hdCwgYi5hdXRob3JfaWQsIGJyLl8pKSBhcyBfIGZyb20gYm9va3MgYiBjcm9zcyBqb2luIGxhdGVyYWwgKCBzZWxlY3QganNvbl9hZ2coanNvbl9idWlsZF9hcnJheShici5pZCwgYnIucmF0aW5nLCBici5pc19wdWJsaWMsIGJyLmlzX3Rlc3QsIGJyLmNyZWF0ZWRfYXQsIGJyLnVwZGF0ZWRfYXQsIGJyLmJvb2tfaWQsIGMuXykpIGFzIF8gZnJvbSBib29rX3Jldmlld3MgYnIgY3Jvc3Mgam9pbiBsYXRlcmFsICggc2VsZWN0IGpzb25fYWdnKGpzb25fYnVpbGRfYXJyYXkoYy5pZCwgYy50ZXh0LCBjLmNyZWF0ZWRfYXQsIGMudXBkYXRlZF9hdCwgYy51c2VyX2lkLCBjLnBhcmVudF9hdXRob3JfaWQsIGMucGFyZW50X2Jvb2tfaWQsIGMucGFyZW50X2Jvb2tfcmV2aWV3X2lkLCBjLnBhcmVudF9wdWJsaXNoZXJfaWQpKSBhcyBfIGZyb20gY29tbWVudHMgYyB3aGVyZSBjLnBhcmVudF9ib29rX3Jldmlld19pZCA9IGJyLmlkICkgYyB3aGVyZSBici5ib29rX2lkID0gYi5pZCApIGJyIHdoZXJlIGIuYXV0aG9yX2lkID0gYS5pZCApIGIgY3Jvc3Mgam9pbiBsYXRlcmFsICggc2VsZWN0IGpzb25fYWdnKGpzb25fYnVpbGRfYXJyYXkoYzEuaWQsIGMxLnRleHQsIGMxLmNyZWF0ZWRfYXQsIGMxLnVwZGF0ZWRfYXQsIGMxLnVzZXJfaWQsIGMxLnBhcmVudF9hdXRob3JfaWQsIGMxLnBhcmVudF9ib29rX2lkLCBjMS5wYXJlbnRfYm9va19yZXZpZXdfaWQsIGMxLnBhcmVudF9wdWJsaXNoZXJfaWQpKSBhcyBfIGZyb20gY29tbWVudHMgYzEgd2hlcmUgYzEucGFyZW50X2F1dGhvcl9pZCA9IGEuaWQgKSBjMSBjcm9zcyBqb2luIGxhdGVyYWwgKCBzZWxlY3QganNvbl9hZ2coanNvbl9idWlsZF9hcnJheShhMS5pZCwgYTEuZmlyc3RfbmFtZSwgYTEubGFzdF9uYW1lLCBhMS5zc24sIGExLmluaXRpYWxzLCBhMS5udW1iZXJfb2ZfYm9va3MsIGExLmJvb2tfY29tbWVudHMsIGExLmlzX3BvcHVsYXIsIGExLmFnZSwgYTEuZ3JhZHVhdGVkLCBhMS5uaWNrX25hbWVzLCBhMS53YXNfZXZlcl9wb3B1bGFyLCBhMS5hZGRyZXNzLCBhMS5idXNpbmVzc19hZGRyZXNzLCBhMS5xdW90ZXMsIGExLm51bWJlcl9vZl9hdG9tcywgYTEuZGVsZXRlZF9hdCwgYTEubnVtYmVyX29mX3B1YmxpY19yZXZpZXdzLCBhMS4ibnVtYmVyT2ZQdWJsaWNSZXZpZXdzMiIsIGExLnRhZ3Nfb2ZfYWxsX2Jvb2tzLCBhMS5jcmVhdGVkX2F0LCBhMS51cGRhdGVkX2F0LCBhMS5mYXZvcml0ZV9zaGFwZSwgYTEuZmF2b3JpdGVfY29sb3JzLCBhMS5tZW50b3JfaWQsIGExLmN1cnJlbnRfZHJhZnRfYm9va19pZCwgYTEuZmF2b3JpdGVfYm9va19pZCwgYTEucHVibGlzaGVyX2lkKSkgYXMgXyBmcm9tIGF1dGhvcnMgYTEgd2hlcmUgYTEuaWQgPSBhLm1lbnRvcl9pZCApIGExIHdoZXJlIGEuaWQgPSAxOw%3D%3D\n */\n\n/**\n * Given a `parent` like Author, and a hint of `{ books: ..., comments: ... }`, create `CROSS JOIN LATERAL`s\n * that will pull in the `books` & `comments` children.\n */\nfunction calcLateralJoins<I extends EntityOrId>(\n assigner: AliasAssigner,\n root: { tree: HintNode<I>; alias: string; meta: EntityMetadata },\n tree: HintNode<I>,\n parentAlias: string,\n parentMeta: EntityMetadata,\n pathPrefix: string = \"\",\n): AggregateJoinResult[] {\n const results: AggregateJoinResult[] = [];\n\n // Join in SQL-able hints from parent\n Object.entries(tree.hints).forEach(([key, subTree]) => {\n const field = parentMeta.allFields[key];\n // AsyncProperties don't have fields, which is fine, skip for now...\n if (field && canPreload(parentMeta, field)) {\n // Enum m2ms have no \"other\" entity to join/hydrate; just aggregate the join table's enum ids.\n if (field.kind === \"m2mEnum\") {\n results.push(calcEnumLateralJoin(assigner, root, subTree, parentAlias, field, key, pathPrefix));\n return;\n }\n const otherMeta = field.otherMetadata();\n const otherField = otherMeta.allFields[field.otherFieldName];\n\n // Short table alias for column refs inside the subquery, e.g. `_b1`\n const otherAlias = `_${assigner.getAlias(otherMeta.tableName)}`;\n // Readable path-based column alias for the outer AS clause, e.g. `_books_reviews`\n const pathKey = key.toLowerCase();\n const relationAlias = `_${assigner.getLiteralAlias(`${pathPrefix}${pathKey}`)}`;\n\n // Do the recursion up-front, so we can work it into our own join/hydrator\n const subJoins = calcLateralJoins(assigner, root, subTree, otherAlias, otherMeta, `${pathPrefix}${pathKey}_`);\n\n // Get all fields with serdes and flatten out the columns, skipping `lazy` columns (fetched on-demand)\n const columns = Object.values(otherMeta.allFields)\n .filter((f) => f.serde && !(f.kind === \"primitive\" && f.lazy))\n .flatMap((f) => f.serde!.columns);\n const selects = [\n ...columns.map((c) => kqDot(otherAlias, c.columnName)),\n // We eventually need to handle parent types/subtypes here...\n // Combine any grandchilden\n ...subJoins.map((sb) => kqDot(sb.alias, \"_\")),\n ];\n\n const aliasMaybeSuffix = kq(`${parentAlias}${field.aliasSuffix}`);\n\n const cb = new ConditionBuilder();\n let m2mTable: JoinTable | undefined;\n let m2mAlias: string | undefined;\n if (otherField.kind === \"m2o\") {\n cb.addRawCondition({\n aliases: [otherAlias, parentAlias],\n condition: `${kqDot(otherAlias, otherField.serde.columns[0].columnName)} = ${kqDot(parentAlias, \"id\")}`,\n pruneable: true,\n });\n } else if (otherField.kind === \"poly\") {\n // Get the component that points to us\n // const comp = otherField.components.find((c) => getAllMetas(parentMeta).some((m) => m.cstr === c.otherMetadata().cstr)) ??\n const comp =\n otherField.components.find((c) => parentMeta.cstr === c.otherMetadata().cstr) ??\n fail(`No component found for ${field.fieldName} -> ${otherField.fieldName}`);\n cb.addRawCondition({\n aliases: [otherAlias, parentAlias],\n condition: `${kqDot(otherAlias, comp.columnName)} = ${kqDot(parentAlias, \"id\")}`,\n pruneable: true,\n });\n } else if (otherField.kind === \"o2m\" || otherField.kind === \"lo2m\") {\n cb.addRawCondition({\n aliases: [otherAlias, aliasMaybeSuffix],\n condition: `${kqDot(otherAlias, \"id\")} = ${aliasMaybeSuffix}.${kq(field.serde!.columns[0].columnName)}`,\n pruneable: true,\n });\n } else if (otherField.kind === \"o2o\") {\n cb.addRawCondition({\n aliases: [otherAlias, aliasMaybeSuffix],\n condition: `${kqDot(otherAlias, \"id\")} = ${aliasMaybeSuffix}.${kq(field.serde!.columns[0].columnName)}`,\n pruneable: true,\n });\n } else if (otherField.kind === \"m2m\") {\n m2mAlias = assigner.getAlias(otherField.joinTableName);\n // Get the m2m row's id to track in JoinRows; id-less tables have no surrogate id.\n if (otherField.hasJoinTableId) selects.unshift(kqDot(m2mAlias, \"id\"));\n m2mTable = {\n join: \"inner\",\n table: otherField.joinTableName,\n alias: m2mAlias,\n col1: kqDot(parentAlias, \"id\"),\n col2: kqDot(m2mAlias, otherField.columnNames[1]),\n };\n cb.addRawCondition({\n aliases: [m2mAlias, otherAlias],\n condition: `${kqDot(m2mAlias, otherField.columnNames[0])} = ${kqDot(otherAlias, \"id\")}`,\n pruneable: true,\n });\n } else {\n throw new Error(`Unsupported otherField.kind ${otherField.kind}`);\n }\n\n const needsSubSelect = subTree.entities.size !== root.tree.entities.size;\n if (needsSubSelect) {\n cb.addRawCondition({\n aliases: [root.alias],\n condition: `${kqDot(root.alias, \"id\")} = ANY(?)`,\n bindings: [\n [...subTree.entities]\n .filter((e) => typeof e === \"string\" || !e.isNewEntity)\n .map((e) => keyToNumber(root.meta, typeof e === \"string\" ? e : e.id)),\n ],\n pruneable: true,\n });\n }\n\n // For m2m, order by the join-row's id so preloaded results match the order the lazy batch\n // loader returns (which orders by join-row id). Id-less join tables have no surrogate id,\n // so order by the other entity's FK column (matching the lazy loader & getOthers). Otherwise,\n // order by the target entity's id.\n const orderBy =\n otherField.kind === \"m2m\" && !otherField.hasJoinTableId\n ? `${kq(m2mAlias!)}.${kq(otherField.columnNames[0])}`\n : `${kq(m2mAlias ?? otherAlias)}.id`;\n\n const join: LateralJoinTable = {\n join: \"lateral\",\n alias: otherAlias,\n // Do we need to say which alias we're coming from, to avoid having it pruned?\n // ...maybe not because preloading is always on the primary table?\n fromAlias: \"unset\",\n table: otherMeta.tableName,\n query: {\n selects: [`json_agg(json_build_array(${selects.join(\", \")}) order by ${orderBy}) as _`],\n tables: [\n { join: \"primary\", table: otherMeta.tableName, alias: otherAlias },\n ...(m2mTable ? [m2mTable] : []),\n ...subJoins.map((sj) => sj.join),\n ],\n condition: cb.toExpressionFilter(),\n orderBys: [],\n },\n };\n\n // Pre-compute column names so we don't re-read them per entity\n const columnNames = columns.map((c) => c.columnName);\n // If we've snuck the m2m row id into the json array, ignore it (id-less tables have no id)\n const m2mOffset = field.kind === \"m2m\" && field.hasJoinTableId ? 1 : 0;\n\n const hydrator: AggregateJsonHydrator = (root, parent, arrays) => {\n const { em } = root;\n\n // If we had overlapping load hints, i.e. `author.books` for [a1, a2] and `author.comments` for [a1], and\n // we're processing the arrays of comments, but for a root author like `a2` that didn't ask for our load\n // hint, then skip it to keep the relation unloaded.\n if (subTree.entitiesKind === \"instances\" && !subTree.entities.has(root as any)) return;\n if (subTree.entitiesKind === \"ids\" && !subTree.entities.has(root.idTagged as any)) return;\n\n // We get back an array of [[1, title], [2, title], [3, title]]\n const children = arrays.map((array) => {\n const taggedId = keyToTaggedId(otherMeta, array[m2mOffset] as any)!;\n const row: Record<string, any> = {};\n for (let i = 0; i < columns.length; i++) {\n row[columnNames[i]] = columns[i].mapFromJsonAgg(array[m2mOffset + i]);\n }\n const entity =\n em.findExistingInstance<Entity>(taggedId) ??\n (em.hydrate(otherMeta.cstr, [row], { overwriteExisting: false }) as Entity[])[0];\n // Tell the internal JoinRow booking-keeping about this m2m row\n if (field.kind === \"m2m\") {\n // TODO This `addExisting` needs to be pulled up, out of the `arrays.map`, so we can do a `loadRows`-ish\n // call that passes all now-known m2m rows into JoinRows as a single list, so that it can mark any\n // deleted-from-under-us m2m rows as deleted.\n const m2m = (parent as any)[key];\n getEmInternalApi(em)\n .joinRows(m2m)\n .addPreloadedRow(m2m, field.hasJoinTableId ? (array[0] as any) : undefined, parent, entity);\n }\n // Within each child, look for grandchildren\n subJoins.forEach((sub, i) => {\n // array[i] could be null if there are no grandchildren, but still call `sub` to\n // process it so that we store the empty array into the em.joinLoadedRelations, to\n // avoid the relation.load method later doing a SQL for rows we know are not there.\n sub.hydrator(root, entity, (array[m2mOffset + columns.length + i] as any) ?? []);\n });\n return entity;\n });\n // Cache the entities so `.load`s will see them\n getEmInternalApi(em).setPreloadedRelation(parent.idTagged, key, children);\n };\n\n results.push({ alias: otherAlias, relationAlias, join, hydrator });\n }\n });\n\n return results;\n}\n\n/**\n * Builds the `CROSS JOIN LATERAL` that aggregates an enum-m2m join table (e.g. `publisher_logo_colors`)\n * into a json array of enum ids, e.g. `[[1], [3]]` (or `[[1, id], [3, id]]` for id-ful join tables).\n */\nfunction calcEnumLateralJoin<I extends EntityOrId>(\n assigner: AliasAssigner,\n root: { tree: HintNode<I>; alias: string; meta: EntityMetadata },\n subTree: HintNode<I>,\n parentAlias: string,\n field: ManyToManyEnumField,\n key: string,\n pathPrefix: string,\n): AggregateJoinResult {\n const [entityColumn, enumColumn] = field.columnNames;\n const jtAlias = `_${assigner.getAlias(field.joinTableName)}`;\n const relationAlias = `_${assigner.getLiteralAlias(`${pathPrefix}${key.toLowerCase()}`)}`;\n\n const parts = [kqDot(jtAlias, enumColumn)];\n if (field.hasJoinTableId) parts.push(kqDot(jtAlias, \"id\"));\n\n const cb = new ConditionBuilder();\n cb.addRawCondition({\n aliases: [jtAlias, parentAlias],\n condition: `${kqDot(jtAlias, entityColumn)} = ${kqDot(parentAlias, \"id\")}`,\n pruneable: true,\n });\n\n const needsSubSelect = subTree.entities.size !== root.tree.entities.size;\n if (needsSubSelect) {\n cb.addRawCondition({\n aliases: [root.alias],\n condition: `${kqDot(root.alias, \"id\")} = ANY(?)`,\n bindings: [\n [...subTree.entities]\n .filter((e) => typeof e === \"string\" || !e.isNewEntity)\n .map((e) => keyToNumber(root.meta, typeof e === \"string\" ? e : e.id)),\n ],\n pruneable: true,\n });\n }\n\n const orderBy = `${kq(jtAlias)}.${kq(field.hasJoinTableId ? \"id\" : enumColumn)}`;\n const join: LateralJoinTable = {\n join: \"lateral\",\n alias: jtAlias,\n fromAlias: \"unset\",\n table: field.joinTableName,\n query: {\n selects: [`json_agg(json_build_array(${parts.join(\", \")}) order by ${orderBy}) as _`],\n tables: [{ join: \"primary\", table: field.joinTableName, alias: jtAlias }],\n condition: cb.toExpressionFilter(),\n orderBys: [],\n },\n };\n\n const hydrator: AggregateJsonHydrator = (root, parent, arrays) => {\n const { em } = root;\n if (subTree.entitiesKind === \"instances\" && !subTree.entities.has(root as any)) return;\n if (subTree.entitiesKind === \"ids\" && !subTree.entities.has(root.idTagged as any)) return;\n const like: ManyToManyLike = {\n entity: parent,\n joinTableName: field.joinTableName,\n columnName: entityColumn,\n otherColumnName: enumColumn,\n fieldName: key,\n meta: getMetadataForField(getMetadata(parent), key),\n otherEnum: field.enumDetailType,\n hasJoinTableId: field.hasJoinTableId,\n };\n const api = getEmInternalApi(em);\n const joinRows = api.joinRows(like);\n const codes: any[] = [];\n for (const array of arrays) {\n const enumId = array[0] as number;\n joinRows.addPreloadedRow(like, field.hasJoinTableId ? (array[1] as number) : undefined, parent, enumId);\n codes.push(field.enumDetailType.findById(enumId)!.code);\n }\n api.setPreloadedRelation(parent.idTagged, key, codes);\n };\n\n return { alias: jtAlias, relationAlias, join, hydrator };\n}\n\n/** A preload-loadable join for a given child, with potentially grand-child joins contained within it. */\ntype AggregateJoinResult = {\n /** The short table alias used for column references inside the subquery, e.g. `_b1`. */\n alias: string;\n /** The readable relation-name alias used in the outer `AS` clause, e.g. `_prequel`. */\n relationAlias: string;\n /** The SQL for this child's lateral join, which itself might have recursive lateral joins. */\n join: LateralJoinTable;\n /** The hydrator for this child's lateral join, which itself might recursively hydrator subjoins. */\n hydrator: AggregateJsonHydrator;\n};\n\n/** Reads one column from either classic POJO rows or a lazy `RowData` result. */\nfunction readRowValue(rows: any[] | RowData, rowIndex: number, columnName: string): any {\n return Array.isArray(rows) ? rows[rowIndex][columnName] : rows.get(rowIndex, columnName);\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canPreload.cjs","names":[],"sources":["../../src/preloading/canPreload.ts"],"sourcesContent":["import {\n type EntityMetadata,\n type Field,\n type ManyToManyEnumField,\n type ManyToManyField,\n type ManyToOneField,\n type OneToManyField,\n type OneToOneField,\n} from \"
|
|
1
|
+
{"version":3,"file":"canPreload.cjs","names":[],"sources":["../../src/preloading/canPreload.ts"],"sourcesContent":["import {\n type EntityMetadata,\n type Field,\n type ManyToManyEnumField,\n type ManyToManyField,\n type ManyToOneField,\n type OneToManyField,\n type OneToOneField,\n} from \"src/EntityMetadata.ts\";\n\nexport function canPreload(\n meta: EntityMetadata,\n field: Field,\n): field is OneToManyField | ManyToOneField | ManyToManyField | ManyToManyEnumField | OneToOneField {\n // Enum m2ms have no \"other\" entity table (the join target is an enum), so they're always preloadable.\n if (field.kind === \"m2mEnum\") return true;\n if (field.kind === \"o2m\" || field.kind === \"o2o\" || field.kind === \"m2o\" || field.kind === \"m2m\") {\n const otherMeta = field.otherMetadata();\n // We don't support preloading tables with inheritance yet\n if (!!otherMeta.baseType || otherMeta.subTypes.length > 0) return false;\n // If `otherField` is missing, this could be a large collection which currently can't be loaded...\n const otherField = otherMeta.allFields[field.otherFieldName];\n if (!otherField) return false;\n // If otherField is a poly that points to a sub/base component, we don't support that yet\n if (otherField.kind === \"poly\" && !otherField.components.some((c) => c.otherMetadata() === meta)) return false;\n return true;\n }\n return false;\n}\n"],"mappings":";;;AAUA,SAAgB,WACd,MACA,OACkG;CAElG,IAAI,MAAM,SAAS,WAAW,OAAO;CACrC,IAAI,MAAM,SAAS,SAAS,MAAM,SAAS,SAAS,MAAM,SAAS,SAAS,MAAM,SAAS,OAAO;EAChG,MAAM,YAAY,MAAM,cAAc;EAEtC,IAAI,CAAC,CAAC,UAAU,YAAY,UAAU,SAAS,SAAS,GAAG,OAAO;EAElE,MAAM,aAAa,UAAU,UAAU,MAAM;EAC7C,IAAI,CAAC,YAAY,OAAO;EAExB,IAAI,WAAW,SAAS,UAAU,CAAC,WAAW,WAAW,MAAM,MAAM,EAAE,cAAc,MAAM,IAAI,GAAG,OAAO;EACzG,OAAO;CACT;CACA,OAAO;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canPreload.js","names":[],"sources":["../../src/preloading/canPreload.ts"],"sourcesContent":["import {\n type EntityMetadata,\n type Field,\n type ManyToManyEnumField,\n type ManyToManyField,\n type ManyToOneField,\n type OneToManyField,\n type OneToOneField,\n} from \"
|
|
1
|
+
{"version":3,"file":"canPreload.js","names":[],"sources":["../../src/preloading/canPreload.ts"],"sourcesContent":["import {\n type EntityMetadata,\n type Field,\n type ManyToManyEnumField,\n type ManyToManyField,\n type ManyToOneField,\n type OneToManyField,\n type OneToOneField,\n} from \"src/EntityMetadata.ts\";\n\nexport function canPreload(\n meta: EntityMetadata,\n field: Field,\n): field is OneToManyField | ManyToOneField | ManyToManyField | ManyToManyEnumField | OneToOneField {\n // Enum m2ms have no \"other\" entity table (the join target is an enum), so they're always preloadable.\n if (field.kind === \"m2mEnum\") return true;\n if (field.kind === \"o2m\" || field.kind === \"o2o\" || field.kind === \"m2o\" || field.kind === \"m2m\") {\n const otherMeta = field.otherMetadata();\n // We don't support preloading tables with inheritance yet\n if (!!otherMeta.baseType || otherMeta.subTypes.length > 0) return false;\n // If `otherField` is missing, this could be a large collection which currently can't be loaded...\n const otherField = otherMeta.allFields[field.otherFieldName];\n if (!otherField) return false;\n // If otherField is a poly that points to a sub/base component, we don't support that yet\n if (otherField.kind === \"poly\" && !otherField.components.some((c) => c.otherMetadata() === meta)) return false;\n return true;\n }\n return false;\n}\n"],"mappings":";;AAUA,SAAgB,WACd,MACA,OACkG;CAElG,IAAI,MAAM,SAAS,WAAW,OAAO;CACrC,IAAI,MAAM,SAAS,SAAS,MAAM,SAAS,SAAS,MAAM,SAAS,SAAS,MAAM,SAAS,OAAO;EAChG,MAAM,YAAY,MAAM,cAAc;EAEtC,IAAI,CAAC,CAAC,UAAU,YAAY,UAAU,SAAS,SAAS,GAAG,OAAO;EAElE,MAAM,aAAa,UAAU,UAAU,MAAM;EAC7C,IAAI,CAAC,YAAY,OAAO;EAExB,IAAI,WAAW,SAAS,UAAU,CAAC,WAAW,WAAW,MAAM,MAAM,EAAE,cAAc,MAAM,IAAI,GAAG,OAAO;EACzG,OAAO;CACT;CACA,OAAO;AACT"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_relations_ReactiveReference = require("../relations/ReactiveReference.cjs");
|
|
3
2
|
const require_normalizeHints = require("../normalizeHints.cjs");
|
|
4
|
-
require("../
|
|
5
|
-
const require_getProperties = require("../getProperties.cjs");
|
|
3
|
+
const require_relations_ReactiveReference = require("../relations/ReactiveReference.cjs");
|
|
6
4
|
require("../relations/index.cjs");
|
|
5
|
+
const require_getProperties = require("../getProperties.cjs");
|
|
7
6
|
require("../EntityMetadata.cjs");
|
|
8
7
|
const require_preloading_canPreload = require("./canPreload.cjs");
|
|
9
8
|
//#region src/preloading/partitionHint.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"partitionHint.cjs","names":["normalizeHint","canPreload","getProperties","ReactiveReferenceImpl","deepNormalizeHint"],"sources":["../../src/preloading/partitionHint.ts"],"sourcesContent":["import { type EntityMetadata } from \"
|
|
1
|
+
{"version":3,"file":"partitionHint.cjs","names":["normalizeHint","canPreload","getProperties","ReactiveReferenceImpl","deepNormalizeHint"],"sources":["../../src/preloading/partitionHint.ts"],"sourcesContent":["import { type EntityMetadata } from \"src/EntityMetadata.ts\";\nimport { getProperties } from \"src/getProperties.ts\";\nimport type { LoadHint, NestedLoadHint } from \"src/loading/loadHints.ts\";\nimport { deepNormalizeHint, normalizeHint } from \"src/normalizeHints.ts\";\nimport { canPreload } from \"src/preloading/canPreload.ts\";\nimport { ReactiveReferenceImpl } from \"src/relations/index.ts\";\n\n/** Partitions a hint into SQL-able and non-SQL-able hints. */\nexport function partitionHint(\n meta: EntityMetadata | undefined,\n hint: LoadHint<any>,\n): [NestedLoadHint<any> | undefined, NestedLoadHint<any> | undefined] {\n let sql: NestedLoadHint<any> | undefined = undefined;\n let non: NestedLoadHint<any> | undefined = undefined;\n for (const [key, subHint] of Object.entries(normalizeHint(hint))) {\n const field = meta?.allFields[key];\n if (field && canPreload(meta!, field)) {\n if (field.kind === \"m2mEnum\") {\n // Enum m2ms are a leaf relation (enum codes have no sub-hint to recurse into).\n (sql ??= {})[key] ??= {};\n } else {\n const [_sql, _non] = partitionHint(field.otherMetadata(), subHint);\n deepMerge(((sql ??= {})[key] ??= {}), _sql ?? {});\n if (_non) deepMerge(((non ??= {})[key] ??= {}), _non);\n }\n } else {\n // If this isn't a raw SQL relation, but it exposes a load-hint, inline that into our SQL.\n // This will get the non-SQL relation's underlying SQL data preloaded.\n const p = meta && getProperties(meta)[key];\n if (p && p.loadHint) {\n // Maybe we could have `PersistedAsyncReferenceImpl` internally/dynamically return us the right\n // load hint, instead of special casing it like this? Like it could internally check \"needs calc?\"\n if (p instanceof ReactiveReferenceImpl) {\n // Instead of using p.loadHint, we'll just follow the FK in the database and go to the subHint\n const [_sql, _non] = partitionHint(p.otherMeta, subHint);\n deepMerge(((sql ??= {})[key] ??= {}), _sql ?? {});\n if (_non) deepMerge(((non ??= {})[key] ??= {}), _non);\n continue;\n } else {\n // It's not clear what to do with the subHint here, if anything--ideally it could stitch\n // on top of load hint but only in the places that made sense. But we'd risk over-fetching.\n // ...also we don't want to preload ReactiveField full hint vs. just using their\n // calculated values.\n // const [_sql, _non] = partitionHint(meta, p.loadHint);\n // if (_sql) deepMerge((sql ??= {}), _sql);\n // if (_non) deepMerge((non ??= {}), _non);\n }\n }\n // Even if we did some SQL preloads, the subHint needs to go through the non-sql path.\n deepMerge(((non ??= {})[key] ??= {}), deepNormalizeHint(subHint));\n }\n }\n return [sql, non];\n}\n\nfunction deepMerge<T extends object>(a: T, b: T): void {\n for (const [key, value] of Object.entries(b)) {\n deepMerge(((a as any)[key] ??= {}), value);\n }\n}\n"],"mappings":";;;;;;;;;AAQA,SAAgB,cACd,MACA,MACoE;CACpE,IAAI,MAAuC,KAAA;CAC3C,IAAI,MAAuC,KAAA;CAC3C,KAAK,MAAM,CAAC,KAAK,YAAY,OAAO,QAAQA,uBAAAA,cAAc,IAAI,CAAC,GAAG;EAChE,MAAM,QAAQ,MAAM,UAAU;EAC9B,IAAI,SAASC,8BAAAA,WAAW,MAAO,KAAK,GAAG;GACrC,IAAI,MAAM,SAAS,WAEjB,CAAC,QAAQ,CAAC,EAAA,CAAG,SAAS,CAAC;QAClB;IACL,MAAM,CAAC,MAAM,QAAQ,cAAc,MAAM,cAAc,GAAG,OAAO;IACjE,UAAW,CAAC,QAAQ,CAAC,EAAA,CAAG,SAAS,CAAC,GAAI,QAAQ,CAAC,CAAC;IAChD,IAAI,MAAM,UAAW,CAAC,QAAQ,CAAC,EAAA,CAAG,SAAS,CAAC,GAAI,IAAI;GACtD;EACF,OAAO;GAGL,MAAM,IAAI,QAAQC,sBAAAA,cAAc,IAAI,CAAC,CAAC;GACtC,IAAI,KAAK,EAAE,UAGL;QAAA,aAAaC,oCAAAA,uBAAuB;KAEtC,MAAM,CAAC,MAAM,QAAQ,cAAc,EAAE,WAAW,OAAO;KACvD,UAAW,CAAC,QAAQ,CAAC,EAAA,CAAG,SAAS,CAAC,GAAI,QAAQ,CAAC,CAAC;KAChD,IAAI,MAAM,UAAW,CAAC,QAAQ,CAAC,EAAA,CAAG,SAAS,CAAC,GAAI,IAAI;KACpD;IACF;;GAWF,UAAW,CAAC,QAAQ,CAAC,EAAA,CAAG,SAAS,CAAC,GAAIC,uBAAAA,kBAAkB,OAAO,CAAC;EAClE;CACF;CACA,OAAO,CAAC,KAAK,GAAG;AAClB;AAEA,SAAS,UAA4B,GAAM,GAAY;CACrD,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,CAAC,GACzC,UAAW,EAAW,SAAS,CAAC,GAAI,KAAK;AAE7C"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LoadHint, NestedLoadHint } from "../loadHints.cjs";
|
|
1
|
+
import { LoadHint, NestedLoadHint } from "../loading/loadHints.cjs";
|
|
2
2
|
import { EntityMetadata } from "../EntityMetadata.cjs";
|
|
3
3
|
//#region src/preloading/partitionHint.d.ts
|
|
4
4
|
/** Partitions a hint into SQL-able and non-SQL-able hints. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LoadHint, NestedLoadHint } from "../loadHints.mjs";
|
|
1
|
+
import { LoadHint, NestedLoadHint } from "../loading/loadHints.mjs";
|
|
2
2
|
import { EntityMetadata } from "../EntityMetadata.mjs";
|
|
3
3
|
//#region src/preloading/partitionHint.d.ts
|
|
4
4
|
/** Partitions a hint into SQL-able and non-SQL-able hints. */
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { ReactiveReferenceImpl } from "../relations/ReactiveReference.js";
|
|
2
1
|
import { deepNormalizeHint, normalizeHint } from "../normalizeHints.js";
|
|
3
|
-
import "../
|
|
4
|
-
import { getProperties } from "../getProperties.js";
|
|
2
|
+
import { ReactiveReferenceImpl } from "../relations/ReactiveReference.js";
|
|
5
3
|
import "../relations/index.js";
|
|
4
|
+
import { getProperties } from "../getProperties.js";
|
|
6
5
|
import "../EntityMetadata.js";
|
|
7
6
|
import { canPreload } from "./canPreload.js";
|
|
8
7
|
//#region src/preloading/partitionHint.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"partitionHint.js","names":[],"sources":["../../src/preloading/partitionHint.ts"],"sourcesContent":["import { type EntityMetadata } from \"
|
|
1
|
+
{"version":3,"file":"partitionHint.js","names":[],"sources":["../../src/preloading/partitionHint.ts"],"sourcesContent":["import { type EntityMetadata } from \"src/EntityMetadata.ts\";\nimport { getProperties } from \"src/getProperties.ts\";\nimport type { LoadHint, NestedLoadHint } from \"src/loading/loadHints.ts\";\nimport { deepNormalizeHint, normalizeHint } from \"src/normalizeHints.ts\";\nimport { canPreload } from \"src/preloading/canPreload.ts\";\nimport { ReactiveReferenceImpl } from \"src/relations/index.ts\";\n\n/** Partitions a hint into SQL-able and non-SQL-able hints. */\nexport function partitionHint(\n meta: EntityMetadata | undefined,\n hint: LoadHint<any>,\n): [NestedLoadHint<any> | undefined, NestedLoadHint<any> | undefined] {\n let sql: NestedLoadHint<any> | undefined = undefined;\n let non: NestedLoadHint<any> | undefined = undefined;\n for (const [key, subHint] of Object.entries(normalizeHint(hint))) {\n const field = meta?.allFields[key];\n if (field && canPreload(meta!, field)) {\n if (field.kind === \"m2mEnum\") {\n // Enum m2ms are a leaf relation (enum codes have no sub-hint to recurse into).\n (sql ??= {})[key] ??= {};\n } else {\n const [_sql, _non] = partitionHint(field.otherMetadata(), subHint);\n deepMerge(((sql ??= {})[key] ??= {}), _sql ?? {});\n if (_non) deepMerge(((non ??= {})[key] ??= {}), _non);\n }\n } else {\n // If this isn't a raw SQL relation, but it exposes a load-hint, inline that into our SQL.\n // This will get the non-SQL relation's underlying SQL data preloaded.\n const p = meta && getProperties(meta)[key];\n if (p && p.loadHint) {\n // Maybe we could have `PersistedAsyncReferenceImpl` internally/dynamically return us the right\n // load hint, instead of special casing it like this? Like it could internally check \"needs calc?\"\n if (p instanceof ReactiveReferenceImpl) {\n // Instead of using p.loadHint, we'll just follow the FK in the database and go to the subHint\n const [_sql, _non] = partitionHint(p.otherMeta, subHint);\n deepMerge(((sql ??= {})[key] ??= {}), _sql ?? {});\n if (_non) deepMerge(((non ??= {})[key] ??= {}), _non);\n continue;\n } else {\n // It's not clear what to do with the subHint here, if anything--ideally it could stitch\n // on top of load hint but only in the places that made sense. But we'd risk over-fetching.\n // ...also we don't want to preload ReactiveField full hint vs. just using their\n // calculated values.\n // const [_sql, _non] = partitionHint(meta, p.loadHint);\n // if (_sql) deepMerge((sql ??= {}), _sql);\n // if (_non) deepMerge((non ??= {}), _non);\n }\n }\n // Even if we did some SQL preloads, the subHint needs to go through the non-sql path.\n deepMerge(((non ??= {})[key] ??= {}), deepNormalizeHint(subHint));\n }\n }\n return [sql, non];\n}\n\nfunction deepMerge<T extends object>(a: T, b: T): void {\n for (const [key, value] of Object.entries(b)) {\n deepMerge(((a as any)[key] ??= {}), value);\n }\n}\n"],"mappings":";;;;;;;;AAQA,SAAgB,cACd,MACA,MACoE;CACpE,IAAI,MAAuC,KAAA;CAC3C,IAAI,MAAuC,KAAA;CAC3C,KAAK,MAAM,CAAC,KAAK,YAAY,OAAO,QAAQ,cAAc,IAAI,CAAC,GAAG;EAChE,MAAM,QAAQ,MAAM,UAAU;EAC9B,IAAI,SAAS,WAAW,MAAO,KAAK,GAAG;GACrC,IAAI,MAAM,SAAS,WAEjB,CAAC,QAAQ,CAAC,EAAA,CAAG,SAAS,CAAC;QAClB;IACL,MAAM,CAAC,MAAM,QAAQ,cAAc,MAAM,cAAc,GAAG,OAAO;IACjE,UAAW,CAAC,QAAQ,CAAC,EAAA,CAAG,SAAS,CAAC,GAAI,QAAQ,CAAC,CAAC;IAChD,IAAI,MAAM,UAAW,CAAC,QAAQ,CAAC,EAAA,CAAG,SAAS,CAAC,GAAI,IAAI;GACtD;EACF,OAAO;GAGL,MAAM,IAAI,QAAQ,cAAc,IAAI,CAAC,CAAC;GACtC,IAAI,KAAK,EAAE,UAGL;QAAA,aAAa,uBAAuB;KAEtC,MAAM,CAAC,MAAM,QAAQ,cAAc,EAAE,WAAW,OAAO;KACvD,UAAW,CAAC,QAAQ,CAAC,EAAA,CAAG,SAAS,CAAC,GAAI,QAAQ,CAAC,CAAC;KAChD,IAAI,MAAM,UAAW,CAAC,QAAQ,CAAC,EAAA,CAAG,SAAS,CAAC,GAAI,IAAI;KACpD;IACF;;GAWF,UAAW,CAAC,QAAQ,CAAC,EAAA,CAAG,SAAS,CAAC,GAAI,kBAAkB,OAAO,CAAC;EAClE;CACF;CACA,OAAO,CAAC,KAAK,GAAG;AAClB;AAEA,SAAS,UAA4B,GAAM,GAAY;CACrD,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,CAAC,GACzC,UAAW,EAAW,SAAS,CAAC,GAAI,KAAK;AAE7C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConditionBuilder.cjs","names":["mapToDb","fail","partition","skipCondition","isDefined"],"sources":["../../src/queries/ConditionBuilder.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"ConditionBuilder.cjs","names":["mapToDb","fail","partition","skipCondition","isDefined"],"sources":["../../src/queries/ConditionBuilder.ts"],"sourcesContent":["import { isDefined } from \"src/EntityManager.ts\";\nimport type { ConditionGroup, ConditionInput } from \"src/queries/conditions.ts\";\nimport type {\n ColumnCondition,\n ParsedExpressionCondition,\n ParsedExpressionFilter,\n ParsedValueFilter,\n RawCondition,\n} from \"src/queries/parsedConditions.ts\";\nimport { skipCondition } from \"src/queries/skipCondition.ts\";\nimport { mapToDb } from \"src/queries/valueFilters.ts\";\nimport type { Column } from \"src/serde/columns.ts\";\nimport { fail, partition } from \"src/utils.ts\";\n\ntype PartialSome<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;\n\n/** Converts domain-level values like string ids/enums into their db equivalent. */\nexport class ConditionBuilder {\n /** Simple, single-column conditions, which will be AND-d together. */\n private conditions: (ColumnCondition | RawCondition)[] = [];\n /** Complex expressions, which will also be AND-d together with `conditions`. */\n private expressions: ParsedExpressionFilter[] = [];\n\n /** Accepts a raw user-facing DSL filter, and parses it into a `ParsedExpressionFilter`. */\n maybeAddExpression(expression: ConditionGroup<ConditionInput>): void {\n const parsed = parseExpression(expression);\n if (parsed) this.expressions.push(parsed);\n }\n\n /** Adds an already-db-level condition to the simple conditions list. */\n addSimpleCondition(condition: ColumnCondition): void {\n this.conditions.push(condition);\n }\n\n /** Adds an already-db-level condition to the simple conditions list. */\n addRawCondition(condition: PartialSome<RawCondition, \"kind\" | \"bindings\">): void {\n this.conditions.push({\n kind: \"raw\",\n bindings: [],\n ...condition,\n });\n }\n\n /** Adds an already-db-level expression to the expressions list. */\n addParsedExpression(parsed: ParsedExpressionFilter): void {\n this.expressions.push(parsed);\n }\n\n /**\n * Adds a user-facing `ParsedValueFilter` to the inline conditions.\n *\n * Unless it's something like `in: [a1, null]`, in which case we split it into two `is-null` and `in` conditions.\n */\n addValueFilter(alias: string, column: Column, filter: ParsedValueFilter<any>): void {\n if (filter.kind === \"in\" && filter.value.includes(null)) {\n // If the filter contains a null, we need to split it into an `is-null` and `in` condition\n const isNull = {\n kind: \"column\",\n alias,\n column: column.columnName,\n dbType: column.dbType,\n cond: { kind: \"is-null\" },\n } satisfies ColumnCondition;\n const inValues = {\n kind: \"column\",\n alias,\n column: column.columnName,\n dbType: column.dbType,\n cond: {\n kind: \"in\",\n // Filter out the nulls from the in condition\n value: filter.value.filter((v) => v !== null).map((v) => column.mapToDb(v)),\n },\n } satisfies ColumnCondition;\n // Now OR them back together\n this.expressions.push({ kind: \"exp\", op: \"or\", conditions: [isNull, inValues] });\n } else {\n const cond = {\n kind: \"column\",\n alias,\n column: column.columnName,\n dbType: column.dbType,\n // Rewrite the user-facing domain values to db values\n cond: mapToDb(column, filter),\n } satisfies ColumnCondition;\n this.conditions.push(cond);\n }\n }\n\n /** Combines our collected `conditions` and `expressions` into a single `ParsedExpressionFilter`. */\n toExpressionFilter(): ParsedExpressionFilter | undefined {\n const { expressions, conditions } = this;\n const allSimple: ParsedExpressionCondition[] = [...conditions];\n if (allSimple.length === 0 && expressions.length === 1) {\n // If no inline conditions, and just 1 opt expression, just use that\n return expressions[0];\n } else if (expressions.length === 1 && expressions[0].op === \"and\") {\n // Merge the 1 `AND` expression with the other simple conditions\n return { kind: \"exp\", op: \"and\", conditions: [...allSimple, ...expressions[0].conditions] };\n } else if (allSimple.length > 0 || expressions.length > 0) {\n // Combine the conditions within the `em.find` join literal & the `conditions` as ANDs\n return { kind: \"exp\", op: \"and\", conditions: [...allSimple, ...expressions] };\n }\n return undefined;\n }\n}\n\n/** Parses user-facing `{ and: ... }` or `{ or: ... }` into a `ParsedExpressionFilter`. */\nfunction parseExpression(expression: ConditionGroup<ConditionInput>): ParsedExpressionFilter | undefined {\n // Look for `{ and: [...] }` or `{ or: [...] }`\n const [op, expressions] =\n \"and\" in expression && expression.and\n ? [\"and\" as const, expression.and]\n : \"or\" in expression && expression.or\n ? [\"or\" as const, expression.or]\n : fail(`Invalid expression ${expression}`);\n // Potentially recurse into nested expressions\n const conditions = expressions.map((exp) => (exp && (\"and\" in exp || \"or\" in exp) ? parseExpression(exp) : exp));\n const [skip, valid] = partition(conditions, (cond) => cond === undefined || cond === skipCondition);\n if ((skip.length > 0 && expression.pruneIfUndefined === \"any\") || valid.length === 0) {\n return undefined;\n }\n return { kind: \"exp\", op, conditions: valid.filter(isDefined) };\n}\n"],"mappings":";;;;;;;AAiBA,IAAa,mBAAb,MAA8B;;CAE5B,aAAyD,CAAC;;CAE1D,cAAgD,CAAC;;CAGjD,mBAAmB,YAAkD;EACnE,MAAM,SAAS,gBAAgB,UAAU;EACzC,IAAI,QAAQ,KAAK,YAAY,KAAK,MAAM;CAC1C;;CAGA,mBAAmB,WAAkC;EACnD,KAAK,WAAW,KAAK,SAAS;CAChC;;CAGA,gBAAgB,WAAiE;EAC/E,KAAK,WAAW,KAAK;GACnB,MAAM;GACN,UAAU,CAAC;GACX,GAAG;EACL,CAAC;CACH;;CAGA,oBAAoB,QAAsC;EACxD,KAAK,YAAY,KAAK,MAAM;CAC9B;;;;;;CAOA,eAAe,OAAe,QAAgB,QAAsC;EAClF,IAAI,OAAO,SAAS,QAAQ,OAAO,MAAM,SAAS,IAAI,GAAG;GAEvD,MAAM,SAAS;IACb,MAAM;IACN;IACA,QAAQ,OAAO;IACf,QAAQ,OAAO;IACf,MAAM,EAAE,MAAM,UAAU;GAC1B;GACA,MAAM,WAAW;IACf,MAAM;IACN;IACA,QAAQ,OAAO;IACf,QAAQ,OAAO;IACf,MAAM;KACJ,MAAM;KAEN,OAAO,OAAO,MAAM,QAAQ,MAAM,MAAM,IAAI,CAAC,CAAC,KAAK,MAAM,OAAO,QAAQ,CAAC,CAAC;IAC5E;GACF;GAEA,KAAK,YAAY,KAAK;IAAE,MAAM;IAAO,IAAI;IAAM,YAAY,CAAC,QAAQ,QAAQ;GAAE,CAAC;EACjF,OAAO;GACL,MAAM,OAAO;IACX,MAAM;IACN;IACA,QAAQ,OAAO;IACf,QAAQ,OAAO;IAEf,MAAMA,6BAAAA,QAAQ,QAAQ,MAAM;GAC9B;GACA,KAAK,WAAW,KAAK,IAAI;EAC3B;CACF;;CAGA,qBAAyD;EACvD,MAAM,EAAE,aAAa,eAAe;EACpC,MAAM,YAAyC,CAAC,GAAG,UAAU;EAC7D,IAAI,UAAU,WAAW,KAAK,YAAY,WAAW,GAEnD,OAAO,YAAY;OACd,IAAI,YAAY,WAAW,KAAK,YAAY,EAAE,CAAC,OAAO,OAE3D,OAAO;GAAE,MAAM;GAAO,IAAI;GAAO,YAAY,CAAC,GAAG,WAAW,GAAG,YAAY,EAAE,CAAC,UAAU;EAAE;OACrF,IAAI,UAAU,SAAS,KAAK,YAAY,SAAS,GAEtD,OAAO;GAAE,MAAM;GAAO,IAAI;GAAO,YAAY,CAAC,GAAG,WAAW,GAAG,WAAW;EAAE;CAGhF;AACF;;AAGA,SAAS,gBAAgB,YAAgF;CAEvG,MAAM,CAAC,IAAI,eACT,SAAS,cAAc,WAAW,MAC9B,CAAC,OAAgB,WAAW,GAAG,IAC/B,QAAQ,cAAc,WAAW,KAC/B,CAAC,MAAe,WAAW,EAAE,IAC7BC,cAAAA,KAAK,sBAAsB,YAAY;CAE/C,MAAM,aAAa,YAAY,KAAK,QAAS,QAAQ,SAAS,OAAO,QAAQ,OAAO,gBAAgB,GAAG,IAAI,GAAI;CAC/G,MAAM,CAAC,MAAM,SAASC,cAAAA,UAAU,aAAa,SAAS,SAAS,KAAA,KAAa,SAASC,8BAAAA,aAAa;CAClG,IAAK,KAAK,SAAS,KAAK,WAAW,qBAAqB,SAAU,MAAM,WAAW,GACjF;CAEF,OAAO;EAAE,MAAM;EAAO;EAAI,YAAY,MAAM,OAAOC,sBAAAA,SAAS;CAAE;AAChE"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Column } from "../columns.cjs";
|
|
2
1
|
import { ColumnCondition, ParsedExpressionFilter, ParsedValueFilter, RawCondition } from "./parsedConditions.cjs";
|
|
3
2
|
import { ConditionGroup, ConditionInput } from "./conditions.cjs";
|
|
3
|
+
import { Column } from "../serde/columns.cjs";
|
|
4
4
|
//#region src/queries/ConditionBuilder.d.ts
|
|
5
5
|
type PartialSome<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
|
6
6
|
/** Converts domain-level values like string ids/enums into their db equivalent. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Column } from "../columns.mjs";
|
|
2
1
|
import { ColumnCondition, ParsedExpressionFilter, ParsedValueFilter, RawCondition } from "./parsedConditions.mjs";
|
|
3
2
|
import { ConditionGroup, ConditionInput } from "./conditions.mjs";
|
|
3
|
+
import { Column } from "../serde/columns.mjs";
|
|
4
4
|
//#region src/queries/ConditionBuilder.d.ts
|
|
5
5
|
type PartialSome<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
|
6
6
|
/** Converts domain-level values like string ids/enums into their db equivalent. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConditionBuilder.js","names":[],"sources":["../../src/queries/ConditionBuilder.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"ConditionBuilder.js","names":[],"sources":["../../src/queries/ConditionBuilder.ts"],"sourcesContent":["import { isDefined } from \"src/EntityManager.ts\";\nimport type { ConditionGroup, ConditionInput } from \"src/queries/conditions.ts\";\nimport type {\n ColumnCondition,\n ParsedExpressionCondition,\n ParsedExpressionFilter,\n ParsedValueFilter,\n RawCondition,\n} from \"src/queries/parsedConditions.ts\";\nimport { skipCondition } from \"src/queries/skipCondition.ts\";\nimport { mapToDb } from \"src/queries/valueFilters.ts\";\nimport type { Column } from \"src/serde/columns.ts\";\nimport { fail, partition } from \"src/utils.ts\";\n\ntype PartialSome<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;\n\n/** Converts domain-level values like string ids/enums into their db equivalent. */\nexport class ConditionBuilder {\n /** Simple, single-column conditions, which will be AND-d together. */\n private conditions: (ColumnCondition | RawCondition)[] = [];\n /** Complex expressions, which will also be AND-d together with `conditions`. */\n private expressions: ParsedExpressionFilter[] = [];\n\n /** Accepts a raw user-facing DSL filter, and parses it into a `ParsedExpressionFilter`. */\n maybeAddExpression(expression: ConditionGroup<ConditionInput>): void {\n const parsed = parseExpression(expression);\n if (parsed) this.expressions.push(parsed);\n }\n\n /** Adds an already-db-level condition to the simple conditions list. */\n addSimpleCondition(condition: ColumnCondition): void {\n this.conditions.push(condition);\n }\n\n /** Adds an already-db-level condition to the simple conditions list. */\n addRawCondition(condition: PartialSome<RawCondition, \"kind\" | \"bindings\">): void {\n this.conditions.push({\n kind: \"raw\",\n bindings: [],\n ...condition,\n });\n }\n\n /** Adds an already-db-level expression to the expressions list. */\n addParsedExpression(parsed: ParsedExpressionFilter): void {\n this.expressions.push(parsed);\n }\n\n /**\n * Adds a user-facing `ParsedValueFilter` to the inline conditions.\n *\n * Unless it's something like `in: [a1, null]`, in which case we split it into two `is-null` and `in` conditions.\n */\n addValueFilter(alias: string, column: Column, filter: ParsedValueFilter<any>): void {\n if (filter.kind === \"in\" && filter.value.includes(null)) {\n // If the filter contains a null, we need to split it into an `is-null` and `in` condition\n const isNull = {\n kind: \"column\",\n alias,\n column: column.columnName,\n dbType: column.dbType,\n cond: { kind: \"is-null\" },\n } satisfies ColumnCondition;\n const inValues = {\n kind: \"column\",\n alias,\n column: column.columnName,\n dbType: column.dbType,\n cond: {\n kind: \"in\",\n // Filter out the nulls from the in condition\n value: filter.value.filter((v) => v !== null).map((v) => column.mapToDb(v)),\n },\n } satisfies ColumnCondition;\n // Now OR them back together\n this.expressions.push({ kind: \"exp\", op: \"or\", conditions: [isNull, inValues] });\n } else {\n const cond = {\n kind: \"column\",\n alias,\n column: column.columnName,\n dbType: column.dbType,\n // Rewrite the user-facing domain values to db values\n cond: mapToDb(column, filter),\n } satisfies ColumnCondition;\n this.conditions.push(cond);\n }\n }\n\n /** Combines our collected `conditions` and `expressions` into a single `ParsedExpressionFilter`. */\n toExpressionFilter(): ParsedExpressionFilter | undefined {\n const { expressions, conditions } = this;\n const allSimple: ParsedExpressionCondition[] = [...conditions];\n if (allSimple.length === 0 && expressions.length === 1) {\n // If no inline conditions, and just 1 opt expression, just use that\n return expressions[0];\n } else if (expressions.length === 1 && expressions[0].op === \"and\") {\n // Merge the 1 `AND` expression with the other simple conditions\n return { kind: \"exp\", op: \"and\", conditions: [...allSimple, ...expressions[0].conditions] };\n } else if (allSimple.length > 0 || expressions.length > 0) {\n // Combine the conditions within the `em.find` join literal & the `conditions` as ANDs\n return { kind: \"exp\", op: \"and\", conditions: [...allSimple, ...expressions] };\n }\n return undefined;\n }\n}\n\n/** Parses user-facing `{ and: ... }` or `{ or: ... }` into a `ParsedExpressionFilter`. */\nfunction parseExpression(expression: ConditionGroup<ConditionInput>): ParsedExpressionFilter | undefined {\n // Look for `{ and: [...] }` or `{ or: [...] }`\n const [op, expressions] =\n \"and\" in expression && expression.and\n ? [\"and\" as const, expression.and]\n : \"or\" in expression && expression.or\n ? [\"or\" as const, expression.or]\n : fail(`Invalid expression ${expression}`);\n // Potentially recurse into nested expressions\n const conditions = expressions.map((exp) => (exp && (\"and\" in exp || \"or\" in exp) ? parseExpression(exp) : exp));\n const [skip, valid] = partition(conditions, (cond) => cond === undefined || cond === skipCondition);\n if ((skip.length > 0 && expression.pruneIfUndefined === \"any\") || valid.length === 0) {\n return undefined;\n }\n return { kind: \"exp\", op, conditions: valid.filter(isDefined) };\n}\n"],"mappings":";;;;;;AAiBA,IAAa,mBAAb,MAA8B;;CAE5B,aAAyD,CAAC;;CAE1D,cAAgD,CAAC;;CAGjD,mBAAmB,YAAkD;EACnE,MAAM,SAAS,gBAAgB,UAAU;EACzC,IAAI,QAAQ,KAAK,YAAY,KAAK,MAAM;CAC1C;;CAGA,mBAAmB,WAAkC;EACnD,KAAK,WAAW,KAAK,SAAS;CAChC;;CAGA,gBAAgB,WAAiE;EAC/E,KAAK,WAAW,KAAK;GACnB,MAAM;GACN,UAAU,CAAC;GACX,GAAG;EACL,CAAC;CACH;;CAGA,oBAAoB,QAAsC;EACxD,KAAK,YAAY,KAAK,MAAM;CAC9B;;;;;;CAOA,eAAe,OAAe,QAAgB,QAAsC;EAClF,IAAI,OAAO,SAAS,QAAQ,OAAO,MAAM,SAAS,IAAI,GAAG;GAEvD,MAAM,SAAS;IACb,MAAM;IACN;IACA,QAAQ,OAAO;IACf,QAAQ,OAAO;IACf,MAAM,EAAE,MAAM,UAAU;GAC1B;GACA,MAAM,WAAW;IACf,MAAM;IACN;IACA,QAAQ,OAAO;IACf,QAAQ,OAAO;IACf,MAAM;KACJ,MAAM;KAEN,OAAO,OAAO,MAAM,QAAQ,MAAM,MAAM,IAAI,CAAC,CAAC,KAAK,MAAM,OAAO,QAAQ,CAAC,CAAC;IAC5E;GACF;GAEA,KAAK,YAAY,KAAK;IAAE,MAAM;IAAO,IAAI;IAAM,YAAY,CAAC,QAAQ,QAAQ;GAAE,CAAC;EACjF,OAAO;GACL,MAAM,OAAO;IACX,MAAM;IACN;IACA,QAAQ,OAAO;IACf,QAAQ,OAAO;IAEf,MAAM,QAAQ,QAAQ,MAAM;GAC9B;GACA,KAAK,WAAW,KAAK,IAAI;EAC3B;CACF;;CAGA,qBAAyD;EACvD,MAAM,EAAE,aAAa,eAAe;EACpC,MAAM,YAAyC,CAAC,GAAG,UAAU;EAC7D,IAAI,UAAU,WAAW,KAAK,YAAY,WAAW,GAEnD,OAAO,YAAY;OACd,IAAI,YAAY,WAAW,KAAK,YAAY,EAAE,CAAC,OAAO,OAE3D,OAAO;GAAE,MAAM;GAAO,IAAI;GAAO,YAAY,CAAC,GAAG,WAAW,GAAG,YAAY,EAAE,CAAC,UAAU;EAAE;OACrF,IAAI,UAAU,SAAS,KAAK,YAAY,SAAS,GAEtD,OAAO;GAAE,MAAM;GAAO,IAAI;GAAO,YAAY,CAAC,GAAG,WAAW,GAAG,WAAW;EAAE;CAGhF;AACF;;AAGA,SAAS,gBAAgB,YAAgF;CAEvG,MAAM,CAAC,IAAI,eACT,SAAS,cAAc,WAAW,MAC9B,CAAC,OAAgB,WAAW,GAAG,IAC/B,QAAQ,cAAc,WAAW,KAC/B,CAAC,MAAe,WAAW,EAAE,IAC7B,KAAK,sBAAsB,YAAY;CAE/C,MAAM,aAAa,YAAY,KAAK,QAAS,QAAQ,SAAS,OAAO,QAAQ,OAAO,gBAAgB,GAAG,IAAI,GAAI;CAC/G,MAAM,CAAC,MAAM,SAAS,UAAU,aAAa,SAAS,SAAS,KAAA,KAAa,SAAS,aAAa;CAClG,IAAK,KAAK,SAAS,KAAK,WAAW,qBAAqB,SAAU,MAAM,WAAW,GACjF;CAEF,OAAO;EAAE,MAAM;EAAO;EAAI,YAAY,MAAM,OAAO,SAAS;CAAE;AAChE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conditions.cjs","names":[],"sources":["../../src/queries/conditions.ts"],"sourcesContent":["import type { ColumnCondition, RawCondition } from \"
|
|
1
|
+
{"version":3,"file":"conditions.cjs","names":[],"sources":["../../src/queries/conditions.ts"],"sourcesContent":["import type { ColumnCondition, RawCondition } from \"src/queries/parsedConditions.ts\";\n\nexport const predicateBrand: unique symbol = Symbol(\"joist.predicate\");\n\n/** Combines conditions without tying AND/OR or optional-filter pruning to either public API. */\nexport type ConditionGroup<C> = AndCondition<C> | OrCondition<C>;\n\n/** Requires every surviving condition to match. */\nexport interface AndCondition<C> {\n and: Array<C | undefined>;\n or?: never;\n pruneIfUndefined?: \"any\" | \"all\";\n}\n\n/** Requires at least one surviving condition to match. */\nexport interface OrCondition<C> {\n or: Array<C | undefined>;\n and?: never;\n pruneIfUndefined?: \"any\" | \"all\";\n}\n\n/** Identifies which API can resolve a predicate's aliases. */\nexport interface PredicateBrand<K extends \"domain\" | \"sql\"> {\n readonly [predicateBrand]: K;\n}\n\n/** A predicate built from alias(...) for em.find and scopes. */\nexport type DomainPredicate = (ColumnCondition | RawCondition) & PredicateBrand<\"domain\">;\n\n/** A predicate built from table(...), an SQL expression, or sql.condition. */\nexport type SqlPredicate = (ColumnCondition | RawCondition) & PredicateBrand<\"sql\">;\n\n/** Existing hand-written conditions remain an escape hatch, but cannot accept a foreign branded predicate. */\nexport type UnbrandedPredicate = (ColumnCondition | RawCondition) & { readonly [predicateBrand]?: never };\n\n/** SQL predicates and nested AND/OR groups, before query-specific clauses such as EXISTS are added. */\nexport type SqlCondition = AndCondition<SqlCondition> | OrCondition<SqlCondition> | SqlPredicate | UnbrandedPredicate;\n\n/** Unbranded compiler input shared by domain filtering and SQL queries after public API validation. */\nexport type ConditionInput =\n | AndCondition<ConditionInput>\n | OrCondition<ConditionInput>\n | ColumnCondition\n | RawCondition;\n\n/** Marks a newly created predicate without changing its enumerable SQL representation. */\nexport function brandPredicate<C extends object, K extends \"domain\" | \"sql\">(cond: C, kind: K): C & PredicateBrand<K> {\n return Object.defineProperty(cond, predicateBrand, { value: kind, enumerable: false }) as C & PredicateBrand<K>;\n}\n"],"mappings":";;AAEA,MAAa,iBAAgC,OAAO,iBAAiB;;AA4CrE,SAAgB,eAA6D,MAAS,MAAgC;CACpH,OAAO,OAAO,eAAe,MAAM,gBAAgB;EAAE,OAAO;EAAM,YAAY;CAAM,CAAC;AACvF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conditions.js","names":[],"sources":["../../src/queries/conditions.ts"],"sourcesContent":["import type { ColumnCondition, RawCondition } from \"
|
|
1
|
+
{"version":3,"file":"conditions.js","names":[],"sources":["../../src/queries/conditions.ts"],"sourcesContent":["import type { ColumnCondition, RawCondition } from \"src/queries/parsedConditions.ts\";\n\nexport const predicateBrand: unique symbol = Symbol(\"joist.predicate\");\n\n/** Combines conditions without tying AND/OR or optional-filter pruning to either public API. */\nexport type ConditionGroup<C> = AndCondition<C> | OrCondition<C>;\n\n/** Requires every surviving condition to match. */\nexport interface AndCondition<C> {\n and: Array<C | undefined>;\n or?: never;\n pruneIfUndefined?: \"any\" | \"all\";\n}\n\n/** Requires at least one surviving condition to match. */\nexport interface OrCondition<C> {\n or: Array<C | undefined>;\n and?: never;\n pruneIfUndefined?: \"any\" | \"all\";\n}\n\n/** Identifies which API can resolve a predicate's aliases. */\nexport interface PredicateBrand<K extends \"domain\" | \"sql\"> {\n readonly [predicateBrand]: K;\n}\n\n/** A predicate built from alias(...) for em.find and scopes. */\nexport type DomainPredicate = (ColumnCondition | RawCondition) & PredicateBrand<\"domain\">;\n\n/** A predicate built from table(...), an SQL expression, or sql.condition. */\nexport type SqlPredicate = (ColumnCondition | RawCondition) & PredicateBrand<\"sql\">;\n\n/** Existing hand-written conditions remain an escape hatch, but cannot accept a foreign branded predicate. */\nexport type UnbrandedPredicate = (ColumnCondition | RawCondition) & { readonly [predicateBrand]?: never };\n\n/** SQL predicates and nested AND/OR groups, before query-specific clauses such as EXISTS are added. */\nexport type SqlCondition = AndCondition<SqlCondition> | OrCondition<SqlCondition> | SqlPredicate | UnbrandedPredicate;\n\n/** Unbranded compiler input shared by domain filtering and SQL queries after public API validation. */\nexport type ConditionInput =\n | AndCondition<ConditionInput>\n | OrCondition<ConditionInput>\n | ColumnCondition\n | RawCondition;\n\n/** Marks a newly created predicate without changing its enumerable SQL representation. */\nexport function brandPredicate<C extends object, K extends \"domain\" | \"sql\">(cond: C, kind: K): C & PredicateBrand<K> {\n return Object.defineProperty(cond, predicateBrand, { value: kind, enumerable: false }) as C & PredicateBrand<K>;\n}\n"],"mappings":";AAEA,MAAa,iBAAgC,OAAO,iBAAiB;;AA4CrE,SAAgB,eAA6D,MAAS,MAAgC;CACpH,OAAO,OAAO,eAAe,MAAM,gBAAgB;EAAE,OAAO;EAAM,YAAY;CAAM,CAAC;AACvF"}
|