From a2f87c271784ea22a5ffb4d725d62c3c6e444680 Mon Sep 17 00:00:00 2001 From: Konstantinos Feretos Date: Wed, 16 Nov 2022 17:49:46 +0200 Subject: [PATCH] fix(database): cms route sorting (#425) --- modules/chat/src/utils/index.ts | 4 ++-- modules/database/src/Database.ts | 4 +++- .../mongoose-adapter/MongooseSchema.ts | 18 +++++++++++------- .../sequelize-adapter/SequelizeSchema.ts | 18 ++++++++---------- .../src/controllers/cms/schema.controller.ts | 2 +- modules/database/src/controllers/cms/utils.ts | 2 +- .../CustomEndpoints/customEndpoint.handler.ts | 5 +++-- .../cms/{handler.ts => crud.handler.ts} | 8 +++++++- modules/database/src/handlers/utils.ts | 12 ++++++++++++ modules/database/src/routes/index.ts | 2 +- 10 files changed, 49 insertions(+), 26 deletions(-) rename modules/database/src/handlers/cms/{handler.ts => crud.handler.ts} (94%) create mode 100644 modules/database/src/handlers/utils.ts diff --git a/modules/chat/src/utils/index.ts b/modules/chat/src/utils/index.ts index 75bb7ca43..a00927a10 100644 --- a/modules/chat/src/utils/index.ts +++ b/modules/chat/src/utils/index.ts @@ -7,8 +7,8 @@ import { v4 as uuid } from 'uuid'; export async function validateUsersInput(grpcSdk: ConduitGrpcSdk, users: any[]) { const uniqueUsers = Array.from(new Set(users)); let errorMessage: string | null = null; - const usersToBeAdded = (await grpcSdk - .databaseProvider!.findMany('User', { _id: { $in: uniqueUsers } }) + const usersToBeAdded = (await User.getInstance() + .findMany({ _id: { $in: uniqueUsers } }) .catch((e: Error) => { errorMessage = e.message; })) as any[]; diff --git a/modules/database/src/Database.ts b/modules/database/src/Database.ts index 1f6759196..de39007a6 100644 --- a/modules/database/src/Database.ts +++ b/modules/database/src/Database.ts @@ -330,7 +330,9 @@ export default class DatabaseModule extends ManagedModule { const skip = call.request.skip; const limit = call.request.limit; const select = call.request.select; - const sort = call.request.sort ? JSON.parse(call.request.sort) : null; + const sort: { [key: string]: number } = call.request.sort + ? JSON.parse(call.request.sort) + : null; const populate = call.request.populate; const schemaAdapter = this._activeAdapter.getSchemaModel(call.request.schemaName); diff --git a/modules/database/src/adapters/mongoose-adapter/MongooseSchema.ts b/modules/database/src/adapters/mongoose-adapter/MongooseSchema.ts index 5631422ac..e002bce78 100644 --- a/modules/database/src/adapters/mongoose-adapter/MongooseSchema.ts +++ b/modules/database/src/adapters/mongoose-adapter/MongooseSchema.ts @@ -1,4 +1,4 @@ -import { Model, Mongoose, Schema } from 'mongoose'; +import { Model, Mongoose, Schema, SortOrder } from 'mongoose'; import { MultiDocQuery, ParsedQuery, @@ -166,7 +166,7 @@ export class MongooseSchema implements SchemaAdapter> { skip?: number, limit?: number, select?: string, - sort?: string, + sort?: { [key: string]: number }, populate?: string[], ) { let parsedQuery: ParsedQuery | ParsedQuery[]; @@ -176,17 +176,17 @@ export class MongooseSchema implements SchemaAdapter> { parsedQuery = query; } let finalQuery = this.model.find(this.parseQuery(parsedQuery), select); - if (skip !== null) { + if (!isNil(skip)) { finalQuery = finalQuery.skip(skip!); } - if (limit !== null) { + if (!isNil(limit)) { finalQuery = finalQuery.limit(limit!); } - if (populate != null) { + if (!isNil(populate)) { finalQuery = this.calculatePopulates(finalQuery, populate); } - if (sort !== null) { - finalQuery = finalQuery.sort(sort); + if (!isNil(sort)) { + finalQuery = finalQuery.sort(this.parseSort(sort)); } // } else { // finalQuery = finalQuery.sort({ createdAt: -1 }); @@ -235,4 +235,8 @@ export class MongooseSchema implements SchemaAdapter> { return parsed; } + + private parseSort(sort: { [key: string]: number }): { [p: string]: SortOrder } { + return sort as { [p: string]: SortOrder }; + } } diff --git a/modules/database/src/adapters/sequelize-adapter/SequelizeSchema.ts b/modules/database/src/adapters/sequelize-adapter/SequelizeSchema.ts index 3a206d992..79b4f5ce2 100644 --- a/modules/database/src/adapters/sequelize-adapter/SequelizeSchema.ts +++ b/modules/database/src/adapters/sequelize-adapter/SequelizeSchema.ts @@ -5,6 +5,7 @@ import { FindOptions, ModelCtor, Sequelize, + Order, OrderItem, } from 'sequelize'; import { @@ -179,7 +180,7 @@ export class SequelizeSchema implements SchemaAdapter> { skip?: number, limit?: number, select?: string, - sort?: string, + sort?: { [key: string]: number }, populate?: string[], relations?: Indexable, ): Promise { @@ -491,18 +492,15 @@ export class SequelizeSchema implements SchemaAdapter> { return { exclude }; } - private parseSort(sort: string) { - const fields = sort.split(' '); - const order = []; - for (const field of fields) { - let tmp; + private parseSort(sort: { [key: string]: number }): Order { + const order: Order = []; + Object.keys(sort).forEach(field => { if (field[0] === '-') { - tmp = [field.slice(1), 'DESC'] as OrderItem; + order.push([field.slice(1), 'DESC'] as OrderItem); } else { - tmp = [field, 'ASC'] as OrderItem; + order.push([field, 'ASC'] as OrderItem); } - order.push(tmp); - } + }); return order; } } diff --git a/modules/database/src/controllers/cms/schema.controller.ts b/modules/database/src/controllers/cms/schema.controller.ts index a0648d8f0..b759d485d 100644 --- a/modules/database/src/controllers/cms/schema.controller.ts +++ b/modules/database/src/controllers/cms/schema.controller.ts @@ -4,7 +4,7 @@ import { sortAndConstructRoutes } from './utils'; import { DatabaseAdapter } from '../../adapters/DatabaseAdapter'; import { MongooseSchema } from '../../adapters/mongoose-adapter/MongooseSchema'; import { SequelizeSchema } from '../../adapters/sequelize-adapter/SequelizeSchema'; -import { CmsHandlers } from '../../handlers/cms/handler'; +import { CmsHandlers } from '../../handlers/cms/crud.handler'; import { ParsedQuery } from '../../interfaces'; import { status } from '@grpc/grpc-js'; import { isNil } from 'lodash'; diff --git a/modules/database/src/controllers/cms/utils.ts b/modules/database/src/controllers/cms/utils.ts index 73c5c7b3f..b661cae10 100644 --- a/modules/database/src/controllers/cms/utils.ts +++ b/modules/database/src/controllers/cms/utils.ts @@ -7,7 +7,7 @@ import { RouteBuilder, TYPE, } from '@conduitplatform/grpc-sdk'; -import { CmsHandlers } from '../../handlers/cms/handler'; +import { CmsHandlers } from '../../handlers/cms/crud.handler'; import { ConduitBuiltRoute } from '../../interfaces'; export function compareFunction(schemaA: ConduitModel, schemaB: ConduitModel): number { diff --git a/modules/database/src/handlers/CustomEndpoints/customEndpoint.handler.ts b/modules/database/src/handlers/CustomEndpoints/customEndpoint.handler.ts index d34802c3e..be6551c31 100644 --- a/modules/database/src/handlers/CustomEndpoints/customEndpoint.handler.ts +++ b/modules/database/src/handlers/CustomEndpoints/customEndpoint.handler.ts @@ -5,6 +5,7 @@ import { Indexable, } from '@conduitplatform/grpc-sdk'; import { constructAssignment, constructQuery } from './utils'; +import { constructSortObj } from '../utils'; import { status } from '@grpc/grpc-js'; import { ICustomEndpoint, PopulatedCustomEndpoint } from '../../interfaces'; import { OperationsEnum } from '../../admin/customEndpoints/customEndpoints.admin'; @@ -111,9 +112,9 @@ export class CustomEndpointHandler { ); } - let sort: string | undefined = undefined; + let sort: { [key: string]: number } | undefined = undefined; if (endpoint.sorted && params.sort && params.sort.length > 0) { - sort = params.sort; + sort = constructSortObj(params.sort); } const createObj = this.parseCreateQuery(createString); diff --git a/modules/database/src/handlers/cms/handler.ts b/modules/database/src/handlers/cms/crud.handler.ts similarity index 94% rename from modules/database/src/handlers/cms/handler.ts rename to modules/database/src/handlers/cms/crud.handler.ts index 8856e4671..e7ee31d75 100644 --- a/modules/database/src/handlers/cms/handler.ts +++ b/modules/database/src/handlers/cms/crud.handler.ts @@ -10,6 +10,7 @@ import { MongooseSchema } from '../../adapters/mongoose-adapter/MongooseSchema'; import { SequelizeSchema } from '../../adapters/sequelize-adapter/SequelizeSchema'; import { Doc } from '../../interfaces'; import { findSchema, getUpdatedDocument, getUpdatedDocuments } from './utils'; +import { constructSortObj } from '../utils'; export class CmsHandlers { constructor( @@ -31,9 +32,14 @@ export class CmsHandlers { limitNumber = Number.parseInt(limit as string); } + let parsedSort: { [key: string]: number } | undefined = undefined; + if (sort && sort.length > 0) { + parsedSort = constructSortObj(sort); + } + const documentsPromise = this.database .getSchemaModel(schemaName) - .model.findMany({}, skipNumber, limitNumber, undefined, sort, populate); + .model.findMany({}, skipNumber, limitNumber, undefined, parsedSort, populate); const countPromise = this.database .getSchemaModel(schemaName) .model.countDocuments({}); diff --git a/modules/database/src/handlers/utils.ts b/modules/database/src/handlers/utils.ts new file mode 100644 index 000000000..083171f2c --- /dev/null +++ b/modules/database/src/handlers/utils.ts @@ -0,0 +1,12 @@ +export function constructSortObj(sort: string[]) { + const sortObj: { [key: string]: number } = {}; + sort.forEach((sortVal: string) => { + sortVal = sortVal.trim(); + if (sortVal.indexOf('-') !== -1) { + sortObj[sortVal.substring(1)] = -1; + } else { + sortObj[sortVal] = 1; + } + }); + return sortObj; +} diff --git a/modules/database/src/routes/index.ts b/modules/database/src/routes/index.ts index fb9b9f6da..d9f7e057b 100644 --- a/modules/database/src/routes/index.ts +++ b/modules/database/src/routes/index.ts @@ -1,4 +1,4 @@ -import { CmsHandlers } from '../handlers/cms/handler'; +import { CmsHandlers } from '../handlers/cms/crud.handler'; import ConduitGrpcSdk, { ConduitRouteOptions, ConduitRouteReturnDefinition,