arkos 1.0.11-beta → 1.0.12-beta
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/cjs/modules/base/base.controller.js +1 -0
- package/dist/cjs/modules/base/base.controller.js.map +1 -1
- package/dist/cjs/modules/base/base.service.js +12 -10
- package/dist/cjs/modules/base/base.service.js.map +1 -1
- package/dist/cjs/utils/helpers/api.features.helpers.js +4 -1
- package/dist/cjs/utils/helpers/api.features.helpers.js.map +1 -1
- package/dist/es2020/modules/base/base.controller.js +1 -0
- package/dist/es2020/modules/base/base.controller.js.map +1 -1
- package/dist/es2020/modules/base/base.service.js +12 -10
- package/dist/es2020/modules/base/base.service.js.map +1 -1
- package/dist/es2020/utils/helpers/api.features.helpers.js +4 -1
- package/dist/es2020/utils/helpers/api.features.helpers.js.map +1 -1
- package/package.json +1 -1
|
@@ -53,6 +53,7 @@ class BaseController {
|
|
|
53
53
|
.sort()
|
|
54
54
|
.limitFields()
|
|
55
55
|
.paginate();
|
|
56
|
+
console.log(JSON.stringify(features.filters, null, 2));
|
|
56
57
|
const { data, total } = yield this.baseService.findMany(features.filters);
|
|
57
58
|
if (this.middlewares.afterFindMany) {
|
|
58
59
|
req.responseData = { total, results: data.length, data };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.controller.js","sourceRoot":"","sources":["../../../../src/modules/base/base.controller.ts"],"names":[],"mappings":"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","sourcesContent":["import { ArkosRequest, ArkosResponse, ArkosNextFunction } from \"../../types\";\nimport catchAsync from \"../error-handler/utils/catch-async\";\nimport APIFeatures from \"../../utils/features/api.features\";\nimport { BaseService } from \"./base.service\";\nimport AppError from \"../error-handler/utils/app-error\";\nimport { kebabCase } from \"../../utils/helpers/change-case.helpers\";\nimport { getExpressApp } from \"../../server\";\nimport { getModelModules, getModels } from \"../../utils/helpers/models.helpers\";\n\n/**\n * BaseController class providing standardized RESTful API endpoints for any prisma model\n * @class BaseController\n */\nexport class BaseController {\n /**\n * Service instance to handle business logic operations\n * @private\n */\n private baseService: BaseService;\n\n /**\n * Name of the model this controller handles\n * @private\n */\n private modelName: string;\n\n /**\n * Model-specific middlewares loaded from model modules\n * @private\n */\n private middlewares: any;\n\n /**\n * Creates a new BaseController instance\n * @param {string} modelName - The name of the model for which this controller will handle operations\n */\n constructor(modelName: string) {\n this.modelName = modelName;\n this.baseService = new BaseService(modelName);\n this.middlewares = getModelModules(modelName)?.middlewares || {};\n }\n\n /**\n * Creates a single resource\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n createOne = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n const data = await this.baseService.createOne(\n req.body,\n req.query?.prismaQueryOptions as string\n );\n\n if (this.middlewares.afterCreateOne) {\n req.responseData = { data };\n req.responseStatus = 201;\n return next();\n }\n\n res.status(201).json({ data });\n }\n );\n\n /**\n * Creates multiple resources in a single operation\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n createMany = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n const { data, total } = await this.baseService.createMany(req.body);\n\n if (this.middlewares.afterCreateMany) {\n req.responseData = { total, results: data.length, data };\n req.responseStatus = 201;\n return next();\n }\n\n res.status(201).json({ total, results: data.length, data });\n }\n );\n\n /**\n * Retrieves multiple resources with filtering, sorting, pagination, and field selection\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n findMany = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n const features = new APIFeatures(\n req,\n this.modelName,\n this.baseService.relationFields?.singular.reduce(\n (acc: Record<string, boolean>, curr) => {\n acc[curr.name] = true;\n return acc;\n },\n {}\n )\n )\n .filter()\n .sort()\n .limitFields()\n .paginate();\n\n const { data, total } = await this.baseService.findMany(features.filters);\n\n if (this.middlewares.afterFindMany) {\n req.responseData = { total, results: data.length, data };\n req.responseStatus = 200;\n return next();\n }\n\n res.status(200).json({ total, results: data.length, data });\n }\n );\n\n /**\n * Retrieves a single resource by its identifier\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n findOne = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n const data = await this.baseService.findOne(\n req.params,\n req.query?.prismaQueryOptions as string\n );\n\n if (this.middlewares.afterFindOne) {\n req.responseData = { data };\n req.responseStatus = 200;\n return next();\n }\n\n res.status(200).json({ data });\n }\n );\n\n /**\n * Updates a single resource by its identifier\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n updateOne = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n const data = await this.baseService.updateOne(\n req.params,\n req.body,\n req.query?.prismaQueryOptions as string\n );\n\n if (this.middlewares.afterUpdateOne) {\n req.responseData = { data };\n req.responseStatus = 200;\n return next();\n }\n\n res.status(200).json({ data });\n }\n );\n\n /**\n * Updates multiple resources that match specified criteria\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n updateMany = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n if (!Object.keys(req.query).some((key) => key !== \"prismaQueryOptions\")) {\n return next(\n new AppError(\"Filter criteria not provided for bulk update.\", 400)\n );\n }\n\n const features = new APIFeatures(req, this.modelName).filter().sort();\n delete features.filters.include;\n\n const { data, total } = await this.baseService.updateMany(\n features.filters,\n req.body\n );\n\n if (this.middlewares.afterUpdateMany) {\n req.responseData = { total, results: data.length, data };\n req.responseStatus = 200;\n return next();\n }\n\n res.status(200).json({ total, results: data.length, data });\n }\n );\n\n /**\n * Deletes a single resource by its identifier\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n deleteOne = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n await this.baseService.deleteOne(req.params);\n\n if (this.middlewares.afterDeleteOne) {\n req.responseData = { id: String(req.params.id) };\n req.responseStatus = 204;\n return next();\n }\n\n res.status(204).send();\n }\n );\n\n /**\n * Deletes multiple resources that match specified criteria\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n deleteMany = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n if (!Object.keys(req.query).some((key) => key !== \"prismaQueryOptions\")) {\n return next(\n new AppError(\"Filter criteria not provided for bulk deletion.\", 400)\n );\n }\n\n const features = new APIFeatures(req, this.modelName).filter().sort();\n delete features.filters.include;\n\n const { data, total } = await this.baseService.deleteMany(\n features.filters\n );\n\n if (this.middlewares.afterDeleteMany) {\n req.responseData = { total, results: data.length, data };\n req.responseStatus = 200;\n return next();\n }\n\n res.status(200).json({ total, results: data.length, data });\n }\n );\n}\n\n/**\n * Returns a list of all registered API routes in the Express application\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {void}\n */\nexport function getAvalibleRoutes(\n req: ArkosRequest,\n res: ArkosResponse,\n next: ArkosNextFunction\n) {\n const routes: { method: string; path: string }[] = [];\n req.params;\n const app = getExpressApp();\n\n app._router.stack.forEach((middleware: any) => {\n if (middleware.route) {\n Object.keys(middleware.route.methods).forEach((method) => {\n routes.push({\n method: method.toUpperCase(),\n path: middleware.route.path,\n });\n });\n } else if (middleware.handle && middleware.handle.stack) {\n middleware.handle.stack.forEach((routerMiddleware: any) => {\n if (routerMiddleware.route) {\n Object.keys(routerMiddleware.route.methods).forEach((method) => {\n const fullPath =\n (middleware.regexp\n ? middleware.regexp.toString().replace(\"/\", \"\")\n : \"\") + routerMiddleware.route.path;\n routes.push({\n method: method.toUpperCase(),\n path: routerMiddleware.route.path,\n });\n });\n }\n });\n }\n });\n\n res.json(routes);\n}\n\n/**\n * Returns a list of all available resource endpoints based on the application's models\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\nexport const getAvailableResources = catchAsync(async (req, res, next) => {\n const models = getModels();\n res.status(200).json({\n data: [...models.map((model) => kebabCase(model)), \"file-upload\"],\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"base.controller.js","sourceRoot":"","sources":["../../../../src/modules/base/base.controller.ts"],"names":[],"mappings":"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","sourcesContent":["import { ArkosRequest, ArkosResponse, ArkosNextFunction } from \"../../types\";\nimport catchAsync from \"../error-handler/utils/catch-async\";\nimport APIFeatures from \"../../utils/features/api.features\";\nimport { BaseService } from \"./base.service\";\nimport AppError from \"../error-handler/utils/app-error\";\nimport { kebabCase } from \"../../utils/helpers/change-case.helpers\";\nimport { getExpressApp } from \"../../server\";\nimport { getModelModules, getModels } from \"../../utils/helpers/models.helpers\";\n\n/**\n * BaseController class providing standardized RESTful API endpoints for any prisma model\n * @class BaseController\n */\nexport class BaseController {\n /**\n * Service instance to handle business logic operations\n * @private\n */\n private baseService: BaseService;\n\n /**\n * Name of the model this controller handles\n * @private\n */\n private modelName: string;\n\n /**\n * Model-specific middlewares loaded from model modules\n * @private\n */\n private middlewares: any;\n\n /**\n * Creates a new BaseController instance\n * @param {string} modelName - The name of the model for which this controller will handle operations\n */\n constructor(modelName: string) {\n this.modelName = modelName;\n this.baseService = new BaseService(modelName);\n this.middlewares = getModelModules(modelName)?.middlewares || {};\n }\n\n /**\n * Creates a single resource\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n createOne = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n const data = await this.baseService.createOne(\n req.body,\n req.query?.prismaQueryOptions as string\n );\n\n if (this.middlewares.afterCreateOne) {\n req.responseData = { data };\n req.responseStatus = 201;\n return next();\n }\n\n res.status(201).json({ data });\n }\n );\n\n /**\n * Creates multiple resources in a single operation\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n createMany = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n const { data, total } = await this.baseService.createMany(req.body);\n\n if (this.middlewares.afterCreateMany) {\n req.responseData = { total, results: data.length, data };\n req.responseStatus = 201;\n return next();\n }\n\n res.status(201).json({ total, results: data.length, data });\n }\n );\n\n /**\n * Retrieves multiple resources with filtering, sorting, pagination, and field selection\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n findMany = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n const features = new APIFeatures(\n req,\n this.modelName,\n this.baseService.relationFields?.singular.reduce(\n (acc: Record<string, boolean>, curr) => {\n acc[curr.name] = true;\n return acc;\n },\n {}\n )\n )\n .filter()\n .sort()\n .limitFields()\n .paginate();\n\n console.log(JSON.stringify(features.filters, null, 2));\n\n const { data, total } = await this.baseService.findMany(features.filters);\n\n if (this.middlewares.afterFindMany) {\n req.responseData = { total, results: data.length, data };\n req.responseStatus = 200;\n return next();\n }\n\n res.status(200).json({ total, results: data.length, data });\n }\n );\n\n /**\n * Retrieves a single resource by its identifier\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n findOne = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n const data = await this.baseService.findOne(\n req.params,\n req.query?.prismaQueryOptions as string\n );\n\n if (this.middlewares.afterFindOne) {\n req.responseData = { data };\n req.responseStatus = 200;\n return next();\n }\n\n res.status(200).json({ data });\n }\n );\n\n /**\n * Updates a single resource by its identifier\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n updateOne = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n const data = await this.baseService.updateOne(\n req.params,\n req.body,\n req.query?.prismaQueryOptions as string\n );\n\n if (this.middlewares.afterUpdateOne) {\n req.responseData = { data };\n req.responseStatus = 200;\n return next();\n }\n\n res.status(200).json({ data });\n }\n );\n\n /**\n * Updates multiple resources that match specified criteria\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n updateMany = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n if (!Object.keys(req.query).some((key) => key !== \"prismaQueryOptions\")) {\n return next(\n new AppError(\"Filter criteria not provided for bulk update.\", 400)\n );\n }\n\n const features = new APIFeatures(req, this.modelName).filter().sort();\n delete features.filters.include;\n\n const { data, total } = await this.baseService.updateMany(\n features.filters,\n req.body\n );\n\n if (this.middlewares.afterUpdateMany) {\n req.responseData = { total, results: data.length, data };\n req.responseStatus = 200;\n return next();\n }\n\n res.status(200).json({ total, results: data.length, data });\n }\n );\n\n /**\n * Deletes a single resource by its identifier\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n deleteOne = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n await this.baseService.deleteOne(req.params);\n\n if (this.middlewares.afterDeleteOne) {\n req.responseData = { id: String(req.params.id) };\n req.responseStatus = 204;\n return next();\n }\n\n res.status(204).send();\n }\n );\n\n /**\n * Deletes multiple resources that match specified criteria\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n deleteMany = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n if (!Object.keys(req.query).some((key) => key !== \"prismaQueryOptions\")) {\n return next(\n new AppError(\"Filter criteria not provided for bulk deletion.\", 400)\n );\n }\n\n const features = new APIFeatures(req, this.modelName).filter().sort();\n delete features.filters.include;\n\n const { data, total } = await this.baseService.deleteMany(\n features.filters\n );\n\n if (this.middlewares.afterDeleteMany) {\n req.responseData = { total, results: data.length, data };\n req.responseStatus = 200;\n return next();\n }\n\n res.status(200).json({ total, results: data.length, data });\n }\n );\n}\n\n/**\n * Returns a list of all registered API routes in the Express application\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {void}\n */\nexport function getAvalibleRoutes(\n req: ArkosRequest,\n res: ArkosResponse,\n next: ArkosNextFunction\n) {\n const routes: { method: string; path: string }[] = [];\n req.params;\n const app = getExpressApp();\n\n app._router.stack.forEach((middleware: any) => {\n if (middleware.route) {\n Object.keys(middleware.route.methods).forEach((method) => {\n routes.push({\n method: method.toUpperCase(),\n path: middleware.route.path,\n });\n });\n } else if (middleware.handle && middleware.handle.stack) {\n middleware.handle.stack.forEach((routerMiddleware: any) => {\n if (routerMiddleware.route) {\n Object.keys(routerMiddleware.route.methods).forEach((method) => {\n const fullPath =\n (middleware.regexp\n ? middleware.regexp.toString().replace(\"/\", \"\")\n : \"\") + routerMiddleware.route.path;\n routes.push({\n method: method.toUpperCase(),\n path: routerMiddleware.route.path,\n });\n });\n }\n });\n }\n });\n\n res.json(routes);\n}\n\n/**\n * Returns a list of all available resource endpoints based on the application's models\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\nexport const getAvailableResources = catchAsync(async (req, res, next) => {\n const models = getModels();\n res.status(200).json({\n data: [...models.map((model) => kebabCase(model)), \"file-upload\"],\n });\n});\n"]}
|
|
@@ -68,16 +68,18 @@ class BaseService {
|
|
|
68
68
|
return __awaiter(this, void 0, void 0, function* () {
|
|
69
69
|
const modelModules = (0, models_helpers_1.getModelModules)((0, change_case_helpers_1.kebabCase)(this.modelName));
|
|
70
70
|
const prisma = (0, prisma_helpers_1.getPrismaInstance)();
|
|
71
|
-
const data = yield
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
71
|
+
const [data, total] = yield Promise.all([
|
|
72
|
+
prisma[this.modelName].findMany("select" in filters
|
|
73
|
+
? (0, deepmerge_helper_1.default)(Object.assign({}, filters), {
|
|
74
|
+
select: this.singularRelationFieldToInclude,
|
|
75
|
+
})
|
|
76
|
+
: (0, deepmerge_helper_1.default)(Object.assign({}, filters), {
|
|
77
|
+
include: this.singularRelationFieldToInclude,
|
|
78
|
+
})),
|
|
79
|
+
prisma[this.modelName].count({
|
|
80
|
+
where: filters.where,
|
|
81
|
+
}),
|
|
82
|
+
]);
|
|
81
83
|
return { total, data };
|
|
82
84
|
});
|
|
83
85
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.service.js","sourceRoot":"","sources":["../../../../src/modules/base/base.service.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n camelCase,\n kebabCase,\n pascalCase,\n} from \"../../utils/helpers/change-case.helpers\";\nimport {\n getModelModules,\n getModels,\n getPrismaModelRelations,\n RelationFields,\n} from \"../../utils/helpers/models.helpers\";\nimport deepmerge from \"../../utils/helpers/deepmerge.helper\";\nimport AppError from \"../error-handler/utils/app-error\";\nimport pluralize from \"pluralize\";\nimport { handleRelationFieldsInBody } from \"./utils/helpers/base.helpers\";\nimport { getPrismaInstance } from \"../../utils/helpers/prisma.helpers\";\nimport validateDto from \"../../utils/validate-dto\";\nimport { getArkosConfig } from \"../../server\";\nimport authService from \"../auth/auth.service\";\n\n/**\n * Base service class for handling CRUD operations on a specific model.\n * This class provides standard implementation of data operations that can be extended\n * by model-specific service classes.\n *\n * @class BaseService\n */\nexport class BaseService {\n /**\n * The camelCase name of the model\n * @public\n */\n modelName: string;\n\n /**\n * Object containing singular and list relation fields for the model\n * @public\n */\n relationFields: RelationFields;\n\n /**\n * Map of singular relation fields to include in queries\n * @public\n */\n singularRelationFieldToInclude: Record<string, boolean>;\n\n /**\n * Map of list relation fields to include in queries\n * @public\n */\n listRelationFieldToInclude: Record<string, boolean>;\n\n /**\n * Instance of the Prisma client\n * @public\n */\n prisma: any;\n\n /**\n * Creates an instance of BaseService.\n * @param {string} modelName - The name of the model to perform operations on.\n */\n constructor(modelName: string) {\n this.modelName = camelCase(modelName);\n this.relationFields = getPrismaModelRelations(pascalCase(modelName))!;\n this.singularRelationFieldToInclude = this.relationFields?.singular?.reduce(\n (acc: Record<string, boolean>, curr) => {\n acc[curr.name] = true;\n return acc;\n },\n {}\n );\n this.listRelationFieldToInclude = this.relationFields?.list?.reduce(\n (acc: Record<string, boolean>, curr) => {\n acc[curr.name] = true;\n return acc;\n },\n {}\n );\n }\n /**\n * Creates a single record in the database.\n *\n * @param {Record<string, any>} body - The data to create the record with.\n * @param {string} [queryOptions] - Additional query options to modify the Prisma query.\n * @returns {Promise<any>} The created record.\n */\n async createOne(\n body: Record<string, any>,\n queryOptions: string = \"{}\"\n ): Promise<any> {\n if (kebabCase(this.modelName) === \"user\" && body.password) {\n body.password = await authService.hashPassword(body.password);\n }\n\n const prisma = getPrismaInstance();\n\n const bodyWithRelationFieldsHandled = handleRelationFieldsInBody(\n body,\n {\n ...this.relationFields,\n },\n [\"delete\", \"disconnect\", \"update\"]\n );\n\n return await prisma[this.modelName].create(\n deepmerge(\n {\n data: bodyWithRelationFieldsHandled,\n include: {\n ...this.singularRelationFieldToInclude,\n ...this.singularRelationFieldToInclude,\n },\n },\n JSON.parse(queryOptions || \"{}\")\n )\n );\n }\n\n /**\n * Creates multiple records in the database.\n *\n * @param {Record<string, any>[]} body - An array of data to create records with.\n * @returns {Promise<{ total: number; data: any }>} The result containing the total count and the created data.\n * @throws {AppError} Throws an error if the data array is invalid or empty.\n */\n async createMany(\n body: Record<string, any>[]\n ): Promise<{ total: number; data: any }> {\n const prisma = getPrismaInstance();\n\n if (!Array.isArray(body) || body.length === 0) {\n throw new AppError(\n \"Invalid or empty data array provided for creation.\",\n 400\n );\n }\n\n const data = await prisma[this.modelName].createMany({\n data: body,\n });\n\n const total = await prisma[this.modelName].count();\n return { total, data };\n }\n\n /**\n * Finds multiple records based on provided filters.\n *\n * @param {Record<string, any>} filters - The filters to apply to the query.\n * @returns {Promise<{ total: number; data: any }>} The result containing the total count and the found data.\n */\n async findMany(\n filters: Record<string, any>\n ): Promise<{ total: number; data: any }> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n // if (modelModules.dtos.query && getArkosConfig()?.validation !== false) {\n // filters = await validateDto(modelModules.dtos.query, filters);\n // }\n\n const prisma = getPrismaInstance();\n\n const data = await prisma[this.modelName].findMany(\n \"select\" in filters\n ? deepmerge(\n { ...filters },\n {\n select: this.singularRelationFieldToInclude,\n }\n )\n : deepmerge(\n { ...filters },\n {\n include: this.singularRelationFieldToInclude,\n }\n )\n );\n\n const total = await prisma[this.modelName].count({\n where: filters.where,\n });\n\n return { total, data };\n }\n\n /**\n * Finds a single record by its parameters.\n *\n * @param {Record<string, any>} filters - The parameters to find the record by.\n * @param {string} [queryOptions] - Additional query options to modify the Prisma query.\n * @returns {Promise<any>} The found record.\n * @throws {AppError} Throws an error if the record is not found.\n */\n async findOne(\n filters: Record<string, any>,\n // queryOptions: string = JSON.stringify(\n // getModelModules(kebabCase(this.modelName)).prismaQueryOptions || {}\n // )\n queryOptions: string = \"{}\"\n ): Promise<any> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n // if (modelModules.dtos.create && getArkosConfig()?.validation !== false) {\n // filters = await validateDto(modelModules.dtos.create, filters);\n // }\n\n const prisma = getPrismaInstance();\n\n const data = await prisma[this.modelName].findUnique(\n deepmerge(\n {\n where: { ...filters, id: String(filters.id) },\n ...(JSON.parse(queryOptions || \"{}\").hasOwnProperty(\"select\")\n ? {\n select: {\n ...this.singularRelationFieldToInclude,\n ...this.listRelationFieldToInclude,\n },\n }\n : {\n include: {\n ...this.singularRelationFieldToInclude,\n ...this.listRelationFieldToInclude,\n },\n }),\n },\n JSON.parse(queryOptions || \"{}\")\n )\n );\n\n if (!data) {\n throw new AppError(\n `${pascalCase(String(this.modelName))} with ID ${filters.id} not found`,\n 404\n );\n }\n\n return data;\n }\n\n /**\n * Updates a single record by its ID.\n *\n * @param {Record<string, any>} filters - The parameters to find the record by.\n * @param {Record<string, any>} body - The data to update the record with.\n * @param {string} [queryOptions] - Additional query options to modify the Prisma query.\n * @returns {Promise<any>} The updated record.\n * @throws {AppError} Throws an error if the record is not found.\n */\n async updateOne(\n filters: Record<string, any>,\n body: Record<string, any>,\n // queryOptions: string = JSON.stringify(\n // getModelModules(kebabCase(this.modelName)).prismaQueryOptions || {}\n // )\n queryOptions: string = \"{}\"\n ): Promise<any> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n if (modelModules.dtos.update && getArkosConfig()?.validation) {\n body = await validateDto(modelModules.dtos.update, body);\n }\n\n const prisma = getPrismaInstance();\n\n if (kebabCase(this.modelName) === \"user\" && body.password) {\n body.password = await authService.hashPassword(body.password);\n }\n\n const bodyWithRelationFieldsHandled = handleRelationFieldsInBody(body, {\n ...this.relationFields,\n });\n\n const data = await prisma[this.modelName].update(\n deepmerge(\n {\n where: { ...filters, id: String(filters.id) },\n data: bodyWithRelationFieldsHandled,\n include: {\n ...this.singularRelationFieldToInclude,\n ...this.singularRelationFieldToInclude,\n },\n },\n JSON.parse(queryOptions || \"{}\")\n )\n );\n\n if (!data) {\n throw new AppError(\n `${pascalCase(String(this.modelName))} with ID ${filters.id} not found`,\n 404\n );\n }\n\n return data;\n }\n\n /**\n * Updates multiple records based on the provided filter and data.\n *\n * @param {Record<string, any>} filters - The filters to identify records to update.\n * @param {Record<string, any>} body - The data to update the records with.\n * @returns {Promise<{ total: number; data: any }>} The result containing the total count and the updated data.\n * @throws {AppError} Throws an error if no records match the filters.\n */\n async updateMany(\n filters: Record<string, any>,\n body: Record<string, any>\n ): Promise<{ total: number; data: any }> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n // if (modelModules.dtos.create && getArkosConfig()?.validation !== false) {\n // body = await validateDto(modelModules.dtos.create, body);\n // }\n\n const prisma = getPrismaInstance();\n\n if (!filters || typeof filters !== \"object\") {\n throw new AppError(\"Invalid filters provided for udpate many.\", 400);\n }\n\n const data = await prisma[this.modelName].updateMany({\n ...filters,\n data: body,\n });\n\n if (!data || data.count === 0) {\n throw new AppError(\n `${pluralize(pascalCase(String(this.modelName)))} not found`,\n 404\n );\n }\n\n const total = await prisma[this.modelName].count();\n return { total, data };\n }\n\n /**\n * Deletes a single record by its ID.\n *\n * @param {Record<string, any>} params - The parameters to find the record by.\n * @returns {Promise<any>} The deleted record.\n */\n async deleteOne(params: Record<string, any>): Promise<any> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n // if (modelModules.dtos.create && getArkosConfig()?.validation !== false) {\n // body = await validateDto(modelModules.dtos.create, body);\n // }\n\n const prisma = getPrismaInstance();\n\n return await prisma[this.modelName].delete({\n where: {\n ...params,\n id: String(params.id),\n },\n });\n }\n\n /**\n * Deletes multiple records based on the provided filter.\n *\n * @param {Record<string, any>} filter - The filter to identify records to delete.\n * @returns {Promise<{ total: number; data: any }>} The result containing the total count and the deleted data.\n * @throws {AppError} Throws an error if no records match the filter.\n */\n async deleteMany(\n filters: Record<string, any>\n ): Promise<{ total: number; data: any }> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n // if (modelModules.dtos.create && getArkosConfig()?.validation !== false) {\n // body = await validateDto(modelModules.dtos.create, body);\n // }\n\n const prisma = getPrismaInstance();\n\n if (!filters || typeof filters !== \"object\") {\n throw new AppError(\"Invalid filters provided for deletion.\", 400);\n }\n\n const data = await prisma[this.modelName].deleteMany(filters);\n\n if (!data || data.count === 0) {\n throw new AppError(`No records found to delete`, 404);\n }\n\n const total = await prisma[this.modelName].count();\n return { total, data };\n }\n}\n\n/**\n * Generates a set of base service instances for all available models.\n *\n * @returns {Record<string, BaseService>} A dictionary of base service instances, keyed by model name.\n */\nexport function getBaseServices(): Record<string, BaseService> {\n const models = getModels();\n const baseServices: Record<string, BaseService> = {};\n models.forEach((model) => {\n baseServices[`${camelCase(model)}`] = new BaseService(model);\n });\n return baseServices;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"base.service.js","sourceRoot":"","sources":["../../../../src/modules/base/base.service.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n camelCase,\n kebabCase,\n pascalCase,\n} from \"../../utils/helpers/change-case.helpers\";\nimport {\n getModelModules,\n getModels,\n getPrismaModelRelations,\n RelationFields,\n} from \"../../utils/helpers/models.helpers\";\nimport deepmerge from \"../../utils/helpers/deepmerge.helper\";\nimport AppError from \"../error-handler/utils/app-error\";\nimport pluralize from \"pluralize\";\nimport { handleRelationFieldsInBody } from \"./utils/helpers/base.helpers\";\nimport { getPrismaInstance } from \"../../utils/helpers/prisma.helpers\";\nimport validateDto from \"../../utils/validate-dto\";\nimport { getArkosConfig } from \"../../server\";\nimport authService from \"../auth/auth.service\";\n\n/**\n * Base service class for handling CRUD operations on a specific model.\n * This class provides standard implementation of data operations that can be extended\n * by model-specific service classes.\n *\n * @class BaseService\n */\nexport class BaseService {\n /**\n * The camelCase name of the model\n * @public\n */\n modelName: string;\n\n /**\n * Object containing singular and list relation fields for the model\n * @public\n */\n relationFields: RelationFields;\n\n /**\n * Map of singular relation fields to include in queries\n * @public\n */\n singularRelationFieldToInclude: Record<string, boolean>;\n\n /**\n * Map of list relation fields to include in queries\n * @public\n */\n listRelationFieldToInclude: Record<string, boolean>;\n\n /**\n * Instance of the Prisma client\n * @public\n */\n prisma: any;\n\n /**\n * Creates an instance of BaseService.\n * @param {string} modelName - The name of the model to perform operations on.\n */\n constructor(modelName: string) {\n this.modelName = camelCase(modelName);\n this.relationFields = getPrismaModelRelations(pascalCase(modelName))!;\n this.singularRelationFieldToInclude = this.relationFields?.singular?.reduce(\n (acc: Record<string, boolean>, curr) => {\n acc[curr.name] = true;\n return acc;\n },\n {}\n );\n this.listRelationFieldToInclude = this.relationFields?.list?.reduce(\n (acc: Record<string, boolean>, curr) => {\n acc[curr.name] = true;\n return acc;\n },\n {}\n );\n }\n /**\n * Creates a single record in the database.\n *\n * @param {Record<string, any>} body - The data to create the record with.\n * @param {string} [queryOptions] - Additional query options to modify the Prisma query.\n * @returns {Promise<any>} The created record.\n */\n async createOne(\n body: Record<string, any>,\n queryOptions: string = \"{}\"\n ): Promise<any> {\n if (kebabCase(this.modelName) === \"user\" && body.password) {\n body.password = await authService.hashPassword(body.password);\n }\n\n const prisma = getPrismaInstance();\n\n const bodyWithRelationFieldsHandled = handleRelationFieldsInBody(\n body,\n {\n ...this.relationFields,\n },\n [\"delete\", \"disconnect\", \"update\"]\n );\n\n return await prisma[this.modelName].create(\n deepmerge(\n {\n data: bodyWithRelationFieldsHandled,\n include: {\n ...this.singularRelationFieldToInclude,\n ...this.singularRelationFieldToInclude,\n },\n },\n JSON.parse(queryOptions || \"{}\")\n )\n );\n }\n\n /**\n * Creates multiple records in the database.\n *\n * @param {Record<string, any>[]} body - An array of data to create records with.\n * @returns {Promise<{ total: number; data: any }>} The result containing the total count and the created data.\n * @throws {AppError} Throws an error if the data array is invalid or empty.\n */\n async createMany(\n body: Record<string, any>[]\n ): Promise<{ total: number; data: any }> {\n const prisma = getPrismaInstance();\n\n if (!Array.isArray(body) || body.length === 0) {\n throw new AppError(\n \"Invalid or empty data array provided for creation.\",\n 400\n );\n }\n\n const data = await prisma[this.modelName].createMany({\n data: body,\n });\n\n const total = await prisma[this.modelName].count();\n return { total, data };\n }\n\n /**\n * Finds multiple records based on provided filters.\n *\n * @param {Record<string, any>} filters - The filters to apply to the query.\n * @returns {Promise<{ total: number; data: any }>} The result containing the total count and the found data.\n */\n async findMany(\n filters: Record<string, any>\n ): Promise<{ total: number; data: any }> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n // if (modelModules.dtos.query && getArkosConfig()?.validation !== false) {\n // filters = await validateDto(modelModules.dtos.query, filters);\n // }\n\n const prisma = getPrismaInstance();\n\n const [data, total] = await Promise.all([\n prisma[this.modelName].findMany(\n \"select\" in filters\n ? deepmerge(\n { ...filters },\n {\n select: this.singularRelationFieldToInclude,\n }\n )\n : deepmerge(\n { ...filters },\n {\n include: this.singularRelationFieldToInclude,\n }\n )\n ),\n prisma[this.modelName].count({\n where: filters.where,\n }),\n ]);\n\n return { total, data };\n }\n\n /**\n * Finds a single record by its parameters.\n *\n * @param {Record<string, any>} filters - The parameters to find the record by.\n * @param {string} [queryOptions] - Additional query options to modify the Prisma query.\n * @returns {Promise<any>} The found record.\n * @throws {AppError} Throws an error if the record is not found.\n */\n async findOne(\n filters: Record<string, any>,\n // queryOptions: string = JSON.stringify(\n // getModelModules(kebabCase(this.modelName)).prismaQueryOptions || {}\n // )\n queryOptions: string = \"{}\"\n ): Promise<any> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n // if (modelModules.dtos.create && getArkosConfig()?.validation !== false) {\n // filters = await validateDto(modelModules.dtos.create, filters);\n // }\n\n const prisma = getPrismaInstance();\n\n const data = await prisma[this.modelName].findUnique(\n deepmerge(\n {\n where: { ...filters, id: String(filters.id) },\n ...(JSON.parse(queryOptions || \"{}\").hasOwnProperty(\"select\")\n ? {\n select: {\n ...this.singularRelationFieldToInclude,\n ...this.listRelationFieldToInclude,\n },\n }\n : {\n include: {\n ...this.singularRelationFieldToInclude,\n ...this.listRelationFieldToInclude,\n },\n }),\n },\n JSON.parse(queryOptions || \"{}\")\n )\n );\n\n if (!data) {\n throw new AppError(\n `${pascalCase(String(this.modelName))} with ID ${filters.id} not found`,\n 404\n );\n }\n\n return data;\n }\n\n /**\n * Updates a single record by its ID.\n *\n * @param {Record<string, any>} filters - The parameters to find the record by.\n * @param {Record<string, any>} body - The data to update the record with.\n * @param {string} [queryOptions] - Additional query options to modify the Prisma query.\n * @returns {Promise<any>} The updated record.\n * @throws {AppError} Throws an error if the record is not found.\n */\n async updateOne(\n filters: Record<string, any>,\n body: Record<string, any>,\n // queryOptions: string = JSON.stringify(\n // getModelModules(kebabCase(this.modelName)).prismaQueryOptions || {}\n // )\n queryOptions: string = \"{}\"\n ): Promise<any> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n if (modelModules.dtos.update && getArkosConfig()?.validation) {\n body = await validateDto(modelModules.dtos.update, body);\n }\n\n const prisma = getPrismaInstance();\n\n if (kebabCase(this.modelName) === \"user\" && body.password) {\n body.password = await authService.hashPassword(body.password);\n }\n\n const bodyWithRelationFieldsHandled = handleRelationFieldsInBody(body, {\n ...this.relationFields,\n });\n\n const data = await prisma[this.modelName].update(\n deepmerge(\n {\n where: { ...filters, id: String(filters.id) },\n data: bodyWithRelationFieldsHandled,\n include: {\n ...this.singularRelationFieldToInclude,\n ...this.singularRelationFieldToInclude,\n },\n },\n JSON.parse(queryOptions || \"{}\")\n )\n );\n\n if (!data) {\n throw new AppError(\n `${pascalCase(String(this.modelName))} with ID ${filters.id} not found`,\n 404\n );\n }\n\n return data;\n }\n\n /**\n * Updates multiple records based on the provided filter and data.\n *\n * @param {Record<string, any>} filters - The filters to identify records to update.\n * @param {Record<string, any>} body - The data to update the records with.\n * @returns {Promise<{ total: number; data: any }>} The result containing the total count and the updated data.\n * @throws {AppError} Throws an error if no records match the filters.\n */\n async updateMany(\n filters: Record<string, any>,\n body: Record<string, any>\n ): Promise<{ total: number; data: any }> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n // if (modelModules.dtos.create && getArkosConfig()?.validation !== false) {\n // body = await validateDto(modelModules.dtos.create, body);\n // }\n\n const prisma = getPrismaInstance();\n\n if (!filters || typeof filters !== \"object\") {\n throw new AppError(\"Invalid filters provided for udpate many.\", 400);\n }\n\n const data = await prisma[this.modelName].updateMany({\n ...filters,\n data: body,\n });\n\n if (!data || data.count === 0) {\n throw new AppError(\n `${pluralize(pascalCase(String(this.modelName)))} not found`,\n 404\n );\n }\n\n const total = await prisma[this.modelName].count();\n return { total, data };\n }\n\n /**\n * Deletes a single record by its ID.\n *\n * @param {Record<string, any>} params - The parameters to find the record by.\n * @returns {Promise<any>} The deleted record.\n */\n async deleteOne(params: Record<string, any>): Promise<any> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n // if (modelModules.dtos.create && getArkosConfig()?.validation !== false) {\n // body = await validateDto(modelModules.dtos.create, body);\n // }\n\n const prisma = getPrismaInstance();\n\n return await prisma[this.modelName].delete({\n where: {\n ...params,\n id: String(params.id),\n },\n });\n }\n\n /**\n * Deletes multiple records based on the provided filter.\n *\n * @param {Record<string, any>} filter - The filter to identify records to delete.\n * @returns {Promise<{ total: number; data: any }>} The result containing the total count and the deleted data.\n * @throws {AppError} Throws an error if no records match the filter.\n */\n async deleteMany(\n filters: Record<string, any>\n ): Promise<{ total: number; data: any }> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n // if (modelModules.dtos.create && getArkosConfig()?.validation !== false) {\n // body = await validateDto(modelModules.dtos.create, body);\n // }\n\n const prisma = getPrismaInstance();\n\n if (!filters || typeof filters !== \"object\") {\n throw new AppError(\"Invalid filters provided for deletion.\", 400);\n }\n\n const data = await prisma[this.modelName].deleteMany(filters);\n\n if (!data || data.count === 0) {\n throw new AppError(`No records found to delete`, 404);\n }\n\n const total = await prisma[this.modelName].count();\n return { total, data };\n }\n}\n\n/**\n * Generates a set of base service instances for all available models.\n *\n * @returns {Record<string, BaseService>} A dictionary of base service instances, keyed by model name.\n */\nexport function getBaseServices(): Record<string, BaseService> {\n const models = getModels();\n const baseServices: Record<string, BaseService> = {};\n models.forEach((model) => {\n baseServices[`${camelCase(model)}`] = new BaseService(model);\n });\n return baseServices;\n}\n"]}
|
|
@@ -16,7 +16,10 @@ function parseQueryParamsWithModifiers(query, fieldConfig = DEFAULT_FIELD_CONFIG
|
|
|
16
16
|
: value.toString();
|
|
17
17
|
const parts = key.split("__");
|
|
18
18
|
if (parts.length < 2) {
|
|
19
|
-
acc[key] =
|
|
19
|
+
acc[key] =
|
|
20
|
+
typeof value === "string"
|
|
21
|
+
? convertValue(stringValue, parts[0], fieldConfig)
|
|
22
|
+
: value;
|
|
20
23
|
return acc;
|
|
21
24
|
}
|
|
22
25
|
const fieldName = parts[0];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.features.helpers.js","sourceRoot":"","sources":["../../../../src/utils/helpers/api.features.helpers.ts"],"names":[],"mappings":";;AAiDA,
|
|
1
|
+
{"version":3,"file":"api.features.helpers.js","sourceRoot":"","sources":["../../../../src/utils/helpers/api.features.helpers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Configuration types for field type mapping\n */\ninterface FieldConfig {\n dateFields: string[];\n booleanFields: string[];\n numericFields: string[];\n}\n\n/**\n * Type for the structured filter object returned by the parser\n */\ntype ParsedFilter = {\n [key: string]: any;\n orderBy?: Record<string, \"asc\" | \"desc\">;\n OR?: Record<string, any>[];\n};\n\n/**\n * Default configuration for field types\n */\nconst DEFAULT_FIELD_CONFIG: FieldConfig = {\n dateFields: [\"createdAt\", \"updatedAt\", \"deletedAt\", \"date\"],\n booleanFields: [\"isActive\", \"isDeleted\", \"isPublished\", \"isArchived\"],\n numericFields: [\"age\", \"price\", \"quantity\", \"amount\", \"rating\"],\n};\n\n/**\n * Parses query parameters into a structured filter object compatible with Prisma queries.\n * Supports various operators and data type conversions.\n *\n * @param query - Object containing query parameters\n * @param fieldConfig - Optional configuration for field type mapping\n * @returns Structured filter object for database queries\n *\n * @example\n * // Basic usage\n * parseQueryParamsWithModifiers({ name__contains: 'john' })\n * // => { name: { contains: 'john', mode: 'sensitive' } }\n *\n * @example\n * // Complex query\n * parseQueryParamsWithModifiers({\n * name__not__equals: 'john',\n * age__gt: '25',\n * tags__in: 'tag1,tag2',\n * orderBy__createdAt: 'desc'\n * })\n */\nexport function parseQueryParamsWithModifiers(\n query: Record<string, any>,\n // excludedFields: string[],\n fieldConfig: FieldConfig = DEFAULT_FIELD_CONFIG\n): ParsedFilter {\n return Object.entries(JSON.parse(JSON.stringify(query))).reduce(\n (acc, [key, value]) => {\n if (!value && value !== false) return acc;\n\n // Convert value to string if it's not already\n const stringValue = Array.isArray(value)\n ? value[0]?.toString()\n : value.toString();\n const parts = key.split(\"__\");\n if (parts.length < 2) {\n acc[key] =\n typeof value === \"string\"\n ? convertValue(stringValue, parts[0], fieldConfig)\n : value;\n return acc;\n }\n const fieldName = parts[0];\n\n // Handle ordering\n if (fieldName === \"orderBy\" && parts.length === 2) {\n if (!acc.orderBy) acc.orderBy = {};\n acc.orderBy[parts[1]] = stringValue as \"asc\" | \"desc\";\n return acc;\n }\n\n // Handle simple equals case\n if (parts.length === 1) {\n acc[fieldName] = {\n equals: convertValue(stringValue, fieldName, fieldConfig),\n };\n return acc;\n }\n\n let currentLevel = acc;\n let currentKey = fieldName;\n\n // Build nested structure\n for (let i = 1; i < parts.length - 1; i++) {\n if (!currentLevel[currentKey]) {\n currentLevel[currentKey] = {};\n }\n currentLevel = currentLevel[currentKey];\n currentKey = parts[i];\n }\n\n const lastOperator = parts[parts.length - 1];\n\n // Handle special operators\n switch (lastOperator) {\n case \"icontains\":\n currentLevel[currentKey] = {\n contains: stringValue,\n mode: \"insensitive\",\n };\n break;\n\n case \"contains\":\n currentLevel[currentKey] = {\n contains: stringValue,\n mode: \"sensitive\",\n };\n break;\n\n case \"in\":\n case \"notIn\":\n currentLevel[currentKey] = {\n [lastOperator]: stringValue\n .split(\",\")\n .map((v: string) =>\n convertValue(v.trim(), fieldName, fieldConfig)\n ),\n };\n break;\n\n case \"or\":\n const values: string[] = stringValue.split(\",\");\n if (!acc.OR) acc.OR = [];\n acc.OR.push(\n ...values.map((val) => ({\n [fieldName]: {\n equals: convertValue(val.trim(), fieldName, fieldConfig),\n },\n }))\n );\n break;\n\n case \"isNull\":\n currentLevel[currentKey] = {\n equals: stringValue.toLowerCase() === \"true\" ? null : undefined,\n };\n break;\n\n case \"isEmpty\":\n currentLevel[currentKey] = {\n equals: stringValue.toLowerCase() === \"true\" ? \"\" : undefined,\n };\n break;\n\n default:\n currentLevel[currentKey] = {\n [lastOperator]: convertValue(stringValue, fieldName, fieldConfig),\n };\n }\n\n return acc;\n },\n {} as ParsedFilter\n );\n}\n\n/**\n * Converts string values to appropriate types based on field configuration\n * \n * // Example usage:\n/*\n const query = {\n name__not__equals: 'uanela',\n email__contains: 'example.com',\n description__icontains: 'test',\n age__gt: '25',\n status: 'active',\n tags__in: 'tag1,tag2,tag3',\n createdAt__gt: '2024-01-01',\n isActive: 'true',\n orderBy__createdAt: 'desc'\n };\n \n const result = parseQueryParamsWithModifiers(query);\n */\nfunction convertValue(\n value: string,\n fieldName: string,\n config: FieldConfig\n): any {\n // Handle date fields\n if (config.dateFields.includes(fieldName)) {\n return new Date(value);\n }\n\n // Handle boolean fields\n if (config.booleanFields.includes(fieldName)) {\n return value.toLowerCase() === \"true\";\n }\n\n // Handle numeric fields\n if (config.numericFields.includes(fieldName)) {\n return Number(value);\n }\n\n return value;\n}\n"]}
|
|
@@ -46,6 +46,7 @@ export class BaseController {
|
|
|
46
46
|
.sort()
|
|
47
47
|
.limitFields()
|
|
48
48
|
.paginate();
|
|
49
|
+
console.log(JSON.stringify(features.filters, null, 2));
|
|
49
50
|
const { data, total } = yield this.baseService.findMany(features.filters);
|
|
50
51
|
if (this.middlewares.afterFindMany) {
|
|
51
52
|
req.responseData = { total, results: data.length, data };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.controller.js","sourceRoot":"","sources":["../../../../src/modules/base/base.controller.ts"],"names":[],"mappings":";;;;;;;;;AACA,OAAO,UAAU,MAAM,oCAAoC,CAAC;AAC5D,OAAO,WAAW,MAAM,mCAAmC,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,QAAQ,MAAM,kCAAkC,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAC;AAMhF,MAAM,OAAO,cAAc;IAuBzB,YAAY,SAAiB;;QAa7B,cAAS,GAAG,UAAU,CACpB,CAAO,GAAiB,EAAE,GAAkB,EAAE,IAAuB,EAAE,EAAE;;YACvE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,SAAS,CAC3C,GAAG,CAAC,IAAI,EACR,MAAA,GAAG,CAAC,KAAK,0CAAE,kBAA4B,CACxC,CAAC;YAEF,IAAI,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE,CAAC;gBACpC,GAAG,CAAC,YAAY,GAAG,EAAE,IAAI,EAAE,CAAC;gBAC5B,GAAG,CAAC,cAAc,GAAG,GAAG,CAAC;gBACzB,OAAO,IAAI,EAAE,CAAC;YAChB,CAAC;YAED,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QACjC,CAAC,CAAA,CACF,CAAC;QASF,eAAU,GAAG,UAAU,CACrB,CAAO,GAAiB,EAAE,GAAkB,EAAE,IAAuB,EAAE,EAAE;YACvE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAEpE,IAAI,IAAI,CAAC,WAAW,CAAC,eAAe,EAAE,CAAC;gBACrC,GAAG,CAAC,YAAY,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;gBACzD,GAAG,CAAC,cAAc,GAAG,GAAG,CAAC;gBACzB,OAAO,IAAI,EAAE,CAAC;YAChB,CAAC;YAED,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9D,CAAC,CAAA,CACF,CAAC;QASF,aAAQ,GAAG,UAAU,CACnB,CAAO,GAAiB,EAAE,GAAkB,EAAE,IAAuB,EAAE,EAAE;;YACvE,MAAM,QAAQ,GAAG,IAAI,WAAW,CAC9B,GAAG,EACH,IAAI,CAAC,SAAS,EACd,MAAA,IAAI,CAAC,WAAW,CAAC,cAAc,0CAAE,QAAQ,CAAC,MAAM,CAC9C,CAAC,GAA4B,EAAE,IAAI,EAAE,EAAE;gBACrC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;gBACtB,OAAO,GAAG,CAAC;YACb,CAAC,EACD,EAAE,CACH,CACF;iBACE,MAAM,EAAE;iBACR,IAAI,EAAE;iBACN,WAAW,EAAE;iBACb,QAAQ,EAAE,CAAC;YAEd,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAE1E,IAAI,IAAI,CAAC,WAAW,CAAC,aAAa,EAAE,CAAC;gBACnC,GAAG,CAAC,YAAY,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;gBACzD,GAAG,CAAC,cAAc,GAAG,GAAG,CAAC;gBACzB,OAAO,IAAI,EAAE,CAAC;YAChB,CAAC;YAED,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9D,CAAC,CAAA,CACF,CAAC;QASF,YAAO,GAAG,UAAU,CAClB,CAAO,GAAiB,EAAE,GAAkB,EAAE,IAAuB,EAAE,EAAE;;YACvE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CACzC,GAAG,CAAC,MAAM,EACV,MAAA,GAAG,CAAC,KAAK,0CAAE,kBAA4B,CACxC,CAAC;YAEF,IAAI,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC;gBAClC,GAAG,CAAC,YAAY,GAAG,EAAE,IAAI,EAAE,CAAC;gBAC5B,GAAG,CAAC,cAAc,GAAG,GAAG,CAAC;gBACzB,OAAO,IAAI,EAAE,CAAC;YAChB,CAAC;YAED,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QACjC,CAAC,CAAA,CACF,CAAC;QASF,cAAS,GAAG,UAAU,CACpB,CAAO,GAAiB,EAAE,GAAkB,EAAE,IAAuB,EAAE,EAAE;;YACvE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,SAAS,CAC3C,GAAG,CAAC,MAAM,EACV,GAAG,CAAC,IAAI,EACR,MAAA,GAAG,CAAC,KAAK,0CAAE,kBAA4B,CACxC,CAAC;YAEF,IAAI,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE,CAAC;gBACpC,GAAG,CAAC,YAAY,GAAG,EAAE,IAAI,EAAE,CAAC;gBAC5B,GAAG,CAAC,cAAc,GAAG,GAAG,CAAC;gBACzB,OAAO,IAAI,EAAE,CAAC;YAChB,CAAC;YAED,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QACjC,CAAC,CAAA,CACF,CAAC;QASF,eAAU,GAAG,UAAU,CACrB,CAAO,GAAiB,EAAE,GAAkB,EAAE,IAAuB,EAAE,EAAE;YACvE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,oBAAoB,CAAC,EAAE,CAAC;gBACxE,OAAO,IAAI,CACT,IAAI,QAAQ,CAAC,+CAA+C,EAAE,GAAG,CAAC,CACnE,CAAC;YACJ,CAAC;YAED,MAAM,QAAQ,GAAG,IAAI,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;YACtE,OAAO,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC;YAEhC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CACvD,QAAQ,CAAC,OAAO,EAChB,GAAG,CAAC,IAAI,CACT,CAAC;YAEF,IAAI,IAAI,CAAC,WAAW,CAAC,eAAe,EAAE,CAAC;gBACrC,GAAG,CAAC,YAAY,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;gBACzD,GAAG,CAAC,cAAc,GAAG,GAAG,CAAC;gBACzB,OAAO,IAAI,EAAE,CAAC;YAChB,CAAC;YAED,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9D,CAAC,CAAA,CACF,CAAC;QASF,cAAS,GAAG,UAAU,CACpB,CAAO,GAAiB,EAAE,GAAkB,EAAE,IAAuB,EAAE,EAAE;YACvE,MAAM,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAE7C,IAAI,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE,CAAC;gBACpC,GAAG,CAAC,YAAY,GAAG,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;gBACjD,GAAG,CAAC,cAAc,GAAG,GAAG,CAAC;gBACzB,OAAO,IAAI,EAAE,CAAC;YAChB,CAAC;YAED,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QACzB,CAAC,CAAA,CACF,CAAC;QASF,eAAU,GAAG,UAAU,CACrB,CAAO,GAAiB,EAAE,GAAkB,EAAE,IAAuB,EAAE,EAAE;YACvE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,oBAAoB,CAAC,EAAE,CAAC;gBACxE,OAAO,IAAI,CACT,IAAI,QAAQ,CAAC,iDAAiD,EAAE,GAAG,CAAC,CACrE,CAAC;YACJ,CAAC;YAED,MAAM,QAAQ,GAAG,IAAI,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;YACtE,OAAO,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC;YAEhC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CACvD,QAAQ,CAAC,OAAO,CACjB,CAAC;YAEF,IAAI,IAAI,CAAC,WAAW,CAAC,eAAe,EAAE,CAAC;gBACrC,GAAG,CAAC,YAAY,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;gBACzD,GAAG,CAAC,cAAc,GAAG,GAAG,CAAC;gBACzB,OAAO,IAAI,EAAE,CAAC;YAChB,CAAC;YAED,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9D,CAAC,CAAA,CACF,CAAC;QA5NA,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,CAAC,SAAS,CAAC,CAAC;QAC9C,IAAI,CAAC,WAAW,GAAG,CAAA,MAAA,eAAe,CAAC,SAAS,CAAC,0CAAE,WAAW,KAAI,EAAE,CAAC;IACnE,CAAC;CA0NF;AASD,MAAM,UAAU,iBAAiB,CAC/B,GAAiB,EACjB,GAAkB,EAClB,IAAuB;IAEvB,MAAM,MAAM,GAAuC,EAAE,CAAC;IACtD,GAAG,CAAC,MAAM,CAAC;IACX,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;IAE5B,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,UAAe,EAAE,EAAE;QAC5C,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;YACrB,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;gBACvD,MAAM,CAAC,IAAI,CAAC;oBACV,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE;oBAC5B,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,IAAI;iBAC5B,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,UAAU,CAAC,MAAM,IAAI,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACxD,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,gBAAqB,EAAE,EAAE;gBACxD,IAAI,gBAAgB,CAAC,KAAK,EAAE,CAAC;oBAC3B,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;wBAC7D,MAAM,QAAQ,GACZ,CAAC,UAAU,CAAC,MAAM;4BAChB,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;4BAC/C,CAAC,CAAC,EAAE,CAAC,GAAG,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC;wBACxC,MAAM,CAAC,IAAI,CAAC;4BACV,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE;4BAC5B,IAAI,EAAE,gBAAgB,CAAC,KAAK,CAAC,IAAI;yBAClC,CAAC,CAAC;oBACL,CAAC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACnB,CAAC;AASD,MAAM,CAAC,MAAM,qBAAqB,GAAG,UAAU,CAAC,CAAO,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACvE,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QACnB,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC;KAClE,CAAC,CAAC;AACL,CAAC,CAAA,CAAC,CAAC","sourcesContent":["import { ArkosRequest, ArkosResponse, ArkosNextFunction } from \"../../types\";\nimport catchAsync from \"../error-handler/utils/catch-async\";\nimport APIFeatures from \"../../utils/features/api.features\";\nimport { BaseService } from \"./base.service\";\nimport AppError from \"../error-handler/utils/app-error\";\nimport { kebabCase } from \"../../utils/helpers/change-case.helpers\";\nimport { getExpressApp } from \"../../server\";\nimport { getModelModules, getModels } from \"../../utils/helpers/models.helpers\";\n\n/**\n * BaseController class providing standardized RESTful API endpoints for any prisma model\n * @class BaseController\n */\nexport class BaseController {\n /**\n * Service instance to handle business logic operations\n * @private\n */\n private baseService: BaseService;\n\n /**\n * Name of the model this controller handles\n * @private\n */\n private modelName: string;\n\n /**\n * Model-specific middlewares loaded from model modules\n * @private\n */\n private middlewares: any;\n\n /**\n * Creates a new BaseController instance\n * @param {string} modelName - The name of the model for which this controller will handle operations\n */\n constructor(modelName: string) {\n this.modelName = modelName;\n this.baseService = new BaseService(modelName);\n this.middlewares = getModelModules(modelName)?.middlewares || {};\n }\n\n /**\n * Creates a single resource\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n createOne = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n const data = await this.baseService.createOne(\n req.body,\n req.query?.prismaQueryOptions as string\n );\n\n if (this.middlewares.afterCreateOne) {\n req.responseData = { data };\n req.responseStatus = 201;\n return next();\n }\n\n res.status(201).json({ data });\n }\n );\n\n /**\n * Creates multiple resources in a single operation\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n createMany = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n const { data, total } = await this.baseService.createMany(req.body);\n\n if (this.middlewares.afterCreateMany) {\n req.responseData = { total, results: data.length, data };\n req.responseStatus = 201;\n return next();\n }\n\n res.status(201).json({ total, results: data.length, data });\n }\n );\n\n /**\n * Retrieves multiple resources with filtering, sorting, pagination, and field selection\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n findMany = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n const features = new APIFeatures(\n req,\n this.modelName,\n this.baseService.relationFields?.singular.reduce(\n (acc: Record<string, boolean>, curr) => {\n acc[curr.name] = true;\n return acc;\n },\n {}\n )\n )\n .filter()\n .sort()\n .limitFields()\n .paginate();\n\n const { data, total } = await this.baseService.findMany(features.filters);\n\n if (this.middlewares.afterFindMany) {\n req.responseData = { total, results: data.length, data };\n req.responseStatus = 200;\n return next();\n }\n\n res.status(200).json({ total, results: data.length, data });\n }\n );\n\n /**\n * Retrieves a single resource by its identifier\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n findOne = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n const data = await this.baseService.findOne(\n req.params,\n req.query?.prismaQueryOptions as string\n );\n\n if (this.middlewares.afterFindOne) {\n req.responseData = { data };\n req.responseStatus = 200;\n return next();\n }\n\n res.status(200).json({ data });\n }\n );\n\n /**\n * Updates a single resource by its identifier\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n updateOne = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n const data = await this.baseService.updateOne(\n req.params,\n req.body,\n req.query?.prismaQueryOptions as string\n );\n\n if (this.middlewares.afterUpdateOne) {\n req.responseData = { data };\n req.responseStatus = 200;\n return next();\n }\n\n res.status(200).json({ data });\n }\n );\n\n /**\n * Updates multiple resources that match specified criteria\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n updateMany = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n if (!Object.keys(req.query).some((key) => key !== \"prismaQueryOptions\")) {\n return next(\n new AppError(\"Filter criteria not provided for bulk update.\", 400)\n );\n }\n\n const features = new APIFeatures(req, this.modelName).filter().sort();\n delete features.filters.include;\n\n const { data, total } = await this.baseService.updateMany(\n features.filters,\n req.body\n );\n\n if (this.middlewares.afterUpdateMany) {\n req.responseData = { total, results: data.length, data };\n req.responseStatus = 200;\n return next();\n }\n\n res.status(200).json({ total, results: data.length, data });\n }\n );\n\n /**\n * Deletes a single resource by its identifier\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n deleteOne = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n await this.baseService.deleteOne(req.params);\n\n if (this.middlewares.afterDeleteOne) {\n req.responseData = { id: String(req.params.id) };\n req.responseStatus = 204;\n return next();\n }\n\n res.status(204).send();\n }\n );\n\n /**\n * Deletes multiple resources that match specified criteria\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n deleteMany = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n if (!Object.keys(req.query).some((key) => key !== \"prismaQueryOptions\")) {\n return next(\n new AppError(\"Filter criteria not provided for bulk deletion.\", 400)\n );\n }\n\n const features = new APIFeatures(req, this.modelName).filter().sort();\n delete features.filters.include;\n\n const { data, total } = await this.baseService.deleteMany(\n features.filters\n );\n\n if (this.middlewares.afterDeleteMany) {\n req.responseData = { total, results: data.length, data };\n req.responseStatus = 200;\n return next();\n }\n\n res.status(200).json({ total, results: data.length, data });\n }\n );\n}\n\n/**\n * Returns a list of all registered API routes in the Express application\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {void}\n */\nexport function getAvalibleRoutes(\n req: ArkosRequest,\n res: ArkosResponse,\n next: ArkosNextFunction\n) {\n const routes: { method: string; path: string }[] = [];\n req.params;\n const app = getExpressApp();\n\n app._router.stack.forEach((middleware: any) => {\n if (middleware.route) {\n Object.keys(middleware.route.methods).forEach((method) => {\n routes.push({\n method: method.toUpperCase(),\n path: middleware.route.path,\n });\n });\n } else if (middleware.handle && middleware.handle.stack) {\n middleware.handle.stack.forEach((routerMiddleware: any) => {\n if (routerMiddleware.route) {\n Object.keys(routerMiddleware.route.methods).forEach((method) => {\n const fullPath =\n (middleware.regexp\n ? middleware.regexp.toString().replace(\"/\", \"\")\n : \"\") + routerMiddleware.route.path;\n routes.push({\n method: method.toUpperCase(),\n path: routerMiddleware.route.path,\n });\n });\n }\n });\n }\n });\n\n res.json(routes);\n}\n\n/**\n * Returns a list of all available resource endpoints based on the application's models\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\nexport const getAvailableResources = catchAsync(async (req, res, next) => {\n const models = getModels();\n res.status(200).json({\n data: [...models.map((model) => kebabCase(model)), \"file-upload\"],\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"base.controller.js","sourceRoot":"","sources":["../../../../src/modules/base/base.controller.ts"],"names":[],"mappings":"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","sourcesContent":["import { ArkosRequest, ArkosResponse, ArkosNextFunction } from \"../../types\";\nimport catchAsync from \"../error-handler/utils/catch-async\";\nimport APIFeatures from \"../../utils/features/api.features\";\nimport { BaseService } from \"./base.service\";\nimport AppError from \"../error-handler/utils/app-error\";\nimport { kebabCase } from \"../../utils/helpers/change-case.helpers\";\nimport { getExpressApp } from \"../../server\";\nimport { getModelModules, getModels } from \"../../utils/helpers/models.helpers\";\n\n/**\n * BaseController class providing standardized RESTful API endpoints for any prisma model\n * @class BaseController\n */\nexport class BaseController {\n /**\n * Service instance to handle business logic operations\n * @private\n */\n private baseService: BaseService;\n\n /**\n * Name of the model this controller handles\n * @private\n */\n private modelName: string;\n\n /**\n * Model-specific middlewares loaded from model modules\n * @private\n */\n private middlewares: any;\n\n /**\n * Creates a new BaseController instance\n * @param {string} modelName - The name of the model for which this controller will handle operations\n */\n constructor(modelName: string) {\n this.modelName = modelName;\n this.baseService = new BaseService(modelName);\n this.middlewares = getModelModules(modelName)?.middlewares || {};\n }\n\n /**\n * Creates a single resource\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n createOne = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n const data = await this.baseService.createOne(\n req.body,\n req.query?.prismaQueryOptions as string\n );\n\n if (this.middlewares.afterCreateOne) {\n req.responseData = { data };\n req.responseStatus = 201;\n return next();\n }\n\n res.status(201).json({ data });\n }\n );\n\n /**\n * Creates multiple resources in a single operation\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n createMany = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n const { data, total } = await this.baseService.createMany(req.body);\n\n if (this.middlewares.afterCreateMany) {\n req.responseData = { total, results: data.length, data };\n req.responseStatus = 201;\n return next();\n }\n\n res.status(201).json({ total, results: data.length, data });\n }\n );\n\n /**\n * Retrieves multiple resources with filtering, sorting, pagination, and field selection\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n findMany = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n const features = new APIFeatures(\n req,\n this.modelName,\n this.baseService.relationFields?.singular.reduce(\n (acc: Record<string, boolean>, curr) => {\n acc[curr.name] = true;\n return acc;\n },\n {}\n )\n )\n .filter()\n .sort()\n .limitFields()\n .paginate();\n\n console.log(JSON.stringify(features.filters, null, 2));\n\n const { data, total } = await this.baseService.findMany(features.filters);\n\n if (this.middlewares.afterFindMany) {\n req.responseData = { total, results: data.length, data };\n req.responseStatus = 200;\n return next();\n }\n\n res.status(200).json({ total, results: data.length, data });\n }\n );\n\n /**\n * Retrieves a single resource by its identifier\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n findOne = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n const data = await this.baseService.findOne(\n req.params,\n req.query?.prismaQueryOptions as string\n );\n\n if (this.middlewares.afterFindOne) {\n req.responseData = { data };\n req.responseStatus = 200;\n return next();\n }\n\n res.status(200).json({ data });\n }\n );\n\n /**\n * Updates a single resource by its identifier\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n updateOne = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n const data = await this.baseService.updateOne(\n req.params,\n req.body,\n req.query?.prismaQueryOptions as string\n );\n\n if (this.middlewares.afterUpdateOne) {\n req.responseData = { data };\n req.responseStatus = 200;\n return next();\n }\n\n res.status(200).json({ data });\n }\n );\n\n /**\n * Updates multiple resources that match specified criteria\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n updateMany = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n if (!Object.keys(req.query).some((key) => key !== \"prismaQueryOptions\")) {\n return next(\n new AppError(\"Filter criteria not provided for bulk update.\", 400)\n );\n }\n\n const features = new APIFeatures(req, this.modelName).filter().sort();\n delete features.filters.include;\n\n const { data, total } = await this.baseService.updateMany(\n features.filters,\n req.body\n );\n\n if (this.middlewares.afterUpdateMany) {\n req.responseData = { total, results: data.length, data };\n req.responseStatus = 200;\n return next();\n }\n\n res.status(200).json({ total, results: data.length, data });\n }\n );\n\n /**\n * Deletes a single resource by its identifier\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n deleteOne = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n await this.baseService.deleteOne(req.params);\n\n if (this.middlewares.afterDeleteOne) {\n req.responseData = { id: String(req.params.id) };\n req.responseStatus = 204;\n return next();\n }\n\n res.status(204).send();\n }\n );\n\n /**\n * Deletes multiple resources that match specified criteria\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\n deleteMany = catchAsync(\n async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {\n if (!Object.keys(req.query).some((key) => key !== \"prismaQueryOptions\")) {\n return next(\n new AppError(\"Filter criteria not provided for bulk deletion.\", 400)\n );\n }\n\n const features = new APIFeatures(req, this.modelName).filter().sort();\n delete features.filters.include;\n\n const { data, total } = await this.baseService.deleteMany(\n features.filters\n );\n\n if (this.middlewares.afterDeleteMany) {\n req.responseData = { total, results: data.length, data };\n req.responseStatus = 200;\n return next();\n }\n\n res.status(200).json({ total, results: data.length, data });\n }\n );\n}\n\n/**\n * Returns a list of all registered API routes in the Express application\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {void}\n */\nexport function getAvalibleRoutes(\n req: ArkosRequest,\n res: ArkosResponse,\n next: ArkosNextFunction\n) {\n const routes: { method: string; path: string }[] = [];\n req.params;\n const app = getExpressApp();\n\n app._router.stack.forEach((middleware: any) => {\n if (middleware.route) {\n Object.keys(middleware.route.methods).forEach((method) => {\n routes.push({\n method: method.toUpperCase(),\n path: middleware.route.path,\n });\n });\n } else if (middleware.handle && middleware.handle.stack) {\n middleware.handle.stack.forEach((routerMiddleware: any) => {\n if (routerMiddleware.route) {\n Object.keys(routerMiddleware.route.methods).forEach((method) => {\n const fullPath =\n (middleware.regexp\n ? middleware.regexp.toString().replace(\"/\", \"\")\n : \"\") + routerMiddleware.route.path;\n routes.push({\n method: method.toUpperCase(),\n path: routerMiddleware.route.path,\n });\n });\n }\n });\n }\n });\n\n res.json(routes);\n}\n\n/**\n * Returns a list of all available resource endpoints based on the application's models\n * @param {ArkosRequest} req - Express request object\n * @param {ArkosResponse} res - Express response object\n * @param {ArkosNextFunction} next - Express next function\n * @returns {Promise<void>}\n */\nexport const getAvailableResources = catchAsync(async (req, res, next) => {\n const models = getModels();\n res.status(200).json({\n data: [...models.map((model) => kebabCase(model)), \"file-upload\"],\n });\n});\n"]}
|
|
@@ -61,16 +61,18 @@ export class BaseService {
|
|
|
61
61
|
return __awaiter(this, void 0, void 0, function* () {
|
|
62
62
|
const modelModules = getModelModules(kebabCase(this.modelName));
|
|
63
63
|
const prisma = getPrismaInstance();
|
|
64
|
-
const data = yield
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
64
|
+
const [data, total] = yield Promise.all([
|
|
65
|
+
prisma[this.modelName].findMany("select" in filters
|
|
66
|
+
? deepmerge(Object.assign({}, filters), {
|
|
67
|
+
select: this.singularRelationFieldToInclude,
|
|
68
|
+
})
|
|
69
|
+
: deepmerge(Object.assign({}, filters), {
|
|
70
|
+
include: this.singularRelationFieldToInclude,
|
|
71
|
+
})),
|
|
72
|
+
prisma[this.modelName].count({
|
|
73
|
+
where: filters.where,
|
|
74
|
+
}),
|
|
75
|
+
]);
|
|
74
76
|
return { total, data };
|
|
75
77
|
});
|
|
76
78
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.service.js","sourceRoot":"","sources":["../../../../src/modules/base/base.service.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n camelCase,\n kebabCase,\n pascalCase,\n} from \"../../utils/helpers/change-case.helpers\";\nimport {\n getModelModules,\n getModels,\n getPrismaModelRelations,\n RelationFields,\n} from \"../../utils/helpers/models.helpers\";\nimport deepmerge from \"../../utils/helpers/deepmerge.helper\";\nimport AppError from \"../error-handler/utils/app-error\";\nimport pluralize from \"pluralize\";\nimport { handleRelationFieldsInBody } from \"./utils/helpers/base.helpers\";\nimport { getPrismaInstance } from \"../../utils/helpers/prisma.helpers\";\nimport validateDto from \"../../utils/validate-dto\";\nimport { getArkosConfig } from \"../../server\";\nimport authService from \"../auth/auth.service\";\n\n/**\n * Base service class for handling CRUD operations on a specific model.\n * This class provides standard implementation of data operations that can be extended\n * by model-specific service classes.\n *\n * @class BaseService\n */\nexport class BaseService {\n /**\n * The camelCase name of the model\n * @public\n */\n modelName: string;\n\n /**\n * Object containing singular and list relation fields for the model\n * @public\n */\n relationFields: RelationFields;\n\n /**\n * Map of singular relation fields to include in queries\n * @public\n */\n singularRelationFieldToInclude: Record<string, boolean>;\n\n /**\n * Map of list relation fields to include in queries\n * @public\n */\n listRelationFieldToInclude: Record<string, boolean>;\n\n /**\n * Instance of the Prisma client\n * @public\n */\n prisma: any;\n\n /**\n * Creates an instance of BaseService.\n * @param {string} modelName - The name of the model to perform operations on.\n */\n constructor(modelName: string) {\n this.modelName = camelCase(modelName);\n this.relationFields = getPrismaModelRelations(pascalCase(modelName))!;\n this.singularRelationFieldToInclude = this.relationFields?.singular?.reduce(\n (acc: Record<string, boolean>, curr) => {\n acc[curr.name] = true;\n return acc;\n },\n {}\n );\n this.listRelationFieldToInclude = this.relationFields?.list?.reduce(\n (acc: Record<string, boolean>, curr) => {\n acc[curr.name] = true;\n return acc;\n },\n {}\n );\n }\n /**\n * Creates a single record in the database.\n *\n * @param {Record<string, any>} body - The data to create the record with.\n * @param {string} [queryOptions] - Additional query options to modify the Prisma query.\n * @returns {Promise<any>} The created record.\n */\n async createOne(\n body: Record<string, any>,\n queryOptions: string = \"{}\"\n ): Promise<any> {\n if (kebabCase(this.modelName) === \"user\" && body.password) {\n body.password = await authService.hashPassword(body.password);\n }\n\n const prisma = getPrismaInstance();\n\n const bodyWithRelationFieldsHandled = handleRelationFieldsInBody(\n body,\n {\n ...this.relationFields,\n },\n [\"delete\", \"disconnect\", \"update\"]\n );\n\n return await prisma[this.modelName].create(\n deepmerge(\n {\n data: bodyWithRelationFieldsHandled,\n include: {\n ...this.singularRelationFieldToInclude,\n ...this.singularRelationFieldToInclude,\n },\n },\n JSON.parse(queryOptions || \"{}\")\n )\n );\n }\n\n /**\n * Creates multiple records in the database.\n *\n * @param {Record<string, any>[]} body - An array of data to create records with.\n * @returns {Promise<{ total: number; data: any }>} The result containing the total count and the created data.\n * @throws {AppError} Throws an error if the data array is invalid or empty.\n */\n async createMany(\n body: Record<string, any>[]\n ): Promise<{ total: number; data: any }> {\n const prisma = getPrismaInstance();\n\n if (!Array.isArray(body) || body.length === 0) {\n throw new AppError(\n \"Invalid or empty data array provided for creation.\",\n 400\n );\n }\n\n const data = await prisma[this.modelName].createMany({\n data: body,\n });\n\n const total = await prisma[this.modelName].count();\n return { total, data };\n }\n\n /**\n * Finds multiple records based on provided filters.\n *\n * @param {Record<string, any>} filters - The filters to apply to the query.\n * @returns {Promise<{ total: number; data: any }>} The result containing the total count and the found data.\n */\n async findMany(\n filters: Record<string, any>\n ): Promise<{ total: number; data: any }> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n // if (modelModules.dtos.query && getArkosConfig()?.validation !== false) {\n // filters = await validateDto(modelModules.dtos.query, filters);\n // }\n\n const prisma = getPrismaInstance();\n\n const data = await prisma[this.modelName].findMany(\n \"select\" in filters\n ? deepmerge(\n { ...filters },\n {\n select: this.singularRelationFieldToInclude,\n }\n )\n : deepmerge(\n { ...filters },\n {\n include: this.singularRelationFieldToInclude,\n }\n )\n );\n\n const total = await prisma[this.modelName].count({\n where: filters.where,\n });\n\n return { total, data };\n }\n\n /**\n * Finds a single record by its parameters.\n *\n * @param {Record<string, any>} filters - The parameters to find the record by.\n * @param {string} [queryOptions] - Additional query options to modify the Prisma query.\n * @returns {Promise<any>} The found record.\n * @throws {AppError} Throws an error if the record is not found.\n */\n async findOne(\n filters: Record<string, any>,\n // queryOptions: string = JSON.stringify(\n // getModelModules(kebabCase(this.modelName)).prismaQueryOptions || {}\n // )\n queryOptions: string = \"{}\"\n ): Promise<any> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n // if (modelModules.dtos.create && getArkosConfig()?.validation !== false) {\n // filters = await validateDto(modelModules.dtos.create, filters);\n // }\n\n const prisma = getPrismaInstance();\n\n const data = await prisma[this.modelName].findUnique(\n deepmerge(\n {\n where: { ...filters, id: String(filters.id) },\n ...(JSON.parse(queryOptions || \"{}\").hasOwnProperty(\"select\")\n ? {\n select: {\n ...this.singularRelationFieldToInclude,\n ...this.listRelationFieldToInclude,\n },\n }\n : {\n include: {\n ...this.singularRelationFieldToInclude,\n ...this.listRelationFieldToInclude,\n },\n }),\n },\n JSON.parse(queryOptions || \"{}\")\n )\n );\n\n if (!data) {\n throw new AppError(\n `${pascalCase(String(this.modelName))} with ID ${filters.id} not found`,\n 404\n );\n }\n\n return data;\n }\n\n /**\n * Updates a single record by its ID.\n *\n * @param {Record<string, any>} filters - The parameters to find the record by.\n * @param {Record<string, any>} body - The data to update the record with.\n * @param {string} [queryOptions] - Additional query options to modify the Prisma query.\n * @returns {Promise<any>} The updated record.\n * @throws {AppError} Throws an error if the record is not found.\n */\n async updateOne(\n filters: Record<string, any>,\n body: Record<string, any>,\n // queryOptions: string = JSON.stringify(\n // getModelModules(kebabCase(this.modelName)).prismaQueryOptions || {}\n // )\n queryOptions: string = \"{}\"\n ): Promise<any> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n if (modelModules.dtos.update && getArkosConfig()?.validation) {\n body = await validateDto(modelModules.dtos.update, body);\n }\n\n const prisma = getPrismaInstance();\n\n if (kebabCase(this.modelName) === \"user\" && body.password) {\n body.password = await authService.hashPassword(body.password);\n }\n\n const bodyWithRelationFieldsHandled = handleRelationFieldsInBody(body, {\n ...this.relationFields,\n });\n\n const data = await prisma[this.modelName].update(\n deepmerge(\n {\n where: { ...filters, id: String(filters.id) },\n data: bodyWithRelationFieldsHandled,\n include: {\n ...this.singularRelationFieldToInclude,\n ...this.singularRelationFieldToInclude,\n },\n },\n JSON.parse(queryOptions || \"{}\")\n )\n );\n\n if (!data) {\n throw new AppError(\n `${pascalCase(String(this.modelName))} with ID ${filters.id} not found`,\n 404\n );\n }\n\n return data;\n }\n\n /**\n * Updates multiple records based on the provided filter and data.\n *\n * @param {Record<string, any>} filters - The filters to identify records to update.\n * @param {Record<string, any>} body - The data to update the records with.\n * @returns {Promise<{ total: number; data: any }>} The result containing the total count and the updated data.\n * @throws {AppError} Throws an error if no records match the filters.\n */\n async updateMany(\n filters: Record<string, any>,\n body: Record<string, any>\n ): Promise<{ total: number; data: any }> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n // if (modelModules.dtos.create && getArkosConfig()?.validation !== false) {\n // body = await validateDto(modelModules.dtos.create, body);\n // }\n\n const prisma = getPrismaInstance();\n\n if (!filters || typeof filters !== \"object\") {\n throw new AppError(\"Invalid filters provided for udpate many.\", 400);\n }\n\n const data = await prisma[this.modelName].updateMany({\n ...filters,\n data: body,\n });\n\n if (!data || data.count === 0) {\n throw new AppError(\n `${pluralize(pascalCase(String(this.modelName)))} not found`,\n 404\n );\n }\n\n const total = await prisma[this.modelName].count();\n return { total, data };\n }\n\n /**\n * Deletes a single record by its ID.\n *\n * @param {Record<string, any>} params - The parameters to find the record by.\n * @returns {Promise<any>} The deleted record.\n */\n async deleteOne(params: Record<string, any>): Promise<any> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n // if (modelModules.dtos.create && getArkosConfig()?.validation !== false) {\n // body = await validateDto(modelModules.dtos.create, body);\n // }\n\n const prisma = getPrismaInstance();\n\n return await prisma[this.modelName].delete({\n where: {\n ...params,\n id: String(params.id),\n },\n });\n }\n\n /**\n * Deletes multiple records based on the provided filter.\n *\n * @param {Record<string, any>} filter - The filter to identify records to delete.\n * @returns {Promise<{ total: number; data: any }>} The result containing the total count and the deleted data.\n * @throws {AppError} Throws an error if no records match the filter.\n */\n async deleteMany(\n filters: Record<string, any>\n ): Promise<{ total: number; data: any }> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n // if (modelModules.dtos.create && getArkosConfig()?.validation !== false) {\n // body = await validateDto(modelModules.dtos.create, body);\n // }\n\n const prisma = getPrismaInstance();\n\n if (!filters || typeof filters !== \"object\") {\n throw new AppError(\"Invalid filters provided for deletion.\", 400);\n }\n\n const data = await prisma[this.modelName].deleteMany(filters);\n\n if (!data || data.count === 0) {\n throw new AppError(`No records found to delete`, 404);\n }\n\n const total = await prisma[this.modelName].count();\n return { total, data };\n }\n}\n\n/**\n * Generates a set of base service instances for all available models.\n *\n * @returns {Record<string, BaseService>} A dictionary of base service instances, keyed by model name.\n */\nexport function getBaseServices(): Record<string, BaseService> {\n const models = getModels();\n const baseServices: Record<string, BaseService> = {};\n models.forEach((model) => {\n baseServices[`${camelCase(model)}`] = new BaseService(model);\n });\n return baseServices;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"base.service.js","sourceRoot":"","sources":["../../../../src/modules/base/base.service.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EACL,SAAS,EACT,SAAS,EACT,UAAU,GACX,MAAM,yCAAyC,CAAC;AACjD,OAAO,EACL,eAAe,EACf,SAAS,EACT,uBAAuB,GAExB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,SAAS,MAAM,sCAAsC,CAAC;AAC7D,OAAO,QAAQ,MAAM,kCAAkC,CAAC;AACxD,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,WAAW,MAAM,0BAA0B,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,WAAW,MAAM,sBAAsB,CAAC;AAS/C,MAAM,OAAO,WAAW;IAmCtB,YAAY,SAAiB;;QAC3B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;QACtC,IAAI,CAAC,cAAc,GAAG,uBAAuB,CAAC,UAAU,CAAC,SAAS,CAAC,CAAE,CAAC;QACtE,IAAI,CAAC,8BAA8B,GAAG,MAAA,MAAA,IAAI,CAAC,cAAc,0CAAE,QAAQ,0CAAE,MAAM,CACzE,CAAC,GAA4B,EAAE,IAAI,EAAE,EAAE;YACrC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;YACtB,OAAO,GAAG,CAAC;QACb,CAAC,EACD,EAAE,CACH,CAAC;QACF,IAAI,CAAC,0BAA0B,GAAG,MAAA,MAAA,IAAI,CAAC,cAAc,0CAAE,IAAI,0CAAE,MAAM,CACjE,CAAC,GAA4B,EAAE,IAAI,EAAE,EAAE;YACrC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;YACtB,OAAO,GAAG,CAAC;QACb,CAAC,EACD,EAAE,CACH,CAAC;IACJ,CAAC;IAQK,SAAS;6DACb,IAAyB,EACzB,eAAuB,IAAI;YAE3B,IAAI,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAC1D,IAAI,CAAC,QAAQ,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAChE,CAAC;YAED,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAC;YAEnC,MAAM,6BAA6B,GAAG,0BAA0B,CAC9D,IAAI,oBAEC,IAAI,CAAC,cAAc,GAExB,CAAC,QAAQ,EAAE,YAAY,EAAE,QAAQ,CAAC,CACnC,CAAC;YAEF,OAAO,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CACxC,SAAS,CACP;gBACE,IAAI,EAAE,6BAA6B;gBACnC,OAAO,kCACF,IAAI,CAAC,8BAA8B,GACnC,IAAI,CAAC,8BAA8B,CACvC;aACF,EACD,IAAI,CAAC,KAAK,CAAC,YAAY,IAAI,IAAI,CAAC,CACjC,CACF,CAAC;QACJ,CAAC;KAAA;IASK,UAAU,CACd,IAA2B;;YAE3B,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAC;YAEnC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC9C,MAAM,IAAI,QAAQ,CAChB,oDAAoD,EACpD,GAAG,CACJ,CAAC;YACJ,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,UAAU,CAAC;gBACnD,IAAI,EAAE,IAAI;aACX,CAAC,CAAC;YAEH,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,CAAC;YACnD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACzB,CAAC;KAAA;IAQK,QAAQ,CACZ,OAA4B;;YAE5B,MAAM,YAAY,GAAG,eAAe,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;YAKhE,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAC;YAEnC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gBACtC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,QAAQ,CAC7B,QAAQ,IAAI,OAAO;oBACjB,CAAC,CAAC,SAAS,mBACF,OAAO,GACZ;wBACE,MAAM,EAAE,IAAI,CAAC,8BAA8B;qBAC5C,CACF;oBACH,CAAC,CAAC,SAAS,mBACF,OAAO,GACZ;wBACE,OAAO,EAAE,IAAI,CAAC,8BAA8B;qBAC7C,CACF,CACN;gBACD,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC;oBAC3B,KAAK,EAAE,OAAO,CAAC,KAAK;iBACrB,CAAC;aACH,CAAC,CAAC;YAEH,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACzB,CAAC;KAAA;IAUK,OAAO;6DACX,OAA4B,EAI5B,eAAuB,IAAI;YAE3B,MAAM,YAAY,GAAG,eAAe,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;YAKhE,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAC;YAEnC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,UAAU,CAClD,SAAS,iBAEL,KAAK,kCAAO,OAAO,KAAE,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,OACxC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,IAAI,IAAI,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC;gBAC3D,CAAC,CAAC;oBACE,MAAM,kCACD,IAAI,CAAC,8BAA8B,GACnC,IAAI,CAAC,0BAA0B,CACnC;iBACF;gBACH,CAAC,CAAC;oBACE,OAAO,kCACF,IAAI,CAAC,8BAA8B,GACnC,IAAI,CAAC,0BAA0B,CACnC;iBACF,CAAC,GAER,IAAI,CAAC,KAAK,CAAC,YAAY,IAAI,IAAI,CAAC,CACjC,CACF,CAAC;YAEF,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,MAAM,IAAI,QAAQ,CAChB,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,YAAY,OAAO,CAAC,EAAE,YAAY,EACvE,GAAG,CACJ,CAAC;YACJ,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;KAAA;IAWK,SAAS;6DACb,OAA4B,EAC5B,IAAyB,EAIzB,eAAuB,IAAI;;YAE3B,MAAM,YAAY,GAAG,eAAe,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;YAChE,IAAI,YAAY,CAAC,IAAI,CAAC,MAAM,KAAI,MAAA,cAAc,EAAE,0CAAE,UAAU,CAAA,EAAE,CAAC;gBAC7D,IAAI,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC3D,CAAC;YAED,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAC;YAEnC,IAAI,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAC1D,IAAI,CAAC,QAAQ,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAChE,CAAC;YAED,MAAM,6BAA6B,GAAG,0BAA0B,CAAC,IAAI,oBAChE,IAAI,CAAC,cAAc,EACtB,CAAC;YAEH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAC9C,SAAS,CACP;gBACE,KAAK,kCAAO,OAAO,KAAE,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,GAAE;gBAC7C,IAAI,EAAE,6BAA6B;gBACnC,OAAO,kCACF,IAAI,CAAC,8BAA8B,GACnC,IAAI,CAAC,8BAA8B,CACvC;aACF,EACD,IAAI,CAAC,KAAK,CAAC,YAAY,IAAI,IAAI,CAAC,CACjC,CACF,CAAC;YAEF,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,MAAM,IAAI,QAAQ,CAChB,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,YAAY,OAAO,CAAC,EAAE,YAAY,EACvE,GAAG,CACJ,CAAC;YACJ,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;KAAA;IAUK,UAAU,CACd,OAA4B,EAC5B,IAAyB;;YAEzB,MAAM,YAAY,GAAG,eAAe,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;YAKhE,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAC;YAEnC,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAC5C,MAAM,IAAI,QAAQ,CAAC,2CAA2C,EAAE,GAAG,CAAC,CAAC;YACvE,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,UAAU,iCAC/C,OAAO,KACV,IAAI,EAAE,IAAI,IACV,CAAC;YAEH,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;gBAC9B,MAAM,IAAI,QAAQ,CAChB,GAAG,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,EAC5D,GAAG,CACJ,CAAC;YACJ,CAAC;YAED,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,CAAC;YACnD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACzB,CAAC;KAAA;IAQK,SAAS,CAAC,MAA2B;;YACzC,MAAM,YAAY,GAAG,eAAe,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;YAKhE,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAC;YAEnC,OAAO,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC;gBACzC,KAAK,kCACA,MAAM,KACT,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,GACtB;aACF,CAAC,CAAC;QACL,CAAC;KAAA;IASK,UAAU,CACd,OAA4B;;YAE5B,MAAM,YAAY,GAAG,eAAe,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;YAKhE,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAC;YAEnC,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAC5C,MAAM,IAAI,QAAQ,CAAC,wCAAwC,EAAE,GAAG,CAAC,CAAC;YACpE,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YAE9D,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;gBAC9B,MAAM,IAAI,QAAQ,CAAC,4BAA4B,EAAE,GAAG,CAAC,CAAC;YACxD,CAAC;YAED,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,CAAC;YACnD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACzB,CAAC;KAAA;CACF;AAOD,MAAM,UAAU,eAAe;IAC7B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,YAAY,GAAgC,EAAE,CAAC;IACrD,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;QACvB,YAAY,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IACH,OAAO,YAAY,CAAC;AACtB,CAAC","sourcesContent":["import {\n camelCase,\n kebabCase,\n pascalCase,\n} from \"../../utils/helpers/change-case.helpers\";\nimport {\n getModelModules,\n getModels,\n getPrismaModelRelations,\n RelationFields,\n} from \"../../utils/helpers/models.helpers\";\nimport deepmerge from \"../../utils/helpers/deepmerge.helper\";\nimport AppError from \"../error-handler/utils/app-error\";\nimport pluralize from \"pluralize\";\nimport { handleRelationFieldsInBody } from \"./utils/helpers/base.helpers\";\nimport { getPrismaInstance } from \"../../utils/helpers/prisma.helpers\";\nimport validateDto from \"../../utils/validate-dto\";\nimport { getArkosConfig } from \"../../server\";\nimport authService from \"../auth/auth.service\";\n\n/**\n * Base service class for handling CRUD operations on a specific model.\n * This class provides standard implementation of data operations that can be extended\n * by model-specific service classes.\n *\n * @class BaseService\n */\nexport class BaseService {\n /**\n * The camelCase name of the model\n * @public\n */\n modelName: string;\n\n /**\n * Object containing singular and list relation fields for the model\n * @public\n */\n relationFields: RelationFields;\n\n /**\n * Map of singular relation fields to include in queries\n * @public\n */\n singularRelationFieldToInclude: Record<string, boolean>;\n\n /**\n * Map of list relation fields to include in queries\n * @public\n */\n listRelationFieldToInclude: Record<string, boolean>;\n\n /**\n * Instance of the Prisma client\n * @public\n */\n prisma: any;\n\n /**\n * Creates an instance of BaseService.\n * @param {string} modelName - The name of the model to perform operations on.\n */\n constructor(modelName: string) {\n this.modelName = camelCase(modelName);\n this.relationFields = getPrismaModelRelations(pascalCase(modelName))!;\n this.singularRelationFieldToInclude = this.relationFields?.singular?.reduce(\n (acc: Record<string, boolean>, curr) => {\n acc[curr.name] = true;\n return acc;\n },\n {}\n );\n this.listRelationFieldToInclude = this.relationFields?.list?.reduce(\n (acc: Record<string, boolean>, curr) => {\n acc[curr.name] = true;\n return acc;\n },\n {}\n );\n }\n /**\n * Creates a single record in the database.\n *\n * @param {Record<string, any>} body - The data to create the record with.\n * @param {string} [queryOptions] - Additional query options to modify the Prisma query.\n * @returns {Promise<any>} The created record.\n */\n async createOne(\n body: Record<string, any>,\n queryOptions: string = \"{}\"\n ): Promise<any> {\n if (kebabCase(this.modelName) === \"user\" && body.password) {\n body.password = await authService.hashPassword(body.password);\n }\n\n const prisma = getPrismaInstance();\n\n const bodyWithRelationFieldsHandled = handleRelationFieldsInBody(\n body,\n {\n ...this.relationFields,\n },\n [\"delete\", \"disconnect\", \"update\"]\n );\n\n return await prisma[this.modelName].create(\n deepmerge(\n {\n data: bodyWithRelationFieldsHandled,\n include: {\n ...this.singularRelationFieldToInclude,\n ...this.singularRelationFieldToInclude,\n },\n },\n JSON.parse(queryOptions || \"{}\")\n )\n );\n }\n\n /**\n * Creates multiple records in the database.\n *\n * @param {Record<string, any>[]} body - An array of data to create records with.\n * @returns {Promise<{ total: number; data: any }>} The result containing the total count and the created data.\n * @throws {AppError} Throws an error if the data array is invalid or empty.\n */\n async createMany(\n body: Record<string, any>[]\n ): Promise<{ total: number; data: any }> {\n const prisma = getPrismaInstance();\n\n if (!Array.isArray(body) || body.length === 0) {\n throw new AppError(\n \"Invalid or empty data array provided for creation.\",\n 400\n );\n }\n\n const data = await prisma[this.modelName].createMany({\n data: body,\n });\n\n const total = await prisma[this.modelName].count();\n return { total, data };\n }\n\n /**\n * Finds multiple records based on provided filters.\n *\n * @param {Record<string, any>} filters - The filters to apply to the query.\n * @returns {Promise<{ total: number; data: any }>} The result containing the total count and the found data.\n */\n async findMany(\n filters: Record<string, any>\n ): Promise<{ total: number; data: any }> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n // if (modelModules.dtos.query && getArkosConfig()?.validation !== false) {\n // filters = await validateDto(modelModules.dtos.query, filters);\n // }\n\n const prisma = getPrismaInstance();\n\n const [data, total] = await Promise.all([\n prisma[this.modelName].findMany(\n \"select\" in filters\n ? deepmerge(\n { ...filters },\n {\n select: this.singularRelationFieldToInclude,\n }\n )\n : deepmerge(\n { ...filters },\n {\n include: this.singularRelationFieldToInclude,\n }\n )\n ),\n prisma[this.modelName].count({\n where: filters.where,\n }),\n ]);\n\n return { total, data };\n }\n\n /**\n * Finds a single record by its parameters.\n *\n * @param {Record<string, any>} filters - The parameters to find the record by.\n * @param {string} [queryOptions] - Additional query options to modify the Prisma query.\n * @returns {Promise<any>} The found record.\n * @throws {AppError} Throws an error if the record is not found.\n */\n async findOne(\n filters: Record<string, any>,\n // queryOptions: string = JSON.stringify(\n // getModelModules(kebabCase(this.modelName)).prismaQueryOptions || {}\n // )\n queryOptions: string = \"{}\"\n ): Promise<any> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n // if (modelModules.dtos.create && getArkosConfig()?.validation !== false) {\n // filters = await validateDto(modelModules.dtos.create, filters);\n // }\n\n const prisma = getPrismaInstance();\n\n const data = await prisma[this.modelName].findUnique(\n deepmerge(\n {\n where: { ...filters, id: String(filters.id) },\n ...(JSON.parse(queryOptions || \"{}\").hasOwnProperty(\"select\")\n ? {\n select: {\n ...this.singularRelationFieldToInclude,\n ...this.listRelationFieldToInclude,\n },\n }\n : {\n include: {\n ...this.singularRelationFieldToInclude,\n ...this.listRelationFieldToInclude,\n },\n }),\n },\n JSON.parse(queryOptions || \"{}\")\n )\n );\n\n if (!data) {\n throw new AppError(\n `${pascalCase(String(this.modelName))} with ID ${filters.id} not found`,\n 404\n );\n }\n\n return data;\n }\n\n /**\n * Updates a single record by its ID.\n *\n * @param {Record<string, any>} filters - The parameters to find the record by.\n * @param {Record<string, any>} body - The data to update the record with.\n * @param {string} [queryOptions] - Additional query options to modify the Prisma query.\n * @returns {Promise<any>} The updated record.\n * @throws {AppError} Throws an error if the record is not found.\n */\n async updateOne(\n filters: Record<string, any>,\n body: Record<string, any>,\n // queryOptions: string = JSON.stringify(\n // getModelModules(kebabCase(this.modelName)).prismaQueryOptions || {}\n // )\n queryOptions: string = \"{}\"\n ): Promise<any> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n if (modelModules.dtos.update && getArkosConfig()?.validation) {\n body = await validateDto(modelModules.dtos.update, body);\n }\n\n const prisma = getPrismaInstance();\n\n if (kebabCase(this.modelName) === \"user\" && body.password) {\n body.password = await authService.hashPassword(body.password);\n }\n\n const bodyWithRelationFieldsHandled = handleRelationFieldsInBody(body, {\n ...this.relationFields,\n });\n\n const data = await prisma[this.modelName].update(\n deepmerge(\n {\n where: { ...filters, id: String(filters.id) },\n data: bodyWithRelationFieldsHandled,\n include: {\n ...this.singularRelationFieldToInclude,\n ...this.singularRelationFieldToInclude,\n },\n },\n JSON.parse(queryOptions || \"{}\")\n )\n );\n\n if (!data) {\n throw new AppError(\n `${pascalCase(String(this.modelName))} with ID ${filters.id} not found`,\n 404\n );\n }\n\n return data;\n }\n\n /**\n * Updates multiple records based on the provided filter and data.\n *\n * @param {Record<string, any>} filters - The filters to identify records to update.\n * @param {Record<string, any>} body - The data to update the records with.\n * @returns {Promise<{ total: number; data: any }>} The result containing the total count and the updated data.\n * @throws {AppError} Throws an error if no records match the filters.\n */\n async updateMany(\n filters: Record<string, any>,\n body: Record<string, any>\n ): Promise<{ total: number; data: any }> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n // if (modelModules.dtos.create && getArkosConfig()?.validation !== false) {\n // body = await validateDto(modelModules.dtos.create, body);\n // }\n\n const prisma = getPrismaInstance();\n\n if (!filters || typeof filters !== \"object\") {\n throw new AppError(\"Invalid filters provided for udpate many.\", 400);\n }\n\n const data = await prisma[this.modelName].updateMany({\n ...filters,\n data: body,\n });\n\n if (!data || data.count === 0) {\n throw new AppError(\n `${pluralize(pascalCase(String(this.modelName)))} not found`,\n 404\n );\n }\n\n const total = await prisma[this.modelName].count();\n return { total, data };\n }\n\n /**\n * Deletes a single record by its ID.\n *\n * @param {Record<string, any>} params - The parameters to find the record by.\n * @returns {Promise<any>} The deleted record.\n */\n async deleteOne(params: Record<string, any>): Promise<any> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n // if (modelModules.dtos.create && getArkosConfig()?.validation !== false) {\n // body = await validateDto(modelModules.dtos.create, body);\n // }\n\n const prisma = getPrismaInstance();\n\n return await prisma[this.modelName].delete({\n where: {\n ...params,\n id: String(params.id),\n },\n });\n }\n\n /**\n * Deletes multiple records based on the provided filter.\n *\n * @param {Record<string, any>} filter - The filter to identify records to delete.\n * @returns {Promise<{ total: number; data: any }>} The result containing the total count and the deleted data.\n * @throws {AppError} Throws an error if no records match the filter.\n */\n async deleteMany(\n filters: Record<string, any>\n ): Promise<{ total: number; data: any }> {\n const modelModules = getModelModules(kebabCase(this.modelName));\n // if (modelModules.dtos.create && getArkosConfig()?.validation !== false) {\n // body = await validateDto(modelModules.dtos.create, body);\n // }\n\n const prisma = getPrismaInstance();\n\n if (!filters || typeof filters !== \"object\") {\n throw new AppError(\"Invalid filters provided for deletion.\", 400);\n }\n\n const data = await prisma[this.modelName].deleteMany(filters);\n\n if (!data || data.count === 0) {\n throw new AppError(`No records found to delete`, 404);\n }\n\n const total = await prisma[this.modelName].count();\n return { total, data };\n }\n}\n\n/**\n * Generates a set of base service instances for all available models.\n *\n * @returns {Record<string, BaseService>} A dictionary of base service instances, keyed by model name.\n */\nexport function getBaseServices(): Record<string, BaseService> {\n const models = getModels();\n const baseServices: Record<string, BaseService> = {};\n models.forEach((model) => {\n baseServices[`${camelCase(model)}`] = new BaseService(model);\n });\n return baseServices;\n}\n"]}
|
|
@@ -13,7 +13,10 @@ export function parseQueryParamsWithModifiers(query, fieldConfig = DEFAULT_FIELD
|
|
|
13
13
|
: value.toString();
|
|
14
14
|
const parts = key.split("__");
|
|
15
15
|
if (parts.length < 2) {
|
|
16
|
-
acc[key] =
|
|
16
|
+
acc[key] =
|
|
17
|
+
typeof value === "string"
|
|
18
|
+
? convertValue(stringValue, parts[0], fieldConfig)
|
|
19
|
+
: value;
|
|
17
20
|
return acc;
|
|
18
21
|
}
|
|
19
22
|
const fieldName = parts[0];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.features.helpers.js","sourceRoot":"","sources":["../../../../src/utils/helpers/api.features.helpers.ts"],"names":[],"mappings":"AAqBA,MAAM,oBAAoB,GAAgB;IACxC,UAAU,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,CAAC;IAC3D,aAAa,EAAE,CAAC,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,CAAC;IACrE,aAAa,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,CAAC;CAChE,CAAC;AAwBF,MAAM,UAAU,6BAA6B,CAC3C,KAA0B,EAE1B,cAA2B,oBAAoB;IAE/C,OAAO,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAC7D,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;;QACpB,IAAI,CAAC,KAAK,IAAI,KAAK,KAAK,KAAK;YAAE,OAAO,GAAG,CAAC;QAG1C,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YACtC,CAAC,CAAC,MAAA,KAAK,CAAC,CAAC,CAAC,0CAAE,QAAQ,EAAE;YACtB,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,GAAG,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"api.features.helpers.js","sourceRoot":"","sources":["../../../../src/utils/helpers/api.features.helpers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Configuration types for field type mapping\n */\ninterface FieldConfig {\n dateFields: string[];\n booleanFields: string[];\n numericFields: string[];\n}\n\n/**\n * Type for the structured filter object returned by the parser\n */\ntype ParsedFilter = {\n [key: string]: any;\n orderBy?: Record<string, \"asc\" | \"desc\">;\n OR?: Record<string, any>[];\n};\n\n/**\n * Default configuration for field types\n */\nconst DEFAULT_FIELD_CONFIG: FieldConfig = {\n dateFields: [\"createdAt\", \"updatedAt\", \"deletedAt\", \"date\"],\n booleanFields: [\"isActive\", \"isDeleted\", \"isPublished\", \"isArchived\"],\n numericFields: [\"age\", \"price\", \"quantity\", \"amount\", \"rating\"],\n};\n\n/**\n * Parses query parameters into a structured filter object compatible with Prisma queries.\n * Supports various operators and data type conversions.\n *\n * @param query - Object containing query parameters\n * @param fieldConfig - Optional configuration for field type mapping\n * @returns Structured filter object for database queries\n *\n * @example\n * // Basic usage\n * parseQueryParamsWithModifiers({ name__contains: 'john' })\n * // => { name: { contains: 'john', mode: 'sensitive' } }\n *\n * @example\n * // Complex query\n * parseQueryParamsWithModifiers({\n * name__not__equals: 'john',\n * age__gt: '25',\n * tags__in: 'tag1,tag2',\n * orderBy__createdAt: 'desc'\n * })\n */\nexport function parseQueryParamsWithModifiers(\n query: Record<string, any>,\n // excludedFields: string[],\n fieldConfig: FieldConfig = DEFAULT_FIELD_CONFIG\n): ParsedFilter {\n return Object.entries(JSON.parse(JSON.stringify(query))).reduce(\n (acc, [key, value]) => {\n if (!value && value !== false) return acc;\n\n // Convert value to string if it's not already\n const stringValue = Array.isArray(value)\n ? value[0]?.toString()\n : value.toString();\n const parts = key.split(\"__\");\n if (parts.length < 2) {\n acc[key] =\n typeof value === \"string\"\n ? convertValue(stringValue, parts[0], fieldConfig)\n : value;\n return acc;\n }\n const fieldName = parts[0];\n\n // Handle ordering\n if (fieldName === \"orderBy\" && parts.length === 2) {\n if (!acc.orderBy) acc.orderBy = {};\n acc.orderBy[parts[1]] = stringValue as \"asc\" | \"desc\";\n return acc;\n }\n\n // Handle simple equals case\n if (parts.length === 1) {\n acc[fieldName] = {\n equals: convertValue(stringValue, fieldName, fieldConfig),\n };\n return acc;\n }\n\n let currentLevel = acc;\n let currentKey = fieldName;\n\n // Build nested structure\n for (let i = 1; i < parts.length - 1; i++) {\n if (!currentLevel[currentKey]) {\n currentLevel[currentKey] = {};\n }\n currentLevel = currentLevel[currentKey];\n currentKey = parts[i];\n }\n\n const lastOperator = parts[parts.length - 1];\n\n // Handle special operators\n switch (lastOperator) {\n case \"icontains\":\n currentLevel[currentKey] = {\n contains: stringValue,\n mode: \"insensitive\",\n };\n break;\n\n case \"contains\":\n currentLevel[currentKey] = {\n contains: stringValue,\n mode: \"sensitive\",\n };\n break;\n\n case \"in\":\n case \"notIn\":\n currentLevel[currentKey] = {\n [lastOperator]: stringValue\n .split(\",\")\n .map((v: string) =>\n convertValue(v.trim(), fieldName, fieldConfig)\n ),\n };\n break;\n\n case \"or\":\n const values: string[] = stringValue.split(\",\");\n if (!acc.OR) acc.OR = [];\n acc.OR.push(\n ...values.map((val) => ({\n [fieldName]: {\n equals: convertValue(val.trim(), fieldName, fieldConfig),\n },\n }))\n );\n break;\n\n case \"isNull\":\n currentLevel[currentKey] = {\n equals: stringValue.toLowerCase() === \"true\" ? null : undefined,\n };\n break;\n\n case \"isEmpty\":\n currentLevel[currentKey] = {\n equals: stringValue.toLowerCase() === \"true\" ? \"\" : undefined,\n };\n break;\n\n default:\n currentLevel[currentKey] = {\n [lastOperator]: convertValue(stringValue, fieldName, fieldConfig),\n };\n }\n\n return acc;\n },\n {} as ParsedFilter\n );\n}\n\n/**\n * Converts string values to appropriate types based on field configuration\n * \n * // Example usage:\n/*\n const query = {\n name__not__equals: 'uanela',\n email__contains: 'example.com',\n description__icontains: 'test',\n age__gt: '25',\n status: 'active',\n tags__in: 'tag1,tag2,tag3',\n createdAt__gt: '2024-01-01',\n isActive: 'true',\n orderBy__createdAt: 'desc'\n };\n \n const result = parseQueryParamsWithModifiers(query);\n */\nfunction convertValue(\n value: string,\n fieldName: string,\n config: FieldConfig\n): any {\n // Handle date fields\n if (config.dateFields.includes(fieldName)) {\n return new Date(value);\n }\n\n // Handle boolean fields\n if (config.booleanFields.includes(fieldName)) {\n return value.toLowerCase() === \"true\";\n }\n\n // Handle numeric fields\n if (config.numericFields.includes(fieldName)) {\n return Number(value);\n }\n\n return value;\n}\n"]}
|