@goatlab/fluent 0.7.38 → 0.7.40
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/dist/BaseConnector.d.ts +112 -0
- package/dist/BaseConnector.js +343 -0
- package/dist/BaseConnector.js.map +1 -0
- package/dist/Fluent.d.ts +11 -0
- package/dist/Fluent.js +27 -0
- package/dist/Fluent.js.map +1 -0
- package/dist/FluentConnectorInterface.d.ts +17 -0
- package/dist/FluentConnectorInterface.js +3 -0
- package/dist/FluentConnectorInterface.js.map +1 -0
- package/dist/FluentEntity.d.ts +7 -0
- package/dist/FluentEntity.js +29 -0
- package/dist/FluentEntity.js.map +1 -0
- package/dist/TypeOrmConnector/TypeOrmConnector.d.ts +123 -0
- package/dist/TypeOrmConnector/TypeOrmConnector.js +760 -0
- package/dist/TypeOrmConnector/TypeOrmConnector.js.map +1 -0
- package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoBaseAggregations.d.ts +12 -0
- package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoBaseAggregations.js +167 -0
- package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoBaseAggregations.js.map +1 -0
- package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoFindAggregatedQuery.d.ts +11 -0
- package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoFindAggregatedQuery.js +52 -0
- package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoFindAggregatedQuery.js.map +1 -0
- package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoOrderBy.d.ts +4 -0
- package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoOrderBy.js +20 -0
- package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoOrderBy.js.map +1 -0
- package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoSelect.d.ts +7 -0
- package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoSelect.js +19 -0
- package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoSelect.js.map +1 -0
- package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoWhere.d.ts +11 -0
- package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoWhere.js +173 -0
- package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoWhere.js.map +1 -0
- package/dist/TypeOrmConnector/queryBuilder/sql/getQueryBuilderWhere.d.ts +13 -0
- package/dist/TypeOrmConnector/queryBuilder/sql/getQueryBuilderWhere.js +207 -0
- package/dist/TypeOrmConnector/queryBuilder/sql/getQueryBuilderWhere.js.map +1 -0
- package/dist/TypeOrmConnector/queryBuilder/sql/getTypeOrmWhere.d.ts +11 -0
- package/dist/TypeOrmConnector/queryBuilder/sql/getTypeOrmWhere.js +214 -0
- package/dist/TypeOrmConnector/queryBuilder/sql/getTypeOrmWhere.js.map +1 -0
- package/dist/TypeOrmConnector/util/clearEmpties.d.ts +7 -0
- package/dist/TypeOrmConnector/util/clearEmpties.js +33 -0
- package/dist/TypeOrmConnector/util/clearEmpties.js.map +1 -0
- package/dist/TypeOrmConnector/util/extractConditions.d.ts +12 -0
- package/dist/TypeOrmConnector/util/extractConditions.js +89 -0
- package/dist/TypeOrmConnector/util/extractConditions.js.map +1 -0
- package/dist/TypeOrmConnector/util/extractInclude.d.ts +2 -0
- package/dist/TypeOrmConnector/util/extractInclude.js +26 -0
- package/dist/TypeOrmConnector/util/extractInclude.js.map +1 -0
- package/dist/TypeOrmConnector/util/extractMetadataFromKeys.d.ts +12 -0
- package/dist/TypeOrmConnector/util/extractMetadataFromKeys.js +49 -0
- package/dist/TypeOrmConnector/util/extractMetadataFromKeys.js.map +1 -0
- package/dist/TypeOrmConnector/util/extractOrderBy.d.ts +2 -0
- package/dist/TypeOrmConnector/util/extractOrderBy.js +24 -0
- package/dist/TypeOrmConnector/util/extractOrderBy.js.map +1 -0
- package/dist/TypeOrmConnector/util/getRelationsFromModelGenerator.d.ts +19 -0
- package/dist/TypeOrmConnector/util/getRelationsFromModelGenerator.js +27 -0
- package/dist/TypeOrmConnector/util/getRelationsFromModelGenerator.js.map +1 -0
- package/dist/TypeOrmConnector/util/getSelectedKeysFromRawSql.d.ts +6 -0
- package/dist/TypeOrmConnector/util/getSelectedKeysFromRawSql.js +29 -0
- package/dist/TypeOrmConnector/util/getSelectedKeysFromRawSql.js.map +1 -0
- package/dist/TypeOrmConnector/util/isAnyObject.d.ts +1 -0
- package/dist/TypeOrmConnector/util/isAnyObject.js +8 -0
- package/dist/TypeOrmConnector/util/isAnyObject.js.map +1 -0
- package/dist/TypeOrmConnector/util/nestQueryResults.d.ts +2 -0
- package/dist/TypeOrmConnector/util/nestQueryResults.js +38 -0
- package/dist/TypeOrmConnector/util/nestQueryResults.js.map +1 -0
- package/dist/core/Loopback/build-schema.d.ts +148 -0
- package/dist/core/Loopback/build-schema.js +443 -0
- package/dist/core/Loopback/build-schema.js.map +1 -0
- package/dist/core/Loopback/common-types.d.ts +96 -0
- package/dist/core/Loopback/common-types.js +24 -0
- package/dist/core/Loopback/common-types.js.map +1 -0
- package/dist/core/Loopback/json-to-schema.d.ts +41 -0
- package/dist/core/Loopback/json-to-schema.js +113 -0
- package/dist/core/Loopback/json-to-schema.js.map +1 -0
- package/dist/core/Loopback/metadata.d.ts +16 -0
- package/dist/core/Loopback/metadata.js +49 -0
- package/dist/core/Loopback/metadata.js.map +1 -0
- package/dist/core/Loopback/model.d.ts +233 -0
- package/dist/core/Loopback/model.js +387 -0
- package/dist/core/Loopback/model.js.map +1 -0
- package/dist/core/Loopback/query.d.ts +394 -0
- package/dist/core/Loopback/query.js +482 -0
- package/dist/core/Loopback/query.js.map +1 -0
- package/dist/core/Loopback/relation.types.d.ts +141 -0
- package/dist/core/Loopback/relation.types.js +18 -0
- package/dist/core/Loopback/relation.types.js.map +1 -0
- package/dist/core/Loopback/type-resolver.d.ts +42 -0
- package/dist/core/Loopback/type-resolver.js +60 -0
- package/dist/core/Loopback/type-resolver.js.map +1 -0
- package/dist/core/Loopback/type.d.ts +38 -0
- package/dist/core/Loopback/type.js +7 -0
- package/dist/core/Loopback/type.js.map +1 -0
- package/dist/core/Nestjs/applyDecorators.d.ts +10 -0
- package/dist/core/Nestjs/applyDecorators.js +26 -0
- package/dist/core/Nestjs/applyDecorators.js.map +1 -0
- package/dist/core/Nestjs/types/common.d.ts +16 -0
- package/dist/core/Nestjs/types/common.js +38 -0
- package/dist/core/Nestjs/types/common.js.map +1 -0
- package/dist/core/Nestjs/types/decorators/api-hide-property.decorator.d.ts +1 -0
- package/dist/core/Nestjs/types/decorators/api-hide-property.decorator.js +8 -0
- package/dist/core/Nestjs/types/decorators/api-hide-property.decorator.js.map +1 -0
- package/dist/core/Nestjs/types/decorators/api-property.decorator.d.ts +27 -0
- package/dist/core/Nestjs/types/decorators/api-property.decorator.js +66 -0
- package/dist/core/Nestjs/types/decorators/api-property.decorator.js.map +1 -0
- package/dist/core/Nestjs/types/decorators/apply-is-optional.decorator.d.ts +5 -0
- package/dist/core/Nestjs/types/decorators/apply-is-optional.decorator.js +136 -0
- package/dist/core/Nestjs/types/decorators/apply-is-optional.decorator.js.map +1 -0
- package/dist/core/Nestjs/types/decorators/args-type.decorator.d.ts +4 -0
- package/dist/core/Nestjs/types/decorators/args-type.decorator.js +24 -0
- package/dist/core/Nestjs/types/decorators/args-type.decorator.js.map +1 -0
- package/dist/core/Nestjs/types/decorators/create-property.decorator.d.ts +2 -0
- package/dist/core/Nestjs/types/decorators/create-property.decorator.js +55 -0
- package/dist/core/Nestjs/types/decorators/create-property.decorator.js.map +1 -0
- package/dist/core/Nestjs/types/decorators/directive.decorator.d.ts +4 -0
- package/dist/core/Nestjs/types/decorators/directive.decorator.js +39 -0
- package/dist/core/Nestjs/types/decorators/directive.decorator.js.map +1 -0
- package/dist/core/Nestjs/types/decorators/extensions.decorator.d.ts +4 -0
- package/dist/core/Nestjs/types/decorators/extensions.decorator.js +28 -0
- package/dist/core/Nestjs/types/decorators/extensions.decorator.js.map +1 -0
- package/dist/core/Nestjs/types/decorators/field.decorator.d.ts +48 -0
- package/dist/core/Nestjs/types/decorators/field.decorator.js +63 -0
- package/dist/core/Nestjs/types/decorators/field.decorator.js.map +1 -0
- package/dist/core/Nestjs/types/decorators/input-type.decorator.d.ts +25 -0
- package/dist/core/Nestjs/types/decorators/input-type.decorator.js +29 -0
- package/dist/core/Nestjs/types/decorators/input-type.decorator.js.map +1 -0
- package/dist/core/Nestjs/types/decorators/interface-type.decorator.d.ts +33 -0
- package/dist/core/Nestjs/types/decorators/interface-type.decorator.js +35 -0
- package/dist/core/Nestjs/types/decorators/interface-type.decorator.js.map +1 -0
- package/dist/core/Nestjs/types/decorators/partial-type.helper.d.ts +3 -0
- package/dist/core/Nestjs/types/decorators/partial-type.helper.js +46 -0
- package/dist/core/Nestjs/types/decorators/partial-type.helper.js.map +1 -0
- package/dist/core/Nestjs/types/errors/cannot-determine-host-type.error.d.ts +3 -0
- package/dist/core/Nestjs/types/errors/cannot-determine-host-type.error.js +10 -0
- package/dist/core/Nestjs/types/errors/cannot-determine-host-type.error.js.map +1 -0
- package/dist/core/Nestjs/types/errors/directive-parsing.error.d.ts +3 -0
- package/dist/core/Nestjs/types/errors/directive-parsing.error.js +10 -0
- package/dist/core/Nestjs/types/errors/directive-parsing.error.js.map +1 -0
- package/dist/core/Nestjs/types/errors/unable-to-find-fields.error.d.ts +3 -0
- package/dist/core/Nestjs/types/errors/unable-to-find-fields.error.js +10 -0
- package/dist/core/Nestjs/types/errors/unable-to-find-fields.error.js.map +1 -0
- package/dist/core/Nestjs/types/errors/undefined-type.error.d.ts +3 -0
- package/dist/core/Nestjs/types/errors/undefined-type.error.js +11 -0
- package/dist/core/Nestjs/types/errors/undefined-type.error.js.map +1 -0
- package/dist/core/Nestjs/types/interfaces/add-class-type-metadata.util.d.ts +3 -0
- package/dist/core/Nestjs/types/interfaces/add-class-type-metadata.util.js +11 -0
- package/dist/core/Nestjs/types/interfaces/add-class-type-metadata.util.js.map +1 -0
- package/dist/core/Nestjs/types/interfaces/base-type-options.interface.d.ts +11 -0
- package/dist/core/Nestjs/types/interfaces/base-type-options.interface.js +3 -0
- package/dist/core/Nestjs/types/interfaces/base-type-options.interface.js.map +1 -0
- package/dist/core/Nestjs/types/interfaces/class-decorator-factory.interface.d.ts +5 -0
- package/dist/core/Nestjs/types/interfaces/class-decorator-factory.interface.js +3 -0
- package/dist/core/Nestjs/types/interfaces/class-decorator-factory.interface.js.map +1 -0
- package/dist/core/Nestjs/types/interfaces/complexity.interface.d.ts +11 -0
- package/dist/core/Nestjs/types/interfaces/complexity.interface.js +3 -0
- package/dist/core/Nestjs/types/interfaces/complexity.interface.js.map +1 -0
- package/dist/core/Nestjs/types/interfaces/field-middleware.interface.d.ts +15 -0
- package/dist/core/Nestjs/types/interfaces/field-middleware.interface.js +3 -0
- package/dist/core/Nestjs/types/interfaces/field-middleware.interface.js.map +1 -0
- package/dist/core/Nestjs/types/interfaces/open-api-spec.interface.d.ts +239 -0
- package/dist/core/Nestjs/types/interfaces/open-api-spec.interface.js +7 -0
- package/dist/core/Nestjs/types/interfaces/open-api-spec.interface.js.map +1 -0
- package/dist/core/Nestjs/types/interfaces/resolve-type-fn.interface.d.ts +2 -0
- package/dist/core/Nestjs/types/interfaces/resolve-type-fn.interface.js +3 -0
- package/dist/core/Nestjs/types/interfaces/resolve-type-fn.interface.js.map +1 -0
- package/dist/core/Nestjs/types/interfaces/return-type-func.interface.d.ts +5 -0
- package/dist/core/Nestjs/types/interfaces/return-type-func.interface.js +3 -0
- package/dist/core/Nestjs/types/interfaces/return-type-func.interface.js.map +1 -0
- package/dist/core/Nestjs/types/interfaces/schema-object-metadata.interface.d.ts +9 -0
- package/dist/core/Nestjs/types/interfaces/schema-object-metadata.interface.js +3 -0
- package/dist/core/Nestjs/types/interfaces/schema-object-metadata.interface.js.map +1 -0
- package/dist/core/Nestjs/types/interfaces/type-options.interface.d.ts +5 -0
- package/dist/core/Nestjs/types/interfaces/type-options.interface.js +3 -0
- package/dist/core/Nestjs/types/interfaces/type-options.interface.js.map +1 -0
- package/dist/core/Nestjs/types/lazy-metadata.storage.d.ts +15 -0
- package/dist/core/Nestjs/types/lazy-metadata.storage.js +68 -0
- package/dist/core/Nestjs/types/lazy-metadata.storage.js.map +1 -0
- package/dist/core/Nestjs/types/metadata/class.metadata.d.ts +11 -0
- package/dist/core/Nestjs/types/metadata/class.metadata.js +3 -0
- package/dist/core/Nestjs/types/metadata/class.metadata.js.map +1 -0
- package/dist/core/Nestjs/types/metadata/directive.metadata.d.ts +8 -0
- package/dist/core/Nestjs/types/metadata/directive.metadata.js +3 -0
- package/dist/core/Nestjs/types/metadata/directive.metadata.js.map +1 -0
- package/dist/core/Nestjs/types/metadata/enum.metadata.d.ts +11 -0
- package/dist/core/Nestjs/types/metadata/enum.metadata.js +3 -0
- package/dist/core/Nestjs/types/metadata/enum.metadata.js.map +1 -0
- package/dist/core/Nestjs/types/metadata/extensions.metadata.d.ts +8 -0
- package/dist/core/Nestjs/types/metadata/extensions.metadata.js +3 -0
- package/dist/core/Nestjs/types/metadata/extensions.metadata.js.map +1 -0
- package/dist/core/Nestjs/types/metadata/index.d.ts +8 -0
- package/dist/core/Nestjs/types/metadata/index.js +12 -0
- package/dist/core/Nestjs/types/metadata/index.js.map +1 -0
- package/dist/core/Nestjs/types/metadata/interface.metadata.d.ts +6 -0
- package/dist/core/Nestjs/types/metadata/interface.metadata.js +3 -0
- package/dist/core/Nestjs/types/metadata/interface.metadata.js.map +1 -0
- package/dist/core/Nestjs/types/metadata/object-type.metadata.d.ts +4 -0
- package/dist/core/Nestjs/types/metadata/object-type.metadata.js +3 -0
- package/dist/core/Nestjs/types/metadata/object-type.metadata.js.map +1 -0
- package/dist/core/Nestjs/types/metadata/param.metadata.d.ts +18 -0
- package/dist/core/Nestjs/types/metadata/param.metadata.js +3 -0
- package/dist/core/Nestjs/types/metadata/param.metadata.js.map +1 -0
- package/dist/core/Nestjs/types/metadata/property.metadata.d.ts +20 -0
- package/dist/core/Nestjs/types/metadata/property.metadata.js +3 -0
- package/dist/core/Nestjs/types/metadata/property.metadata.js.map +1 -0
- package/dist/core/Nestjs/types/metadata/resolver.metadata.d.ts +34 -0
- package/dist/core/Nestjs/types/metadata/resolver.metadata.js +3 -0
- package/dist/core/Nestjs/types/metadata/resolver.metadata.js.map +1 -0
- package/dist/core/Nestjs/types/metadata/union.metadata.d.ts +9 -0
- package/dist/core/Nestjs/types/metadata/union.metadata.js +3 -0
- package/dist/core/Nestjs/types/metadata/union.metadata.js.map +1 -0
- package/dist/core/Nestjs/types/object-type.decorator.d.ts +32 -0
- package/dist/core/Nestjs/types/object-type.decorator.js +33 -0
- package/dist/core/Nestjs/types/object-type.decorator.js.map +1 -0
- package/dist/core/Nestjs/types/omit-type.d.ts +2 -0
- package/dist/core/Nestjs/types/omit-type.js +34 -0
- package/dist/core/Nestjs/types/omit-type.js.map +1 -0
- package/dist/core/Nestjs/types/reflection.utils.d.ts +15 -0
- package/dist/core/Nestjs/types/reflection.utils.js +65 -0
- package/dist/core/Nestjs/types/reflection.utils.js.map +1 -0
- package/dist/core/Nestjs/types/set-metadata.decorator.d.ts +20 -0
- package/dist/core/Nestjs/types/set-metadata.decorator.js +33 -0
- package/dist/core/Nestjs/types/set-metadata.decorator.js.map +1 -0
- package/dist/core/Nestjs/types/type-metadata.storage.d.ts +73 -0
- package/dist/core/Nestjs/types/type-metadata.storage.js +351 -0
- package/dist/core/Nestjs/types/type-metadata.storage.js.map +1 -0
- package/dist/core/Nestjs/types/utils/enum.utils.d.ts +3 -0
- package/dist/core/Nestjs/types/utils/enum.utils.js +31 -0
- package/dist/core/Nestjs/types/utils/enum.utils.js.map +1 -0
- package/dist/core/Nestjs/types/utils/get-fields-and-decorator.util.d.ts +13 -0
- package/dist/core/Nestjs/types/utils/get-fields-and-decorator.util.js +72 -0
- package/dist/core/Nestjs/types/utils/get-fields-and-decorator.util.js.map +1 -0
- package/dist/core/Nestjs/types/utils/mapped-types.utils.d.ts +2 -0
- package/dist/core/Nestjs/types/utils/mapped-types.utils.js +38 -0
- package/dist/core/Nestjs/types/utils/mapped-types.utils.js.map +1 -0
- package/dist/core/Nestjs/types/utils/model-properties-accessor.d.ts +6 -0
- package/dist/core/Nestjs/types/utils/model-properties-accessor.js +37 -0
- package/dist/core/Nestjs/types/utils/model-properties-accessor.js.map +1 -0
- package/dist/core/Nestjs/types/utils/type-helpers.utils.d.ts +2 -0
- package/dist/core/Nestjs/types/utils/type-helpers.utils.js +16 -0
- package/dist/core/Nestjs/types/utils/type-helpers.utils.js.map +1 -0
- package/dist/core/types.d.ts +23 -0
- package/dist/core/types.js +31 -0
- package/dist/core/types.js.map +1 -0
- package/dist/decorators.d.ts +92 -0
- package/dist/decorators.js +162 -0
- package/dist/decorators.js.map +1 -0
- package/dist/generatorDatasource.d.ts +2 -0
- package/dist/generatorDatasource.js +13 -0
- package/dist/generatorDatasource.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +50 -0
- package/dist/index.js.map +1 -0
- package/dist/loadRelations.d.ts +12 -0
- package/dist/loadRelations.js +139 -0
- package/dist/loadRelations.js.map +1 -0
- package/dist/outputKeys.d.ts +2 -0
- package/dist/outputKeys.js +18 -0
- package/dist/outputKeys.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types.d.ts +104 -0
- package/dist/types.js +23 -0
- package/dist/types.js.map +1 -0
- package/package.json +48 -24
|
@@ -0,0 +1,760 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TypeOrmConnector = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const js_utils_1 = require("@goatlab/js-utils");
|
|
6
|
+
const bson_1 = require("bson");
|
|
7
|
+
const BaseConnector_1 = require("../BaseConnector");
|
|
8
|
+
const outputKeys_1 = require("../outputKeys");
|
|
9
|
+
const generatorDatasource_1 = require("../generatorDatasource");
|
|
10
|
+
const getMongoWhere_1 = require("./queryBuilder/mongodb/getMongoWhere");
|
|
11
|
+
const getRelationsFromModelGenerator_1 = require("./util/getRelationsFromModelGenerator");
|
|
12
|
+
const getMongoFindAggregatedQuery_1 = require("./queryBuilder/mongodb/getMongoFindAggregatedQuery");
|
|
13
|
+
const extractInclude_1 = require("./util/extractInclude");
|
|
14
|
+
const extractOrderBy_1 = require("./util/extractOrderBy");
|
|
15
|
+
const getTypeOrmWhere_1 = require("./queryBuilder/sql/getTypeOrmWhere");
|
|
16
|
+
const getQueryBuilderWhere_1 = require("./queryBuilder/sql/getQueryBuilderWhere");
|
|
17
|
+
const clearEmpties_1 = require("./util/clearEmpties");
|
|
18
|
+
class TypeOrmConnector extends BaseConnector_1.BaseConnector {
|
|
19
|
+
constructor({ entity, dataSource, inputSchema, outputSchema }) {
|
|
20
|
+
super();
|
|
21
|
+
this.dataSource = dataSource;
|
|
22
|
+
this.inputSchema = inputSchema;
|
|
23
|
+
this.outputSchema =
|
|
24
|
+
outputSchema || inputSchema;
|
|
25
|
+
this.entity = entity;
|
|
26
|
+
}
|
|
27
|
+
initDB() {
|
|
28
|
+
this.repository = this.dataSource.getRepository(this.entity);
|
|
29
|
+
this.isMongoDB =
|
|
30
|
+
this.repository.metadata.connection.driver.options.type === 'mongodb';
|
|
31
|
+
if (this.isMongoDB) {
|
|
32
|
+
this.repository = this.dataSource.getMongoRepository(this.entity);
|
|
33
|
+
}
|
|
34
|
+
const relationShipBuilder = generatorDatasource_1.modelGeneratorDataSource.getRepository(this.entity);
|
|
35
|
+
const { relations } = (0, getRelationsFromModelGenerator_1.getRelationsFromModelGenerator)(relationShipBuilder);
|
|
36
|
+
this.modelRelations = relations;
|
|
37
|
+
this.outputKeys = (0, outputKeys_1.getOutputKeys)(relationShipBuilder) || [];
|
|
38
|
+
return 1;
|
|
39
|
+
}
|
|
40
|
+
// CREATE
|
|
41
|
+
/**
|
|
42
|
+
* Insert the data object into the database.
|
|
43
|
+
* @param data
|
|
44
|
+
*/
|
|
45
|
+
async insert(data) {
|
|
46
|
+
this.initDB();
|
|
47
|
+
// Validate Input
|
|
48
|
+
const validatedData = this.inputSchema.parse(data);
|
|
49
|
+
if (this.isMongoDB && validatedData['id']) {
|
|
50
|
+
validatedData['_id'] = new bson_1.ObjectId(validatedData['id']);
|
|
51
|
+
delete validatedData['id'];
|
|
52
|
+
}
|
|
53
|
+
// Only Way to Skip the DeepPartial requirement from TypeORm
|
|
54
|
+
let datum = await this.repository.save(validatedData);
|
|
55
|
+
if (this.isMongoDB) {
|
|
56
|
+
datum['id'] = datum['id'].toString();
|
|
57
|
+
}
|
|
58
|
+
// Validate Output
|
|
59
|
+
return this.outputSchema.parse((0, clearEmpties_1.clearEmpties)(js_utils_1.Objects.deleteNulls(datum)));
|
|
60
|
+
}
|
|
61
|
+
async insertMany(data) {
|
|
62
|
+
this.initDB();
|
|
63
|
+
const validatedData = this.inputSchema.array().parse(data);
|
|
64
|
+
//
|
|
65
|
+
const inserted = await this.repository.save(validatedData, {
|
|
66
|
+
chunk: data.length / 300
|
|
67
|
+
});
|
|
68
|
+
return this.outputSchema.array().parse(inserted.map(d => {
|
|
69
|
+
if (this.isMongoDB && d['id']) {
|
|
70
|
+
d['id'] = d['id'].toString();
|
|
71
|
+
}
|
|
72
|
+
return (0, clearEmpties_1.clearEmpties)(js_utils_1.Objects.deleteNulls(d));
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
75
|
+
// READ
|
|
76
|
+
async findMany(query) {
|
|
77
|
+
this.initDB();
|
|
78
|
+
const requiresCustomQuery = query?.include && Object.keys(query.include).length;
|
|
79
|
+
if (this.isMongoDB) {
|
|
80
|
+
const results = await this.customMongoRelatedFind(query);
|
|
81
|
+
return results;
|
|
82
|
+
}
|
|
83
|
+
if (requiresCustomQuery) {
|
|
84
|
+
const { queryBuilder: customQuery, selectedKeys } = this.customTypeOrmRelatedFind({
|
|
85
|
+
fluentQuery: query
|
|
86
|
+
});
|
|
87
|
+
customQuery.select(selectedKeys);
|
|
88
|
+
// Get the count for pagination
|
|
89
|
+
// TODO: do the pagination
|
|
90
|
+
let [result, count] = await customQuery.getManyAndCount();
|
|
91
|
+
// Apply select filtering if needed
|
|
92
|
+
//TODO: We have to validate the results!
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
// Generate normal TypeORM Query
|
|
96
|
+
const generatedQuery = this.generateTypeOrmQuery(query);
|
|
97
|
+
let [found, count] = await this.repository.findAndCount(generatedQuery);
|
|
98
|
+
found.map(d => {
|
|
99
|
+
if (this.isMongoDB && d['_id']) {
|
|
100
|
+
d.id = d['_id'].toString();
|
|
101
|
+
}
|
|
102
|
+
(0, clearEmpties_1.clearEmpties)(js_utils_1.Objects.deleteNulls(d));
|
|
103
|
+
});
|
|
104
|
+
if (query?.paginated) {
|
|
105
|
+
const paginationInfo = {
|
|
106
|
+
total: count,
|
|
107
|
+
perPage: query.paginated.perPage,
|
|
108
|
+
currentPage: query.paginated.page,
|
|
109
|
+
nextPage: query.paginated.page + 1,
|
|
110
|
+
firstPage: 1,
|
|
111
|
+
lastPage: Math.ceil(count / query.paginated.perPage),
|
|
112
|
+
prevPage: query.paginated.page === 1 ? null : query.paginated.page - 1,
|
|
113
|
+
from: (query.paginated.page - 1) * query.paginated.perPage + 1,
|
|
114
|
+
to: query.paginated.perPage * query.paginated.page,
|
|
115
|
+
data: found
|
|
116
|
+
};
|
|
117
|
+
return paginationInfo;
|
|
118
|
+
}
|
|
119
|
+
if (query?.select) {
|
|
120
|
+
// Filter out fields that are explicitly set to false
|
|
121
|
+
found = this.applySelectFilter(found, query.select);
|
|
122
|
+
return found;
|
|
123
|
+
}
|
|
124
|
+
// Validate Output against schema
|
|
125
|
+
return this.outputSchema?.array().parse(found);
|
|
126
|
+
}
|
|
127
|
+
// UPDATE
|
|
128
|
+
/**
|
|
129
|
+
* PATCH operation
|
|
130
|
+
* @param data
|
|
131
|
+
*/
|
|
132
|
+
async updateById(id, data) {
|
|
133
|
+
this.initDB();
|
|
134
|
+
const dataToInsert = this.outputKeys.includes('updated')
|
|
135
|
+
? {
|
|
136
|
+
...data,
|
|
137
|
+
...{ updated: new Date() }
|
|
138
|
+
}
|
|
139
|
+
: data;
|
|
140
|
+
const validatedData = this.inputSchema.parse(dataToInsert);
|
|
141
|
+
await this.repository.update(id, validatedData);
|
|
142
|
+
// Validate Output
|
|
143
|
+
return (await this.requireById(id));
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
*
|
|
147
|
+
* PUT operation. All fields not included in the data
|
|
148
|
+
* param will be set to null
|
|
149
|
+
*
|
|
150
|
+
* @param id
|
|
151
|
+
* @param data
|
|
152
|
+
*/
|
|
153
|
+
async replaceById(id, data) {
|
|
154
|
+
this.initDB();
|
|
155
|
+
const idFieldName = this.isMongoDB ? '_id' : 'id';
|
|
156
|
+
const value = this.requireById(id);
|
|
157
|
+
const flatValue = js_utils_1.Objects.flatten(JSON.parse(JSON.stringify(value)));
|
|
158
|
+
Object.keys(flatValue).forEach(key => {
|
|
159
|
+
flatValue[key] = null;
|
|
160
|
+
});
|
|
161
|
+
const nullObject = js_utils_1.Objects.nest(flatValue);
|
|
162
|
+
const newValue = { ...nullObject, ...data };
|
|
163
|
+
delete newValue._id;
|
|
164
|
+
delete newValue.id;
|
|
165
|
+
delete newValue.created;
|
|
166
|
+
delete newValue.updated;
|
|
167
|
+
const dataToInsert = this.outputKeys.includes('updated')
|
|
168
|
+
? {
|
|
169
|
+
...data,
|
|
170
|
+
...{ updated: new Date() }
|
|
171
|
+
}
|
|
172
|
+
: data;
|
|
173
|
+
const validatedData = this.inputSchema.parse(dataToInsert);
|
|
174
|
+
await this.repository.update(id, validatedData);
|
|
175
|
+
return (await this.requireById(id));
|
|
176
|
+
}
|
|
177
|
+
// DELETE
|
|
178
|
+
/**
|
|
179
|
+
*
|
|
180
|
+
* @param id
|
|
181
|
+
* @returns
|
|
182
|
+
*/
|
|
183
|
+
async deleteById(id) {
|
|
184
|
+
this.initDB();
|
|
185
|
+
const parsedId = this.isMongoDB
|
|
186
|
+
? new bson_1.ObjectId(id)
|
|
187
|
+
: id;
|
|
188
|
+
await this.repository.delete(parsedId);
|
|
189
|
+
return id;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
*
|
|
193
|
+
* @returns
|
|
194
|
+
*/
|
|
195
|
+
async clear() {
|
|
196
|
+
this.initDB();
|
|
197
|
+
await this.repository.clear();
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
// RELATIONS
|
|
201
|
+
/**
|
|
202
|
+
*
|
|
203
|
+
* @param query
|
|
204
|
+
* @returns
|
|
205
|
+
*/
|
|
206
|
+
loadFirst(query) {
|
|
207
|
+
this.initDB();
|
|
208
|
+
// Create a clone of the original class
|
|
209
|
+
// to avoid polluting attributes (relatedQuery)
|
|
210
|
+
const newInstance = this.clone();
|
|
211
|
+
newInstance.setRelatedQuery({
|
|
212
|
+
entity: this.entity,
|
|
213
|
+
repository: this,
|
|
214
|
+
query: {
|
|
215
|
+
...query,
|
|
216
|
+
limit: 1
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
return newInstance;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
*
|
|
223
|
+
* @param id
|
|
224
|
+
* @returns
|
|
225
|
+
*/
|
|
226
|
+
loadById(id) {
|
|
227
|
+
this.initDB();
|
|
228
|
+
// Create a new instance to avoid polluting the original one
|
|
229
|
+
const newInstance = this.clone();
|
|
230
|
+
newInstance.setRelatedQuery({
|
|
231
|
+
entity: this.entity,
|
|
232
|
+
repository: this,
|
|
233
|
+
query: {
|
|
234
|
+
where: {
|
|
235
|
+
id
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
return newInstance;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
*
|
|
243
|
+
* Returns the TypeOrm Repository, you can use it
|
|
244
|
+
* form more complex queries and to get
|
|
245
|
+
* the TypeOrm query builder
|
|
246
|
+
*
|
|
247
|
+
* @param query
|
|
248
|
+
*/
|
|
249
|
+
raw() {
|
|
250
|
+
this.initDB();
|
|
251
|
+
return this.repository;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
*
|
|
255
|
+
* Returns the TypeOrm Repository, you can use it
|
|
256
|
+
* form more complex queries and to get
|
|
257
|
+
* the TypeOrm query builder
|
|
258
|
+
*
|
|
259
|
+
* @param query
|
|
260
|
+
*/
|
|
261
|
+
mongoRaw() {
|
|
262
|
+
this.initDB();
|
|
263
|
+
return this.repository;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Creates a Clone of the current instance of the class
|
|
267
|
+
* @returns
|
|
268
|
+
*/
|
|
269
|
+
clone() {
|
|
270
|
+
this.initDB();
|
|
271
|
+
return new this.constructor();
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Apply select filter to remove fields explicitly set to false
|
|
275
|
+
* @param results The query results
|
|
276
|
+
* @param select The select configuration
|
|
277
|
+
* @returns Filtered results
|
|
278
|
+
*/
|
|
279
|
+
applySelectFilter(results, select) {
|
|
280
|
+
if (!select)
|
|
281
|
+
return results;
|
|
282
|
+
const flatSelect = js_utils_1.Objects.flatten(select);
|
|
283
|
+
const fieldsToInclude = new Set();
|
|
284
|
+
const fieldsToExclude = new Set();
|
|
285
|
+
let hasIncludes = false;
|
|
286
|
+
// Separate fields to include and exclude
|
|
287
|
+
for (const [key, value] of Object.entries(flatSelect)) {
|
|
288
|
+
// Convert to string for consistent comparison
|
|
289
|
+
const strValue = String(value);
|
|
290
|
+
if (strValue === 'true' || strValue === '1') {
|
|
291
|
+
fieldsToInclude.add(key);
|
|
292
|
+
hasIncludes = true;
|
|
293
|
+
}
|
|
294
|
+
else if (strValue === 'false' || strValue === '0') {
|
|
295
|
+
fieldsToExclude.add(key);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return results.map(result => {
|
|
299
|
+
// If there are explicit includes, only include those fields (exclusive selection)
|
|
300
|
+
if (hasIncludes) {
|
|
301
|
+
const filtered = {};
|
|
302
|
+
// For exclusive selection, only copy fields that are explicitly included
|
|
303
|
+
for (const field of fieldsToInclude) {
|
|
304
|
+
if (field.includes('.')) {
|
|
305
|
+
// Handle nested field paths
|
|
306
|
+
const parts = field.split('.');
|
|
307
|
+
let source = result;
|
|
308
|
+
let target = filtered;
|
|
309
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
310
|
+
const part = parts[i];
|
|
311
|
+
if (!part || !source[part])
|
|
312
|
+
break;
|
|
313
|
+
source = source[part];
|
|
314
|
+
if (!target[part])
|
|
315
|
+
target[part] = {};
|
|
316
|
+
target = target[part];
|
|
317
|
+
}
|
|
318
|
+
if (source && parts.length > 0) {
|
|
319
|
+
const lastPart = parts[parts.length - 1];
|
|
320
|
+
if (lastPart) {
|
|
321
|
+
target[lastPart] = source[lastPart];
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
else if (field in result) {
|
|
326
|
+
filtered[field] = result[field];
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return filtered;
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
// If there are only excludes, include all fields except excluded ones
|
|
333
|
+
const filtered = { ...result };
|
|
334
|
+
for (const field of fieldsToExclude) {
|
|
335
|
+
if (field.includes('.')) {
|
|
336
|
+
const parts = field.split('.');
|
|
337
|
+
let current = filtered;
|
|
338
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
339
|
+
const part = parts[i];
|
|
340
|
+
if (!part || !current[part])
|
|
341
|
+
break;
|
|
342
|
+
current = current[part];
|
|
343
|
+
}
|
|
344
|
+
if (current && parts.length > 0) {
|
|
345
|
+
const lastPart = parts[parts.length - 1];
|
|
346
|
+
if (lastPart) {
|
|
347
|
+
delete current[lastPart];
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
delete filtered[field];
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return filtered;
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
*
|
|
361
|
+
* @param query
|
|
362
|
+
* @returns
|
|
363
|
+
*/
|
|
364
|
+
generateTypeOrmQuery(query) {
|
|
365
|
+
let filter = {};
|
|
366
|
+
filter.where = this.isMongoDB
|
|
367
|
+
? (0, getMongoWhere_1.getMongoWhere)({
|
|
368
|
+
where: query?.where
|
|
369
|
+
})
|
|
370
|
+
: (0, getTypeOrmWhere_1.getTypeOrmWhere)({
|
|
371
|
+
where: query?.where
|
|
372
|
+
});
|
|
373
|
+
filter.take = query?.limit;
|
|
374
|
+
filter.skip = query?.offset;
|
|
375
|
+
// Pagination
|
|
376
|
+
if (query?.paginated) {
|
|
377
|
+
filter.take = query.paginated.perPage;
|
|
378
|
+
filter.skip = (query.paginated?.page - 1) * query?.paginated.perPage;
|
|
379
|
+
}
|
|
380
|
+
if (query?.select) {
|
|
381
|
+
const selectQuery = js_utils_1.Objects.flatten(query?.select || {});
|
|
382
|
+
// Filter out fields with false values - TypeORM only accepts fields to include
|
|
383
|
+
const fieldsToSelect = Object.keys(selectQuery).filter(key => {
|
|
384
|
+
const val = selectQuery[key];
|
|
385
|
+
return val !== undefined && (String(val) === 'true' || String(val) === '1');
|
|
386
|
+
});
|
|
387
|
+
if (fieldsToSelect.length > 0) {
|
|
388
|
+
// TypeORM expects select to be an object with field names as keys
|
|
389
|
+
const selectObject = fieldsToSelect.reduce((acc, field) => {
|
|
390
|
+
acc[field] = true;
|
|
391
|
+
return acc;
|
|
392
|
+
}, {});
|
|
393
|
+
filter.select = selectObject;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
if (query?.orderBy) {
|
|
397
|
+
filter.order = (0, extractOrderBy_1.extractOrderBy)(query.orderBy);
|
|
398
|
+
}
|
|
399
|
+
if (query?.include) {
|
|
400
|
+
filter.relations = (0, extractInclude_1.extractInclude)(query.include);
|
|
401
|
+
}
|
|
402
|
+
return filter;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
*
|
|
406
|
+
* @param query
|
|
407
|
+
* @returns
|
|
408
|
+
*/
|
|
409
|
+
customTypeOrmRelatedFind({ fluentQuery: query, queryBuilder, targetFluentRepository, alias, isLeftJoin }) {
|
|
410
|
+
const queryAlias = alias || queryBuilder?.alias || `${this.repository.metadata.tableName}`;
|
|
411
|
+
let customQuery = queryBuilder || this.raw().createQueryBuilder(queryAlias);
|
|
412
|
+
const self = targetFluentRepository || this;
|
|
413
|
+
if (!isLeftJoin) {
|
|
414
|
+
customQuery = (0, getQueryBuilderWhere_1.getQueryBuilderWhere)({
|
|
415
|
+
queryBuilder: customQuery,
|
|
416
|
+
queryAlias,
|
|
417
|
+
where: query?.where
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
const { queryBuilder: qb, selectedKeys } = this.getTypeOrmQueryBuilderSubqueries({
|
|
421
|
+
queryBuilder: customQuery,
|
|
422
|
+
selfReference: targetFluentRepository,
|
|
423
|
+
include: query?.include,
|
|
424
|
+
leftTableAlias: alias
|
|
425
|
+
});
|
|
426
|
+
customQuery = qb;
|
|
427
|
+
const extraKeys = this.getTypeOrmQueryBuilderSelect(queryAlias, self, query?.select);
|
|
428
|
+
const keySet = new Set([...selectedKeys, ...extraKeys]);
|
|
429
|
+
// if (query?.limit) {
|
|
430
|
+
// customQuery = customQuery.limit(query?.limit)
|
|
431
|
+
// }
|
|
432
|
+
// if (query?.offset) {
|
|
433
|
+
// customQuery = customQuery.offset(query?.offset)
|
|
434
|
+
// }
|
|
435
|
+
// if (query?.take) {
|
|
436
|
+
// customQuery = customQuery.take(query?.take)
|
|
437
|
+
// }
|
|
438
|
+
return {
|
|
439
|
+
queryBuilder: customQuery,
|
|
440
|
+
selectedKeys: Array.from(keySet)
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
getTypeOrmQueryBuilderSelect(queryAlias, self, select) {
|
|
444
|
+
const selected = js_utils_1.Objects.flatten(select || {});
|
|
445
|
+
const selectedKeys = [];
|
|
446
|
+
const iterableKeys = Object.keys(selected).length
|
|
447
|
+
? Object.keys(selected)
|
|
448
|
+
: self.outputKeys || [];
|
|
449
|
+
const baseNestedKeys = new Set();
|
|
450
|
+
for (const key of iterableKeys) {
|
|
451
|
+
const keyArray = key.split('.');
|
|
452
|
+
// There are no nested objects
|
|
453
|
+
if (keyArray.length <= 1) {
|
|
454
|
+
continue;
|
|
455
|
+
}
|
|
456
|
+
const total = keyArray.length;
|
|
457
|
+
for (const [index, val] of keyArray.entries()) {
|
|
458
|
+
// No need to iterate over the last object
|
|
459
|
+
if (total === index + 1) {
|
|
460
|
+
continue;
|
|
461
|
+
}
|
|
462
|
+
let excludedField = '';
|
|
463
|
+
if (excludedField) {
|
|
464
|
+
excludedField = `${excludedField}.${excludedField}${val}`;
|
|
465
|
+
}
|
|
466
|
+
excludedField = `${excludedField}${val}`;
|
|
467
|
+
baseNestedKeys.add(excludedField);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
for (const k of iterableKeys) {
|
|
471
|
+
const field = k.includes('.') ? js_utils_1.Strings.camel(`${k}`) : k;
|
|
472
|
+
const search = `${queryAlias}.${field}`;
|
|
473
|
+
// isRelatedField: We can tell if the field is a "related model"
|
|
474
|
+
// checking "this" for the name of the relation
|
|
475
|
+
let isNestedRelation = false;
|
|
476
|
+
for (const item of k.split('.')) {
|
|
477
|
+
if (!!self[item]) {
|
|
478
|
+
isNestedRelation = true;
|
|
479
|
+
break;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
if (!!self[field] || !!self[queryAlias] || isNestedRelation) {
|
|
483
|
+
continue;
|
|
484
|
+
}
|
|
485
|
+
// No need to include base keys
|
|
486
|
+
if (baseNestedKeys.has(field)) {
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
selectedKeys.push(search);
|
|
490
|
+
}
|
|
491
|
+
return selectedKeys;
|
|
492
|
+
}
|
|
493
|
+
getTypeOrmQueryBuilderSubqueries({ queryBuilder, selfReference, include, leftTableAlias }) {
|
|
494
|
+
const selectedKeys = [];
|
|
495
|
+
if (!include) {
|
|
496
|
+
return { queryBuilder, selectedKeys };
|
|
497
|
+
}
|
|
498
|
+
for (const relation of Object.keys(include)) {
|
|
499
|
+
// i.e To make this code more understandable
|
|
500
|
+
// table "users" has many "cars"
|
|
501
|
+
// For a first level query, represents "users"
|
|
502
|
+
const self = selfReference || this;
|
|
503
|
+
// All information about the users[cars] relation
|
|
504
|
+
const dbRelation = self.modelRelations[relation];
|
|
505
|
+
// The "cars" table repository
|
|
506
|
+
// this will be use for possible recursive queries
|
|
507
|
+
const newSelf = self[relation]();
|
|
508
|
+
// Extract new query for this included relationship
|
|
509
|
+
const fluentRelatedQuery = include[relation] === true ? {} : include[relation];
|
|
510
|
+
if (!dbRelation) {
|
|
511
|
+
throw new Error(`The relation ${relation} is not properly defined. Check your entity and repository`);
|
|
512
|
+
}
|
|
513
|
+
// Now we need to decide which properties we want to select from the related model
|
|
514
|
+
// If the query has some {select: [x]: true}
|
|
515
|
+
const selectedKeysArray = fluentRelatedQuery?.select
|
|
516
|
+
? Object.keys(js_utils_1.Objects.flatten(fluentRelatedQuery.select))
|
|
517
|
+
: [];
|
|
518
|
+
if (dbRelation.isManyToOne) {
|
|
519
|
+
// We now have the opposite "cars" has one "users"
|
|
520
|
+
// "cars"
|
|
521
|
+
// Or users___cars if it comes from a nested relation
|
|
522
|
+
const leftSideTableName = leftTableAlias || queryBuilder.alias;
|
|
523
|
+
// "cars.userId"
|
|
524
|
+
// users___cars.userId (if nested)
|
|
525
|
+
const leftSideForeignKey = `${leftSideTableName}.${dbRelation.joinColumns[0].propertyPath}`;
|
|
526
|
+
// Right side considering nested relations
|
|
527
|
+
// users___cars___cars___user
|
|
528
|
+
const rightSideTableName = `${leftSideTableName}_${relation}`;
|
|
529
|
+
const rightSidePrimaryKey = `${rightSideTableName}.id`;
|
|
530
|
+
const keys = new Set(selectedKeysArray.map(k => `${rightSideTableName}.${k}`));
|
|
531
|
+
selectedKeys.push(...Array.from(keys));
|
|
532
|
+
const shallowQuery = { ...fluentRelatedQuery };
|
|
533
|
+
delete shallowQuery['include'];
|
|
534
|
+
const { queryBuilder: leftJoinBuilder, selectedKeys: deepkeys } = this.customTypeOrmRelatedFind({
|
|
535
|
+
queryBuilder: this.raw().createQueryBuilder(rightSideTableName),
|
|
536
|
+
fluentQuery: shallowQuery,
|
|
537
|
+
targetFluentRepository: newSelf,
|
|
538
|
+
alias: rightSideTableName
|
|
539
|
+
});
|
|
540
|
+
selectedKeys.push(...deepkeys);
|
|
541
|
+
const joinQuery = leftJoinBuilder.getQuery().split('WHERE');
|
|
542
|
+
const customLeftJoin = joinQuery && joinQuery[1] ? joinQuery[1].trim() : '1=1';
|
|
543
|
+
const leftJoinParams = leftJoinBuilder.getParameters();
|
|
544
|
+
// Finally we get to do the LEFT JOIN
|
|
545
|
+
queryBuilder.leftJoinAndMapOne(`${leftSideTableName}.${relation}`, dbRelation.targetClass,
|
|
546
|
+
// Right side of the JOIN table name
|
|
547
|
+
// The name of the table that comes from the query above!
|
|
548
|
+
rightSideTableName,
|
|
549
|
+
// Keys to JOIN ON
|
|
550
|
+
// This must account for all aliases used above
|
|
551
|
+
`(${leftSideForeignKey} = ${rightSidePrimaryKey} AND ${customLeftJoin} )`, leftJoinParams);
|
|
552
|
+
const { queryBuilder: qb, selectedKeys: k } = this.customTypeOrmRelatedFind({
|
|
553
|
+
queryBuilder,
|
|
554
|
+
fluentQuery: fluentRelatedQuery,
|
|
555
|
+
targetFluentRepository: newSelf,
|
|
556
|
+
alias: rightSideTableName,
|
|
557
|
+
isLeftJoin: true
|
|
558
|
+
});
|
|
559
|
+
selectedKeys.push(...k);
|
|
560
|
+
queryBuilder = qb;
|
|
561
|
+
}
|
|
562
|
+
if (dbRelation.isOneToMany) {
|
|
563
|
+
// "users"
|
|
564
|
+
const leftSideTableName = leftTableAlias || queryBuilder.alias;
|
|
565
|
+
// As it is one to many, primary key will always be "id"
|
|
566
|
+
// users.id
|
|
567
|
+
const leftSidePrimaryKey = `${leftSideTableName}.id`;
|
|
568
|
+
// "cars"
|
|
569
|
+
const rightSideTableName = `${leftSideTableName}_${relation}`;
|
|
570
|
+
// "cars".userId
|
|
571
|
+
const rightSideForeignKey = `${rightSideTableName}.${dbRelation.inverseSidePropertyPath}`;
|
|
572
|
+
const keys = new Set(selectedKeysArray.map(k => `${rightSideTableName}.${k}`));
|
|
573
|
+
selectedKeys.push(...Array.from(keys));
|
|
574
|
+
// Left join query, without including any nested tables
|
|
575
|
+
const shallowQuery = { ...fluentRelatedQuery };
|
|
576
|
+
delete shallowQuery['include'];
|
|
577
|
+
const { queryBuilder: leftJoinBuilder, selectedKeys: deepKeys } = this.customTypeOrmRelatedFind({
|
|
578
|
+
queryBuilder: this.raw().createQueryBuilder(rightSideTableName),
|
|
579
|
+
fluentQuery: shallowQuery,
|
|
580
|
+
targetFluentRepository: newSelf,
|
|
581
|
+
alias: rightSideTableName
|
|
582
|
+
});
|
|
583
|
+
selectedKeys.push(...deepKeys);
|
|
584
|
+
const joinQuery = leftJoinBuilder.getQuery().split('WHERE');
|
|
585
|
+
const customLeftJoin = joinQuery && joinQuery[1] ? joinQuery[1].trim() : '1=1';
|
|
586
|
+
const leftJoinParams = leftJoinBuilder.getParameters();
|
|
587
|
+
// Finally we get to do the LEFT JOIN
|
|
588
|
+
queryBuilder.leftJoinAndMapMany(`${leftSideTableName}.${relation}`, dbRelation.targetClass,
|
|
589
|
+
// Right side of the JOIN table name
|
|
590
|
+
rightSideTableName,
|
|
591
|
+
// Keys to JOIN ON
|
|
592
|
+
`(${leftSidePrimaryKey} = ${rightSideForeignKey} AND ${customLeftJoin} )`, leftJoinParams);
|
|
593
|
+
const { queryBuilder: q, selectedKeys: k } = this.customTypeOrmRelatedFind({
|
|
594
|
+
queryBuilder,
|
|
595
|
+
fluentQuery: fluentRelatedQuery,
|
|
596
|
+
targetFluentRepository: newSelf,
|
|
597
|
+
alias: rightSideTableName,
|
|
598
|
+
isLeftJoin: true
|
|
599
|
+
});
|
|
600
|
+
selectedKeys.push(...k);
|
|
601
|
+
queryBuilder = q;
|
|
602
|
+
}
|
|
603
|
+
// if (dbRelation.isManyToMany) {
|
|
604
|
+
// const relatedTableName = dbRelation.tableName
|
|
605
|
+
// const pivotTableName =
|
|
606
|
+
// dbRelation.joinColumns[0].relationMetadata.joinTableName
|
|
607
|
+
// const pivotForeignField = dbRelation.joinColumns[0].propertyPath
|
|
608
|
+
// const inverseForeignField =
|
|
609
|
+
// dbRelation.inverseJoinColumns[0].propertyPath
|
|
610
|
+
// if (
|
|
611
|
+
// !relatedTableName ||
|
|
612
|
+
// !pivotTableName ||
|
|
613
|
+
// !pivotForeignField ||
|
|
614
|
+
// !inverseForeignField
|
|
615
|
+
// ) {
|
|
616
|
+
// throw new Error(
|
|
617
|
+
// `Your many to many relation is not properly set up. Please check both your models and schema for relation: ${relation}`
|
|
618
|
+
// )
|
|
619
|
+
// }
|
|
620
|
+
// // "users"
|
|
621
|
+
// const leftSideTableName = leftTableAlias || queryBuilder.alias
|
|
622
|
+
// // As it is one to many, primary key will always be "id"
|
|
623
|
+
// // users.id
|
|
624
|
+
// const leftSidePrimaryKey = `${leftSideTableName}.id`
|
|
625
|
+
// // "roles_users"
|
|
626
|
+
// const rightSideTableName = `${relatedTableName}`
|
|
627
|
+
// // "roles_users".userId
|
|
628
|
+
// const rightSideForeignKey = `${rightSideTableName}.${pivotForeignField}`
|
|
629
|
+
// const keys = new Set(
|
|
630
|
+
// selectedKeysArray.map(k => `${rightSideTableName}.${k}`)
|
|
631
|
+
// )
|
|
632
|
+
// selectedKeys.push(...Array.from(keys))
|
|
633
|
+
// // Left join query, without including any nested tables
|
|
634
|
+
// const shallowQuery = { ...fluentRelatedQuery }
|
|
635
|
+
// delete shallowQuery['include']
|
|
636
|
+
// const { queryBuilder: leftJoinBuilder, selectedKeys: deepKeys } =
|
|
637
|
+
// this.customTypeOrmRelatedFind({
|
|
638
|
+
// queryBuilder: this.raw().createQueryBuilder(rightSideTableName),
|
|
639
|
+
// fluentQuery: shallowQuery,
|
|
640
|
+
// targetFluentRepository: newSelf,
|
|
641
|
+
// alias: rightSideTableName
|
|
642
|
+
// })
|
|
643
|
+
// selectedKeys.push(...deepKeys)
|
|
644
|
+
// const joinQuery = leftJoinBuilder.getQuery().split('WHERE')
|
|
645
|
+
// const customLeftJoin =
|
|
646
|
+
// joinQuery && joinQuery[1] ? joinQuery[1].trim() : '1=1'
|
|
647
|
+
// const leftJoinParams = leftJoinBuilder.getParameters()
|
|
648
|
+
// // Finally we get to do the LEFT JOIN
|
|
649
|
+
// queryBuilder.leftJoinAndMapMany(
|
|
650
|
+
// `${leftSideTableName}.${relation}`,
|
|
651
|
+
// dbRelation.targetClass,
|
|
652
|
+
// // Right side of the JOIN table name
|
|
653
|
+
// rightSideTableName,
|
|
654
|
+
// // Keys to JOIN ON
|
|
655
|
+
// `(${leftSidePrimaryKey} = ${rightSideForeignKey} AND ${customLeftJoin} )`,
|
|
656
|
+
// leftJoinParams
|
|
657
|
+
// )
|
|
658
|
+
// const { queryBuilder: q, selectedKeys: k } =
|
|
659
|
+
// this.customTypeOrmRelatedFind({
|
|
660
|
+
// queryBuilder,
|
|
661
|
+
// fluentQuery: fluentRelatedQuery,
|
|
662
|
+
// targetFluentRepository: newSelf,
|
|
663
|
+
// alias: rightSideTableName,
|
|
664
|
+
// isLeftJoin: true
|
|
665
|
+
// })
|
|
666
|
+
// selectedKeys.push(...k)
|
|
667
|
+
// queryBuilder = q
|
|
668
|
+
// console.log(
|
|
669
|
+
// relatedTableName,
|
|
670
|
+
// pivotTableName,
|
|
671
|
+
// pivotForeignField,
|
|
672
|
+
// inverseForeignField
|
|
673
|
+
// )
|
|
674
|
+
// continue
|
|
675
|
+
// // lookUps.push({ $addFields: { id: { $toString: '$_id' } } })
|
|
676
|
+
// // lookUps.push({
|
|
677
|
+
// // $addFields: { parent_string_id: { $toString: '$_id' } }
|
|
678
|
+
// // })
|
|
679
|
+
// // lookUps.push({
|
|
680
|
+
// // $lookup: {
|
|
681
|
+
// // from: pivotTableName,
|
|
682
|
+
// // localField: 'parent_string_id',
|
|
683
|
+
// // foreignField: pivotForeignField,
|
|
684
|
+
// // as: dbRelation.propertyName,
|
|
685
|
+
// // pipeline: [
|
|
686
|
+
// // // This is the pivot table
|
|
687
|
+
// // { $addFields: { id: { $toString: '$_id' } } },
|
|
688
|
+
// // {
|
|
689
|
+
// // $addFields: {
|
|
690
|
+
// // [`${inverseForeignField}_object`]: {
|
|
691
|
+
// // $toObjectId: `$${inverseForeignField}`
|
|
692
|
+
// // }
|
|
693
|
+
// // }
|
|
694
|
+
// // },
|
|
695
|
+
// // // The other side of the relationShip
|
|
696
|
+
// // {
|
|
697
|
+
// // $lookup: {
|
|
698
|
+
// // from: relatedTableName,
|
|
699
|
+
// // localField: `${inverseForeignField}_object`,
|
|
700
|
+
// // foreignField: '_id',
|
|
701
|
+
// // pipeline: [
|
|
702
|
+
// // { $addFields: { id: { $toString: '$_id' } } }
|
|
703
|
+
// // // Here we could add more filters like
|
|
704
|
+
// // //{ $limit: 2 }
|
|
705
|
+
// // ],
|
|
706
|
+
// // as: dbRelation.propertyName
|
|
707
|
+
// // }
|
|
708
|
+
// // },
|
|
709
|
+
// // { $unwind: `$${dbRelation.propertyName}` },
|
|
710
|
+
// // // Select (ish)
|
|
711
|
+
// // {
|
|
712
|
+
// // $project: {
|
|
713
|
+
// // [dbRelation.propertyName]: `$${dbRelation.propertyName}`,
|
|
714
|
+
// // pivot: '$$ROOT'
|
|
715
|
+
// // }
|
|
716
|
+
// // },
|
|
717
|
+
// // {
|
|
718
|
+
// // $replaceRoot: {
|
|
719
|
+
// // newRoot: {
|
|
720
|
+
// // $mergeObjects: ['$$ROOT', `$${dbRelation.propertyName}`]
|
|
721
|
+
// // }
|
|
722
|
+
// // }
|
|
723
|
+
// // },
|
|
724
|
+
// // { $project: { [dbRelation.propertyName]: 0 } }
|
|
725
|
+
// // // Here we could add more filters like
|
|
726
|
+
// // //{ $limit: 2 }
|
|
727
|
+
// // ]
|
|
728
|
+
// // }
|
|
729
|
+
// // })
|
|
730
|
+
// }
|
|
731
|
+
}
|
|
732
|
+
return { queryBuilder, selectedKeys };
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
*
|
|
736
|
+
* @param query
|
|
737
|
+
* @returns
|
|
738
|
+
*/
|
|
739
|
+
async customMongoRelatedFind(query) {
|
|
740
|
+
const aggregate = (0, getMongoFindAggregatedQuery_1.getMongoFindAggregatedQuery)({
|
|
741
|
+
query,
|
|
742
|
+
self: this
|
|
743
|
+
});
|
|
744
|
+
const raw = await this.mongoRaw().aggregate(aggregate).toArray();
|
|
745
|
+
if (query?.select) {
|
|
746
|
+
// Apply select filtering for MongoDB results
|
|
747
|
+
const filtered = this.applySelectFilter(raw, query.select);
|
|
748
|
+
return filtered;
|
|
749
|
+
}
|
|
750
|
+
return this.outputSchema?.array().parse(raw);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
exports.TypeOrmConnector = TypeOrmConnector;
|
|
754
|
+
tslib_1.__decorate([
|
|
755
|
+
js_utils_1.Memo.syncMethod(),
|
|
756
|
+
tslib_1.__metadata("design:type", Function),
|
|
757
|
+
tslib_1.__metadata("design:paramtypes", []),
|
|
758
|
+
tslib_1.__metadata("design:returntype", void 0)
|
|
759
|
+
], TypeOrmConnector.prototype, "initDB", null);
|
|
760
|
+
//# sourceMappingURL=TypeOrmConnector.js.map
|