joist-core 2.3.0-next.95 → 2.3.0-next.97
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/EntityManager.cjs +36 -39
- package/build/EntityManager.cjs.map +1 -1
- package/build/EntityManager.d.cts +4 -4
- package/build/EntityManager.d.mts +4 -4
- package/build/EntityManager.js +29 -32
- package/build/EntityManager.js.map +1 -1
- package/build/EntityMetadata.cjs +3 -3
- package/build/EntityMetadata.js +3 -3
- package/build/IndexManager.cjs +1 -1
- package/build/IndexManager.js +1 -1
- package/build/InstanceData.cjs +1 -1
- package/build/InstanceData.js +1 -1
- package/build/JoinRows.cjs +1 -1
- package/build/JoinRows.js +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/ReactionsManager.cjs +2 -2
- package/build/ReactionsManager.js +2 -2
- package/build/Todo.cjs +1 -1
- package/build/Todo.js +1 -1
- package/build/batchloaders/enumCollectionBatchLoader.cjs +1 -1
- package/build/batchloaders/enumCollectionBatchLoader.js +1 -1
- package/build/batchloaders/loadBatchLoader.cjs +6 -5
- package/build/batchloaders/loadBatchLoader.cjs.map +1 -1
- package/build/batchloaders/loadBatchLoader.d.cts.map +1 -1
- package/build/batchloaders/loadBatchLoader.d.mts.map +1 -1
- package/build/batchloaders/loadBatchLoader.js +4 -3
- package/build/batchloaders/loadBatchLoader.js.map +1 -1
- package/build/batchloaders/manyToManyBatchLoader.cjs +1 -1
- package/build/batchloaders/manyToManyBatchLoader.js +1 -1
- package/build/batchloaders/oneToManyBatchLoader.cjs +3 -3
- package/build/batchloaders/oneToManyBatchLoader.cjs.map +1 -1
- package/build/batchloaders/oneToManyBatchLoader.js +2 -2
- package/build/batchloaders/oneToOneBatchLoader.cjs +4 -4
- package/build/batchloaders/oneToOneBatchLoader.cjs.map +1 -1
- package/build/batchloaders/oneToOneBatchLoader.js +3 -3
- package/build/batchloaders/populateBatchLoader.cjs +11 -11
- package/build/batchloaders/populateBatchLoader.cjs.map +1 -1
- package/build/batchloaders/populateBatchLoader.js +8 -8
- package/build/batchloaders/recursiveChildrenBatchLoader.cjs +8 -8
- package/build/batchloaders/recursiveChildrenBatchLoader.cjs.map +1 -1
- package/build/batchloaders/recursiveChildrenBatchLoader.js +5 -5
- package/build/batchloaders/recursiveM2mBatchLoader.cjs +5 -5
- package/build/batchloaders/recursiveM2mBatchLoader.cjs.map +1 -1
- package/build/batchloaders/recursiveM2mBatchLoader.js +2 -2
- package/build/batchloaders/recursiveParentsBatchLoader.cjs +8 -8
- package/build/batchloaders/recursiveParentsBatchLoader.cjs.map +1 -1
- package/build/batchloaders/recursiveParentsBatchLoader.js +5 -5
- package/build/changes.cjs +4 -4
- package/build/changes.js +4 -4
- package/build/config.cjs +3 -3
- package/build/config.js +3 -3
- package/build/configure.cjs +6 -6
- package/build/configure.js +6 -6
- package/build/dataloaders/fastWhereFilterHash.cjs +3 -3
- package/build/dataloaders/fastWhereFilterHash.cjs.map +1 -1
- package/build/dataloaders/fastWhereFilterHash.js +2 -2
- package/build/dataloaders/fastWhereFilterHash.js.map +1 -1
- package/build/dataloaders/findByUniqueDataLoader.cjs +5 -6
- 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 +3 -4
- package/build/dataloaders/findByUniqueDataLoader.js.map +1 -1
- package/build/dataloaders/findCountDataLoader.cjs +10 -13
- package/build/dataloaders/findCountDataLoader.cjs.map +1 -1
- package/build/dataloaders/findCountDataLoader.d.cts +2 -2
- package/build/dataloaders/findCountDataLoader.d.mts +2 -2
- package/build/dataloaders/findCountDataLoader.js +4 -7
- package/build/dataloaders/findCountDataLoader.js.map +1 -1
- package/build/dataloaders/findDataLoader.cjs +15 -19
- package/build/dataloaders/findDataLoader.cjs.map +1 -1
- package/build/dataloaders/findDataLoader.d.cts +2 -2
- package/build/dataloaders/findDataLoader.d.cts.map +1 -1
- package/build/dataloaders/findDataLoader.d.mts +2 -2
- package/build/dataloaders/findDataLoader.d.mts.map +1 -1
- package/build/dataloaders/findDataLoader.js +5 -9
- package/build/dataloaders/findDataLoader.js.map +1 -1
- package/build/dataloaders/findIdsDataLoader.cjs +6 -9
- package/build/dataloaders/findIdsDataLoader.cjs.map +1 -1
- package/build/dataloaders/findIdsDataLoader.d.cts +1 -1
- package/build/dataloaders/findIdsDataLoader.d.mts +1 -1
- package/build/dataloaders/findIdsDataLoader.js +3 -6
- package/build/dataloaders/findIdsDataLoader.js.map +1 -1
- package/build/dataloaders/findOrCreateDataLoader.cjs +1 -2
- package/build/dataloaders/findOrCreateDataLoader.cjs.map +1 -1
- package/build/dataloaders/findOrCreateDataLoader.js +1 -2
- package/build/dataloaders/findOrCreateDataLoader.js.map +1 -1
- package/build/dataloaders/findPaginatedDataLoader.cjs +3 -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 +2 -5
- package/build/dataloaders/findPaginatedDataLoader.js.map +1 -1
- package/build/dataloaders/lensDataLoader.cjs +4 -4
- package/build/dataloaders/lensDataLoader.cjs.map +1 -1
- package/build/dataloaders/lensDataLoader.js +2 -2
- package/build/dataloaders/lensDataLoader.js.map +1 -1
- package/build/dataloaders/manyToManyFindDataLoader.cjs +1 -4
- package/build/dataloaders/manyToManyFindDataLoader.cjs.map +1 -1
- package/build/dataloaders/manyToManyFindDataLoader.d.cts +0 -1
- package/build/dataloaders/manyToManyFindDataLoader.d.cts.map +1 -1
- package/build/dataloaders/manyToManyFindDataLoader.d.mts +0 -1
- package/build/dataloaders/manyToManyFindDataLoader.d.mts.map +1 -1
- package/build/dataloaders/manyToManyFindDataLoader.js +1 -4
- package/build/dataloaders/manyToManyFindDataLoader.js.map +1 -1
- package/build/dataloaders/oneToManyFindDataLoader.cjs +3 -6
- package/build/dataloaders/oneToManyFindDataLoader.cjs.map +1 -1
- package/build/dataloaders/oneToManyFindDataLoader.d.cts +0 -1
- package/build/dataloaders/oneToManyFindDataLoader.d.cts.map +1 -1
- package/build/dataloaders/oneToManyFindDataLoader.d.mts +0 -1
- package/build/dataloaders/oneToManyFindDataLoader.d.mts.map +1 -1
- package/build/dataloaders/oneToManyFindDataLoader.js +2 -5
- package/build/dataloaders/oneToManyFindDataLoader.js.map +1 -1
- package/build/defaults.cjs +4 -4
- package/build/defaults.js +4 -4
- package/build/driverApi.cjs +4 -5
- package/build/driverApi.cjs.map +1 -1
- package/build/driverApi.d.cts +1 -1
- package/build/driverApi.d.mts +1 -1
- package/build/driverApi.js +2 -2
- package/build/driverApi.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 +2 -2
- package/build/drivers/EntityWriter.js +2 -2
- package/build/drivers/index.cjs +0 -6
- package/build/drivers/index.d.cts +1 -3
- package/build/drivers/index.d.mts +1 -3
- package/build/drivers/index.js +1 -3
- package/build/fieldSerde.cjs +2 -2
- package/build/fieldSerde.js +2 -2
- package/build/fields.cjs +2 -2
- package/build/fields.js +2 -2
- package/build/getProperties.cjs +1 -1
- package/build/getProperties.js +1 -1
- package/build/index.cjs +109 -106
- package/build/index.cjs.map +1 -1
- package/build/index.d.cts +27 -24
- package/build/index.d.cts.map +1 -1
- package/build/index.d.mts +27 -24
- package/build/index.d.mts.map +1 -1
- package/build/index.js +52 -50
- package/build/index.js.map +1 -1
- package/build/json.cjs +3 -3
- package/build/json.js +3 -3
- package/build/keys.cjs +1 -1
- package/build/keys.js +1 -1
- package/build/loadHints.cjs +1 -1
- package/build/loadHints.js +1 -1
- package/build/loadLens.cjs +1 -1
- package/build/loadLens.js +1 -1
- package/build/logging/FactoryLogger.cjs +1 -1
- package/build/logging/FactoryLogger.js +1 -1
- package/build/logging/FieldLogger.cjs +1 -1
- package/build/logging/FieldLogger.js +1 -1
- package/build/logging/ReactionLogger.cjs +1 -1
- package/build/logging/ReactionLogger.js +1 -1
- package/build/newEntity.cjs +1 -1
- package/build/newEntity.js +1 -1
- package/build/newTestInstance.cjs +3 -3
- package/build/newTestInstance.js +3 -3
- package/build/plugins/PreloadPlugin.cjs +1 -2
- package/build/plugins/PreloadPlugin.d.cts +1 -1
- package/build/plugins/PreloadPlugin.d.mts +1 -1
- package/build/plugins/PreloadPlugin.js +1 -2
- package/build/preloading/JsonAggregatePreloader.cjs +31 -31
- package/build/preloading/JsonAggregatePreloader.cjs.map +1 -1
- package/build/preloading/JsonAggregatePreloader.d.cts +1 -1
- package/build/preloading/JsonAggregatePreloader.d.mts +1 -1
- package/build/preloading/JsonAggregatePreloader.js +6 -6
- package/build/preloading/JsonAggregatePreloader.js.map +1 -1
- package/build/preloading/partitionHint.cjs +3 -3
- package/build/preloading/partitionHint.js +3 -3
- package/build/{ConditionBuilder.cjs → queries/ConditionBuilder.cjs} +7 -8
- package/build/queries/ConditionBuilder.cjs.map +1 -0
- package/build/{ConditionBuilder.d.cts → queries/ConditionBuilder.d.cts} +3 -3
- package/build/queries/ConditionBuilder.d.cts.map +1 -0
- package/build/{ConditionBuilder.d.mts → queries/ConditionBuilder.d.mts} +3 -3
- package/build/queries/ConditionBuilder.d.mts.map +1 -0
- package/build/{ConditionBuilder.js → queries/ConditionBuilder.js} +4 -5
- package/build/queries/ConditionBuilder.js.map +1 -0
- package/build/{conditions.cjs → queries/conditions.cjs} +1 -2
- package/build/queries/conditions.cjs.map +1 -0
- package/build/{conditions.d.cts → queries/conditions.d.cts} +2 -2
- package/build/queries/conditions.d.cts.map +1 -0
- package/build/{conditions.d.mts → queries/conditions.d.mts} +2 -2
- package/build/queries/conditions.d.mts.map +1 -0
- package/build/{conditions.js → queries/conditions.js} +1 -2
- package/build/queries/conditions.js.map +1 -0
- package/build/queries/entityQueryUtils.cjs +60 -0
- package/build/queries/entityQueryUtils.cjs.map +1 -0
- package/build/queries/entityQueryUtils.d.cts +19 -0
- package/build/queries/entityQueryUtils.d.cts.map +1 -0
- package/build/queries/entityQueryUtils.d.mts +19 -0
- package/build/queries/entityQueryUtils.d.mts.map +1 -0
- package/build/queries/entityQueryUtils.js +56 -0
- package/build/queries/entityQueryUtils.js.map +1 -0
- package/build/{Aliases.cjs → queries/find/Aliases.cjs} +23 -28
- package/build/queries/find/Aliases.cjs.map +1 -0
- package/build/{Aliases.d.cts → queries/find/Aliases.d.cts} +7 -7
- package/build/queries/find/Aliases.d.cts.map +1 -0
- package/build/{Aliases.d.mts → queries/find/Aliases.d.mts} +7 -7
- package/build/queries/find/Aliases.d.mts.map +1 -0
- package/build/{Aliases.js → queries/find/Aliases.js} +7 -12
- package/build/queries/find/Aliases.js.map +1 -0
- package/build/{DeferredAlias.cjs → queries/find/DeferredAlias.cjs} +3 -6
- package/build/queries/find/DeferredAlias.cjs.map +1 -0
- package/build/{DeferredAlias.d.cts → queries/find/DeferredAlias.d.cts} +4 -4
- package/build/queries/find/DeferredAlias.d.cts.map +1 -0
- package/build/{DeferredAlias.d.mts → queries/find/DeferredAlias.d.mts} +4 -4
- package/build/queries/find/DeferredAlias.d.mts.map +1 -0
- package/build/{DeferredAlias.js → queries/find/DeferredAlias.js} +2 -5
- package/build/queries/find/DeferredAlias.js.map +1 -0
- package/build/{EntityFilter.cjs → queries/find/EntityFilter.cjs} +4 -9
- package/build/queries/find/EntityFilter.cjs.map +1 -0
- package/build/{EntityFilter.d.cts → queries/find/EntityFilter.d.cts} +6 -6
- package/build/queries/find/EntityFilter.d.cts.map +1 -0
- package/build/{EntityFilter.d.mts → queries/find/EntityFilter.d.mts} +6 -6
- package/build/queries/find/EntityFilter.d.mts.map +1 -0
- package/build/{EntityFilter.js → queries/find/EntityFilter.js} +1 -6
- package/build/queries/find/EntityFilter.js.map +1 -0
- package/build/{EntityGraphQLFilter.cjs → queries/find/EntityGraphQLFilter.cjs} +1 -5
- package/build/queries/find/EntityGraphQLFilter.cjs.map +1 -0
- package/build/{EntityGraphQLFilter.d.cts → queries/find/EntityGraphQLFilter.d.cts} +3 -3
- package/build/queries/find/EntityGraphQLFilter.d.cts.map +1 -0
- package/build/{EntityGraphQLFilter.d.mts → queries/find/EntityGraphQLFilter.d.mts} +3 -3
- package/build/queries/find/EntityGraphQLFilter.d.mts.map +1 -0
- package/build/{EntityGraphQLFilter.js → queries/find/EntityGraphQLFilter.js} +1 -5
- package/build/queries/find/EntityGraphQLFilter.js.map +1 -0
- package/build/{QueryParser.cjs → queries/find/QueryParser.cjs} +68 -356
- package/build/queries/find/QueryParser.cjs.map +1 -0
- package/build/{QueryParser.collectionJoins.cjs → queries/find/QueryParser.collectionJoins.cjs} +8 -8
- package/build/queries/find/QueryParser.collectionJoins.cjs.map +1 -0
- package/build/{QueryParser.collectionJoins.d.cts → queries/find/QueryParser.collectionJoins.d.cts} +1 -1
- package/build/queries/find/QueryParser.collectionJoins.d.cts.map +1 -0
- package/build/{QueryParser.collectionJoins.d.mts → queries/find/QueryParser.collectionJoins.d.mts} +1 -1
- package/build/queries/find/QueryParser.collectionJoins.d.mts.map +1 -0
- package/build/{QueryParser.collectionJoins.js → queries/find/QueryParser.collectionJoins.js} +2 -2
- package/build/queries/find/QueryParser.collectionJoins.js.map +1 -0
- package/build/{QueryParser.d.cts → queries/find/QueryParser.d.cts} +5 -159
- package/build/queries/find/QueryParser.d.cts.map +1 -0
- package/build/{QueryParser.d.mts → queries/find/QueryParser.d.mts} +5 -159
- package/build/queries/find/QueryParser.d.mts.map +1 -0
- package/build/{QueryParser.js → queries/find/QueryParser.js} +15 -295
- package/build/queries/find/QueryParser.js.map +1 -0
- package/build/{QueryParser.pruning.cjs → queries/find/QueryParser.pruning.cjs} +6 -20
- package/build/queries/find/QueryParser.pruning.cjs.map +1 -0
- package/build/queries/find/QueryParser.pruning.d.cts +8 -0
- package/build/queries/find/QueryParser.pruning.d.cts.map +1 -0
- package/build/queries/find/QueryParser.pruning.d.mts +8 -0
- package/build/queries/find/QueryParser.pruning.d.mts.map +1 -0
- package/build/{QueryParser.pruning.js → queries/find/QueryParser.pruning.js} +4 -17
- package/build/queries/find/QueryParser.pruning.js.map +1 -0
- package/build/{QueryVisitor.cjs → queries/find/QueryVisitor.cjs} +2 -3
- package/build/queries/find/QueryVisitor.cjs.map +1 -0
- package/build/{QueryVisitor.d.cts → queries/find/QueryVisitor.d.cts} +3 -2
- package/build/queries/find/QueryVisitor.d.cts.map +1 -0
- package/build/{QueryVisitor.d.mts → queries/find/QueryVisitor.d.mts} +3 -2
- package/build/queries/find/QueryVisitor.d.mts.map +1 -0
- package/build/{QueryVisitor.js → queries/find/QueryVisitor.js} +2 -3
- package/build/queries/find/QueryVisitor.js.map +1 -0
- package/build/{drivers/buildRawQuery.cjs → queries/find/buildFindQuery.cjs} +14 -15
- package/build/queries/find/buildFindQuery.cjs.map +1 -0
- package/build/{drivers/buildRawQuery.d.cts → queries/find/buildFindQuery.d.cts} +3 -3
- package/build/queries/find/buildFindQuery.d.cts.map +1 -0
- package/build/{drivers/buildRawQuery.d.mts → queries/find/buildFindQuery.d.mts} +3 -3
- package/build/queries/find/buildFindQuery.d.mts.map +1 -0
- package/build/{drivers/buildRawQuery.js → queries/find/buildFindQuery.js} +5 -6
- package/build/queries/find/buildFindQuery.js.map +1 -0
- package/build/{scopes.cjs → queries/find/scopes.cjs} +2 -3
- package/build/queries/find/scopes.cjs.map +1 -0
- package/build/{scopes.d.cts → queries/find/scopes.d.cts} +6 -6
- package/build/queries/find/scopes.d.cts.map +1 -0
- package/build/{scopes.d.mts → queries/find/scopes.d.mts} +6 -6
- package/build/queries/find/scopes.d.mts.map +1 -0
- package/build/{scopes.js → queries/find/scopes.js} +2 -3
- package/build/queries/find/scopes.js.map +1 -0
- package/build/queries/parsedConditions.cjs +21 -0
- package/build/queries/parsedConditions.cjs.map +1 -0
- package/build/queries/parsedConditions.d.cts +127 -0
- package/build/queries/parsedConditions.d.cts.map +1 -0
- package/build/queries/parsedConditions.d.mts +127 -0
- package/build/queries/parsedConditions.d.mts.map +1 -0
- package/build/queries/parsedConditions.js +20 -0
- package/build/queries/parsedConditions.js.map +1 -0
- package/build/{drivers/buildUtils.cjs → queries/renderConditions.cjs} +7 -8
- package/build/queries/renderConditions.cjs.map +1 -0
- package/build/{drivers/buildUtils.d.mts → queries/renderConditions.d.cts} +5 -4
- package/build/queries/renderConditions.d.cts.map +1 -0
- package/build/{drivers/buildUtils.d.cts → queries/renderConditions.d.mts} +5 -4
- package/build/queries/renderConditions.d.mts.map +1 -0
- package/build/{drivers/buildUtils.js → queries/renderConditions.js} +4 -5
- package/build/queries/renderConditions.js.map +1 -0
- package/build/{skipCondition.cjs → queries/skipCondition.cjs} +1 -2
- package/build/queries/skipCondition.cjs.map +1 -0
- package/build/{skipCondition.d.cts → queries/skipCondition.d.cts} +2 -2
- package/build/{skipCondition.d.cts.map → queries/skipCondition.d.cts.map} +1 -1
- package/build/{skipCondition.d.mts → queries/skipCondition.d.mts} +2 -2
- package/build/{skipCondition.d.mts.map → queries/skipCondition.d.mts.map} +1 -1
- package/build/{skipCondition.js → queries/skipCondition.js} +1 -2
- package/build/queries/skipCondition.js.map +1 -0
- package/build/{AliasAssigner.cjs → queries/sql/AliasAssigner.cjs} +2 -3
- package/build/queries/sql/AliasAssigner.cjs.map +1 -0
- package/build/{AliasAssigner.d.cts → queries/sql/AliasAssigner.d.cts} +2 -2
- package/build/queries/sql/AliasAssigner.d.cts.map +1 -0
- package/build/{AliasAssigner.d.mts → queries/sql/AliasAssigner.d.mts} +2 -2
- package/build/queries/sql/AliasAssigner.d.mts.map +1 -0
- package/build/{AliasAssigner.js → queries/sql/AliasAssigner.js} +2 -3
- package/build/queries/sql/AliasAssigner.js.map +1 -0
- package/build/{Expr.cjs → queries/sql/Expr.cjs} +9 -9
- package/build/queries/sql/Expr.cjs.map +1 -0
- package/build/{Expr.d.cts → queries/sql/Expr.d.cts} +4 -4
- package/build/queries/sql/Expr.d.cts.map +1 -0
- package/build/{Expr.d.mts → queries/sql/Expr.d.mts} +4 -4
- package/build/queries/sql/Expr.d.mts.map +1 -0
- package/build/{Expr.js → queries/sql/Expr.js} +4 -4
- package/build/queries/sql/Expr.js.map +1 -0
- package/build/{Tables.cjs → queries/sql/Tables.cjs} +63 -67
- package/build/queries/sql/Tables.cjs.map +1 -0
- package/build/{Tables.d.cts → queries/sql/Tables.d.cts} +6 -7
- package/build/queries/sql/Tables.d.cts.map +1 -0
- package/build/{Tables.d.mts → queries/sql/Tables.d.mts} +6 -7
- package/build/queries/sql/Tables.d.mts.map +1 -0
- package/build/{Tables.js → queries/sql/Tables.js} +9 -13
- package/build/queries/sql/Tables.js.map +1 -0
- package/build/{execute.cjs → queries/sql/execute.cjs} +32 -37
- package/build/queries/sql/execute.cjs.map +1 -0
- package/build/{execute.d.cts → queries/sql/execute.d.cts} +6 -6
- package/build/queries/sql/execute.d.cts.map +1 -0
- package/build/{execute.d.mts → queries/sql/execute.d.mts} +6 -6
- package/build/queries/sql/execute.d.mts.map +1 -0
- package/build/{execute.js → queries/sql/execute.js} +5 -10
- package/build/queries/sql/execute.js.map +1 -0
- package/build/{expressions → queries/sql/expressions}/arrayAgg.cjs +12 -12
- package/build/queries/sql/expressions/arrayAgg.cjs.map +1 -0
- package/build/{expressions → queries/sql/expressions}/arrayAgg.d.cts +1 -1
- package/build/queries/sql/expressions/arrayAgg.d.cts.map +1 -0
- package/build/{expressions → queries/sql/expressions}/arrayAgg.d.mts +1 -1
- package/build/queries/sql/expressions/arrayAgg.d.mts.map +1 -0
- package/build/{expressions → queries/sql/expressions}/arrayAgg.js +1 -1
- package/build/queries/sql/expressions/arrayAgg.js.map +1 -0
- package/build/{expressions → queries/sql/expressions}/case.cjs +14 -14
- package/build/queries/sql/expressions/case.cjs.map +1 -0
- package/build/{expressions → queries/sql/expressions}/case.d.cts +1 -1
- package/build/queries/sql/expressions/case.d.cts.map +1 -0
- package/build/{expressions → queries/sql/expressions}/case.d.mts +1 -1
- package/build/queries/sql/expressions/case.d.mts.map +1 -0
- package/build/{expressions → queries/sql/expressions}/case.js +1 -1
- package/build/queries/sql/expressions/case.js.map +1 -0
- package/build/queries/sql/expressions/coalesce.cjs +25 -0
- package/build/queries/sql/expressions/coalesce.cjs.map +1 -0
- package/build/{expressions → queries/sql/expressions}/coalesce.d.cts +1 -1
- package/build/queries/sql/expressions/coalesce.d.cts.map +1 -0
- package/build/{expressions → queries/sql/expressions}/coalesce.d.mts +1 -1
- package/build/queries/sql/expressions/coalesce.d.mts.map +1 -0
- package/build/{expressions → queries/sql/expressions}/coalesce.js +1 -1
- package/build/queries/sql/expressions/coalesce.js.map +1 -0
- package/build/{expressions → queries/sql/expressions}/codecs.cjs +5 -5
- package/build/queries/sql/expressions/codecs.cjs.map +1 -0
- package/build/{expressions → queries/sql/expressions}/codecs.d.cts +1 -1
- package/build/queries/sql/expressions/codecs.d.cts.map +1 -0
- package/build/{expressions → queries/sql/expressions}/codecs.d.mts +1 -1
- package/build/queries/sql/expressions/codecs.d.mts.map +1 -0
- package/build/{expressions → queries/sql/expressions}/codecs.js +3 -3
- package/build/queries/sql/expressions/codecs.js.map +1 -0
- package/build/queries/sql/expressions/expression.cjs +102 -0
- package/build/queries/sql/expressions/expression.cjs.map +1 -0
- package/build/{expressions → queries/sql/expressions}/expression.d.cts +1 -1
- package/build/queries/sql/expressions/expression.d.cts.map +1 -0
- package/build/{expressions → queries/sql/expressions}/expression.d.mts +1 -1
- package/build/queries/sql/expressions/expression.d.mts.map +1 -0
- package/build/{expressions → queries/sql/expressions}/expression.js +2 -2
- package/build/queries/sql/expressions/expression.js.map +1 -0
- package/build/queries/sql/expressions/greatest.cjs +25 -0
- package/build/queries/sql/expressions/greatest.cjs.map +1 -0
- package/build/{expressions → queries/sql/expressions}/greatest.d.cts +1 -1
- package/build/queries/sql/expressions/greatest.d.cts.map +1 -0
- package/build/{expressions → queries/sql/expressions}/greatest.d.mts +1 -1
- package/build/queries/sql/expressions/greatest.d.mts.map +1 -0
- package/build/{expressions → queries/sql/expressions}/greatest.js +1 -1
- package/build/queries/sql/expressions/greatest.js.map +1 -0
- package/build/queries/sql/expressions/least.cjs +25 -0
- package/build/queries/sql/expressions/least.cjs.map +1 -0
- package/build/{expressions → queries/sql/expressions}/least.d.cts +1 -1
- package/build/queries/sql/expressions/least.d.cts.map +1 -0
- package/build/{expressions → queries/sql/expressions}/least.d.mts +1 -1
- package/build/queries/sql/expressions/least.d.mts.map +1 -0
- package/build/{expressions → queries/sql/expressions}/least.js +1 -1
- package/build/queries/sql/expressions/least.js.map +1 -0
- package/build/{expressions → queries/sql/expressions}/nullIf.cjs +6 -6
- package/build/queries/sql/expressions/nullIf.cjs.map +1 -0
- package/build/{expressions → queries/sql/expressions}/nullIf.d.cts +1 -1
- package/build/queries/sql/expressions/nullIf.d.cts.map +1 -0
- package/build/{expressions → queries/sql/expressions}/nullIf.d.mts +1 -1
- package/build/queries/sql/expressions/nullIf.d.mts.map +1 -0
- package/build/{expressions → queries/sql/expressions}/nullIf.js +1 -1
- package/build/queries/sql/expressions/nullIf.js.map +1 -0
- package/build/{expressions → queries/sql/expressions}/parseExpression.cjs +16 -16
- package/build/queries/sql/expressions/parseExpression.cjs.map +1 -0
- package/build/{expressions → queries/sql/expressions}/parseExpression.d.cts +1 -1
- package/build/queries/sql/expressions/parseExpression.d.cts.map +1 -0
- package/build/{expressions → queries/sql/expressions}/parseExpression.d.mts +1 -1
- package/build/queries/sql/expressions/parseExpression.d.mts.map +1 -0
- package/build/{expressions → queries/sql/expressions}/parseExpression.js +2 -2
- package/build/queries/sql/expressions/parseExpression.js.map +1 -0
- package/build/{expressions → queries/sql/expressions}/types.d.cts +1 -1
- package/build/queries/sql/expressions/types.d.cts.map +1 -0
- package/build/{expressions → queries/sql/expressions}/types.d.mts +1 -1
- package/build/queries/sql/expressions/types.d.mts.map +1 -0
- package/build/{keywords.cjs → queries/sql/keywords.cjs} +1 -1
- package/build/queries/sql/keywords.cjs.map +1 -0
- package/build/{keywords.d.cts → queries/sql/keywords.d.cts} +1 -1
- package/build/queries/sql/keywords.d.cts.map +1 -0
- package/build/{keywords.d.mts → queries/sql/keywords.d.mts} +1 -1
- package/build/queries/sql/keywords.d.mts.map +1 -0
- package/build/{keywords.js → queries/sql/keywords.js} +1 -1
- package/build/queries/sql/keywords.js.map +1 -0
- package/build/{query.cjs → queries/sql/query.cjs} +112 -83
- package/build/queries/sql/query.cjs.map +1 -0
- package/build/{query.d.cts → queries/sql/query.d.cts} +18 -8
- package/build/queries/sql/query.d.cts.map +1 -0
- package/build/{query.d.mts → queries/sql/query.d.mts} +18 -8
- package/build/queries/sql/query.d.mts.map +1 -0
- package/build/{query.js → queries/sql/query.js} +41 -13
- package/build/queries/sql/query.js.map +1 -0
- package/build/queries/valueFilters.cjs +248 -0
- package/build/queries/valueFilters.cjs.map +1 -0
- package/build/queries/valueFilters.d.cts +28 -0
- package/build/queries/valueFilters.d.cts.map +1 -0
- package/build/queries/valueFilters.d.mts +28 -0
- package/build/queries/valueFilters.d.mts.map +1 -0
- package/build/queries/valueFilters.js +243 -0
- package/build/queries/valueFilters.js.map +1 -0
- package/build/reactiveHints.cjs +5 -5
- package/build/reactiveHints.js +5 -5
- package/build/relations/AbstractRelationImpl.cjs +0 -5
- package/build/relations/AbstractRelationImpl.cjs.map +1 -1
- package/build/relations/AbstractRelationImpl.d.cts +1 -2
- package/build/relations/AbstractRelationImpl.d.cts.map +1 -1
- package/build/relations/AbstractRelationImpl.d.mts +1 -2
- package/build/relations/AbstractRelationImpl.d.mts.map +1 -1
- package/build/relations/AbstractRelationImpl.js +1 -5
- package/build/relations/AbstractRelationImpl.js.map +1 -1
- package/build/relations/AsyncProperty.cjs +1 -1
- package/build/relations/AsyncProperty.js +1 -1
- package/build/relations/AsyncReactiveField.cjs +3 -3
- package/build/relations/AsyncReactiveField.js +3 -3
- package/build/relations/Collection.cjs +1 -1
- package/build/relations/Collection.js +1 -1
- package/build/relations/CustomCollection.cjs +1 -1
- package/build/relations/CustomCollection.js +1 -1
- package/build/relations/CustomReference.cjs +3 -3
- package/build/relations/CustomReference.js +3 -3
- package/build/relations/EnumCollection.cjs +2 -2
- package/build/relations/EnumCollection.js +2 -2
- package/build/relations/LazyField.cjs +6 -7
- package/build/relations/LazyField.cjs.map +1 -1
- package/build/relations/LazyField.js +5 -6
- package/build/relations/LazyField.js.map +1 -1
- package/build/relations/ManyToManyCollection.cjs +4 -3
- package/build/relations/ManyToManyCollection.cjs.map +1 -1
- package/build/relations/ManyToManyCollection.d.cts.map +1 -1
- package/build/relations/ManyToManyCollection.d.mts.map +1 -1
- package/build/relations/ManyToManyCollection.js +4 -3
- package/build/relations/ManyToManyCollection.js.map +1 -1
- package/build/relations/ManyToManyLargeCollection.cjs +2 -2
- package/build/relations/ManyToManyLargeCollection.js +2 -2
- package/build/relations/ManyToOneReference.cjs +7 -6
- package/build/relations/ManyToOneReference.cjs.map +1 -1
- package/build/relations/ManyToOneReference.d.cts.map +1 -1
- package/build/relations/ManyToOneReference.d.mts.map +1 -1
- package/build/relations/ManyToOneReference.js +7 -6
- package/build/relations/ManyToOneReference.js.map +1 -1
- package/build/relations/OneToManyCollection.cjs +6 -5
- package/build/relations/OneToManyCollection.cjs.map +1 -1
- package/build/relations/OneToManyCollection.d.cts.map +1 -1
- package/build/relations/OneToManyCollection.d.mts.map +1 -1
- package/build/relations/OneToManyCollection.js +4 -3
- package/build/relations/OneToManyCollection.js.map +1 -1
- package/build/relations/OneToManyLargeCollection.cjs +3 -3
- package/build/relations/OneToManyLargeCollection.js +3 -3
- package/build/relations/OneToOneReference.cjs +6 -5
- package/build/relations/OneToOneReference.cjs.map +1 -1
- package/build/relations/OneToOneReference.d.cts.map +1 -1
- package/build/relations/OneToOneReference.d.mts.map +1 -1
- package/build/relations/OneToOneReference.js +6 -5
- package/build/relations/OneToOneReference.js.map +1 -1
- package/build/relations/PolymorphicReference.cjs +7 -6
- package/build/relations/PolymorphicReference.cjs.map +1 -1
- package/build/relations/PolymorphicReference.d.cts.map +1 -1
- package/build/relations/PolymorphicReference.d.mts.map +1 -1
- package/build/relations/PolymorphicReference.js +7 -6
- package/build/relations/PolymorphicReference.js.map +1 -1
- package/build/relations/ReactiveField.cjs +3 -3
- package/build/relations/ReactiveField.js +3 -3
- package/build/relations/ReactiveGetter.cjs +1 -1
- package/build/relations/ReactiveGetter.js +1 -1
- package/build/relations/ReactiveManyToMany.cjs +5 -4
- package/build/relations/ReactiveManyToMany.cjs.map +1 -1
- package/build/relations/ReactiveManyToMany.d.cts.map +1 -1
- package/build/relations/ReactiveManyToMany.d.mts.map +1 -1
- package/build/relations/ReactiveManyToMany.js +5 -4
- package/build/relations/ReactiveManyToMany.js.map +1 -1
- package/build/relations/ReactiveManyToManyOtherSide.cjs +3 -3
- package/build/relations/ReactiveManyToManyOtherSide.js +3 -3
- package/build/relations/ReactiveReference.cjs +8 -7
- package/build/relations/ReactiveReference.cjs.map +1 -1
- package/build/relations/ReactiveReference.d.cts.map +1 -1
- package/build/relations/ReactiveReference.d.mts.map +1 -1
- package/build/relations/ReactiveReference.js +8 -7
- package/build/relations/ReactiveReference.js.map +1 -1
- package/build/relations/RecursiveCollection.cjs +3 -3
- package/build/relations/RecursiveCollection.js +3 -3
- package/build/relations/Reference.cjs +1 -1
- package/build/relations/Reference.js +1 -1
- package/build/relations/hasAsyncMethod.cjs +1 -1
- package/build/relations/hasAsyncMethod.js +1 -1
- package/build/relations/hasManyDerived.cjs +1 -1
- package/build/relations/hasManyDerived.js +1 -1
- package/build/relations/hasOneDerived.cjs +2 -2
- package/build/relations/hasOneDerived.js +2 -2
- package/build/relations/hasProperty.cjs +2 -2
- package/build/relations/hasProperty.js +2 -2
- package/build/relations/index.cjs +13 -13
- package/build/relations/index.js +13 -13
- package/build/relations/isCascadeDelete.cjs +11 -0
- package/build/relations/isCascadeDelete.cjs.map +1 -0
- package/build/relations/isCascadeDelete.d.cts +7 -0
- package/build/relations/isCascadeDelete.d.cts.map +1 -0
- package/build/relations/isCascadeDelete.d.mts +7 -0
- package/build/relations/isCascadeDelete.d.mts.map +1 -0
- package/build/relations/isCascadeDelete.js +10 -0
- package/build/relations/isCascadeDelete.js.map +1 -0
- package/build/resurrection.cjs +1 -1
- package/build/resurrection.js +1 -1
- package/build/rules.cjs +4 -4
- package/build/rules.js +4 -4
- package/build/serde.cjs +1 -1
- package/build/serde.js +1 -1
- package/build/unnest.cjs +0 -1
- package/build/unnest.cjs.map +1 -1
- package/build/unnest.d.cts +1 -1
- package/build/unnest.d.mts +1 -1
- package/build/unnest.js +0 -1
- package/build/unnest.js.map +1 -1
- package/build/upsert.cjs +3 -3
- package/build/upsert.js +3 -3
- package/build/utils.cjs +1 -2
- 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 +1 -2
- package/build/utils.js.map +1 -1
- package/build/withLoaded.cjs +3 -3
- package/build/withLoaded.js +3 -3
- package/package.json +2 -2
- package/build/AliasAssigner.cjs.map +0 -1
- package/build/AliasAssigner.d.cts.map +0 -1
- package/build/AliasAssigner.d.mts.map +0 -1
- package/build/AliasAssigner.js.map +0 -1
- package/build/Aliases.cjs.map +0 -1
- package/build/Aliases.d.cts.map +0 -1
- package/build/Aliases.d.mts.map +0 -1
- package/build/Aliases.js.map +0 -1
- package/build/ConditionBuilder.cjs.map +0 -1
- package/build/ConditionBuilder.d.cts.map +0 -1
- package/build/ConditionBuilder.d.mts.map +0 -1
- package/build/ConditionBuilder.js.map +0 -1
- package/build/DeferredAlias.cjs.map +0 -1
- package/build/DeferredAlias.d.cts.map +0 -1
- package/build/DeferredAlias.d.mts.map +0 -1
- package/build/DeferredAlias.js.map +0 -1
- package/build/EntityFilter.cjs.map +0 -1
- package/build/EntityFilter.d.cts.map +0 -1
- package/build/EntityFilter.d.mts.map +0 -1
- package/build/EntityFilter.js.map +0 -1
- package/build/EntityGraphQLFilter.cjs.map +0 -1
- package/build/EntityGraphQLFilter.d.cts.map +0 -1
- package/build/EntityGraphQLFilter.d.mts.map +0 -1
- package/build/EntityGraphQLFilter.js.map +0 -1
- package/build/Expr.cjs.map +0 -1
- package/build/Expr.d.cts.map +0 -1
- package/build/Expr.d.mts.map +0 -1
- package/build/Expr.js.map +0 -1
- package/build/QueryParser.cjs.map +0 -1
- package/build/QueryParser.collectionJoins.cjs.map +0 -1
- package/build/QueryParser.collectionJoins.d.cts.map +0 -1
- package/build/QueryParser.collectionJoins.d.mts.map +0 -1
- package/build/QueryParser.collectionJoins.js.map +0 -1
- package/build/QueryParser.d.cts.map +0 -1
- package/build/QueryParser.d.mts.map +0 -1
- package/build/QueryParser.js.map +0 -1
- package/build/QueryParser.pruning.cjs.map +0 -1
- package/build/QueryParser.pruning.d.cts +0 -10
- package/build/QueryParser.pruning.d.cts.map +0 -1
- package/build/QueryParser.pruning.d.mts +0 -10
- package/build/QueryParser.pruning.d.mts.map +0 -1
- package/build/QueryParser.pruning.js.map +0 -1
- package/build/QueryVisitor.cjs.map +0 -1
- package/build/QueryVisitor.d.cts.map +0 -1
- package/build/QueryVisitor.d.mts.map +0 -1
- package/build/QueryVisitor.js.map +0 -1
- package/build/Tables.cjs.map +0 -1
- package/build/Tables.d.cts.map +0 -1
- package/build/Tables.d.mts.map +0 -1
- package/build/Tables.js.map +0 -1
- package/build/conditions.cjs.map +0 -1
- package/build/conditions.d.cts.map +0 -1
- package/build/conditions.d.mts.map +0 -1
- package/build/conditions.js.map +0 -1
- package/build/drivers/buildRawQuery.cjs.map +0 -1
- package/build/drivers/buildRawQuery.d.cts.map +0 -1
- package/build/drivers/buildRawQuery.d.mts.map +0 -1
- package/build/drivers/buildRawQuery.js.map +0 -1
- package/build/drivers/buildUtils.cjs.map +0 -1
- package/build/drivers/buildUtils.d.cts.map +0 -1
- package/build/drivers/buildUtils.d.mts.map +0 -1
- package/build/drivers/buildUtils.js.map +0 -1
- package/build/execute.cjs.map +0 -1
- package/build/execute.d.cts.map +0 -1
- package/build/execute.d.mts.map +0 -1
- package/build/execute.js.map +0 -1
- package/build/expressions/arrayAgg.cjs.map +0 -1
- package/build/expressions/arrayAgg.d.cts.map +0 -1
- package/build/expressions/arrayAgg.d.mts.map +0 -1
- package/build/expressions/arrayAgg.js.map +0 -1
- package/build/expressions/case.cjs.map +0 -1
- package/build/expressions/case.d.cts.map +0 -1
- package/build/expressions/case.d.mts.map +0 -1
- package/build/expressions/case.js.map +0 -1
- package/build/expressions/coalesce.cjs +0 -25
- package/build/expressions/coalesce.cjs.map +0 -1
- package/build/expressions/coalesce.d.cts.map +0 -1
- package/build/expressions/coalesce.d.mts.map +0 -1
- package/build/expressions/coalesce.js.map +0 -1
- package/build/expressions/codecs.cjs.map +0 -1
- package/build/expressions/codecs.d.cts.map +0 -1
- package/build/expressions/codecs.d.mts.map +0 -1
- package/build/expressions/codecs.js.map +0 -1
- package/build/expressions/expression.cjs +0 -102
- package/build/expressions/expression.cjs.map +0 -1
- package/build/expressions/expression.d.cts.map +0 -1
- package/build/expressions/expression.d.mts.map +0 -1
- package/build/expressions/expression.js.map +0 -1
- package/build/expressions/greatest.cjs +0 -25
- package/build/expressions/greatest.cjs.map +0 -1
- package/build/expressions/greatest.d.cts.map +0 -1
- package/build/expressions/greatest.d.mts.map +0 -1
- package/build/expressions/greatest.js.map +0 -1
- package/build/expressions/least.cjs +0 -25
- package/build/expressions/least.cjs.map +0 -1
- package/build/expressions/least.d.cts.map +0 -1
- package/build/expressions/least.d.mts.map +0 -1
- package/build/expressions/least.js.map +0 -1
- package/build/expressions/nullIf.cjs.map +0 -1
- package/build/expressions/nullIf.d.cts.map +0 -1
- package/build/expressions/nullIf.d.mts.map +0 -1
- package/build/expressions/nullIf.js.map +0 -1
- package/build/expressions/parseExpression.cjs.map +0 -1
- package/build/expressions/parseExpression.d.cts.map +0 -1
- package/build/expressions/parseExpression.d.mts.map +0 -1
- package/build/expressions/parseExpression.js.map +0 -1
- package/build/expressions/types.d.cts.map +0 -1
- package/build/expressions/types.d.mts.map +0 -1
- package/build/keywords.cjs.map +0 -1
- package/build/keywords.d.cts.map +0 -1
- package/build/keywords.d.mts.map +0 -1
- package/build/keywords.js.map +0 -1
- package/build/query.cjs.map +0 -1
- package/build/query.d.cts.map +0 -1
- package/build/query.d.mts.map +0 -1
- package/build/query.js.map +0 -1
- package/build/scopes.cjs.map +0 -1
- package/build/scopes.d.cts.map +0 -1
- package/build/scopes.d.mts.map +0 -1
- package/build/scopes.js.map +0 -1
- package/build/skipCondition.cjs.map +0 -1
- package/build/skipCondition.js.map +0 -1
- /package/build/{expressions → queries/sql/expressions}/types.cjs +0 -0
- /package/build/{expressions → queries/sql/expressions}/types.js +0 -0
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import "../typeMap.js";
|
|
2
1
|
import { isLoadedReference } from "../relations/Reference.js";
|
|
2
|
+
import { cleanStringValue, fail } from "../utils.js";
|
|
3
3
|
import "../relations/index.js";
|
|
4
4
|
import { getMetadata } from "../EntityMetadata.js";
|
|
5
|
-
import { cleanStringValue, fail } from "../utils.js";
|
|
6
5
|
import { whereFilterHash } from "./findDataLoader.js";
|
|
7
6
|
import { resurrectIfSoftDeleted } from "../resurrection.js";
|
|
8
7
|
import { TooManyError, sameEntity } from "../EntityManager.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"findOrCreateDataLoader.js","names":[],"sources":["../../src/dataloaders/findOrCreateDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\n\nimport { type Entity, isEntity } from \"../Entity.ts\";\nimport { type EntityConstructor, type EntityManager, TooManyError, sameEntity } from \"../EntityManager.ts\";\nimport { type EntityMetadata, getMetadata } from \"../EntityMetadata.ts\";\nimport { type ManyToOneReference, type PolymorphicReference, isLoadedReference } from \"../relations/index.ts\";\nimport { resurrectIfSoftDeleted } from \"../resurrection.ts\";\nimport { type OptsOf } from \"../typeMap.ts\";\nimport { cleanStringValue, fail } from \"../utils.ts\";\nimport { whereFilterHash } from \"./findDataLoader.ts\";\n\ninterface FindOrCreateKey<T extends Entity> {\n ifNew: OptsOf<T>;\n upsert: Partial<OptsOf<T>> | undefined;\n}\n\nexport function findOrCreateDataLoader<T extends Entity>(\n em: EntityManager,\n type: EntityConstructor<T>,\n where: Partial<OptsOf<T>>,\n softDeletes: \"include\" | \"exclude\",\n): DataLoader<FindOrCreateKey<T>, T> {\n const meta = getMetadata(type);\n\n // Do some extra logic to make unclean strings/citext not create duplicate entities\n const hasAnyStrings = Object.values(meta.allFields).some((f) => f.kind === \"primitive\" && f.type === \"string\");\n const hasAnyCitext = Object.values(meta.allFields).some((f) => f.kind === \"primitive\" && f.citext);\n\n // The `where` here will be later used to `em.create`, so we only clean (not lower for citext)\n where = hasAnyStrings ? maybeClean(meta, where) : where;\n // Use `whereFilterHash` to batch the same `findOrCreate` `where: { firstName: \"a1\" }` calls together to avoid duplicates\n const whereValue = whereFilterHash(\n // Only maybeLower for the purposes of batching, not the later em.create\n hasAnyCitext ? maybeLower(meta, where) : (where as any),\n );\n const batchKey = `${type.name}-${whereValue}-${softDeletes}`;\n\n const invalidKeys = Object.keys(where).filter((key) => {\n const field = meta.allFields[key] ?? fail(`Invalid field ${key}`);\n const supported =\n field.kind === \"primitive\" || field.kind === \"enum\" || field.kind === \"m2o\" || field.kind === \"poly\";\n return !supported;\n });\n if (invalidKeys.length > 0) {\n throw new Error(\n \"findOrCreate only supports primitive, enum, m2o, or poly fields in the where clause. Invalid keys: \" +\n invalidKeys.join(\", \"),\n );\n }\n\n return em.getLoader<FindOrCreateKey<T>, T>(\n \"find-or-create\",\n batchKey,\n async (keys) => {\n // Because our `batchKey` is based only on the `where` clause, if the user called\n // `findOrCreate({ firstName: a1 })` multiple times, but with different ifNew/upsert\n // conditions (or different cased strings and is using a citext column), we'll end\n // up with multiple keys...\n //\n // This is fundamentally asking to create the same entity, but with different ifNew/upsert\n // conditions, which we could fail on, but for now just take the first tuple of\n // {where/ifNew/upsert} and assume it wins\n const [{ ifNew, upsert }] = keys;\n\n // Before we find/create an entity, see if we have a maybe-new one in the EM already.\n // This will also use any WIP changes we've made to the found entity, which ideally is\n // something `em.find` would do as well, but its queries are much more complex...\n const inMemory = em.filterEntities(type, where);\n if (inMemory.length > 1) {\n throw new TooManyError(`Found more than one existing ${type.name} with ${whereAsString(where)}`);\n } else if (inMemory.length === 1) {\n const entity = inMemory[0] as T;\n resurrectIfSoftDeleted(entity);\n if (upsert) {\n entity.set(upsert);\n }\n return keys.map(() => entity);\n }\n\n // If there is a param like `{ publisher: newPublisherEntity }`, then we know that\n // an entity matching this condition can't be in the db anyway, so skip the em.find\n const hasNewEntityParam = Object.values(where).some((v) => isEntity(v) && v.isNewEntity);\n if (hasNewEntityParam) {\n const entity = em.create(type, { ...where, ...(ifNew as object) } as OptsOf<T>);\n if (upsert) {\n entity.set(upsert);\n }\n return keys.map(() => entity);\n }\n\n // If we didn't find it in the EM, do the db query/em.create\n const entities = await em.find(\n type,\n // Convert `publisher: undefined` --> `publisher: null`, and we need to make a copy anyway\n Object.fromEntries(Object.entries(where).map(([k, v]) => [k, v === undefined ? null : v])) as any,\n // Always include soft-deleted rows so findOrCreate can resurrect them instead of creating duplicates.\n { softDeletes: \"include\" },\n );\n let entity: T;\n if (entities.length > 1) {\n throw new TooManyError(`Found more than one existing ${type.name} with ${whereAsString(where)}`);\n } else if (entities.length === 1) {\n entity = entities[0];\n resurrectIfSoftDeleted(entity);\n } else {\n entity = em.create(type, { ...where, ...(ifNew as object) } as OptsOf<T>);\n }\n if (upsert) {\n entity.set(upsert);\n }\n return keys.map(() => entity);\n },\n // Our filter tuple is a complex object, so use a stable cache key to ensure caching works.\n { cacheKeyFn: whereFilterHash as any },\n );\n}\n\n/** A simple in-memory match of `entity` against a mini/flat \"WHERE clause\" of `opts`. */\nexport function entityMatches<T extends Entity>(entity: T, opts: Partial<OptsOf<T>>): boolean {\n const meta = getMetadata(entity);\n return Object.entries(opts).every(([fieldName, value]) => {\n const field = meta.allFields[fieldName] ?? fail(`Invalid field ${fieldName}`);\n const fn = fieldName as keyof T & keyof OptsOf<T>;\n switch (field.kind) {\n case \"primaryKey\":\n case \"enum\":\n return entity[fn] === value;\n case \"primitive\":\n if (field.citext) {\n return compareCaseInsensitive(entity[fn], value);\n } else {\n return entity[fn] === value;\n }\n case \"m2o\":\n case \"poly\":\n const relation = entity[fn] as ManyToOneReference<T, any, any> | PolymorphicReference<T, any, any>;\n if (isLoadedReference(relation)) {\n // Prefer using `.get` because it will handle new/id-less entities\n return sameEntity(relation.get, value as any);\n } else if (relation.isSet) {\n // Otherwise use ids\n return sameEntity(relation.id as any, value as any);\n } else {\n // Relation is not set, match if value is null-ish (null or undefined)\n return value === undefined || value === null;\n }\n default:\n throw new Error(`Unsupported field ${fieldName}`);\n }\n });\n}\n\nfunction whereAsString(where: object): string {\n return Object.entries(where)\n .map(([key, value]) => `${key}=${value}`)\n .join(\", \");\n}\n\nfunction compareCaseInsensitive(str1: any, str2: any): boolean {\n return (\n str1 !== undefined &&\n str2 !== undefined &&\n typeof str1 === \"string\" &&\n typeof str2 === \"string\" &&\n str1.toLowerCase() === str2.toLowerCase()\n );\n}\n\n/** Returns a copy of `opts` with any `citext` values turned to lower case. */\nfunction maybeLower<T extends object | undefined>(meta: EntityMetadata, opts: T): T {\n if (!opts) return opts;\n let result: T | undefined = undefined;\n for (const k in opts) {\n const v = (opts as any)[k];\n const field = meta.allFields[k];\n const isString = field && field.kind === \"primitive\" && field.type === \"string\";\n if (isString && field.citext) {\n const lowered = v?.toLowerCase();\n if (lowered !== v) {\n result ??= { ...opts };\n (result as any)[k] = lowered as any;\n }\n }\n }\n return result ?? opts;\n}\n\n/** Returns a copy of `opts` with any string values trimmed/coalesced. */\nfunction maybeClean<T extends object | undefined>(meta: EntityMetadata, opts: T): T {\n if (!opts) return opts;\n let result: T | undefined = undefined;\n for (const k in opts) {\n const v = (opts as any)[k];\n const field = meta.allFields[k];\n const isString = field && field.kind === \"primitive\" && field.type === \"string\";\n if (isString && field.sanitize !== false) {\n const cleaned = cleanStringValue(v);\n if (cleaned !== v) {\n result ??= { ...opts }; // Only create copy on first change\n (result as any)[k] = cleaned;\n }\n }\n }\n return result ?? opts;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"findOrCreateDataLoader.js","names":[],"sources":["../../src/dataloaders/findOrCreateDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\n\nimport { type Entity, isEntity } from \"../Entity.ts\";\nimport { type EntityConstructor, type EntityManager, TooManyError, sameEntity } from \"../EntityManager.ts\";\nimport { type EntityMetadata, getMetadata } from \"../EntityMetadata.ts\";\nimport { type ManyToOneReference, type PolymorphicReference, isLoadedReference } from \"../relations/index.ts\";\nimport { resurrectIfSoftDeleted } from \"../resurrection.ts\";\nimport type { OptsOf } from \"../typeMap.ts\";\nimport { cleanStringValue, fail } from \"../utils.ts\";\nimport { whereFilterHash } from \"./findDataLoader.ts\";\n\ninterface FindOrCreateKey<T extends Entity> {\n ifNew: OptsOf<T>;\n upsert: Partial<OptsOf<T>> | undefined;\n}\n\nexport function findOrCreateDataLoader<T extends Entity>(\n em: EntityManager,\n type: EntityConstructor<T>,\n where: Partial<OptsOf<T>>,\n softDeletes: \"include\" | \"exclude\",\n): DataLoader<FindOrCreateKey<T>, T> {\n const meta = getMetadata(type);\n\n // Do some extra logic to make unclean strings/citext not create duplicate entities\n const hasAnyStrings = Object.values(meta.allFields).some((f) => f.kind === \"primitive\" && f.type === \"string\");\n const hasAnyCitext = Object.values(meta.allFields).some((f) => f.kind === \"primitive\" && f.citext);\n\n // The `where` here will be later used to `em.create`, so we only clean (not lower for citext)\n where = hasAnyStrings ? maybeClean(meta, where) : where;\n // Use `whereFilterHash` to batch the same `findOrCreate` `where: { firstName: \"a1\" }` calls together to avoid duplicates\n const whereValue = whereFilterHash(\n // Only maybeLower for the purposes of batching, not the later em.create\n hasAnyCitext ? maybeLower(meta, where) : (where as any),\n );\n const batchKey = `${type.name}-${whereValue}-${softDeletes}`;\n\n const invalidKeys = Object.keys(where).filter((key) => {\n const field = meta.allFields[key] ?? fail(`Invalid field ${key}`);\n const supported =\n field.kind === \"primitive\" || field.kind === \"enum\" || field.kind === \"m2o\" || field.kind === \"poly\";\n return !supported;\n });\n if (invalidKeys.length > 0) {\n throw new Error(\n \"findOrCreate only supports primitive, enum, m2o, or poly fields in the where clause. Invalid keys: \" +\n invalidKeys.join(\", \"),\n );\n }\n\n return em.getLoader<FindOrCreateKey<T>, T>(\n \"find-or-create\",\n batchKey,\n async (keys) => {\n // Because our `batchKey` is based only on the `where` clause, if the user called\n // `findOrCreate({ firstName: a1 })` multiple times, but with different ifNew/upsert\n // conditions (or different cased strings and is using a citext column), we'll end\n // up with multiple keys...\n //\n // This is fundamentally asking to create the same entity, but with different ifNew/upsert\n // conditions, which we could fail on, but for now just take the first tuple of\n // {where/ifNew/upsert} and assume it wins\n const [{ ifNew, upsert }] = keys;\n\n // Before we find/create an entity, see if we have a maybe-new one in the EM already.\n // This will also use any WIP changes we've made to the found entity, which ideally is\n // something `em.find` would do as well, but its queries are much more complex...\n const inMemory = em.filterEntities(type, where);\n if (inMemory.length > 1) {\n throw new TooManyError(`Found more than one existing ${type.name} with ${whereAsString(where)}`);\n } else if (inMemory.length === 1) {\n const entity = inMemory[0] as T;\n resurrectIfSoftDeleted(entity);\n if (upsert) {\n entity.set(upsert);\n }\n return keys.map(() => entity);\n }\n\n // If there is a param like `{ publisher: newPublisherEntity }`, then we know that\n // an entity matching this condition can't be in the db anyway, so skip the em.find\n const hasNewEntityParam = Object.values(where).some((v) => isEntity(v) && v.isNewEntity);\n if (hasNewEntityParam) {\n const entity = em.create(type, { ...where, ...(ifNew as object) } as OptsOf<T>);\n if (upsert) {\n entity.set(upsert);\n }\n return keys.map(() => entity);\n }\n\n // If we didn't find it in the EM, do the db query/em.create\n const entities = await em.find(\n type,\n // Convert `publisher: undefined` --> `publisher: null`, and we need to make a copy anyway\n Object.fromEntries(Object.entries(where).map(([k, v]) => [k, v === undefined ? null : v])) as any,\n // Always include soft-deleted rows so findOrCreate can resurrect them instead of creating duplicates.\n { softDeletes: \"include\" },\n );\n let entity: T;\n if (entities.length > 1) {\n throw new TooManyError(`Found more than one existing ${type.name} with ${whereAsString(where)}`);\n } else if (entities.length === 1) {\n entity = entities[0];\n resurrectIfSoftDeleted(entity);\n } else {\n entity = em.create(type, { ...where, ...(ifNew as object) } as OptsOf<T>);\n }\n if (upsert) {\n entity.set(upsert);\n }\n return keys.map(() => entity);\n },\n // Our filter tuple is a complex object, so use a stable cache key to ensure caching works.\n { cacheKeyFn: whereFilterHash as any },\n );\n}\n\n/** A simple in-memory match of `entity` against a mini/flat \"WHERE clause\" of `opts`. */\nexport function entityMatches<T extends Entity>(entity: T, opts: Partial<OptsOf<T>>): boolean {\n const meta = getMetadata(entity);\n return Object.entries(opts).every(([fieldName, value]) => {\n const field = meta.allFields[fieldName] ?? fail(`Invalid field ${fieldName}`);\n const fn = fieldName as keyof T & keyof OptsOf<T>;\n switch (field.kind) {\n case \"primaryKey\":\n case \"enum\":\n return entity[fn] === value;\n case \"primitive\":\n if (field.citext) {\n return compareCaseInsensitive(entity[fn], value);\n } else {\n return entity[fn] === value;\n }\n case \"m2o\":\n case \"poly\":\n const relation = entity[fn] as ManyToOneReference<T, any, any> | PolymorphicReference<T, any, any>;\n if (isLoadedReference(relation)) {\n // Prefer using `.get` because it will handle new/id-less entities\n return sameEntity(relation.get, value as any);\n } else if (relation.isSet) {\n // Otherwise use ids\n return sameEntity(relation.id as any, value as any);\n } else {\n // Relation is not set, match if value is null-ish (null or undefined)\n return value === undefined || value === null;\n }\n default:\n throw new Error(`Unsupported field ${fieldName}`);\n }\n });\n}\n\nfunction whereAsString(where: object): string {\n return Object.entries(where)\n .map(([key, value]) => `${key}=${value}`)\n .join(\", \");\n}\n\nfunction compareCaseInsensitive(str1: any, str2: any): boolean {\n return (\n str1 !== undefined &&\n str2 !== undefined &&\n typeof str1 === \"string\" &&\n typeof str2 === \"string\" &&\n str1.toLowerCase() === str2.toLowerCase()\n );\n}\n\n/** Returns a copy of `opts` with any `citext` values turned to lower case. */\nfunction maybeLower<T extends object | undefined>(meta: EntityMetadata, opts: T): T {\n if (!opts) return opts;\n let result: T | undefined = undefined;\n for (const k in opts) {\n const v = (opts as any)[k];\n const field = meta.allFields[k];\n const isString = field && field.kind === \"primitive\" && field.type === \"string\";\n if (isString && field.citext) {\n const lowered = v?.toLowerCase();\n if (lowered !== v) {\n result ??= { ...opts };\n (result as any)[k] = lowered as any;\n }\n }\n }\n return result ?? opts;\n}\n\n/** Returns a copy of `opts` with any string values trimmed/coalesced. */\nfunction maybeClean<T extends object | undefined>(meta: EntityMetadata, opts: T): T {\n if (!opts) return opts;\n let result: T | undefined = undefined;\n for (const k in opts) {\n const v = (opts as any)[k];\n const field = meta.allFields[k];\n const isString = field && field.kind === \"primitive\" && field.type === \"string\";\n if (isString && field.sanitize !== false) {\n const cleaned = cleanStringValue(v);\n if (cleaned !== v) {\n result ??= { ...opts }; // Only create copy on first change\n (result as any)[k] = cleaned;\n }\n }\n }\n return result ?? opts;\n}\n"],"mappings":"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"}
|
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
require("../
|
|
3
|
-
const require_EntityMetadata = require("../EntityMetadata.cjs");
|
|
2
|
+
const require_queries_find_QueryParser = require("../queries/find/QueryParser.cjs");
|
|
4
3
|
const require_normalizeHints = require("../normalizeHints.cjs");
|
|
5
|
-
require("../
|
|
4
|
+
const require_EntityMetadata = require("../EntityMetadata.cjs");
|
|
6
5
|
const require_HintTree = require("../HintTree.cjs");
|
|
7
6
|
const require_unnest = require("../unnest.cjs");
|
|
8
7
|
const require_dataloaders_findDataLoader = require("./findDataLoader.cjs");
|
|
9
8
|
const require_EntityManager = require("../EntityManager.cjs");
|
|
10
|
-
require("../Entity.cjs");
|
|
11
|
-
const require_QueryParser = require("../QueryParser.cjs");
|
|
12
9
|
//#region src/dataloaders/findPaginatedDataLoader.ts
|
|
13
10
|
/** Returns a dataloader that batches paginated finds by applying pagination inside each lateral subquery. */
|
|
14
11
|
function findPaginatedDataLoader(em, type, filter, hint) {
|
|
15
12
|
const { where, limit, offset, ...opts } = filter;
|
|
16
13
|
const meta = require_EntityMetadata.getMetadata(type);
|
|
17
|
-
const query =
|
|
14
|
+
const query = require_queries_find_QueryParser.parseFindQuery(meta, where, opts);
|
|
18
15
|
const { findSettings } = em["prepareFind"](meta, require_dataloaders_findDataLoader.findOperation, query, {
|
|
19
16
|
...opts,
|
|
20
17
|
limit,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"findPaginatedDataLoader.cjs","names":["getMetadata","parseFindQuery","findOperation","getBatchKeyFromGenericStructure","hintKey","getEmInternalApi","buildHintTree","filterDeletedEntities","collectAndReplaceArgs","createColumnValuesFromPrepared","buildUnnestCte","queryFilterHash"],"sources":["../../src/dataloaders/findPaginatedDataLoader.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"findPaginatedDataLoader.cjs","names":["getMetadata","parseFindQuery","findOperation","getBatchKeyFromGenericStructure","hintKey","getEmInternalApi","buildHintTree","filterDeletedEntities","collectAndReplaceArgs","createColumnValuesFromPrepared","buildUnnestCte","queryFilterHash"],"sources":["../../src/dataloaders/findPaginatedDataLoader.ts"],"sourcesContent":["import type { Entity } from \"../Entity.ts\";\nimport { type EntityManager, type MaybeAbstractEntityConstructor, getEmInternalApi } from \"../EntityManager.ts\";\nimport { getMetadata } from \"../EntityMetadata.ts\";\nimport { buildHintTree } from \"../HintTree.ts\";\nimport type { LoadHint } from \"../loadHints.ts\";\nimport { hintKey } from \"../normalizeHints.ts\";\nimport type { FilterAndSettings } from \"../queries/find/EntityFilter.ts\";\nimport { type ParsedFindQuery, parseFindQuery } from \"../queries/find/QueryParser.ts\";\nimport { buildUnnestCte } from \"../unnest.ts\";\nimport {\n collectAndReplaceArgs,\n collectValues,\n createColumnValuesFromPrepared,\n filterDeletedEntities,\n findOperation,\n getBatchKeyFromGenericStructure,\n queryFilterHash,\n} from \"./findDataLoader.ts\";\n\ninterface PreparedPaginatedFindEntry<T extends Entity> {\n filter: FilterAndSettings<T>;\n query: ParsedFindQuery;\n bindings: any[];\n findSettings: any;\n limit: number | undefined;\n offset: number | undefined;\n}\n\n/** Returns a dataloader that batches paginated finds by applying pagination inside each lateral subquery. */\nexport function findPaginatedDataLoader<T extends Entity>(\n em: EntityManager,\n type: MaybeAbstractEntityConstructor<T>,\n filter: FilterAndSettings<T>,\n hint: LoadHint<T> | undefined,\n): Promise<T[]> {\n const { where, limit, offset, ...opts } = filter;\n const meta = getMetadata(type);\n const query = parseFindQuery(meta, where, opts);\n const { findSettings } = em[\"prepareFind\"](meta, findOperation, query, { ...opts, limit, offset, checkLimit: false });\n const bindings: any[] = [];\n collectValues(bindings, query);\n const prepared = {\n filter,\n query,\n bindings,\n findSettings,\n limit: findSettings.limit,\n offset: findSettings.offset,\n };\n const batchKey = [\n getBatchKeyFromGenericStructure(meta, query),\n hintKey(hint),\n findSettings.limit,\n findSettings.offset,\n ].join(\"-\");\n\n return em\n .getLoader<PreparedPaginatedFindEntry<T>, T[]>(\n findOperation,\n batchKey,\n async (entries) => {\n if (entries.length === 1) {\n // Skip batching & just execute the query as-is\n const { query, findSettings } = entries[0];\n const { preloader } = getEmInternalApi(em);\n const preloadHydrator = preloader && hint && preloader.addPreloading(meta, buildHintTree(hint), query);\n const rows = await em[\"executePreparedFind\"](meta, findOperation, query, findSettings, false);\n const entities = em.hydrate(type, rows);\n preloadHydrator?.(rows, entities);\n return [filterDeletedEntities(em, entities)];\n }\n\n const { query, findSettings, limit, offset } = entries[0];\n const { preloader } = getEmInternalApi(em);\n const preloadHydrator = preloader && hint && preloader.addPreloading(meta, buildHintTree(hint), query);\n\n // Now craft the actual batched query\n const args = collectAndReplaceArgs(query, entries);\n const argsColumns = [{ columnName: \"tag\", dbType: \"int\" }, ...args.map((a) => a.column)];\n const columnValues = createColumnValuesFromPrepared(args, entries);\n const query2: ParsedFindQuery = {\n selects: [\"_find.tag as tag\", \"_data.*\"],\n tables: [\n { join: \"primary\", table: \"_find\", alias: \"_find\" },\n {\n join: \"lateral\",\n query,\n table: meta.tableName,\n alias: \"_data\",\n fromAlias: \"_find\",\n settings: { limit, offset },\n },\n ],\n ctes: [buildUnnestCte(\"_find\", argsColumns, columnValues)],\n orderBys: [],\n };\n\n const rows = await em[\"executePreparedFind\"](\n meta,\n findOperation,\n query2,\n { ...findSettings, limit: undefined, offset: undefined },\n false,\n );\n const entities = em.hydrate(type, rows);\n preloadHydrator?.(rows, entities);\n\n const results = entries.map(() => [] as T[]);\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i];\n const entity = entities[i];\n if (!entity.isDeletedEntity) {\n results[row.tag].push(entity);\n }\n delete row.tag;\n }\n return results;\n },\n { cacheKeyFn: queryFilterHash },\n )\n .load(prepared);\n}\n"],"mappings":";;;;;;;;;;AA6BA,SAAgB,wBACd,IACA,MACA,QACA,MACc;CACd,MAAM,EAAE,OAAO,OAAO,QAAQ,GAAG,SAAS;CAC1C,MAAM,OAAOA,uBAAAA,YAAY,IAAI;CAC7B,MAAM,QAAQC,iCAAAA,eAAe,MAAM,OAAO,IAAI;CAC9C,MAAM,EAAE,iBAAiB,GAAG,cAAc,CAAC,MAAMC,mCAAAA,eAAe,OAAO;EAAE,GAAG;EAAM;EAAO;EAAQ,YAAY;CAAM,CAAC;CACpH,MAAM,WAAkB,CAAC;CACzB,mCAAA,cAAc,UAAU,KAAK;CAC7B,MAAM,WAAW;EACf;EACA;EACA;EACA;EACA,OAAO,aAAa;EACpB,QAAQ,aAAa;CACvB;CACA,MAAM,WAAW;EACfC,mCAAAA,gCAAgC,MAAM,KAAK;EAC3CC,uBAAAA,QAAQ,IAAI;EACZ,aAAa;EACb,aAAa;CACf,CAAC,CAAC,KAAK,GAAG;CAEV,OAAO,GACJ,UACCF,mCAAAA,eACA,UACA,OAAO,YAAY;EACjB,IAAI,QAAQ,WAAW,GAAG;GAExB,MAAM,EAAE,OAAO,iBAAiB,QAAQ;GACxC,MAAM,EAAE,cAAcG,sBAAAA,iBAAiB,EAAE;GACzC,MAAM,kBAAkB,aAAa,QAAQ,UAAU,cAAc,MAAMC,iBAAAA,cAAc,IAAI,GAAG,KAAK;GACrG,MAAM,OAAO,MAAM,GAAG,sBAAsB,CAAC,MAAMJ,mCAAAA,eAAe,OAAO,cAAc,KAAK;GAC5F,MAAM,WAAW,GAAG,QAAQ,MAAM,IAAI;GACtC,kBAAkB,MAAM,QAAQ;GAChC,OAAO,CAACK,mCAAAA,sBAAsB,IAAI,QAAQ,CAAC;EAC7C;EAEA,MAAM,EAAE,OAAO,cAAc,OAAO,WAAW,QAAQ;EACvD,MAAM,EAAE,cAAcF,sBAAAA,iBAAiB,EAAE;EACzC,MAAM,kBAAkB,aAAa,QAAQ,UAAU,cAAc,MAAMC,iBAAAA,cAAc,IAAI,GAAG,KAAK;EAGrG,MAAM,OAAOE,mCAAAA,sBAAsB,OAAO,OAAO;EACjD,MAAM,cAAc,CAAC;GAAE,YAAY;GAAO,QAAQ;EAAM,GAAG,GAAG,KAAK,KAAK,MAAM,EAAE,MAAM,CAAC;EACvF,MAAM,eAAeC,mCAAAA,+BAA+B,MAAM,OAAO;EACjE,MAAM,SAA0B;GAC9B,SAAS,CAAC,oBAAoB,SAAS;GACvC,QAAQ,CACN;IAAE,MAAM;IAAW,OAAO;IAAS,OAAO;GAAQ,GAClD;IACE,MAAM;IACN;IACA,OAAO,KAAK;IACZ,OAAO;IACP,WAAW;IACX,UAAU;KAAE;KAAO;IAAO;GAC5B,CACF;GACA,MAAM,CAACC,eAAAA,eAAe,SAAS,aAAa,YAAY,CAAC;GACzD,UAAU,CAAC;EACb;EAEA,MAAM,OAAO,MAAM,GAAG,sBAAsB,CAC1C,MACAR,mCAAAA,eACA,QACA;GAAE,GAAG;GAAc,OAAO,KAAA;GAAW,QAAQ,KAAA;EAAU,GACvD,KACF;EACA,MAAM,WAAW,GAAG,QAAQ,MAAM,IAAI;EACtC,kBAAkB,MAAM,QAAQ;EAEhC,MAAM,UAAU,QAAQ,UAAU,CAAC,CAAQ;EAC3C,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;GACpC,MAAM,MAAM,KAAK;GACjB,MAAM,SAAS,SAAS;GACxB,IAAI,CAAC,OAAO,iBACV,QAAQ,IAAI,IAAI,CAAC,KAAK,MAAM;GAE9B,OAAO,IAAI;EACb;EACA,OAAO;CACT,GACA,EAAE,YAAYS,mCAAAA,gBAAgB,CAChC,CAAC,CACA,KAAK,QAAQ;AAClB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { FilterAndSettings } from "../queries/find/EntityFilter.cjs";
|
|
1
2
|
import { LoadHint } from "../loadHints.cjs";
|
|
2
3
|
import { EntityManager, MaybeAbstractEntityConstructor } from "../EntityManager.cjs";
|
|
3
4
|
import { Entity } from "../Entity.cjs";
|
|
4
|
-
import { FilterAndSettings } from "../EntityFilter.cjs";
|
|
5
5
|
//#region src/dataloaders/findPaginatedDataLoader.d.ts
|
|
6
6
|
/** Returns a dataloader that batches paginated finds by applying pagination inside each lateral subquery. */
|
|
7
7
|
declare function findPaginatedDataLoader<T extends Entity>(em: EntityManager, type: MaybeAbstractEntityConstructor<T>, filter: FilterAndSettings<T>, hint: LoadHint<T> | undefined): Promise<T[]>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { FilterAndSettings } from "../queries/find/EntityFilter.mjs";
|
|
1
2
|
import { LoadHint } from "../loadHints.mjs";
|
|
2
3
|
import { EntityManager, MaybeAbstractEntityConstructor } from "../EntityManager.mjs";
|
|
3
4
|
import { Entity } from "../Entity.mjs";
|
|
4
|
-
import { FilterAndSettings } from "../EntityFilter.mjs";
|
|
5
5
|
//#region src/dataloaders/findPaginatedDataLoader.d.ts
|
|
6
6
|
/** Returns a dataloader that batches paginated finds by applying pagination inside each lateral subquery. */
|
|
7
7
|
declare function findPaginatedDataLoader<T extends Entity>(em: EntityManager, type: MaybeAbstractEntityConstructor<T>, filter: FilterAndSettings<T>, hint: LoadHint<T> | undefined): Promise<T[]>;
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import "../
|
|
2
|
-
import { getMetadata } from "../EntityMetadata.js";
|
|
1
|
+
import { parseFindQuery } from "../queries/find/QueryParser.js";
|
|
3
2
|
import { hintKey } from "../normalizeHints.js";
|
|
4
|
-
import "../
|
|
3
|
+
import { getMetadata } from "../EntityMetadata.js";
|
|
5
4
|
import { buildHintTree } from "../HintTree.js";
|
|
6
5
|
import { buildUnnestCte } from "../unnest.js";
|
|
7
6
|
import { collectAndReplaceArgs, collectValues, createColumnValuesFromPrepared, filterDeletedEntities, findOperation, getBatchKeyFromGenericStructure, queryFilterHash } from "./findDataLoader.js";
|
|
8
7
|
import { getEmInternalApi } from "../EntityManager.js";
|
|
9
|
-
import "../Entity.js";
|
|
10
|
-
import { parseFindQuery } from "../QueryParser.js";
|
|
11
8
|
//#region src/dataloaders/findPaginatedDataLoader.ts
|
|
12
9
|
/** Returns a dataloader that batches paginated finds by applying pagination inside each lateral subquery. */
|
|
13
10
|
function findPaginatedDataLoader(em, type, filter, hint) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"findPaginatedDataLoader.js","names":[],"sources":["../../src/dataloaders/findPaginatedDataLoader.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"findPaginatedDataLoader.js","names":[],"sources":["../../src/dataloaders/findPaginatedDataLoader.ts"],"sourcesContent":["import type { Entity } from \"../Entity.ts\";\nimport { type EntityManager, type MaybeAbstractEntityConstructor, getEmInternalApi } from \"../EntityManager.ts\";\nimport { getMetadata } from \"../EntityMetadata.ts\";\nimport { buildHintTree } from \"../HintTree.ts\";\nimport type { LoadHint } from \"../loadHints.ts\";\nimport { hintKey } from \"../normalizeHints.ts\";\nimport type { FilterAndSettings } from \"../queries/find/EntityFilter.ts\";\nimport { type ParsedFindQuery, parseFindQuery } from \"../queries/find/QueryParser.ts\";\nimport { buildUnnestCte } from \"../unnest.ts\";\nimport {\n collectAndReplaceArgs,\n collectValues,\n createColumnValuesFromPrepared,\n filterDeletedEntities,\n findOperation,\n getBatchKeyFromGenericStructure,\n queryFilterHash,\n} from \"./findDataLoader.ts\";\n\ninterface PreparedPaginatedFindEntry<T extends Entity> {\n filter: FilterAndSettings<T>;\n query: ParsedFindQuery;\n bindings: any[];\n findSettings: any;\n limit: number | undefined;\n offset: number | undefined;\n}\n\n/** Returns a dataloader that batches paginated finds by applying pagination inside each lateral subquery. */\nexport function findPaginatedDataLoader<T extends Entity>(\n em: EntityManager,\n type: MaybeAbstractEntityConstructor<T>,\n filter: FilterAndSettings<T>,\n hint: LoadHint<T> | undefined,\n): Promise<T[]> {\n const { where, limit, offset, ...opts } = filter;\n const meta = getMetadata(type);\n const query = parseFindQuery(meta, where, opts);\n const { findSettings } = em[\"prepareFind\"](meta, findOperation, query, { ...opts, limit, offset, checkLimit: false });\n const bindings: any[] = [];\n collectValues(bindings, query);\n const prepared = {\n filter,\n query,\n bindings,\n findSettings,\n limit: findSettings.limit,\n offset: findSettings.offset,\n };\n const batchKey = [\n getBatchKeyFromGenericStructure(meta, query),\n hintKey(hint),\n findSettings.limit,\n findSettings.offset,\n ].join(\"-\");\n\n return em\n .getLoader<PreparedPaginatedFindEntry<T>, T[]>(\n findOperation,\n batchKey,\n async (entries) => {\n if (entries.length === 1) {\n // Skip batching & just execute the query as-is\n const { query, findSettings } = entries[0];\n const { preloader } = getEmInternalApi(em);\n const preloadHydrator = preloader && hint && preloader.addPreloading(meta, buildHintTree(hint), query);\n const rows = await em[\"executePreparedFind\"](meta, findOperation, query, findSettings, false);\n const entities = em.hydrate(type, rows);\n preloadHydrator?.(rows, entities);\n return [filterDeletedEntities(em, entities)];\n }\n\n const { query, findSettings, limit, offset } = entries[0];\n const { preloader } = getEmInternalApi(em);\n const preloadHydrator = preloader && hint && preloader.addPreloading(meta, buildHintTree(hint), query);\n\n // Now craft the actual batched query\n const args = collectAndReplaceArgs(query, entries);\n const argsColumns = [{ columnName: \"tag\", dbType: \"int\" }, ...args.map((a) => a.column)];\n const columnValues = createColumnValuesFromPrepared(args, entries);\n const query2: ParsedFindQuery = {\n selects: [\"_find.tag as tag\", \"_data.*\"],\n tables: [\n { join: \"primary\", table: \"_find\", alias: \"_find\" },\n {\n join: \"lateral\",\n query,\n table: meta.tableName,\n alias: \"_data\",\n fromAlias: \"_find\",\n settings: { limit, offset },\n },\n ],\n ctes: [buildUnnestCte(\"_find\", argsColumns, columnValues)],\n orderBys: [],\n };\n\n const rows = await em[\"executePreparedFind\"](\n meta,\n findOperation,\n query2,\n { ...findSettings, limit: undefined, offset: undefined },\n false,\n );\n const entities = em.hydrate(type, rows);\n preloadHydrator?.(rows, entities);\n\n const results = entries.map(() => [] as T[]);\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i];\n const entity = entities[i];\n if (!entity.isDeletedEntity) {\n results[row.tag].push(entity);\n }\n delete row.tag;\n }\n return results;\n },\n { cacheKeyFn: queryFilterHash },\n )\n .load(prepared);\n}\n"],"mappings":";;;;;;;;;AA6BA,SAAgB,wBACd,IACA,MACA,QACA,MACc;CACd,MAAM,EAAE,OAAO,OAAO,QAAQ,GAAG,SAAS;CAC1C,MAAM,OAAO,YAAY,IAAI;CAC7B,MAAM,QAAQ,eAAe,MAAM,OAAO,IAAI;CAC9C,MAAM,EAAE,iBAAiB,GAAG,cAAc,CAAC,MAAM,eAAe,OAAO;EAAE,GAAG;EAAM;EAAO;EAAQ,YAAY;CAAM,CAAC;CACpH,MAAM,WAAkB,CAAC;CACzB,cAAc,UAAU,KAAK;CAC7B,MAAM,WAAW;EACf;EACA;EACA;EACA;EACA,OAAO,aAAa;EACpB,QAAQ,aAAa;CACvB;CACA,MAAM,WAAW;EACf,gCAAgC,MAAM,KAAK;EAC3C,QAAQ,IAAI;EACZ,aAAa;EACb,aAAa;CACf,CAAC,CAAC,KAAK,GAAG;CAEV,OAAO,GACJ,UACC,eACA,UACA,OAAO,YAAY;EACjB,IAAI,QAAQ,WAAW,GAAG;GAExB,MAAM,EAAE,OAAO,iBAAiB,QAAQ;GACxC,MAAM,EAAE,cAAc,iBAAiB,EAAE;GACzC,MAAM,kBAAkB,aAAa,QAAQ,UAAU,cAAc,MAAM,cAAc,IAAI,GAAG,KAAK;GACrG,MAAM,OAAO,MAAM,GAAG,sBAAsB,CAAC,MAAM,eAAe,OAAO,cAAc,KAAK;GAC5F,MAAM,WAAW,GAAG,QAAQ,MAAM,IAAI;GACtC,kBAAkB,MAAM,QAAQ;GAChC,OAAO,CAAC,sBAAsB,IAAI,QAAQ,CAAC;EAC7C;EAEA,MAAM,EAAE,OAAO,cAAc,OAAO,WAAW,QAAQ;EACvD,MAAM,EAAE,cAAc,iBAAiB,EAAE;EACzC,MAAM,kBAAkB,aAAa,QAAQ,UAAU,cAAc,MAAM,cAAc,IAAI,GAAG,KAAK;EAGrG,MAAM,OAAO,sBAAsB,OAAO,OAAO;EACjD,MAAM,cAAc,CAAC;GAAE,YAAY;GAAO,QAAQ;EAAM,GAAG,GAAG,KAAK,KAAK,MAAM,EAAE,MAAM,CAAC;EACvF,MAAM,eAAe,+BAA+B,MAAM,OAAO;EACjE,MAAM,SAA0B;GAC9B,SAAS,CAAC,oBAAoB,SAAS;GACvC,QAAQ,CACN;IAAE,MAAM;IAAW,OAAO;IAAS,OAAO;GAAQ,GAClD;IACE,MAAM;IACN;IACA,OAAO,KAAK;IACZ,OAAO;IACP,WAAW;IACX,UAAU;KAAE;KAAO;IAAO;GAC5B,CACF;GACA,MAAM,CAAC,eAAe,SAAS,aAAa,YAAY,CAAC;GACzD,UAAU,CAAC;EACb;EAEA,MAAM,OAAO,MAAM,GAAG,sBAAsB,CAC1C,MACA,eACA,QACA;GAAE,GAAG;GAAc,OAAO,KAAA;GAAW,QAAQ,KAAA;EAAU,GACvD,KACF;EACA,MAAM,WAAW,GAAG,QAAQ,MAAM,IAAI;EACtC,kBAAkB,MAAM,QAAQ;EAEhC,MAAM,UAAU,QAAQ,UAAU,CAAC,CAAQ;EAC3C,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;GACpC,MAAM,MAAM,KAAK;GACjB,MAAM,SAAS,SAAS;GACxB,IAAI,CAAC,OAAO,iBACV,QAAQ,IAAI,IAAI,CAAC,KAAK,MAAM;GAE9B,OAAO,IAAI;EACb;EACA,OAAO;CACT,GACA,EAAE,YAAY,gBAAgB,CAChC,CAAC,CACA,KAAK,QAAQ;AAClB"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_queries_find_QueryParser = require("../queries/find/QueryParser.cjs");
|
|
3
|
+
const require_utils = require("../utils.cjs");
|
|
2
4
|
const require_keys = require("../keys.cjs");
|
|
3
5
|
const require_EntityMetadata = require("../EntityMetadata.cjs");
|
|
4
|
-
const require_utils = require("../utils.cjs");
|
|
5
6
|
const require_loadLens = require("../loadLens.cjs");
|
|
6
7
|
require("../EntityManager.cjs");
|
|
7
8
|
require("../Entity.cjs");
|
|
8
|
-
const require_QueryParser = require("../QueryParser.cjs");
|
|
9
9
|
//#region src/dataloaders/lensDataLoader.ts
|
|
10
10
|
const lensOperation = "lens";
|
|
11
11
|
/**
|
|
@@ -45,8 +45,8 @@ function lensDataLoader(em, type, startIsArray, paths) {
|
|
|
45
45
|
},
|
|
46
46
|
orderBys: []
|
|
47
47
|
};
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
require_queries_find_QueryParser.addTablePerClassJoinsAndClassTag(query, target, alias, true);
|
|
49
|
+
require_queries_find_QueryParser.maybeAddOrderBy(query, target, alias);
|
|
50
50
|
function maybeAddNotSoftDeleted(other, alias) {
|
|
51
51
|
const { deletedAt } = require_EntityMetadata.getBaseMeta(other).timestampFields ?? {};
|
|
52
52
|
if (deletedAt) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lensDataLoader.cjs","names":["abbreviation","getMetadata","mapPathsToTarget","getBaseMeta","deTagIds","groupBy","tagId"],"sources":["../../src/dataloaders/lensDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\n\nimport { type Entity } from \"../Entity.ts\";\nimport { type EntityManager, type MaybeAbstractEntityConstructor, type TaggedId } from \"../EntityManager.ts\";\nimport {\n type EntityMetadata,\n type ManyToOneField,\n type OneToManyField,\n type OneToOneField,\n getBaseMeta,\n getMetadata,\n} from \"../EntityMetadata.ts\";\nimport { deTagIds, tagId } from \"../keys.ts\";\nimport { mapPathsToTarget } from \"../loadLens.ts\";\nimport {\n type ColumnCondition,\n type ParsedFindQuery,\n type ParsedOrderBy,\n type ParsedTable,\n addTablePerClassJoinsAndClassTag,\n maybeAddOrderBy,\n} from \"../QueryParser.ts\";\nimport { abbreviation, groupBy } from \"../utils.ts\";\n\nexport const lensOperation = \"lens\";\n\n/**\n * Loads lens paths via SQL.\n *\n * I.e. instead of loading `author.load(a => a.books.reviews)` by pulling all\n * Books into memory, we do a join from the Author to BookReviews.\n */\nexport function lensDataLoader<T extends Entity>(\n em: EntityManager,\n type: MaybeAbstractEntityConstructor<T>,\n startIsArray: boolean,\n paths: string[],\n): DataLoader<TaggedId, T | T[]> {\n // Batch lens loads by type + path to avoid N+1s\n const batchKey = `${type.name}-${paths.join(\"/\")}`;\n return em.getLoader(lensOperation, batchKey, async (sourceIds) => {\n const aliases: Record<string, number> = {};\n function getAlias(tableName: string): string {\n const abbrev = abbreviation(tableName);\n const i = aliases[abbrev] || 0;\n aliases[abbrev] = i + 1;\n return i === 0 ? abbrev : `${abbrev}${i}`;\n }\n\n // br.load(br => br.book.author)\n // select br.id as __source_id, a.*\n // from authors a\n // join books b ON b.author_id = a.id\n // join book_reviews br ON br.book_id = br.id\n // where br.id in (keys)\n // source=BR, target=Author, fields=books,bookReviews\n\n // a.load(a => a.books.reviews)\n // select b.author_id as __source_id, br.*\n // from book_reviews br\n // join books b on b.id = br.book_id\n // where b.author_id in (keys)\n\n const source = getMetadata(type);\n // Walk source -> paths -> the target, and return the target -> source fields\n const [target, fields] = mapPathsToTarget(source, paths);\n let resultIsArray = startIsArray;\n\n const alias = getAlias(target.tableName);\n const selects = [`\"${alias}\".*`];\n const tables: ParsedTable[] = [{ alias, join: \"primary\", table: target.tableName }];\n const conditions: ColumnCondition[] = [];\n const orderBys: ParsedOrderBy[] = [];\n const query: ParsedFindQuery = { selects, tables, condition: { kind: \"exp\", op: \"and\", conditions }, orderBys };\n addTablePerClassJoinsAndClassTag(query, target, alias, true);\n maybeAddOrderBy(query, target, alias);\n\n function maybeAddNotSoftDeleted(other: EntityMetadata, alias: string): void {\n const { deletedAt } = getBaseMeta(other).timestampFields ?? {};\n if (deletedAt) {\n const column = other.allFields[deletedAt].serde?.columns[0]!;\n conditions.push({\n kind: \"column\",\n alias,\n column: column.columnName,\n dbType: column.dbType,\n cond: { kind: \"is-null\" },\n });\n }\n }\n\n let lastAlias = alias;\n fields.forEach(([, field], i) => {\n const isLast = i === fields.length - 1;\n switch (field.kind) {\n case \"o2o\":\n case \"o2m\": {\n // This is `Publisher.authors` and we want to join in the authors table,\n // so get the `Author.publisher` field to know the column name\n const other = field.otherMetadata();\n const m2o = other.allFields[field.otherFieldName] as ManyToOneField;\n const alias = getAlias(other.tableName);\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.${m2o.serde.columns[0].columnName}`,\n col2: `${lastAlias}.id`,\n });\n maybeAddNotSoftDeleted(other, alias);\n if (isLast) {\n selects.push(`\"${alias}\".id as __source_id`);\n conditions.push({\n kind: \"column\",\n alias,\n column: \"id\",\n dbType: other.idDbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n }\n lastAlias = alias;\n break;\n }\n case \"m2o\": {\n // This is `Book.author` and we want to join in the authors table\n const other = field.otherMetadata();\n const otherField = other.fields[field.otherFieldName] as OneToManyField | OneToOneField;\n const alias = getAlias(other.tableName);\n if (!isLast) {\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.id`,\n col2: `${lastAlias}.${field.serde.columns[0].columnName}`,\n });\n maybeAddNotSoftDeleted(other, alias);\n } else {\n selects.push(`\"${lastAlias}\".${field.serde.columns[0].columnName} as __source_id`);\n conditions.push({\n kind: \"column\",\n alias: lastAlias,\n column: field.serde.columns[0].columnName,\n dbType: field.serde.columns[0].dbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n // Need to add filter for soft-deleted...\n }\n resultIsArray = otherField.kind === \"o2o\" ? resultIsArray : true;\n lastAlias = alias;\n break;\n }\n case \"m2m\": {\n // This is `Book.tags` and we want to join through the m2m table\n const other = field.otherMetadata();\n const alias = getAlias(other.tableName);\n tables.push({\n alias: `${alias}_m2m`,\n join: \"inner\",\n table: field.joinTableName,\n col1: `${alias}_m2m.${field.columnNames[0]}`,\n col2: `${lastAlias}.id`,\n });\n // If this is the last table, we could skip this join like we do for m2os\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.id`,\n col2: `${alias}_m2m.${field.columnNames[1]}`,\n });\n maybeAddNotSoftDeleted(other, alias);\n if (isLast) {\n selects.push(`\"${alias}\".id as __source_id`);\n conditions.push({\n kind: \"column\",\n alias,\n column: \"id\",\n dbType: other.idDbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n }\n resultIsArray = true;\n lastAlias = alias;\n break;\n }\n default:\n throw new Error(\"Unsupported field kind: \" + field.kind);\n }\n });\n\n // Get back `__source_id, target.*`\n const rows = await em[\"executeFind\"](target, lensOperation, query, {});\n\n // Group the target entities (i.e. BookReview) by the source id we reached them from.\n const entitiesBySourceId = new Map(\n [...groupBy(rows, (row) => row[\"__source_id\"]).entries()].map(([sourceId, rows]) => {\n // We may technically re-hydrate the same entity twice if it was reached\n // via multiple sources, but that should be fine/get deduped by hydrate.\n return [tagId(source, sourceId), em.hydrate(target.cstr, rows)];\n }),\n );\n\n // Re-order the output by the batched input\n return sourceIds.map((id) => {\n const result = entitiesBySourceId.get(id);\n return resultIsArray ? [...new Set(result ?? [])] : result?.[0];\n });\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lensDataLoader.cjs","names":["abbreviation","getMetadata","mapPathsToTarget","getBaseMeta","deTagIds","groupBy","tagId"],"sources":["../../src/dataloaders/lensDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\n\nimport { type Entity } from \"../Entity.ts\";\nimport { type EntityManager, type MaybeAbstractEntityConstructor, type TaggedId } from \"../EntityManager.ts\";\nimport {\n type EntityMetadata,\n type ManyToOneField,\n type OneToManyField,\n type OneToOneField,\n getBaseMeta,\n getMetadata,\n} from \"../EntityMetadata.ts\";\nimport { deTagIds, tagId } from \"../keys.ts\";\nimport { mapPathsToTarget } from \"../loadLens.ts\";\nimport {\n type ParsedFindQuery,\n type ParsedOrderBy,\n type ParsedTable,\n addTablePerClassJoinsAndClassTag,\n maybeAddOrderBy,\n} from \"../queries/find/QueryParser.ts\";\nimport type { ColumnCondition } from \"../queries/parsedConditions.ts\";\nimport { abbreviation, groupBy } from \"../utils.ts\";\n\nexport const lensOperation = \"lens\";\n\n/**\n * Loads lens paths via SQL.\n *\n * I.e. instead of loading `author.load(a => a.books.reviews)` by pulling all\n * Books into memory, we do a join from the Author to BookReviews.\n */\nexport function lensDataLoader<T extends Entity>(\n em: EntityManager,\n type: MaybeAbstractEntityConstructor<T>,\n startIsArray: boolean,\n paths: string[],\n): DataLoader<TaggedId, T | T[]> {\n // Batch lens loads by type + path to avoid N+1s\n const batchKey = `${type.name}-${paths.join(\"/\")}`;\n return em.getLoader(lensOperation, batchKey, async (sourceIds) => {\n const aliases: Record<string, number> = {};\n function getAlias(tableName: string): string {\n const abbrev = abbreviation(tableName);\n const i = aliases[abbrev] || 0;\n aliases[abbrev] = i + 1;\n return i === 0 ? abbrev : `${abbrev}${i}`;\n }\n\n // br.load(br => br.book.author)\n // select br.id as __source_id, a.*\n // from authors a\n // join books b ON b.author_id = a.id\n // join book_reviews br ON br.book_id = br.id\n // where br.id in (keys)\n // source=BR, target=Author, fields=books,bookReviews\n\n // a.load(a => a.books.reviews)\n // select b.author_id as __source_id, br.*\n // from book_reviews br\n // join books b on b.id = br.book_id\n // where b.author_id in (keys)\n\n const source = getMetadata(type);\n // Walk source -> paths -> the target, and return the target -> source fields\n const [target, fields] = mapPathsToTarget(source, paths);\n let resultIsArray = startIsArray;\n\n const alias = getAlias(target.tableName);\n const selects = [`\"${alias}\".*`];\n const tables: ParsedTable[] = [{ alias, join: \"primary\", table: target.tableName }];\n const conditions: ColumnCondition[] = [];\n const orderBys: ParsedOrderBy[] = [];\n const query: ParsedFindQuery = { selects, tables, condition: { kind: \"exp\", op: \"and\", conditions }, orderBys };\n addTablePerClassJoinsAndClassTag(query, target, alias, true);\n maybeAddOrderBy(query, target, alias);\n\n function maybeAddNotSoftDeleted(other: EntityMetadata, alias: string): void {\n const { deletedAt } = getBaseMeta(other).timestampFields ?? {};\n if (deletedAt) {\n const column = other.allFields[deletedAt].serde?.columns[0]!;\n conditions.push({\n kind: \"column\",\n alias,\n column: column.columnName,\n dbType: column.dbType,\n cond: { kind: \"is-null\" },\n });\n }\n }\n\n let lastAlias = alias;\n fields.forEach(([, field], i) => {\n const isLast = i === fields.length - 1;\n switch (field.kind) {\n case \"o2o\":\n case \"o2m\": {\n // This is `Publisher.authors` and we want to join in the authors table,\n // so get the `Author.publisher` field to know the column name\n const other = field.otherMetadata();\n const m2o = other.allFields[field.otherFieldName] as ManyToOneField;\n const alias = getAlias(other.tableName);\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.${m2o.serde.columns[0].columnName}`,\n col2: `${lastAlias}.id`,\n });\n maybeAddNotSoftDeleted(other, alias);\n if (isLast) {\n selects.push(`\"${alias}\".id as __source_id`);\n conditions.push({\n kind: \"column\",\n alias,\n column: \"id\",\n dbType: other.idDbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n }\n lastAlias = alias;\n break;\n }\n case \"m2o\": {\n // This is `Book.author` and we want to join in the authors table\n const other = field.otherMetadata();\n const otherField = other.fields[field.otherFieldName] as OneToManyField | OneToOneField;\n const alias = getAlias(other.tableName);\n if (!isLast) {\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.id`,\n col2: `${lastAlias}.${field.serde.columns[0].columnName}`,\n });\n maybeAddNotSoftDeleted(other, alias);\n } else {\n selects.push(`\"${lastAlias}\".${field.serde.columns[0].columnName} as __source_id`);\n conditions.push({\n kind: \"column\",\n alias: lastAlias,\n column: field.serde.columns[0].columnName,\n dbType: field.serde.columns[0].dbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n // Need to add filter for soft-deleted...\n }\n resultIsArray = otherField.kind === \"o2o\" ? resultIsArray : true;\n lastAlias = alias;\n break;\n }\n case \"m2m\": {\n // This is `Book.tags` and we want to join through the m2m table\n const other = field.otherMetadata();\n const alias = getAlias(other.tableName);\n tables.push({\n alias: `${alias}_m2m`,\n join: \"inner\",\n table: field.joinTableName,\n col1: `${alias}_m2m.${field.columnNames[0]}`,\n col2: `${lastAlias}.id`,\n });\n // If this is the last table, we could skip this join like we do for m2os\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.id`,\n col2: `${alias}_m2m.${field.columnNames[1]}`,\n });\n maybeAddNotSoftDeleted(other, alias);\n if (isLast) {\n selects.push(`\"${alias}\".id as __source_id`);\n conditions.push({\n kind: \"column\",\n alias,\n column: \"id\",\n dbType: other.idDbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n }\n resultIsArray = true;\n lastAlias = alias;\n break;\n }\n default:\n throw new Error(\"Unsupported field kind: \" + field.kind);\n }\n });\n\n // Get back `__source_id, target.*`\n const rows = await em[\"executeFind\"](target, lensOperation, query, {});\n\n // Group the target entities (i.e. BookReview) by the source id we reached them from.\n const entitiesBySourceId = new Map(\n [...groupBy(rows, (row) => row[\"__source_id\"]).entries()].map(([sourceId, rows]) => {\n // We may technically re-hydrate the same entity twice if it was reached\n // via multiple sources, but that should be fine/get deduped by hydrate.\n return [tagId(source, sourceId), em.hydrate(target.cstr, rows)];\n }),\n );\n\n // Re-order the output by the batched input\n return sourceIds.map((id) => {\n const result = entitiesBySourceId.get(id);\n return resultIsArray ? [...new Set(result ?? [])] : result?.[0];\n });\n });\n}\n"],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { addTablePerClassJoinsAndClassTag, maybeAddOrderBy } from "../queries/find/QueryParser.js";
|
|
2
|
+
import { abbreviation, groupBy } from "../utils.js";
|
|
1
3
|
import { deTagIds, tagId } from "../keys.js";
|
|
2
4
|
import { getBaseMeta, getMetadata } from "../EntityMetadata.js";
|
|
3
|
-
import { abbreviation, groupBy } from "../utils.js";
|
|
4
5
|
import { mapPathsToTarget } from "../loadLens.js";
|
|
5
6
|
import "../EntityManager.js";
|
|
6
7
|
import "../Entity.js";
|
|
7
|
-
import { addTablePerClassJoinsAndClassTag, maybeAddOrderBy } from "../QueryParser.js";
|
|
8
8
|
//#region src/dataloaders/lensDataLoader.ts
|
|
9
9
|
const lensOperation = "lens";
|
|
10
10
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lensDataLoader.js","names":[],"sources":["../../src/dataloaders/lensDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\n\nimport { type Entity } from \"../Entity.ts\";\nimport { type EntityManager, type MaybeAbstractEntityConstructor, type TaggedId } from \"../EntityManager.ts\";\nimport {\n type EntityMetadata,\n type ManyToOneField,\n type OneToManyField,\n type OneToOneField,\n getBaseMeta,\n getMetadata,\n} from \"../EntityMetadata.ts\";\nimport { deTagIds, tagId } from \"../keys.ts\";\nimport { mapPathsToTarget } from \"../loadLens.ts\";\nimport {\n type ColumnCondition,\n type ParsedFindQuery,\n type ParsedOrderBy,\n type ParsedTable,\n addTablePerClassJoinsAndClassTag,\n maybeAddOrderBy,\n} from \"../QueryParser.ts\";\nimport { abbreviation, groupBy } from \"../utils.ts\";\n\nexport const lensOperation = \"lens\";\n\n/**\n * Loads lens paths via SQL.\n *\n * I.e. instead of loading `author.load(a => a.books.reviews)` by pulling all\n * Books into memory, we do a join from the Author to BookReviews.\n */\nexport function lensDataLoader<T extends Entity>(\n em: EntityManager,\n type: MaybeAbstractEntityConstructor<T>,\n startIsArray: boolean,\n paths: string[],\n): DataLoader<TaggedId, T | T[]> {\n // Batch lens loads by type + path to avoid N+1s\n const batchKey = `${type.name}-${paths.join(\"/\")}`;\n return em.getLoader(lensOperation, batchKey, async (sourceIds) => {\n const aliases: Record<string, number> = {};\n function getAlias(tableName: string): string {\n const abbrev = abbreviation(tableName);\n const i = aliases[abbrev] || 0;\n aliases[abbrev] = i + 1;\n return i === 0 ? abbrev : `${abbrev}${i}`;\n }\n\n // br.load(br => br.book.author)\n // select br.id as __source_id, a.*\n // from authors a\n // join books b ON b.author_id = a.id\n // join book_reviews br ON br.book_id = br.id\n // where br.id in (keys)\n // source=BR, target=Author, fields=books,bookReviews\n\n // a.load(a => a.books.reviews)\n // select b.author_id as __source_id, br.*\n // from book_reviews br\n // join books b on b.id = br.book_id\n // where b.author_id in (keys)\n\n const source = getMetadata(type);\n // Walk source -> paths -> the target, and return the target -> source fields\n const [target, fields] = mapPathsToTarget(source, paths);\n let resultIsArray = startIsArray;\n\n const alias = getAlias(target.tableName);\n const selects = [`\"${alias}\".*`];\n const tables: ParsedTable[] = [{ alias, join: \"primary\", table: target.tableName }];\n const conditions: ColumnCondition[] = [];\n const orderBys: ParsedOrderBy[] = [];\n const query: ParsedFindQuery = { selects, tables, condition: { kind: \"exp\", op: \"and\", conditions }, orderBys };\n addTablePerClassJoinsAndClassTag(query, target, alias, true);\n maybeAddOrderBy(query, target, alias);\n\n function maybeAddNotSoftDeleted(other: EntityMetadata, alias: string): void {\n const { deletedAt } = getBaseMeta(other).timestampFields ?? {};\n if (deletedAt) {\n const column = other.allFields[deletedAt].serde?.columns[0]!;\n conditions.push({\n kind: \"column\",\n alias,\n column: column.columnName,\n dbType: column.dbType,\n cond: { kind: \"is-null\" },\n });\n }\n }\n\n let lastAlias = alias;\n fields.forEach(([, field], i) => {\n const isLast = i === fields.length - 1;\n switch (field.kind) {\n case \"o2o\":\n case \"o2m\": {\n // This is `Publisher.authors` and we want to join in the authors table,\n // so get the `Author.publisher` field to know the column name\n const other = field.otherMetadata();\n const m2o = other.allFields[field.otherFieldName] as ManyToOneField;\n const alias = getAlias(other.tableName);\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.${m2o.serde.columns[0].columnName}`,\n col2: `${lastAlias}.id`,\n });\n maybeAddNotSoftDeleted(other, alias);\n if (isLast) {\n selects.push(`\"${alias}\".id as __source_id`);\n conditions.push({\n kind: \"column\",\n alias,\n column: \"id\",\n dbType: other.idDbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n }\n lastAlias = alias;\n break;\n }\n case \"m2o\": {\n // This is `Book.author` and we want to join in the authors table\n const other = field.otherMetadata();\n const otherField = other.fields[field.otherFieldName] as OneToManyField | OneToOneField;\n const alias = getAlias(other.tableName);\n if (!isLast) {\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.id`,\n col2: `${lastAlias}.${field.serde.columns[0].columnName}`,\n });\n maybeAddNotSoftDeleted(other, alias);\n } else {\n selects.push(`\"${lastAlias}\".${field.serde.columns[0].columnName} as __source_id`);\n conditions.push({\n kind: \"column\",\n alias: lastAlias,\n column: field.serde.columns[0].columnName,\n dbType: field.serde.columns[0].dbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n // Need to add filter for soft-deleted...\n }\n resultIsArray = otherField.kind === \"o2o\" ? resultIsArray : true;\n lastAlias = alias;\n break;\n }\n case \"m2m\": {\n // This is `Book.tags` and we want to join through the m2m table\n const other = field.otherMetadata();\n const alias = getAlias(other.tableName);\n tables.push({\n alias: `${alias}_m2m`,\n join: \"inner\",\n table: field.joinTableName,\n col1: `${alias}_m2m.${field.columnNames[0]}`,\n col2: `${lastAlias}.id`,\n });\n // If this is the last table, we could skip this join like we do for m2os\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.id`,\n col2: `${alias}_m2m.${field.columnNames[1]}`,\n });\n maybeAddNotSoftDeleted(other, alias);\n if (isLast) {\n selects.push(`\"${alias}\".id as __source_id`);\n conditions.push({\n kind: \"column\",\n alias,\n column: \"id\",\n dbType: other.idDbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n }\n resultIsArray = true;\n lastAlias = alias;\n break;\n }\n default:\n throw new Error(\"Unsupported field kind: \" + field.kind);\n }\n });\n\n // Get back `__source_id, target.*`\n const rows = await em[\"executeFind\"](target, lensOperation, query, {});\n\n // Group the target entities (i.e. BookReview) by the source id we reached them from.\n const entitiesBySourceId = new Map(\n [...groupBy(rows, (row) => row[\"__source_id\"]).entries()].map(([sourceId, rows]) => {\n // We may technically re-hydrate the same entity twice if it was reached\n // via multiple sources, but that should be fine/get deduped by hydrate.\n return [tagId(source, sourceId), em.hydrate(target.cstr, rows)];\n }),\n );\n\n // Re-order the output by the batched input\n return sourceIds.map((id) => {\n const result = entitiesBySourceId.get(id);\n return resultIsArray ? [...new Set(result ?? [])] : result?.[0];\n });\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lensDataLoader.js","names":[],"sources":["../../src/dataloaders/lensDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\n\nimport { type Entity } from \"../Entity.ts\";\nimport { type EntityManager, type MaybeAbstractEntityConstructor, type TaggedId } from \"../EntityManager.ts\";\nimport {\n type EntityMetadata,\n type ManyToOneField,\n type OneToManyField,\n type OneToOneField,\n getBaseMeta,\n getMetadata,\n} from \"../EntityMetadata.ts\";\nimport { deTagIds, tagId } from \"../keys.ts\";\nimport { mapPathsToTarget } from \"../loadLens.ts\";\nimport {\n type ParsedFindQuery,\n type ParsedOrderBy,\n type ParsedTable,\n addTablePerClassJoinsAndClassTag,\n maybeAddOrderBy,\n} from \"../queries/find/QueryParser.ts\";\nimport type { ColumnCondition } from \"../queries/parsedConditions.ts\";\nimport { abbreviation, groupBy } from \"../utils.ts\";\n\nexport const lensOperation = \"lens\";\n\n/**\n * Loads lens paths via SQL.\n *\n * I.e. instead of loading `author.load(a => a.books.reviews)` by pulling all\n * Books into memory, we do a join from the Author to BookReviews.\n */\nexport function lensDataLoader<T extends Entity>(\n em: EntityManager,\n type: MaybeAbstractEntityConstructor<T>,\n startIsArray: boolean,\n paths: string[],\n): DataLoader<TaggedId, T | T[]> {\n // Batch lens loads by type + path to avoid N+1s\n const batchKey = `${type.name}-${paths.join(\"/\")}`;\n return em.getLoader(lensOperation, batchKey, async (sourceIds) => {\n const aliases: Record<string, number> = {};\n function getAlias(tableName: string): string {\n const abbrev = abbreviation(tableName);\n const i = aliases[abbrev] || 0;\n aliases[abbrev] = i + 1;\n return i === 0 ? abbrev : `${abbrev}${i}`;\n }\n\n // br.load(br => br.book.author)\n // select br.id as __source_id, a.*\n // from authors a\n // join books b ON b.author_id = a.id\n // join book_reviews br ON br.book_id = br.id\n // where br.id in (keys)\n // source=BR, target=Author, fields=books,bookReviews\n\n // a.load(a => a.books.reviews)\n // select b.author_id as __source_id, br.*\n // from book_reviews br\n // join books b on b.id = br.book_id\n // where b.author_id in (keys)\n\n const source = getMetadata(type);\n // Walk source -> paths -> the target, and return the target -> source fields\n const [target, fields] = mapPathsToTarget(source, paths);\n let resultIsArray = startIsArray;\n\n const alias = getAlias(target.tableName);\n const selects = [`\"${alias}\".*`];\n const tables: ParsedTable[] = [{ alias, join: \"primary\", table: target.tableName }];\n const conditions: ColumnCondition[] = [];\n const orderBys: ParsedOrderBy[] = [];\n const query: ParsedFindQuery = { selects, tables, condition: { kind: \"exp\", op: \"and\", conditions }, orderBys };\n addTablePerClassJoinsAndClassTag(query, target, alias, true);\n maybeAddOrderBy(query, target, alias);\n\n function maybeAddNotSoftDeleted(other: EntityMetadata, alias: string): void {\n const { deletedAt } = getBaseMeta(other).timestampFields ?? {};\n if (deletedAt) {\n const column = other.allFields[deletedAt].serde?.columns[0]!;\n conditions.push({\n kind: \"column\",\n alias,\n column: column.columnName,\n dbType: column.dbType,\n cond: { kind: \"is-null\" },\n });\n }\n }\n\n let lastAlias = alias;\n fields.forEach(([, field], i) => {\n const isLast = i === fields.length - 1;\n switch (field.kind) {\n case \"o2o\":\n case \"o2m\": {\n // This is `Publisher.authors` and we want to join in the authors table,\n // so get the `Author.publisher` field to know the column name\n const other = field.otherMetadata();\n const m2o = other.allFields[field.otherFieldName] as ManyToOneField;\n const alias = getAlias(other.tableName);\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.${m2o.serde.columns[0].columnName}`,\n col2: `${lastAlias}.id`,\n });\n maybeAddNotSoftDeleted(other, alias);\n if (isLast) {\n selects.push(`\"${alias}\".id as __source_id`);\n conditions.push({\n kind: \"column\",\n alias,\n column: \"id\",\n dbType: other.idDbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n }\n lastAlias = alias;\n break;\n }\n case \"m2o\": {\n // This is `Book.author` and we want to join in the authors table\n const other = field.otherMetadata();\n const otherField = other.fields[field.otherFieldName] as OneToManyField | OneToOneField;\n const alias = getAlias(other.tableName);\n if (!isLast) {\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.id`,\n col2: `${lastAlias}.${field.serde.columns[0].columnName}`,\n });\n maybeAddNotSoftDeleted(other, alias);\n } else {\n selects.push(`\"${lastAlias}\".${field.serde.columns[0].columnName} as __source_id`);\n conditions.push({\n kind: \"column\",\n alias: lastAlias,\n column: field.serde.columns[0].columnName,\n dbType: field.serde.columns[0].dbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n // Need to add filter for soft-deleted...\n }\n resultIsArray = otherField.kind === \"o2o\" ? resultIsArray : true;\n lastAlias = alias;\n break;\n }\n case \"m2m\": {\n // This is `Book.tags` and we want to join through the m2m table\n const other = field.otherMetadata();\n const alias = getAlias(other.tableName);\n tables.push({\n alias: `${alias}_m2m`,\n join: \"inner\",\n table: field.joinTableName,\n col1: `${alias}_m2m.${field.columnNames[0]}`,\n col2: `${lastAlias}.id`,\n });\n // If this is the last table, we could skip this join like we do for m2os\n tables.push({\n alias,\n join: \"inner\",\n table: other.tableName,\n col1: `${alias}.id`,\n col2: `${alias}_m2m.${field.columnNames[1]}`,\n });\n maybeAddNotSoftDeleted(other, alias);\n if (isLast) {\n selects.push(`\"${alias}\".id as __source_id`);\n conditions.push({\n kind: \"column\",\n alias,\n column: \"id\",\n dbType: other.idDbType,\n cond: { kind: \"in\", value: deTagIds(source, sourceIds) },\n });\n }\n resultIsArray = true;\n lastAlias = alias;\n break;\n }\n default:\n throw new Error(\"Unsupported field kind: \" + field.kind);\n }\n });\n\n // Get back `__source_id, target.*`\n const rows = await em[\"executeFind\"](target, lensOperation, query, {});\n\n // Group the target entities (i.e. BookReview) by the source id we reached them from.\n const entitiesBySourceId = new Map(\n [...groupBy(rows, (row) => row[\"__source_id\"]).entries()].map(([sourceId, rows]) => {\n // We may technically re-hydrate the same entity twice if it was reached\n // via multiple sources, but that should be fine/get deduped by hydrate.\n return [tagId(source, sourceId), em.hydrate(target.cstr, rows)];\n }),\n );\n\n // Re-order the output by the batched input\n return sourceIds.map((id) => {\n const result = entitiesBySourceId.get(id);\n return resultIsArray ? [...new Set(result ?? [])] : result?.[0];\n });\n });\n}\n"],"mappings":"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"}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_keys = require("../keys.cjs");
|
|
3
2
|
const require_utils = require("../utils.cjs");
|
|
4
|
-
require("../
|
|
5
|
-
require("../EntityManager.cjs");
|
|
6
|
-
require("../Entity.cjs");
|
|
3
|
+
const require_keys = require("../keys.cjs");
|
|
7
4
|
//#region src/dataloaders/manyToManyFindDataLoader.ts
|
|
8
5
|
const manyToManyFindOperation = "m2m-find";
|
|
9
6
|
/** Batches m2m.find/include calls (i.e. that don't fully load the m2m relation). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manyToManyFindDataLoader.cjs","names":["abbreviation","keyToNumber","tagId"],"sources":["../../src/dataloaders/manyToManyFindDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\n\nimport {
|
|
1
|
+
{"version":3,"file":"manyToManyFindDataLoader.cjs","names":["abbreviation","keyToNumber","tagId"],"sources":["../../src/dataloaders/manyToManyFindDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\n\nimport type { Entity } from \"../Entity.ts\";\nimport type { EntityManager } from \"../EntityManager.ts\";\nimport { keyToNumber, tagId } from \"../keys.ts\";\nimport type { ParsedFindQuery } from \"../queries/find/QueryParser.ts\";\nimport type { ManyToManyCollection } from \"../relations/ManyToManyCollection.ts\";\nimport type { ManyToManyLargeCollection } from \"../relations/ManyToManyLargeCollection.ts\";\nimport { abbreviation } from \"../utils.ts\";\n\nexport const manyToManyFindOperation = \"m2m-find\";\n\n/** Batches m2m.find/include calls (i.e. that don't fully load the m2m relation). */\nexport function manyToManyFindDataLoader<T extends Entity, U extends Entity>(\n em: EntityManager,\n collection: ManyToManyCollection<T, U> | ManyToManyLargeCollection<T, U>,\n): DataLoader<string, boolean> {\n return em.getLoader(manyToManyFindOperation, collection.joinTableName, (keys) => load(collection, keys));\n}\n\nasync function load<T extends Entity, U extends Entity>(\n collection: ManyToManyCollection<T, U> | ManyToManyLargeCollection<T, U>,\n keys: ReadonlyArray<string>,\n): Promise<boolean[]> {\n const { joinTableName } = collection;\n const { em } = collection.entity;\n\n const alias = abbreviation(joinTableName);\n const query: ParsedFindQuery = {\n selects: [`\"${alias}\".*`],\n tables: [{ alias, join: \"primary\", table: joinTableName }],\n // Or together `where (tag_id = X and book_id = Y)` or `(book_id = B and tag_id = A)`\n condition: {\n kind: \"exp\",\n op: \"or\",\n conditions: keys.map((key) => {\n const [one, two] = key.split(\",\");\n const [columnOne, idOne] = one.split(\"=\");\n const [columnTwo, idTwo] = two.split(\"=\");\n // Pick the right meta i.e. tag_id --> TagMeta or book_id --> BookMeta\n const [meta1, meta2] =\n collection.columnName === columnOne\n ? [collection.meta, collection.otherMeta]\n : [collection.otherMeta, collection.meta];\n return {\n kind: \"exp\",\n op: \"and\",\n conditions: [\n {\n kind: \"column\",\n alias,\n column: columnOne,\n dbType: meta1.idDbType,\n cond: { kind: \"eq\", value: keyToNumber(meta1, idOne) },\n },\n {\n kind: \"column\",\n alias,\n column: columnTwo,\n dbType: meta2.idDbType,\n cond: { kind: \"eq\", value: keyToNumber(meta2, idTwo) },\n },\n ],\n };\n }),\n },\n // Id-less join tables have no surrogate id to order by, so order by the FK columns instead.\n orderBys: collection.hasJoinTableId\n ? [{ alias, column: \"id\", order: \"ASC\" }]\n : [\n { alias, column: collection.columnName, order: \"ASC\" },\n { alias, column: collection.otherColumnName, order: \"ASC\" },\n ],\n };\n\n const rows = await em[\"executeFind\"](collection.otherMeta, manyToManyFindOperation, query, {});\n\n const column1 = collection.columnName;\n const column2 = collection.otherColumnName;\n const meta1 = collection.meta;\n const meta2 = collection.otherMeta;\n\n // Because keys might come from either side of the m2m relationship, build\n // a list of both `foo_id=2,bar_id=3` and `bar_id=3,foo_id=2` to make the\n // final return value just a map of `Set.has`.\n const found = new Set(\n rows.flatMap((dbRow) => {\n const a = `${column1}=${tagId(meta1, dbRow[column1] as number)}`;\n const b = `${column2}=${tagId(meta2, dbRow[column2] as number)}`;\n return [`${a},${b}`, `${b},${a}`];\n }),\n );\n\n return keys.map((key) => found.has(key));\n}\n"],"mappings":";;;;AAUA,MAAa,0BAA0B;;AAGvC,SAAgB,yBACd,IACA,YAC6B;CAC7B,OAAO,GAAG,UAAU,yBAAyB,WAAW,gBAAgB,SAAS,KAAK,YAAY,IAAI,CAAC;AACzG;AAEA,eAAe,KACb,YACA,MACoB;CACpB,MAAM,EAAE,kBAAkB;CAC1B,MAAM,EAAE,OAAO,WAAW;CAE1B,MAAM,QAAQA,cAAAA,aAAa,aAAa;CACxC,MAAM,QAAyB;EAC7B,SAAS,CAAC,IAAI,MAAM,IAAI;EACxB,QAAQ,CAAC;GAAE;GAAO,MAAM;GAAW,OAAO;EAAc,CAAC;EAEzD,WAAW;GACT,MAAM;GACN,IAAI;GACJ,YAAY,KAAK,KAAK,QAAQ;IAC5B,MAAM,CAAC,KAAK,OAAO,IAAI,MAAM,GAAG;IAChC,MAAM,CAAC,WAAW,SAAS,IAAI,MAAM,GAAG;IACxC,MAAM,CAAC,WAAW,SAAS,IAAI,MAAM,GAAG;IAExC,MAAM,CAAC,OAAO,SACZ,WAAW,eAAe,YACtB,CAAC,WAAW,MAAM,WAAW,SAAS,IACtC,CAAC,WAAW,WAAW,WAAW,IAAI;IAC5C,OAAO;KACL,MAAM;KACN,IAAI;KACJ,YAAY,CACV;MACE,MAAM;MACN;MACA,QAAQ;MACR,QAAQ,MAAM;MACd,MAAM;OAAE,MAAM;OAAM,OAAOC,aAAAA,YAAY,OAAO,KAAK;MAAE;KACvD,GACA;MACE,MAAM;MACN;MACA,QAAQ;MACR,QAAQ,MAAM;MACd,MAAM;OAAE,MAAM;OAAM,OAAOA,aAAAA,YAAY,OAAO,KAAK;MAAE;KACvD,CACF;IACF;GACF,CAAC;EACH;EAEA,UAAU,WAAW,iBACjB,CAAC;GAAE;GAAO,QAAQ;GAAM,OAAO;EAAM,CAAC,IACtC,CACE;GAAE;GAAO,QAAQ,WAAW;GAAY,OAAO;EAAM,GACrD;GAAE;GAAO,QAAQ,WAAW;GAAiB,OAAO;EAAM,CAC5D;CACN;CAEA,MAAM,OAAO,MAAM,GAAG,cAAc,CAAC,WAAW,WAAW,yBAAyB,OAAO,CAAC,CAAC;CAE7F,MAAM,UAAU,WAAW;CAC3B,MAAM,UAAU,WAAW;CAC3B,MAAM,QAAQ,WAAW;CACzB,MAAM,QAAQ,WAAW;CAKzB,MAAM,QAAQ,IAAI,IAChB,KAAK,SAAS,UAAU;EACtB,MAAM,IAAI,GAAG,QAAQ,GAAGC,aAAAA,MAAM,OAAO,MAAM,QAAkB;EAC7D,MAAM,IAAI,GAAG,QAAQ,GAAGA,aAAAA,MAAM,OAAO,MAAM,QAAkB;EAC7D,OAAO,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,EAAE,GAAG,GAAG;CAClC,CAAC,CACH;CAEA,OAAO,KAAK,KAAK,QAAQ,MAAM,IAAI,GAAG,CAAC;AACzC"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ManyToManyCollection } from "../relations/ManyToManyCollection.cjs";
|
|
2
2
|
import { ManyToManyLargeCollection } from "../relations/ManyToManyLargeCollection.cjs";
|
|
3
|
-
import "../index.cjs";
|
|
4
3
|
import { EntityManager } from "../EntityManager.cjs";
|
|
5
4
|
import { Entity } from "../Entity.cjs";
|
|
6
5
|
import DataLoader from "dataloader";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manyToManyFindDataLoader.d.cts","names":[],"sources":["../../src/dataloaders/manyToManyFindDataLoader.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"manyToManyFindDataLoader.d.cts","names":[],"sources":["../../src/dataloaders/manyToManyFindDataLoader.ts"],"mappings":";;;;;;cAUa;;iBAGG,yBAAyB,UAAU,QAAQ,UAAU,QACnE,IAAI,eACJ,YAAY,qBAAqB,GAAG,KAAK,0BAA0B,GAAG,KACrE"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ManyToManyCollection } from "../relations/ManyToManyCollection.mjs";
|
|
2
2
|
import { ManyToManyLargeCollection } from "../relations/ManyToManyLargeCollection.mjs";
|
|
3
|
-
import "../index.mjs";
|
|
4
3
|
import { EntityManager } from "../EntityManager.mjs";
|
|
5
4
|
import { Entity } from "../Entity.mjs";
|
|
6
5
|
import DataLoader from "dataloader";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manyToManyFindDataLoader.d.mts","names":[],"sources":["../../src/dataloaders/manyToManyFindDataLoader.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"manyToManyFindDataLoader.d.mts","names":[],"sources":["../../src/dataloaders/manyToManyFindDataLoader.ts"],"mappings":";;;;;;cAUa;;iBAGG,yBAAyB,UAAU,QAAQ,UAAU,QACnE,IAAI,eACJ,YAAY,qBAAqB,GAAG,KAAK,0BAA0B,GAAG,KACrE"}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import { keyToNumber, tagId } from "../keys.js";
|
|
2
1
|
import { abbreviation } from "../utils.js";
|
|
3
|
-
import "../
|
|
4
|
-
import "../EntityManager.js";
|
|
5
|
-
import "../Entity.js";
|
|
2
|
+
import { keyToNumber, tagId } from "../keys.js";
|
|
6
3
|
//#region src/dataloaders/manyToManyFindDataLoader.ts
|
|
7
4
|
const manyToManyFindOperation = "m2m-find";
|
|
8
5
|
/** Batches m2m.find/include calls (i.e. that don't fully load the m2m relation). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manyToManyFindDataLoader.js","names":[],"sources":["../../src/dataloaders/manyToManyFindDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\n\nimport {
|
|
1
|
+
{"version":3,"file":"manyToManyFindDataLoader.js","names":[],"sources":["../../src/dataloaders/manyToManyFindDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\n\nimport type { Entity } from \"../Entity.ts\";\nimport type { EntityManager } from \"../EntityManager.ts\";\nimport { keyToNumber, tagId } from \"../keys.ts\";\nimport type { ParsedFindQuery } from \"../queries/find/QueryParser.ts\";\nimport type { ManyToManyCollection } from \"../relations/ManyToManyCollection.ts\";\nimport type { ManyToManyLargeCollection } from \"../relations/ManyToManyLargeCollection.ts\";\nimport { abbreviation } from \"../utils.ts\";\n\nexport const manyToManyFindOperation = \"m2m-find\";\n\n/** Batches m2m.find/include calls (i.e. that don't fully load the m2m relation). */\nexport function manyToManyFindDataLoader<T extends Entity, U extends Entity>(\n em: EntityManager,\n collection: ManyToManyCollection<T, U> | ManyToManyLargeCollection<T, U>,\n): DataLoader<string, boolean> {\n return em.getLoader(manyToManyFindOperation, collection.joinTableName, (keys) => load(collection, keys));\n}\n\nasync function load<T extends Entity, U extends Entity>(\n collection: ManyToManyCollection<T, U> | ManyToManyLargeCollection<T, U>,\n keys: ReadonlyArray<string>,\n): Promise<boolean[]> {\n const { joinTableName } = collection;\n const { em } = collection.entity;\n\n const alias = abbreviation(joinTableName);\n const query: ParsedFindQuery = {\n selects: [`\"${alias}\".*`],\n tables: [{ alias, join: \"primary\", table: joinTableName }],\n // Or together `where (tag_id = X and book_id = Y)` or `(book_id = B and tag_id = A)`\n condition: {\n kind: \"exp\",\n op: \"or\",\n conditions: keys.map((key) => {\n const [one, two] = key.split(\",\");\n const [columnOne, idOne] = one.split(\"=\");\n const [columnTwo, idTwo] = two.split(\"=\");\n // Pick the right meta i.e. tag_id --> TagMeta or book_id --> BookMeta\n const [meta1, meta2] =\n collection.columnName === columnOne\n ? [collection.meta, collection.otherMeta]\n : [collection.otherMeta, collection.meta];\n return {\n kind: \"exp\",\n op: \"and\",\n conditions: [\n {\n kind: \"column\",\n alias,\n column: columnOne,\n dbType: meta1.idDbType,\n cond: { kind: \"eq\", value: keyToNumber(meta1, idOne) },\n },\n {\n kind: \"column\",\n alias,\n column: columnTwo,\n dbType: meta2.idDbType,\n cond: { kind: \"eq\", value: keyToNumber(meta2, idTwo) },\n },\n ],\n };\n }),\n },\n // Id-less join tables have no surrogate id to order by, so order by the FK columns instead.\n orderBys: collection.hasJoinTableId\n ? [{ alias, column: \"id\", order: \"ASC\" }]\n : [\n { alias, column: collection.columnName, order: \"ASC\" },\n { alias, column: collection.otherColumnName, order: \"ASC\" },\n ],\n };\n\n const rows = await em[\"executeFind\"](collection.otherMeta, manyToManyFindOperation, query, {});\n\n const column1 = collection.columnName;\n const column2 = collection.otherColumnName;\n const meta1 = collection.meta;\n const meta2 = collection.otherMeta;\n\n // Because keys might come from either side of the m2m relationship, build\n // a list of both `foo_id=2,bar_id=3` and `bar_id=3,foo_id=2` to make the\n // final return value just a map of `Set.has`.\n const found = new Set(\n rows.flatMap((dbRow) => {\n const a = `${column1}=${tagId(meta1, dbRow[column1] as number)}`;\n const b = `${column2}=${tagId(meta2, dbRow[column2] as number)}`;\n return [`${a},${b}`, `${b},${a}`];\n }),\n );\n\n return keys.map((key) => found.has(key));\n}\n"],"mappings":";;;AAUA,MAAa,0BAA0B;;AAGvC,SAAgB,yBACd,IACA,YAC6B;CAC7B,OAAO,GAAG,UAAU,yBAAyB,WAAW,gBAAgB,SAAS,KAAK,YAAY,IAAI,CAAC;AACzG;AAEA,eAAe,KACb,YACA,MACoB;CACpB,MAAM,EAAE,kBAAkB;CAC1B,MAAM,EAAE,OAAO,WAAW;CAE1B,MAAM,QAAQ,aAAa,aAAa;CACxC,MAAM,QAAyB;EAC7B,SAAS,CAAC,IAAI,MAAM,IAAI;EACxB,QAAQ,CAAC;GAAE;GAAO,MAAM;GAAW,OAAO;EAAc,CAAC;EAEzD,WAAW;GACT,MAAM;GACN,IAAI;GACJ,YAAY,KAAK,KAAK,QAAQ;IAC5B,MAAM,CAAC,KAAK,OAAO,IAAI,MAAM,GAAG;IAChC,MAAM,CAAC,WAAW,SAAS,IAAI,MAAM,GAAG;IACxC,MAAM,CAAC,WAAW,SAAS,IAAI,MAAM,GAAG;IAExC,MAAM,CAAC,OAAO,SACZ,WAAW,eAAe,YACtB,CAAC,WAAW,MAAM,WAAW,SAAS,IACtC,CAAC,WAAW,WAAW,WAAW,IAAI;IAC5C,OAAO;KACL,MAAM;KACN,IAAI;KACJ,YAAY,CACV;MACE,MAAM;MACN;MACA,QAAQ;MACR,QAAQ,MAAM;MACd,MAAM;OAAE,MAAM;OAAM,OAAO,YAAY,OAAO,KAAK;MAAE;KACvD,GACA;MACE,MAAM;MACN;MACA,QAAQ;MACR,QAAQ,MAAM;MACd,MAAM;OAAE,MAAM;OAAM,OAAO,YAAY,OAAO,KAAK;MAAE;KACvD,CACF;IACF;GACF,CAAC;EACH;EAEA,UAAU,WAAW,iBACjB,CAAC;GAAE;GAAO,QAAQ;GAAM,OAAO;EAAM,CAAC,IACtC,CACE;GAAE;GAAO,QAAQ,WAAW;GAAY,OAAO;EAAM,GACrD;GAAE;GAAO,QAAQ,WAAW;GAAiB,OAAO;EAAM,CAC5D;CACN;CAEA,MAAM,OAAO,MAAM,GAAG,cAAc,CAAC,WAAW,WAAW,yBAAyB,OAAO,CAAC,CAAC;CAE7F,MAAM,UAAU,WAAW;CAC3B,MAAM,UAAU,WAAW;CAC3B,MAAM,QAAQ,WAAW;CACzB,MAAM,QAAQ,WAAW;CAKzB,MAAM,QAAQ,IAAI,IAChB,KAAK,SAAS,UAAU;EACtB,MAAM,IAAI,GAAG,QAAQ,GAAG,MAAM,OAAO,MAAM,QAAkB;EAC7D,MAAM,IAAI,GAAG,QAAQ,GAAG,MAAM,OAAO,MAAM,QAAkB;EAC7D,OAAO,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,EAAE,GAAG,GAAG;CAClC,CAAC,CACH;CAEA,OAAO,KAAK,KAAK,QAAQ,MAAM,IAAI,GAAG,CAAC;AACzC"}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const
|
|
2
|
+
const require_queries_find_QueryParser = require("../queries/find/QueryParser.cjs");
|
|
3
3
|
const require_utils = require("../utils.cjs");
|
|
4
|
-
require("../
|
|
5
|
-
require("../EntityManager.cjs");
|
|
6
|
-
require("../Entity.cjs");
|
|
7
|
-
const require_QueryParser = require("../QueryParser.cjs");
|
|
4
|
+
const require_keys = require("../keys.cjs");
|
|
8
5
|
//#region src/dataloaders/oneToManyFindDataLoader.ts
|
|
9
6
|
const oneToManyFindOperation = "o2m-find";
|
|
10
7
|
/** Batches o2m.find/include calls (i.e. that don't fully load the o2m relation). */
|
|
@@ -61,7 +58,7 @@ function oneToManyFindDataLoader(em, collection) {
|
|
|
61
58
|
order: "ASC"
|
|
62
59
|
}]
|
|
63
60
|
};
|
|
64
|
-
|
|
61
|
+
require_queries_find_QueryParser.addTablePerClassJoinsAndClassTag(query, meta, alias, true);
|
|
65
62
|
const rows = await em["executeFind"](collection.otherMeta, oneToManyFindOperation, query, {});
|
|
66
63
|
em.hydrate(collection.otherMeta.cstr, rows);
|
|
67
64
|
return keys.map((k) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oneToManyFindDataLoader.cjs","names":["abbreviation","keyToNumber"],"sources":["../../src/dataloaders/oneToManyFindDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\n\nimport {
|
|
1
|
+
{"version":3,"file":"oneToManyFindDataLoader.cjs","names":["abbreviation","keyToNumber"],"sources":["../../src/dataloaders/oneToManyFindDataLoader.ts"],"sourcesContent":["import type DataLoader from \"dataloader\";\n\nimport type { Entity } from \"../Entity.ts\";\nimport type { EntityManager } from \"../EntityManager.ts\";\nimport { keyToNumber } from \"../keys.ts\";\nimport { type ParsedFindQuery, addTablePerClassJoinsAndClassTag } from \"../queries/find/QueryParser.ts\";\nimport type { OneToManyCollection } from \"../relations/OneToManyCollection.ts\";\nimport type { OneToManyLargeCollection } from \"../relations/OneToManyLargeCollection.ts\";\nimport { abbreviation } from \"../utils.ts\";\n\nexport const oneToManyFindOperation = \"o2m-find\";\n\n/** Batches o2m.find/include calls (i.e. that don't fully load the o2m relation). */\nexport function oneToManyFindDataLoader<T extends Entity, U extends Entity>(\n em: EntityManager,\n collection: OneToManyCollection<T, U> | OneToManyLargeCollection<T, U>,\n): DataLoader<string, U | undefined> {\n const { meta } = collection;\n const batchKey = `${meta.tableName}-${collection.fieldName}`;\n return em.getLoader(oneToManyFindOperation, batchKey, async (keys) => {\n const { em } = collection.entity;\n\n const meta = collection.otherMeta;\n const alias = abbreviation(meta.tableName);\n const query: ParsedFindQuery = {\n selects: [`\"${alias}\".*`],\n tables: [{ alias, join: \"primary\", table: meta.tableName }],\n // Or together `where (id = X and book_id = Y)`\n condition: {\n kind: \"exp\",\n op: \"or\",\n conditions: keys.map((key) => {\n const [one, two] = key.split(\",\");\n // columnOne is the `id=`, so is really the \"other\" side of the o2m\n const [columnOne, idOne] = one.split(\"=\");\n const [columnTwo, idTwo] = two.split(\"=\");\n const [meta1, meta2] = [collection.otherMeta, collection.meta];\n // Pick the right meta i.e. tag_id --> TagMeta or book_id --> BookMeta\n return {\n kind: \"exp\",\n op: \"and\",\n conditions: [\n {\n kind: \"column\",\n alias,\n column: columnOne,\n dbType: meta1.idDbType,\n cond: { kind: \"eq\", value: keyToNumber(meta1, idOne) },\n },\n {\n kind: \"column\",\n alias,\n column: columnTwo,\n dbType: meta2.idDbType,\n cond: { kind: \"eq\", value: keyToNumber(meta2, idTwo) },\n },\n ],\n };\n }),\n },\n orderBys: [{ alias, column: \"id\", order: \"ASC\" }],\n };\n\n addTablePerClassJoinsAndClassTag(query, meta, alias, true);\n // Skip maybeAddOrderBy b/c we're only returning 1 result\n // maybeAddNotSoftDeleted(conditions, meta, alias, \"include\");\n\n const rows = await em[\"executeFind\"](collection.otherMeta, oneToManyFindOperation, query, {});\n em.hydrate(collection.otherMeta.cstr, rows);\n\n // Decode `id=b:1,author_id=a:1`\n return keys.map((k) => {\n const [otherKey, parentKey] = k.split(\",\");\n const [, otherId] = otherKey.split(\"=\");\n const [, parentId] = parentKey.split(\"=\");\n const other = em.getEntity(otherId) as U;\n // We have may fetched `other` for a different parent in our batch\n const isMine = (other as any)?.[collection.otherFieldName].id === parentId;\n return isMine ? other : undefined;\n });\n });\n}\n"],"mappings":";;;;;AAUA,MAAa,yBAAyB;;AAGtC,SAAgB,wBACd,IACA,YACmC;CACnC,MAAM,EAAE,SAAS;CACjB,MAAM,WAAW,GAAG,KAAK,UAAU,GAAG,WAAW;CACjD,OAAO,GAAG,UAAU,wBAAwB,UAAU,OAAO,SAAS;EACpE,MAAM,EAAE,OAAO,WAAW;EAE1B,MAAM,OAAO,WAAW;EACxB,MAAM,QAAQA,cAAAA,aAAa,KAAK,SAAS;EACzC,MAAM,QAAyB;GAC7B,SAAS,CAAC,IAAI,MAAM,IAAI;GACxB,QAAQ,CAAC;IAAE;IAAO,MAAM;IAAW,OAAO,KAAK;GAAU,CAAC;GAE1D,WAAW;IACT,MAAM;IACN,IAAI;IACJ,YAAY,KAAK,KAAK,QAAQ;KAC5B,MAAM,CAAC,KAAK,OAAO,IAAI,MAAM,GAAG;KAEhC,MAAM,CAAC,WAAW,SAAS,IAAI,MAAM,GAAG;KACxC,MAAM,CAAC,WAAW,SAAS,IAAI,MAAM,GAAG;KACxC,MAAM,CAAC,OAAO,SAAS,CAAC,WAAW,WAAW,WAAW,IAAI;KAE7D,OAAO;MACL,MAAM;MACN,IAAI;MACJ,YAAY,CACV;OACE,MAAM;OACN;OACA,QAAQ;OACR,QAAQ,MAAM;OACd,MAAM;QAAE,MAAM;QAAM,OAAOC,aAAAA,YAAY,OAAO,KAAK;OAAE;MACvD,GACA;OACE,MAAM;OACN;OACA,QAAQ;OACR,QAAQ,MAAM;OACd,MAAM;QAAE,MAAM;QAAM,OAAOA,aAAAA,YAAY,OAAO,KAAK;OAAE;MACvD,CACF;KACF;IACF,CAAC;GACH;GACA,UAAU,CAAC;IAAE;IAAO,QAAQ;IAAM,OAAO;GAAM,CAAC;EAClD;EAEA,iCAAA,iCAAiC,OAAO,MAAM,OAAO,IAAI;EAIzD,MAAM,OAAO,MAAM,GAAG,cAAc,CAAC,WAAW,WAAW,wBAAwB,OAAO,CAAC,CAAC;EAC5F,GAAG,QAAQ,WAAW,UAAU,MAAM,IAAI;EAG1C,OAAO,KAAK,KAAK,MAAM;GACrB,MAAM,CAAC,UAAU,aAAa,EAAE,MAAM,GAAG;GACzC,MAAM,GAAG,WAAW,SAAS,MAAM,GAAG;GACtC,MAAM,GAAG,YAAY,UAAU,MAAM,GAAG;GACxC,MAAM,QAAQ,GAAG,UAAU,OAAO;GAGlC,OADgB,QAAgB,WAAW,eAAe,CAAC,OAAO,WAClD,QAAQ,KAAA;EAC1B,CAAC;CACH,CAAC;AACH"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { OneToManyCollection } from "../relations/OneToManyCollection.cjs";
|
|
2
2
|
import { OneToManyLargeCollection } from "../relations/OneToManyLargeCollection.cjs";
|
|
3
|
-
import "../index.cjs";
|
|
4
3
|
import { EntityManager } from "../EntityManager.cjs";
|
|
5
4
|
import { Entity } from "../Entity.cjs";
|
|
6
5
|
import DataLoader from "dataloader";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oneToManyFindDataLoader.d.cts","names":[],"sources":["../../src/dataloaders/oneToManyFindDataLoader.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"oneToManyFindDataLoader.d.cts","names":[],"sources":["../../src/dataloaders/oneToManyFindDataLoader.ts"],"mappings":";;;;;;cAUa;;iBAGG,wBAAwB,UAAU,QAAQ,UAAU,QAClE,IAAI,eACJ,YAAY,oBAAoB,GAAG,KAAK,yBAAyB,GAAG,KACnE,mBAAmB"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { OneToManyCollection } from "../relations/OneToManyCollection.mjs";
|
|
2
2
|
import { OneToManyLargeCollection } from "../relations/OneToManyLargeCollection.mjs";
|
|
3
|
-
import "../index.mjs";
|
|
4
3
|
import { EntityManager } from "../EntityManager.mjs";
|
|
5
4
|
import { Entity } from "../Entity.mjs";
|
|
6
5
|
import DataLoader from "dataloader";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oneToManyFindDataLoader.d.mts","names":[],"sources":["../../src/dataloaders/oneToManyFindDataLoader.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"oneToManyFindDataLoader.d.mts","names":[],"sources":["../../src/dataloaders/oneToManyFindDataLoader.ts"],"mappings":";;;;;;cAUa;;iBAGG,wBAAwB,UAAU,QAAQ,UAAU,QAClE,IAAI,eACJ,YAAY,oBAAoB,GAAG,KAAK,yBAAyB,GAAG,KACnE,mBAAmB"}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { addTablePerClassJoinsAndClassTag } from "../queries/find/QueryParser.js";
|
|
2
2
|
import { abbreviation } from "../utils.js";
|
|
3
|
-
import "../
|
|
4
|
-
import "../EntityManager.js";
|
|
5
|
-
import "../Entity.js";
|
|
6
|
-
import { addTablePerClassJoinsAndClassTag } from "../QueryParser.js";
|
|
3
|
+
import { keyToNumber } from "../keys.js";
|
|
7
4
|
//#region src/dataloaders/oneToManyFindDataLoader.ts
|
|
8
5
|
const oneToManyFindOperation = "o2m-find";
|
|
9
6
|
/** Batches o2m.find/include calls (i.e. that don't fully load the o2m relation). */
|