@loomcore/api 0.0.59 → 0.1.2
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/LICENSE +201 -0
- package/README.md +50 -0
- package/dist/__tests__/common-test.utils.d.ts +29 -60
- package/dist/__tests__/common-test.utils.js +88 -166
- package/dist/__tests__/index.d.ts +6 -0
- package/dist/__tests__/index.js +6 -0
- package/dist/__tests__/models/category.model.d.ts +8 -0
- package/dist/__tests__/models/category.model.js +6 -0
- package/dist/__tests__/models/product.model.d.ts +17 -0
- package/dist/__tests__/models/product.model.js +10 -0
- package/dist/__tests__/models/test-entity.model.d.ts +11 -0
- package/dist/__tests__/models/test-entity.model.js +10 -0
- package/dist/__tests__/models/test-item.model.d.ts +12 -0
- package/dist/__tests__/models/test-item.model.js +9 -0
- package/dist/__tests__/mongo-db.test-database.d.ts +15 -0
- package/dist/__tests__/mongo-db.test-database.js +74 -0
- package/dist/__tests__/postgres-test-migrations/001-create-test-entities-table.migration.d.ts +11 -0
- package/dist/__tests__/postgres-test-migrations/001-create-test-entities-table.migration.js +59 -0
- package/dist/__tests__/postgres-test-migrations/002-create-categories-table.migration.d.ts +11 -0
- package/dist/__tests__/postgres-test-migrations/002-create-categories-table.migration.js +52 -0
- package/dist/__tests__/postgres-test-migrations/003-create-products-table.migration.d.ts +11 -0
- package/dist/__tests__/postgres-test-migrations/003-create-products-table.migration.js +62 -0
- package/dist/__tests__/postgres-test-migrations/004-create-test-users-table.migration.d.ts +11 -0
- package/dist/__tests__/postgres-test-migrations/004-create-test-users-table.migration.js +66 -0
- package/dist/__tests__/postgres-test-migrations/005-create-test-items-table.migration.d.ts +11 -0
- package/dist/__tests__/postgres-test-migrations/005-create-test-items-table.migration.js +50 -0
- package/dist/__tests__/postgres-test-migrations/run-test-migrations.d.ts +2 -0
- package/dist/__tests__/postgres-test-migrations/run-test-migrations.js +22 -0
- package/dist/__tests__/postgres.test-database.d.ts +13 -0
- package/dist/__tests__/postgres.test-database.js +85 -0
- package/dist/__tests__/test-database.interface.d.ts +7 -0
- package/dist/__tests__/test-express-app.d.ts +9 -7
- package/dist/__tests__/test-express-app.js +38 -48
- package/dist/__tests__/test-objects.d.ts +23 -0
- package/dist/__tests__/test-objects.js +45 -0
- package/dist/config/base-api-config.d.ts +2 -2
- package/dist/config/base-api-config.js +2 -2
- package/dist/controllers/api.controller.d.ts +1 -5
- package/dist/controllers/api.controller.js +4 -11
- package/dist/controllers/auth.controller.d.ts +2 -2
- package/dist/controllers/auth.controller.js +4 -5
- package/dist/controllers/organizations.controller.d.ts +2 -2
- package/dist/controllers/organizations.controller.js +4 -4
- package/dist/controllers/users.controller.d.ts +2 -2
- package/dist/controllers/users.controller.js +2 -2
- package/dist/databases/index.d.ts +1 -0
- package/dist/databases/index.js +1 -0
- package/dist/databases/models/constants.d.ts +1 -0
- package/dist/databases/models/constants.js +1 -0
- package/dist/databases/models/database.d.ts +3 -0
- package/dist/databases/models/database.interface.d.ts +28 -0
- package/dist/databases/models/delete-result.d.ts +5 -0
- package/dist/databases/models/delete-result.js +8 -0
- package/dist/databases/models/index.d.ts +5 -0
- package/dist/databases/models/index.js +5 -0
- package/dist/databases/models/update-result.d.ts +5 -0
- package/dist/databases/models/update-result.js +8 -0
- package/dist/databases/mongo-db/commands/index.d.ts +8 -0
- package/dist/databases/mongo-db/commands/index.js +8 -0
- package/dist/databases/mongo-db/commands/mongo-batch-update.command.d.ts +4 -0
- package/dist/databases/mongo-db/commands/mongo-batch-update.command.js +41 -0
- package/dist/databases/mongo-db/commands/mongo-create-many.command.d.ts +5 -0
- package/dist/databases/mongo-db/commands/mongo-create-many.command.js +17 -0
- package/dist/databases/mongo-db/commands/mongo-create.command.d.ts +5 -0
- package/dist/databases/mongo-db/commands/mongo-create.command.js +17 -0
- package/dist/databases/mongo-db/commands/mongo-delete-by-id.command.d.ts +3 -0
- package/dist/databases/mongo-db/commands/mongo-delete-by-id.command.js +14 -0
- package/dist/databases/mongo-db/commands/mongo-delete-many.command.d.ts +4 -0
- package/dist/databases/mongo-db/commands/mongo-delete-many.command.js +9 -0
- package/dist/databases/mongo-db/commands/mongo-full-updateby-id.command.d.ts +3 -0
- package/dist/databases/mongo-db/commands/mongo-full-updateby-id.command.js +25 -0
- package/dist/databases/mongo-db/commands/mongo-partial-update-by-id.command.d.ts +3 -0
- package/dist/databases/mongo-db/commands/mongo-partial-update-by-id.command.js +25 -0
- package/dist/databases/mongo-db/commands/mongo-update.command.d.ts +4 -0
- package/dist/databases/mongo-db/commands/mongo-update.command.js +19 -0
- package/dist/databases/mongo-db/index.d.ts +4 -0
- package/dist/databases/mongo-db/index.js +4 -0
- package/dist/databases/mongo-db/models/no-sql-pipeline.d.ts +15 -0
- package/dist/databases/mongo-db/models/no-sql-pipeline.interface.d.ts +11 -0
- package/dist/databases/mongo-db/models/no-sql-pipeline.js +43 -0
- package/dist/databases/mongo-db/mongo-db.database.d.ts +32 -0
- package/dist/databases/mongo-db/mongo-db.database.js +65 -0
- package/dist/databases/mongo-db/queries/index.d.ts +6 -0
- package/dist/databases/mongo-db/queries/index.js +6 -0
- package/dist/databases/mongo-db/queries/mongo-find-one.query.d.ts +3 -0
- package/dist/databases/mongo-db/queries/mongo-find-one.query.js +9 -0
- package/dist/databases/mongo-db/queries/mongo-find.query.d.ts +3 -0
- package/dist/databases/mongo-db/queries/mongo-find.query.js +9 -0
- package/dist/databases/mongo-db/queries/mongo-get-all.query.d.ts +3 -0
- package/dist/databases/mongo-db/queries/mongo-get-all.query.js +17 -0
- package/dist/databases/mongo-db/queries/mongo-get-by-id.query.d.ts +4 -0
- package/dist/databases/mongo-db/queries/mongo-get-by-id.query.js +17 -0
- package/dist/databases/mongo-db/queries/mongo-get-count.query.d.ts +2 -0
- package/dist/databases/mongo-db/queries/mongo-get-count.query.js +5 -0
- package/dist/databases/mongo-db/queries/mongo-get.query.d.ts +4 -0
- package/dist/databases/mongo-db/queries/mongo-get.query.js +14 -0
- package/dist/databases/mongo-db/utils/build-find-options.util.d.ts +3 -0
- package/dist/databases/mongo-db/utils/build-find-options.util.js +15 -0
- package/dist/databases/mongo-db/utils/build-no-sql-match.util.d.ts +3 -0
- package/dist/databases/mongo-db/utils/build-no-sql-match.util.js +59 -0
- package/dist/databases/mongo-db/utils/convert-object-ids-to-strings.util.d.ts +1 -0
- package/dist/databases/mongo-db/utils/convert-object-ids-to-strings.util.js +32 -0
- package/dist/databases/mongo-db/utils/convert-operations-to-pipeline.util.d.ts +3 -0
- package/dist/databases/mongo-db/utils/convert-operations-to-pipeline.util.js +68 -0
- package/dist/databases/mongo-db/utils/convert-query-options-to-pipeline.util.d.ts +3 -0
- package/dist/databases/mongo-db/utils/convert-query-options-to-pipeline.util.js +31 -0
- package/dist/databases/mongo-db/utils/convert-strings-to-object-ids.util.d.ts +3 -0
- package/dist/databases/mongo-db/utils/convert-strings-to-object-ids.util.js +72 -0
- package/dist/databases/mongo-db/utils/index.d.ts +7 -0
- package/dist/databases/mongo-db/utils/index.js +7 -0
- package/dist/databases/operations/join.operation.d.ts +7 -0
- package/dist/databases/operations/join.operation.js +12 -0
- package/dist/databases/operations/operation.d.ts +2 -0
- package/dist/databases/postgres/commands/postgres-batch-update.command.d.ts +4 -0
- package/dist/databases/postgres/commands/postgres-batch-update.command.js +56 -0
- package/dist/databases/postgres/commands/postgres-create-many.command.d.ts +6 -0
- package/dist/databases/postgres/commands/postgres-create-many.command.js +63 -0
- package/dist/databases/postgres/commands/postgres-create.command.d.ts +6 -0
- package/dist/databases/postgres/commands/postgres-create.command.js +29 -0
- package/dist/databases/postgres/commands/postgres-delete-by-id.command.d.ts +3 -0
- package/dist/databases/postgres/commands/postgres-delete-by-id.command.js +6 -0
- package/dist/databases/postgres/commands/postgres-delete-many.command.d.ts +4 -0
- package/dist/databases/postgres/commands/postgres-delete-many.command.js +13 -0
- package/dist/databases/postgres/commands/postgres-full-update-by-id.command.d.ts +4 -0
- package/dist/databases/postgres/commands/postgres-full-update-by-id.command.js +72 -0
- package/dist/databases/postgres/commands/postgres-partial-update-by-id.command.d.ts +4 -0
- package/dist/databases/postgres/commands/postgres-partial-update-by-id.command.js +42 -0
- package/dist/databases/postgres/commands/postgres-update.command.d.ts +5 -0
- package/dist/databases/postgres/commands/postgres-update.command.js +48 -0
- package/dist/databases/postgres/migrations/001-create-migrations-table.migration.d.ts +11 -0
- package/dist/databases/postgres/migrations/001-create-migrations-table.migration.js +52 -0
- package/dist/databases/postgres/migrations/002-create-organizations-table.migration.d.ts +11 -0
- package/dist/databases/postgres/migrations/002-create-organizations-table.migration.js +55 -0
- package/dist/databases/postgres/migrations/003-create-users-table.migration.d.ts +11 -0
- package/dist/databases/postgres/migrations/003-create-users-table.migration.js +65 -0
- package/dist/databases/postgres/migrations/004-create-refresh-token-table.migration.d.ts +11 -0
- package/dist/databases/postgres/migrations/004-create-refresh-token-table.migration.js +57 -0
- package/dist/databases/postgres/migrations/index.d.ts +3 -0
- package/dist/databases/postgres/migrations/index.js +3 -0
- package/dist/databases/postgres/migrations/migration.interface.d.ts +6 -0
- package/dist/databases/postgres/migrations/migration.interface.js +1 -0
- package/dist/databases/postgres/migrations/setup-for-auth.migration.d.ts +2 -0
- package/dist/databases/postgres/migrations/setup-for-auth.migration.js +18 -0
- package/dist/databases/postgres/migrations/setup-for-multitenant.migration.d.ts +2 -0
- package/dist/databases/postgres/migrations/setup-for-multitenant.migration.js +16 -0
- package/dist/databases/postgres/postgres.database.d.ts +31 -0
- package/dist/databases/postgres/postgres.database.js +69 -0
- package/dist/databases/postgres/queries/postgres-find-one.query.d.ts +3 -0
- package/dist/databases/postgres/queries/postgres-find-one.query.js +13 -0
- package/dist/databases/postgres/queries/postgres-find.query.d.ts +3 -0
- package/dist/databases/postgres/queries/postgres-find.query.js +11 -0
- package/dist/databases/postgres/queries/postgres-get-all.query.d.ts +3 -0
- package/dist/databases/postgres/queries/postgres-get-all.query.js +14 -0
- package/dist/databases/postgres/queries/postgres-get-by-id.query.d.ts +4 -0
- package/dist/databases/postgres/queries/postgres-get-by-id.query.js +26 -0
- package/dist/databases/postgres/queries/postgres-get-count.query.d.ts +2 -0
- package/dist/databases/postgres/queries/postgres-get-count.query.js +4 -0
- package/dist/databases/postgres/queries/postgres-get.query.d.ts +4 -0
- package/dist/databases/postgres/queries/postgres-get.query.js +26 -0
- package/dist/databases/postgres/utils/build-count-query.d.ts +3 -0
- package/dist/databases/postgres/utils/build-count-query.js +7 -0
- package/dist/databases/postgres/utils/build-join-clauses.d.ts +2 -0
- package/dist/databases/postgres/utils/build-join-clauses.js +12 -0
- package/dist/databases/postgres/utils/build-order-by-clause.d.ts +2 -0
- package/dist/databases/postgres/utils/build-order-by-clause.js +8 -0
- package/dist/databases/postgres/utils/build-pagination-clause.d.ts +2 -0
- package/dist/databases/postgres/utils/build-pagination-clause.js +9 -0
- package/dist/databases/postgres/utils/build-select-clause.d.ts +3 -0
- package/dist/databases/postgres/utils/build-select-clause.js +28 -0
- package/dist/databases/postgres/utils/build-where-clause.d.ts +5 -0
- package/dist/databases/postgres/utils/build-where-clause.js +50 -0
- package/dist/databases/postgres/utils/columns-and-values-from-entity.d.ts +5 -0
- package/dist/databases/postgres/utils/columns-and-values-from-entity.js +9 -0
- package/dist/databases/postgres/utils/convert-null-to-undefined.util.d.ts +2 -0
- package/dist/databases/postgres/utils/convert-null-to-undefined.util.js +70 -0
- package/dist/databases/postgres/utils/transform-join-results.d.ts +2 -0
- package/dist/databases/postgres/utils/transform-join-results.js +33 -0
- package/dist/databases/utils/get-property-schema.util.d.ts +2 -0
- package/dist/databases/utils/get-property-schema.util.js +15 -0
- package/dist/databases/utils/index.d.ts +1 -0
- package/dist/databases/utils/index.js +1 -0
- package/dist/models/base-api-config.interface.d.ts +3 -2
- package/dist/models/index.d.ts +1 -1
- package/dist/models/index.js +1 -1
- package/dist/models/refresh-token.model.d.ts +18 -0
- package/dist/models/refresh-token.model.js +13 -0
- package/dist/services/auth.service.d.ts +11 -18
- package/dist/services/auth.service.js +29 -50
- package/dist/services/generic-api-service/generic-api-service.interface.d.ts +29 -0
- package/dist/services/generic-api-service/generic-api-service.interface.js +1 -0
- package/dist/services/generic-api-service/generic-api.service.d.ts +37 -0
- package/dist/services/generic-api-service/generic-api.service.js +178 -0
- package/dist/services/index.d.ts +2 -2
- package/dist/services/index.js +2 -2
- package/dist/services/multi-tenant-api.service.d.ts +9 -6
- package/dist/services/multi-tenant-api.service.js +10 -18
- package/dist/services/organization.service.d.ts +5 -5
- package/dist/services/organization.service.js +9 -6
- package/dist/services/password-reset-token.service.d.ts +3 -3
- package/dist/services/password-reset-token.service.js +5 -5
- package/dist/services/tenant-query-decorator.d.ts +1 -1
- package/dist/services/tenant-query-decorator.js +1 -1
- package/dist/services/user.service.d.ts +4 -6
- package/dist/services/user.service.js +4 -10
- package/dist/services/utils/audit-for-create.util.d.ts +2 -0
- package/dist/services/utils/audit-for-create.util.js +9 -0
- package/dist/services/utils/audit-for-update.util.d.ts +2 -0
- package/dist/services/utils/audit-for-update.util.js +7 -0
- package/dist/services/utils/strip-sender-provided-system-properties.util.d.ts +2 -0
- package/dist/services/utils/strip-sender-provided-system-properties.util.js +15 -0
- package/dist/utils/api.utils.js +2 -1
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.js +0 -1
- package/package.json +17 -6
- package/dist/services/generic-api-service.interface.d.ts +0 -27
- package/dist/services/generic-api.service.d.ts +0 -50
- package/dist/services/generic-api.service.js +0 -424
- package/dist/utils/db.utils.d.ts +0 -27
- package/dist/utils/db.utils.js +0 -318
- /package/dist/{controllers/api-controller.utils.d.ts → __tests__/test-database.interface.js} +0 -0
- /package/dist/{controllers/api-controller.utils.js → databases/models/database.interface.js} +0 -0
- /package/dist/{models/types/index.d.ts → databases/models/database.js} +0 -0
- /package/dist/{models/types/index.js → databases/mongo-db/models/no-sql-pipeline.interface.js} +0 -0
- /package/dist/{services/generic-api-service.interface.js → databases/operations/operation.js} +0 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Db } from "mongodb";
|
|
2
|
+
import { IModelSpec, IQueryOptions, IPagedResult, IEntity } from "@loomcore/common/models";
|
|
3
|
+
import { Operation } from "../operations/operation.js";
|
|
4
|
+
import { DeleteResult as GenericDeleteResult } from "../models/delete-result.js";
|
|
5
|
+
import { TSchema } from "@sinclair/typebox";
|
|
6
|
+
import { IDatabase } from "../models/database.interface.js";
|
|
7
|
+
export declare class MongoDBDatabase implements IDatabase {
|
|
8
|
+
private db;
|
|
9
|
+
constructor(db: Db);
|
|
10
|
+
preprocessEntity<T extends IEntity>(entity: Partial<T>, schema: TSchema): Partial<T>;
|
|
11
|
+
postprocessEntity<T extends IEntity>(single: T, schema: TSchema): T;
|
|
12
|
+
getAll<T extends IEntity>(operations: Operation[], pluralResourceName: string): Promise<T[]>;
|
|
13
|
+
get<T extends IEntity>(operations: Operation[], queryOptions: IQueryOptions, modelSpec: IModelSpec, pluralResourceName: string): Promise<IPagedResult<T>>;
|
|
14
|
+
getById<T extends IEntity>(operations: Operation[], queryObject: IQueryOptions, id: string, pluralResourceName: string): Promise<T | null>;
|
|
15
|
+
getCount(pluralResourceName: string): Promise<number>;
|
|
16
|
+
create<T extends IEntity>(entity: Partial<T>, pluralResourceName: string): Promise<{
|
|
17
|
+
insertedId: string;
|
|
18
|
+
entity: T;
|
|
19
|
+
}>;
|
|
20
|
+
createMany<T extends IEntity>(entities: Partial<T>[], pluralResourceName: string): Promise<{
|
|
21
|
+
insertedIds: string[];
|
|
22
|
+
entities: T[];
|
|
23
|
+
}>;
|
|
24
|
+
batchUpdate<T extends IEntity>(entities: Partial<T>[], operations: Operation[], queryObject: IQueryOptions, pluralResourceName: string): Promise<T[]>;
|
|
25
|
+
fullUpdateById<T extends IEntity>(operations: Operation[], id: string, entity: Partial<T>, pluralResourceName: string): Promise<T>;
|
|
26
|
+
partialUpdateById<T extends IEntity>(operations: Operation[], id: string, entity: Partial<T>, pluralResourceName: string): Promise<T>;
|
|
27
|
+
update<T extends IEntity>(queryObject: IQueryOptions, entity: Partial<T>, operations: Operation[], pluralResourceName: string): Promise<T[]>;
|
|
28
|
+
deleteById(id: string, pluralResourceName: string): Promise<GenericDeleteResult>;
|
|
29
|
+
deleteMany(queryObject: IQueryOptions, pluralResourceName: string): Promise<GenericDeleteResult>;
|
|
30
|
+
find<T extends IEntity>(queryObject: IQueryOptions, pluralResourceName: string): Promise<T[]>;
|
|
31
|
+
findOne<T extends IEntity>(queryObject: IQueryOptions, pluralResourceName: string): Promise<T | null>;
|
|
32
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { convertObjectIdsToStrings, convertStringsToObjectIds } from "./utils/index.js";
|
|
2
|
+
import { create, createMany, batchUpdate, fullUpdateById, partialUpdateById, update, deleteById, deleteMany } from "./commands/index.js";
|
|
3
|
+
import { getAll, get, getById, getCount, find, findOne } from "./queries/index.js";
|
|
4
|
+
import { entityUtils } from "@loomcore/common/utils";
|
|
5
|
+
import { BadRequestError } from "../../errors/bad-request.error.js";
|
|
6
|
+
export class MongoDBDatabase {
|
|
7
|
+
db;
|
|
8
|
+
constructor(db) {
|
|
9
|
+
this.db = db;
|
|
10
|
+
}
|
|
11
|
+
preprocessEntity(entity, schema) {
|
|
12
|
+
if (entity._id && !entityUtils.isValidObjectId(entity._id)) {
|
|
13
|
+
throw new BadRequestError('id is not a valid ObjectId');
|
|
14
|
+
}
|
|
15
|
+
return convertStringsToObjectIds(entity, schema);
|
|
16
|
+
}
|
|
17
|
+
postprocessEntity(single, schema) {
|
|
18
|
+
if (!single)
|
|
19
|
+
return single;
|
|
20
|
+
return convertObjectIdsToStrings(single);
|
|
21
|
+
}
|
|
22
|
+
async getAll(operations, pluralResourceName) {
|
|
23
|
+
return getAll(this.db, operations, pluralResourceName);
|
|
24
|
+
}
|
|
25
|
+
async get(operations, queryOptions, modelSpec, pluralResourceName) {
|
|
26
|
+
return get(this.db, operations, queryOptions, modelSpec, pluralResourceName);
|
|
27
|
+
}
|
|
28
|
+
async getById(operations, queryObject, id, pluralResourceName) {
|
|
29
|
+
return getById(this.db, operations, queryObject, id, pluralResourceName);
|
|
30
|
+
}
|
|
31
|
+
async getCount(pluralResourceName) {
|
|
32
|
+
return getCount(this.db, pluralResourceName);
|
|
33
|
+
}
|
|
34
|
+
async create(entity, pluralResourceName) {
|
|
35
|
+
return create(this.db, pluralResourceName, entity);
|
|
36
|
+
}
|
|
37
|
+
async createMany(entities, pluralResourceName) {
|
|
38
|
+
return createMany(this.db, pluralResourceName, entities);
|
|
39
|
+
}
|
|
40
|
+
async batchUpdate(entities, operations, queryObject, pluralResourceName) {
|
|
41
|
+
return batchUpdate(this.db, entities, operations, queryObject, pluralResourceName);
|
|
42
|
+
}
|
|
43
|
+
async fullUpdateById(operations, id, entity, pluralResourceName) {
|
|
44
|
+
return fullUpdateById(this.db, operations, id, entity, pluralResourceName);
|
|
45
|
+
}
|
|
46
|
+
async partialUpdateById(operations, id, entity, pluralResourceName) {
|
|
47
|
+
return partialUpdateById(this.db, operations, id, entity, pluralResourceName);
|
|
48
|
+
}
|
|
49
|
+
async update(queryObject, entity, operations, pluralResourceName) {
|
|
50
|
+
return update(this.db, queryObject, entity, operations, pluralResourceName);
|
|
51
|
+
}
|
|
52
|
+
async deleteById(id, pluralResourceName) {
|
|
53
|
+
return deleteById(this.db, id, pluralResourceName);
|
|
54
|
+
}
|
|
55
|
+
async deleteMany(queryObject, pluralResourceName) {
|
|
56
|
+
return deleteMany(this.db, queryObject, pluralResourceName);
|
|
57
|
+
}
|
|
58
|
+
async find(queryObject, pluralResourceName) {
|
|
59
|
+
return find(this.db, queryObject, pluralResourceName);
|
|
60
|
+
}
|
|
61
|
+
async findOne(queryObject, pluralResourceName) {
|
|
62
|
+
return findOne(this.db, queryObject, pluralResourceName);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { buildNoSqlMatch, buildFindOptions } from "../utils/index.js";
|
|
2
|
+
export async function findOne(db, queryObject, pluralResourceName) {
|
|
3
|
+
const collection = db.collection(pluralResourceName);
|
|
4
|
+
const matchDocument = buildNoSqlMatch(queryObject);
|
|
5
|
+
const filter = matchDocument.$match;
|
|
6
|
+
const options = buildFindOptions(queryObject);
|
|
7
|
+
const entity = await collection.findOne(filter, options);
|
|
8
|
+
return entity;
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { buildNoSqlMatch, buildFindOptions } from "../utils/index.js";
|
|
2
|
+
export async function find(db, queryObject, pluralResourceName) {
|
|
3
|
+
const collection = db.collection(pluralResourceName);
|
|
4
|
+
const matchDocument = buildNoSqlMatch(queryObject);
|
|
5
|
+
const filter = matchDocument.$match;
|
|
6
|
+
const options = buildFindOptions(queryObject);
|
|
7
|
+
const entities = await collection.find(filter, options).toArray();
|
|
8
|
+
return entities;
|
|
9
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import NoSqlPipeline from "../models/no-sql-pipeline.js";
|
|
2
|
+
export async function getAll(db, operations, pluralResourceName) {
|
|
3
|
+
const collection = db.collection(pluralResourceName);
|
|
4
|
+
const pipeline = new NoSqlPipeline()
|
|
5
|
+
.addOperations(operations)
|
|
6
|
+
.build();
|
|
7
|
+
let aggregateResult;
|
|
8
|
+
if (pipeline.length === 0) {
|
|
9
|
+
const cursor = collection.find();
|
|
10
|
+
aggregateResult = await cursor.toArray();
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
const cursor = collection.aggregate(pipeline);
|
|
14
|
+
aggregateResult = await cursor.toArray();
|
|
15
|
+
}
|
|
16
|
+
return aggregateResult;
|
|
17
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Db } from "mongodb";
|
|
2
|
+
import { Operation } from "../../operations/operation.js";
|
|
3
|
+
import { IQueryOptions } from "@loomcore/common/models";
|
|
4
|
+
export declare function getById<T>(db: Db, operations: Operation[], queryObject: IQueryOptions, id: string, pluralResourceName: string): Promise<T | null>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { entityUtils } from "@loomcore/common/utils";
|
|
2
|
+
import { BadRequestError } from "../../../errors/index.js";
|
|
3
|
+
import NoSqlPipeline from "../models/no-sql-pipeline.js";
|
|
4
|
+
export async function getById(db, operations, queryObject, id, pluralResourceName) {
|
|
5
|
+
if (!entityUtils.isValidObjectId(id)) {
|
|
6
|
+
throw new BadRequestError('id is not a valid ObjectId');
|
|
7
|
+
}
|
|
8
|
+
const collection = db.collection(pluralResourceName);
|
|
9
|
+
queryObject.filters || (queryObject.filters = {});
|
|
10
|
+
queryObject.filters._id = { eq: id };
|
|
11
|
+
const pipeline = new NoSqlPipeline()
|
|
12
|
+
.addMatch(queryObject)
|
|
13
|
+
.addOperations(operations)
|
|
14
|
+
.build();
|
|
15
|
+
const entity = await collection.aggregate(pipeline).next();
|
|
16
|
+
return entity;
|
|
17
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Db } from "mongodb";
|
|
2
|
+
import { IModelSpec, IQueryOptions, IPagedResult } from "@loomcore/common/models";
|
|
3
|
+
import { Operation } from "../../operations/operation.js";
|
|
4
|
+
export declare function get<T>(db: Db, operations: Operation[], queryOptions: IQueryOptions, modelSpec: IModelSpec, pluralResourceName: string): Promise<IPagedResult<T>>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import NoSqlPipeline from "../models/no-sql-pipeline.js";
|
|
2
|
+
import { apiUtils } from "../../../utils/api.utils.js";
|
|
3
|
+
export async function get(db, operations, queryOptions, modelSpec, pluralResourceName) {
|
|
4
|
+
const collection = db.collection(pluralResourceName);
|
|
5
|
+
const pipeline = new NoSqlPipeline()
|
|
6
|
+
.addMatch(queryOptions, modelSpec)
|
|
7
|
+
.addOperations(operations)
|
|
8
|
+
.addQueryOptions(queryOptions, true)
|
|
9
|
+
.build();
|
|
10
|
+
const cursor = collection.aggregate(pipeline);
|
|
11
|
+
const aggregateResult = await cursor.next();
|
|
12
|
+
const pagedResult = apiUtils.getPagedResult(aggregateResult?.data || [], aggregateResult?.total || 0, queryOptions);
|
|
13
|
+
return pagedResult;
|
|
14
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function buildFindOptions(queryOptions) {
|
|
2
|
+
let findOptions = {};
|
|
3
|
+
if (queryOptions) {
|
|
4
|
+
if (queryOptions.orderBy) {
|
|
5
|
+
findOptions.sort = {
|
|
6
|
+
[queryOptions.orderBy]: queryOptions.sortDirection === 'asc' ? 1 : -1
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
if (queryOptions.page && queryOptions.pageSize) {
|
|
10
|
+
findOptions.skip = (queryOptions.page - 1) * queryOptions.pageSize;
|
|
11
|
+
findOptions.limit = queryOptions.pageSize;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return findOptions;
|
|
15
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { entityUtils } from '@loomcore/common/utils';
|
|
2
|
+
import { ObjectId } from 'mongodb';
|
|
3
|
+
import { PROPERTIES_THAT_ARE_NOT_OBJECT_IDS } from '../../models/constants.js';
|
|
4
|
+
import { getPropertySchema } from '../../utils/get-property-schema.util.js';
|
|
5
|
+
export function buildNoSqlMatch(queryOptions, modelSpec) {
|
|
6
|
+
const filters = queryOptions.filters || {};
|
|
7
|
+
const schema = modelSpec?.fullSchema;
|
|
8
|
+
let match = {};
|
|
9
|
+
for (const [key, value] of Object.entries(filters)) {
|
|
10
|
+
if (value) {
|
|
11
|
+
const propSchema = schema ? getPropertySchema(key, schema) : undefined;
|
|
12
|
+
if (value.eq !== undefined) {
|
|
13
|
+
const isObjectIdField = propSchema?.format === 'objectid';
|
|
14
|
+
const valueToCompare = value.eq;
|
|
15
|
+
if ((key === '_id' || isObjectIdField || (!schema && key.endsWith('Id') && !PROPERTIES_THAT_ARE_NOT_OBJECT_IDS.includes(key)))
|
|
16
|
+
&& typeof valueToCompare === 'string' && entityUtils.isValidObjectId(valueToCompare)) {
|
|
17
|
+
match[key] = new ObjectId(valueToCompare);
|
|
18
|
+
}
|
|
19
|
+
else if (typeof valueToCompare === 'string' && !isNaN(Number(valueToCompare))) {
|
|
20
|
+
match[key] = Number(valueToCompare);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
match[key] = valueToCompare;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
else if (value.in !== undefined && Array.isArray(value.in)) {
|
|
27
|
+
const isObjectIdArray = propSchema?.type === 'array' && propSchema.items?.format === 'objectid';
|
|
28
|
+
if (key === '_id' || isObjectIdArray || (!schema && (key.endsWith('Id') || key.endsWith('Ids')) && !PROPERTIES_THAT_ARE_NOT_OBJECT_IDS.includes(key))) {
|
|
29
|
+
const objectIds = value.in
|
|
30
|
+
.filter(val => typeof val === 'string' && entityUtils.isValidObjectId(val))
|
|
31
|
+
.map(val => new ObjectId(val));
|
|
32
|
+
if (objectIds.length > 0) {
|
|
33
|
+
match[key] = { $in: objectIds };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
const convertedValues = value.in.map(val => typeof val === 'string' && !isNaN(Number(val)) ? Number(val) : val);
|
|
38
|
+
match[key] = { $in: convertedValues };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else if (value.gte !== undefined) {
|
|
42
|
+
match[key] = { $gte: value.gte };
|
|
43
|
+
}
|
|
44
|
+
else if (value.lte !== undefined) {
|
|
45
|
+
match[key] = { $lte: value.lte };
|
|
46
|
+
}
|
|
47
|
+
else if (value.gt !== undefined) {
|
|
48
|
+
match[key] = { $gt: value.gt };
|
|
49
|
+
}
|
|
50
|
+
else if (value.lt !== undefined) {
|
|
51
|
+
match[key] = { $lt: value.lt };
|
|
52
|
+
}
|
|
53
|
+
else if (value.contains !== undefined) {
|
|
54
|
+
match[key] = { $regex: value.contains, $options: 'i' };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return { $match: match };
|
|
59
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function convertObjectIdsToStrings<T>(entity: T): T;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
import { ObjectId } from 'mongodb';
|
|
3
|
+
export function convertObjectIdsToStrings(entity) {
|
|
4
|
+
if (!entity)
|
|
5
|
+
return entity;
|
|
6
|
+
const clone = _.cloneDeep(entity);
|
|
7
|
+
const processEntity = (obj) => {
|
|
8
|
+
if (!obj)
|
|
9
|
+
return obj;
|
|
10
|
+
if (obj instanceof ObjectId) {
|
|
11
|
+
return obj.toString();
|
|
12
|
+
}
|
|
13
|
+
if (obj instanceof Date) {
|
|
14
|
+
return obj;
|
|
15
|
+
}
|
|
16
|
+
if (Array.isArray(obj)) {
|
|
17
|
+
return obj.map(item => processEntity(item));
|
|
18
|
+
}
|
|
19
|
+
if (typeof obj === 'object') {
|
|
20
|
+
const result = { ...obj };
|
|
21
|
+
for (const key of Object.keys(result)) {
|
|
22
|
+
const value = result[key];
|
|
23
|
+
if (value !== null && value !== undefined) {
|
|
24
|
+
result[key] = processEntity(value);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
return obj;
|
|
30
|
+
};
|
|
31
|
+
return processEntity(clone);
|
|
32
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Join } from '../../operations/join.operation.js';
|
|
2
|
+
export function convertOperationsToPipeline(operations) {
|
|
3
|
+
let pipeline = [];
|
|
4
|
+
operations.forEach(operation => {
|
|
5
|
+
if (operation instanceof Join) {
|
|
6
|
+
const needsObjectIdConversion = operation.foreignField === '_id';
|
|
7
|
+
if (needsObjectIdConversion) {
|
|
8
|
+
pipeline.push({
|
|
9
|
+
$lookup: {
|
|
10
|
+
from: operation.from,
|
|
11
|
+
let: { localId: { $cond: [
|
|
12
|
+
{ $eq: [{ $type: `$${operation.localField}` }, 'string'] },
|
|
13
|
+
{ $toObjectId: `$${operation.localField}` },
|
|
14
|
+
`$${operation.localField}`
|
|
15
|
+
] } },
|
|
16
|
+
pipeline: [
|
|
17
|
+
{
|
|
18
|
+
$match: {
|
|
19
|
+
$expr: {
|
|
20
|
+
$eq: [`$${operation.foreignField}`, '$$localId']
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
as: `${operation.as}Arr`
|
|
26
|
+
}
|
|
27
|
+
}, {
|
|
28
|
+
$unwind: {
|
|
29
|
+
path: `$${operation.as}Arr`,
|
|
30
|
+
preserveNullAndEmptyArrays: true
|
|
31
|
+
}
|
|
32
|
+
}, {
|
|
33
|
+
$addFields: {
|
|
34
|
+
[operation.as]: `$${operation.as}Arr`
|
|
35
|
+
}
|
|
36
|
+
}, {
|
|
37
|
+
$project: {
|
|
38
|
+
[`${operation.as}Arr`]: 0
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
pipeline.push({
|
|
44
|
+
$lookup: {
|
|
45
|
+
from: operation.from,
|
|
46
|
+
localField: operation.localField,
|
|
47
|
+
foreignField: operation.foreignField,
|
|
48
|
+
as: `${operation.as}Arr`
|
|
49
|
+
}
|
|
50
|
+
}, {
|
|
51
|
+
$unwind: {
|
|
52
|
+
path: `$${operation.as}Arr`,
|
|
53
|
+
preserveNullAndEmptyArrays: true
|
|
54
|
+
}
|
|
55
|
+
}, {
|
|
56
|
+
$addFields: {
|
|
57
|
+
[operation.as]: `$${operation.as}Arr`
|
|
58
|
+
}
|
|
59
|
+
}, {
|
|
60
|
+
$project: {
|
|
61
|
+
[`${operation.as}Arr`]: 0
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
return pipeline;
|
|
68
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export function convertQueryOptionsToPipeline(queryOptions, pagination) {
|
|
2
|
+
let pipeline = [];
|
|
3
|
+
if (queryOptions.orderBy || (queryOptions.page && queryOptions.pageSize)) {
|
|
4
|
+
let results = [];
|
|
5
|
+
if (queryOptions.orderBy) {
|
|
6
|
+
results.push({
|
|
7
|
+
$sort: {
|
|
8
|
+
[queryOptions.orderBy]: queryOptions.sortDirection === 'asc' ? 1 : -1
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
if (queryOptions.page && queryOptions.pageSize) {
|
|
13
|
+
results.push({ $skip: (queryOptions.page - 1) * queryOptions.pageSize });
|
|
14
|
+
results.push({ $limit: queryOptions.pageSize });
|
|
15
|
+
}
|
|
16
|
+
if (pagination) {
|
|
17
|
+
pipeline.push({
|
|
18
|
+
$facet: {
|
|
19
|
+
data: results,
|
|
20
|
+
count: [{ $count: 'total' }]
|
|
21
|
+
}
|
|
22
|
+
}, {
|
|
23
|
+
$project: {
|
|
24
|
+
data: 1,
|
|
25
|
+
total: { $arrayElemAt: ['$count.total', 0] }
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return pipeline;
|
|
31
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { entityUtils } from '@loomcore/common/utils';
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
import { ObjectId } from 'mongodb';
|
|
4
|
+
import { PROPERTIES_THAT_ARE_NOT_OBJECT_IDS } from '../../models/constants.js';
|
|
5
|
+
export function convertStringsToObjectIds(entity, schema) {
|
|
6
|
+
if (!entity)
|
|
7
|
+
return entity;
|
|
8
|
+
const clone = _.cloneDeep(entity);
|
|
9
|
+
if (clone._id && typeof clone._id === 'string' && entityUtils.isValidObjectId(clone._id)) {
|
|
10
|
+
clone._id = new ObjectId(clone._id);
|
|
11
|
+
}
|
|
12
|
+
const processEntity = (obj, subSchema, path = []) => {
|
|
13
|
+
if (!obj || typeof obj !== 'object')
|
|
14
|
+
return obj;
|
|
15
|
+
if (obj instanceof Date) {
|
|
16
|
+
return obj;
|
|
17
|
+
}
|
|
18
|
+
if (subSchema.allOf && Array.isArray(subSchema.allOf)) {
|
|
19
|
+
let result = { ...obj };
|
|
20
|
+
for (const nestedSchema of subSchema.allOf) {
|
|
21
|
+
result = processEntity(result, nestedSchema, path);
|
|
22
|
+
}
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
if (Array.isArray(obj)) {
|
|
26
|
+
const items = subSchema.items;
|
|
27
|
+
if (!items)
|
|
28
|
+
return obj;
|
|
29
|
+
if (items.format === 'objectid') {
|
|
30
|
+
if (path.length === 1 && PROPERTIES_THAT_ARE_NOT_OBJECT_IDS.includes(path[0])) {
|
|
31
|
+
return obj;
|
|
32
|
+
}
|
|
33
|
+
return obj.map(item => {
|
|
34
|
+
if (typeof item === 'string' && entityUtils.isValidObjectId(item)) {
|
|
35
|
+
return new ObjectId(item);
|
|
36
|
+
}
|
|
37
|
+
return item;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
if (items.type === 'object') {
|
|
41
|
+
return obj.map((item, index) => processEntity(item, items, [...path, index.toString()]));
|
|
42
|
+
}
|
|
43
|
+
return obj;
|
|
44
|
+
}
|
|
45
|
+
const result = { ...obj };
|
|
46
|
+
if (subSchema.type === 'object' && subSchema.properties) {
|
|
47
|
+
for (const [key, propSchema] of Object.entries(subSchema.properties)) {
|
|
48
|
+
if (!propSchema || typeof propSchema !== 'object' || result[key] === null || result[key] === undefined) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const typedPropSchema = propSchema;
|
|
52
|
+
const fullPath = [...path, key];
|
|
53
|
+
const value = result[key];
|
|
54
|
+
const isObjectIdField = typedPropSchema.format === 'objectid';
|
|
55
|
+
if (isObjectIdField && path.length === 0 && PROPERTIES_THAT_ARE_NOT_OBJECT_IDS.includes(key)) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (isObjectIdField && typeof value === 'string' && entityUtils.isValidObjectId(value)) {
|
|
59
|
+
result[key] = new ObjectId(value);
|
|
60
|
+
}
|
|
61
|
+
else if (typedPropSchema.type === 'array' && Array.isArray(value)) {
|
|
62
|
+
result[key] = processEntity(value, typedPropSchema, fullPath);
|
|
63
|
+
}
|
|
64
|
+
else if (typedPropSchema.type === 'object' && typeof value === 'object' && !Array.isArray(value)) {
|
|
65
|
+
result[key] = processEntity(value, typedPropSchema, fullPath);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
};
|
|
71
|
+
return processEntity(clone, schema);
|
|
72
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './build-find-options.util.js';
|
|
2
|
+
export * from './build-no-sql-match.util.js';
|
|
3
|
+
export * from './convert-object-ids-to-strings.util.js';
|
|
4
|
+
export * from './convert-operations-to-pipeline.util.js';
|
|
5
|
+
export * from './convert-query-options-to-pipeline.util.js';
|
|
6
|
+
export * from './convert-strings-to-object-ids.util.js';
|
|
7
|
+
export * from '../models/no-sql-pipeline.js';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './build-find-options.util.js';
|
|
2
|
+
export * from './build-no-sql-match.util.js';
|
|
3
|
+
export * from './convert-object-ids-to-strings.util.js';
|
|
4
|
+
export * from './convert-operations-to-pipeline.util.js';
|
|
5
|
+
export * from './convert-query-options-to-pipeline.util.js';
|
|
6
|
+
export * from './convert-strings-to-object-ids.util.js';
|
|
7
|
+
export * from '../models/no-sql-pipeline.js';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Client } from 'pg';
|
|
2
|
+
import { Operation } from "../../operations/operation.js";
|
|
3
|
+
import { IEntity, IQueryOptions } from '@loomcore/common/models';
|
|
4
|
+
export declare function batchUpdate<T extends IEntity>(client: Client, entities: Partial<T>[], operations: Operation[], queryObject: IQueryOptions, pluralResourceName: string): Promise<T[]>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Join } from "../../operations/join.operation.js";
|
|
2
|
+
import { BadRequestError } from "../../../errors/index.js";
|
|
3
|
+
import { buildJoinClauses } from '../utils/build-join-clauses.js';
|
|
4
|
+
import { columnsAndValuesFromEntity } from '../utils/columns-and-values-from-entity.js';
|
|
5
|
+
import { buildWhereClause } from '../utils/build-where-clause.js';
|
|
6
|
+
export async function batchUpdate(client, entities, operations, queryObject, pluralResourceName) {
|
|
7
|
+
if (!entities || entities.length === 0) {
|
|
8
|
+
return [];
|
|
9
|
+
}
|
|
10
|
+
const entityIds = [];
|
|
11
|
+
for (const entity of entities) {
|
|
12
|
+
if (!entity._id || typeof entity._id !== 'string') {
|
|
13
|
+
throw new BadRequestError('Each entity in a batch update must have a valid _id.');
|
|
14
|
+
}
|
|
15
|
+
entityIds.push(entity._id);
|
|
16
|
+
}
|
|
17
|
+
queryObject.filters = queryObject.filters || {};
|
|
18
|
+
try {
|
|
19
|
+
await client.query('BEGIN');
|
|
20
|
+
for (const entity of entities) {
|
|
21
|
+
const { _id, ...updateData } = entity;
|
|
22
|
+
if (Object.keys(updateData).length === 0) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const { columns, values } = columnsAndValuesFromEntity(updateData);
|
|
26
|
+
const setClause = columns.map((col, index) => `${col} = $${index + 1}`).join(', ');
|
|
27
|
+
queryObject.filters._id = { eq: _id };
|
|
28
|
+
const { whereClause } = buildWhereClause(queryObject, values);
|
|
29
|
+
const query = `
|
|
30
|
+
UPDATE "${pluralResourceName}"
|
|
31
|
+
SET ${setClause}
|
|
32
|
+
${whereClause}
|
|
33
|
+
`;
|
|
34
|
+
await client.query(query, values);
|
|
35
|
+
}
|
|
36
|
+
await client.query('COMMIT');
|
|
37
|
+
const joinClauses = buildJoinClauses(operations, pluralResourceName);
|
|
38
|
+
const hasJoins = operations.some(op => op instanceof Join);
|
|
39
|
+
const tablePrefix = hasJoins ? pluralResourceName : undefined;
|
|
40
|
+
queryObject.filters._id = { in: entityIds };
|
|
41
|
+
const { whereClause, values } = buildWhereClause(queryObject, [], tablePrefix);
|
|
42
|
+
const selectQuery = `
|
|
43
|
+
SELECT * FROM "${pluralResourceName}" ${joinClauses}
|
|
44
|
+
${whereClause}
|
|
45
|
+
`;
|
|
46
|
+
const result = await client.query(selectQuery, values);
|
|
47
|
+
return result.rows;
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
await client.query('ROLLBACK');
|
|
51
|
+
if (err.code === '23505') {
|
|
52
|
+
throw new BadRequestError(`One or more ${pluralResourceName} have duplicate key violations`);
|
|
53
|
+
}
|
|
54
|
+
throw new BadRequestError(`Error updating ${pluralResourceName}: ${err.message}`);
|
|
55
|
+
}
|
|
56
|
+
}
|