{"id":23268402,"url":"https://github.com/mae776569/xprevalent","last_synced_at":"2026-04-06T02:34:19.740Z","repository":{"id":39800433,"uuid":"325979905","full_name":"MAE776569/xprevalent","owner":"MAE776569","description":"The next level library for creating express controllers","archived":false,"fork":false,"pushed_at":"2023-04-10T09:25:54.000Z","size":350,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-13T00:04:32.407Z","etag":null,"topics":["backend","expressjs","mongodb","nodejs","npm","npm-package"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MAE776569.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-01-01T13:00:01.000Z","updated_at":"2023-09-03T16:15:34.000Z","dependencies_parsed_at":"2022-09-06T03:42:46.733Z","dependency_job_id":null,"html_url":"https://github.com/MAE776569/xprevalent","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MAE776569%2Fxprevalent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MAE776569%2Fxprevalent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MAE776569%2Fxprevalent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MAE776569%2Fxprevalent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MAE776569","download_url":"https://codeload.github.com/MAE776569/xprevalent/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247457727,"owners_count":20941905,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["backend","expressjs","mongodb","nodejs","npm","npm-package"],"created_at":"2024-12-19T17:18:18.060Z","updated_at":"2025-12-30T20:24:04.059Z","avatar_url":"https://github.com/MAE776569.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# xprevalent\r\n\r\nxprevalent is a library for creating express controllers. Define a controller and use with express router. Controllers are declarative and divides request handling into many stages.\r\n\r\n## How to Install\r\n\r\n```javascript\r\nnpm install xprevalent\r\n```\r\n\r\n## Docs\r\n\r\n1. For a detailed explanation on how to use: [/docs](https://github.com/MAE776569/xprevalent/tree/main/docs)\r\n2. For code examples: [/examples](https://github.com/MAE776569/xprevalent/tree/main/examples)\r\n\r\n## Table of Contents\r\n\r\n- [Generic Controller](#generic-controller)\r\n- [How to Use with Express Router](#how-to-use-with-express-router)\r\n- [Validator](#validator)\r\n  - [How to Use in Controllers](#how-to-use-in-controllers)\r\n  - [How to Validate Data](#how-to-validate-data)\r\n- [List Controller](#list-controller)\r\n- [Details Controller](#details-controller)\r\n- [Create Controller](#create-controller)\r\n- [Update Controller](#update-controller)\r\n- [Delete Controller](#delete-controller)\r\n\r\n## Generic Controller\r\n\r\nController is a generic class that handles the request and returns a response.\r\n\r\nThere are four types of controllers:\r\ntype | description |\r\n----- | ---- |\r\nlist | returns list of records (optionally paginated) |\r\ndetails | returns single record |\r\ncreate | create a new record in database |\r\nupdate | update a record in database |\r\ndelete | deletes a record from database |\r\n\r\nAll the controllers share the following params:\r\nname | type | description |\r\n----- | ---- | ---- |\r\n`req` | object | express req object |\r\n`res` | object | express response object |\r\n`next` | function | express next function |\r\n`model` | object |mongoose model |\r\n`queryObjectName` | string | the name of the field in response representing the data returned from controller |\r\n`selectedFields` | array of strings | used by mongoose model to select certain fields |\r\n`excludedFields` | array of strings | used by mongoose model to exclude certain fields |\r\n`sortBy` | object | used by mongoose model to sort the result |\r\n`populatedFields` | array | used by mongoose model to populate fields |\r\n\r\nThere are some common methods that is shared by all the controllers:\r\n\r\n| name               | input                                                                                                                                        | returns                              | description                                                                                                     |\r\n| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------- |\r\n| `getContextObject` |                                                                                                                                              | object                               | used to return any additional data with response body                                                           |\r\n| `getQueryResult`   |                                                                                                                                              | object or array of objects           | used to fetch/change data in database and returns the query result that will be returned in the response body   |\r\n| `sendResponse`     | type = \"json\" or \"generic\", success = boolean, status = status code, message = string, error = object, body = object represent response body | express response                     | used to return a response based on the given input                                                              |\r\n| `handleRequest`    |                                                                                                                                              | a response or calls the next handler | used to handle the request and returns a response or either uses `next()` to pass the error to the next handler |\r\n\r\n## How to Use with Express Router\r\n\r\nIn order to use the controller with express router, all you have to do is to pass `Controller.handle` as the request handler.\r\n\r\n```javascript\r\nconst { ApiListController } = require(\"xprevalent\");\r\nconst userModel = require(\"models/user\");\r\n\r\nclass UsersListController extends ApiListController {\r\n  model = userModel;\r\n  paginate = true;\r\n}\r\n\r\nmodule.exports = UsersListController;\r\n```\r\n\r\n```javascript\r\nconst router = require(\"express\").Router();\r\nconst UsersListController = require(\"controllers/users.list.controller\");\r\n\r\nrouter.get(\"/users\", UsersListController.handle);\r\n\r\nmodule.exports = router;\r\n```\r\n\r\n## Validator\r\n\r\nThe validator is used to validate all the data passed to the controller.\r\n\r\nTo use the validator you must create a validation schema using `ValidationSchema` class and pass a `schema` to it.\r\n\r\n```javascript\r\nconst { ValidationSchema, schema } = require(\"xprevalent\");\r\nconst userSchema = {\r\n  body: schema.object({\r\n    email: schema.string().email().required()\r\n  })\r\n};\r\nconst validationSchema = new ValidationSchema(userSchema);\r\n```\r\n\r\nThe schema is an object that consists of three different keys. each key represent a request location:\r\n\r\n1. params\r\n2. query\r\n3. body\r\n\r\nThe value of params, query and body is based on [yup](https://github.com/jquense/yup) validator library.\r\n\r\n```javascript\r\nconst { ValidationSchema, schema } = require(\"xprevalent\");\r\nconst userSchema = {\r\n  params: schema.object({\r\n    id: schema.number().integer().positive().required()\r\n  }),\r\n  query: schema.object({\r\n    name: schema.string().required()\r\n  }),\r\n  body: schema.object({\r\n    email: schema.string().email().required()\r\n  })\r\n};\r\nconst validationSchema = new ValidationSchema(userSchema);\r\n```\r\n\r\n### How to Use in Controllers\r\n\r\nIn order to use validator in controllers, all you have to do is to set validation schema. and the controller will handle the validation automatically.\r\n\r\n```javascript\r\nclass UserUpdateController extends ApiUpdateController {\r\n  model = userModel;\r\n  validationSchema = new ValidationSchema({\r\n    body: schema.object({\r\n      email: schema.string().email().required()\r\n    })\r\n  });\r\n}\r\n```\r\n\r\nIt is better to create schemas into its own separate files and export it into controller.\r\n\r\n```javascript\r\n// schemas/users.schema.js\r\nconst { schema } = require(\"xprevalent\");\r\n\r\nconst updateUserSchema = {\r\n  body: schema.object({\r\n    email: schema.string().email().required()\r\n  })\r\n};\r\n```\r\n\r\n```javascript\r\nconst { ValidationSchema } = require(\"xprevalent\");\r\nconst { updateUserSchema } = require(\"schemas/users.schema\");\r\n\r\nclass UserUpdateController extends ApiUpdateController {\r\n  model = userModel;\r\n  validationSchema = new ValidationSchema(updateUserSchema);\r\n}\r\n```\r\n\r\n### How to Validate Data\r\n\r\nValidation schema validates the input using `validate()` which takes in the request object and validates it based on the different locations used in the validation schema.\r\n\r\nThe `validationSchema.validate(req)` returns an object that contains three methods:\r\n\r\n1. `hasError`: takes in an optional object consists of `{ name, location }` and returns boolean based on whether the request has an error or not.\r\n   the location is one of three strings `params, query, body` if the location is specified it will check if the location has any error in one of its fields. and if the name is specified, it will check if `location[name]` has an error, if none of them is specified it will check if the schema has an error in any of the three locations.\r\n2. `getValue`: takes in an optional parameter `name` and returns the validated value of that field specified by `req[name]`. if name is not specified it will return an object consists of the three locations `{ params, query, body }`.\r\n3. `getErrors`: takes in an optional object consists of `{ name, location }` and returns error object. the location is one of three strings `params, query, body` if the location is specified it will return the location errors. and if the name is specified, it will return `location[name]` errors, if none of them is specified it will return all the errors in all of the three locations.\r\n\r\n```javascript\r\n// schemas/users.schema.js\r\nconst { ValidationSchema, schema } = require(\"xprevalent\");\r\n\r\nconst updateUserSchema = {\r\n  body: schema.object({\r\n    email: schema.string().email().required(),\r\n    name: schema.string().required()\r\n  })\r\n};\r\n\r\nconst validationSchema = new ValidationSchema(updateUserSchema);\r\nconst validationResult = validationSchema.validate({\r\n  body: {\r\n    email: \"\",\r\n    name: \"Mohamed\"\r\n  }\r\n});\r\n\r\n// will return true as email is invalid\r\nconsole.log(validationResult.hasError());\r\n// will return true as body[email] is invalid\r\nconsole.log(validationResult.hasError({ location: \"body\" }));\r\n// will return true as email is invalid\r\nconsole.log(validationResult.hasError({ location: \"body\", name: \"email\" }));\r\n// will return false as body[name] is valid\r\nconsole.log(validationResult.hasError({ location: \"body\", name: \"name\" }));\r\n\r\n// will return {} as body is invalid\r\nconsole.log(validationResult.getValue());\r\n// will return undefined as body is invalid\r\nconsole.log(validationResult.getValue(\"body\"));\r\n\r\n// will return { body: { email: \"email is a required field\" } }\r\nconsole.log(validationResult.getErrors());\r\n// will return { email: \"email is a required field\" }\r\nconsole.log(validationResult.getErrors({ location: \"body\" }));\r\n// will return \"email is a required field\"\r\nconsole.log(validationResult.getErrors({ location: \"body\", name: \"email\" }));\r\n// will return undefined as name is valid\r\nconsole.log(validationResult.getErrors({ location: \"body\", name: \"name\" }));\r\n```\r\n\r\n## List Controller\r\n\r\nUsed To list all documents optionally paginated.\r\n\r\n```javascript\r\nclass UsersListController extends ApiListController {\r\n  model = userModel;\r\n}\r\n```\r\n\r\nTo list documents with pagination; set paginate to `true`.\r\n\r\n```javascript\r\nclass UsersListController extends ApiListController {\r\n  model = userModel;\r\n  paginate = true;\r\n}\r\n```\r\n\r\nBy default the controller will get the pagination parameters from request query `page`, `limit` and if neither of them is provided will use a default `page = 1` and `limit = 25`.\r\n\r\nTo override the default parameters, you can set `paginateBy` object.\r\n\r\n```javascript\r\nclass UsersListController extends ApiListController {\r\n  model = userModel;\r\n  paginate = true;\r\n\r\n  paginateBy = {\r\n    // use req.query.cursor to get page number\r\n    pageParam: \"cursor\",\r\n    // use req.query.offset to get the limit\r\n    limitParam: \"offset\",\r\n    // use a default limit of 30 if limit is not provided\r\n    defaultLimit: 30\r\n  };\r\n}\r\n```\r\n\r\nBy default the controller will get the document count using `getDocumentsCount()` and will use `getQueryFilter()` as the filter used to count documents. you can override `getDocumentsCount()` to control how the documents is counted.\r\n\r\n```javascript\r\nclass UsersListController extends ApiListController {\r\n  ...\r\n  async getDocumentsCount() {\r\n    const count = await this.model.countDocuments({ deletedAt: { $eq: null } });\r\n    return count;\r\n  }\r\n}\r\n```\r\n\r\nBy default the controller will return a pagination object in the response with the following structure:\r\n\r\n```javascript\r\nreturn { count, totalPages, page, limit, nextPage, previousPage };\r\n```\r\n\r\nTo control what data is returned in this object you can override `getPaginationMeta()`.\r\n\r\n```javascript\r\nclass UsersListController extends ApiListController {\r\n  ...\r\n  async getPaginationMeta() {\r\n    const count = await this.getDocumentsCount();\r\n    const { page, limit } = this.getPaginationParams();\r\n    const lastPage = Math.ceil(count / limit);\r\n    // need to set this.totalPages as it will be used in getQueryResult\r\n    this.totalPages = lastPage \u003e 0 ? lastPage : 1;\r\n\r\n    const meta = {\r\n      count,\r\n      totalPages: lastPage,\r\n      page: page \u003c lastPage ? page : this.totalPages,\r\n      limit,\r\n      nextPage: page \u003c lastPage ? page + 1 : null,\r\n      previousPage:\r\n        page \u003e 1 ? (page \u003c lastPage ? page - 1 : lastPage - 1) : null\r\n    };\r\n\r\n    return meta;\r\n  }\r\n}\r\n```\r\n\r\nTo control the filter that is used to count documents and to fetch data from database, you can override `getQueryFilter()`.\r\n\r\n```javascript\r\nclass UsersListController extends ApiListController {\r\n  ...\r\n  async getQueryFilter() {\r\n    return {\r\n      isActive: { $eq: Boolean(this.req.query.isActive) }\r\n    }\r\n  }\r\n}\r\n```\r\n\r\nTo control how data is fetched from database you can override `getQueryResult()`.\r\n\r\n```javascript\r\nclass UsersListController extends ApiListController {\r\n  ...\r\n  getQueryResult() {\r\n    const { page, limit } = this.getPaginationParams();\r\n    return this.model.aggregate([\r\n      {\r\n        $skip: (page - 1) * limit\r\n      },\r\n      {\r\n        $limit: limit\r\n      }\r\n      ...\r\n    ]);\r\n  }\r\n}\r\n```\r\n\r\nTo return any additional data with the response you can override `getContextObject()`.\r\n\r\n```javascript\r\nclass UsersListController extends ApiListController {\r\n  ...\r\n  async getContextObject() {\r\n    const context = await super.getContextObject();\r\n    // get any data you want to return in response\r\n    const additionalData = this.getAdditionalData();\r\n    return {\r\n      ...context,\r\n      ...additionalData\r\n    };\r\n  }\r\n}\r\n```\r\n\r\n## Details Controller\r\n\r\nDetails controller is used to get a single object.\r\nBy default this object will be fetched by id and will use `req.params.id` to fetch the object from database.\r\n\r\n```javascript\r\nclass UserDetailsController extends ApiDetailsController {\r\n  model = userModel;\r\n}\r\n```\r\n\r\nTo control the parameter used to fetch the document from database you can override `idParam`.\r\n\r\n```javascript\r\nclass UserDetailsController extends ApiDetailsController {\r\n  model = userModel;\r\n  // this will use req.params.userId to fetch the document from database\r\n  idParam = \"userId\";\r\n}\r\n```\r\n\r\nTo controller how the id is validated you can override `idParamIsInvalid()` and return a boolean indicating if the id is valid or not.\r\n\r\nIf the id is not valid the controller will return `404`.\r\n\r\n```javascript\r\nclass UserDetailsController extends ApiDetailsController {\r\n  ...\r\n  idParamIsInvalid() {\r\n    const id = this.req.params[this.idParam];\r\n    return !Number.isInteger(parseInt(id));\r\n  }\r\n}\r\n```\r\n\r\nTo get a single document using query filter, you can set `findOne` to true and override `getQueryFilter()` to return the filter used to get the document.\r\n\r\n```javascript\r\nclass UserDetailsController extends ApiDetailsController {\r\n  model = userModel;\r\n  findOne = true;\r\n\r\n  getQueryFilter() {\r\n    return {\r\n      name: { $regex: /Mohamed/, $options: \"i\" }\r\n    };\r\n  }\r\n}\r\n```\r\n\r\nTo control how data is fetched from database you can override `getQueryResult()`.\r\n\r\n```javascript\r\nclass UserDetailsController extends ApiDetailsController {\r\n  ...\r\n  getQueryResult() {\r\n    const id = this.req.params[this.idParam];\r\n    return this.model.findById(id);\r\n  }\r\n}\r\n```\r\n\r\nTo return any additional data with the response you can override `getContextObject()`.\r\n\r\n```javascript\r\nclass UserDetailsController extends ApiDetailsController {\r\n  ...\r\n  async getContextObject() {\r\n    const context = await super.getContextObject();\r\n    // get any data you want to return in response\r\n    const additionalData = this.getAdditionalData();\r\n    return {\r\n      ...context,\r\n      ...additionalData\r\n    };\r\n  }\r\n}\r\n```\r\n\r\n## Create Controller\r\n\r\nCreate controller is used to insert document(s) into database.\r\n\r\nThe controller will first validate the request before inserting new documents using validation schema.\r\n\r\n```javascript\r\nclass UserCreateController extends ApiCreateController {\r\n  model = userModel;\r\n  validationSchema = new ValidationSchema(createUserSchema);\r\n}\r\n```\r\n\r\nBy default the inserted document will be the result of the validation returned from validating the request body.\r\n\r\nIf the data is not valid `422` status code will be returned with error object in the response.\r\n\r\nTo customize the inserted document or control the values of the document fields, you can override `getDocument()`.\r\n\r\n```javascript\r\nclass UserCreateController extends ApiCreateController {\r\n  ...\r\n  getDocument() {\r\n    const user = this.validationResult.getValue(\"body\");\r\n    return {\r\n      ...user,\r\n      role: \"default\"\r\n    };\r\n  }\r\n}\r\n```\r\n\r\nTo control how data is inserted into database you can override `getQueryResult()`.\r\n\r\n```javascript\r\nclass UserCreateController extends ApiCreateController {\r\n  ...\r\n  getQueryResult() {\r\n    const document = this.getDocument();\r\n    return this.model.create(document);\r\n  }\r\n}\r\n```\r\n\r\nBy default the created document will be returned in the response.\r\n\r\nTo return any additional data with the response you can override `getContextObject()`.\r\n\r\n```javascript\r\nclass UserCreateController extends ApiCreateController {\r\n  ...\r\n  async getContextObject() {\r\n    const context = await super.getContextObject();\r\n    // get any data you want to return in response\r\n    const additionalData = this.getAdditionalData();\r\n    return {\r\n      ...context,\r\n      ...additionalData\r\n    };\r\n  }\r\n}\r\n```\r\n\r\n## Update Controller\r\n\r\nUpdate controller is used to update document(s) into database.\r\n\r\nThe controller will first validate the request before updating documents using validation schema.\r\n\r\n```javascript\r\nclass UserUpdateController extends ApiUpdateController {\r\n  model = userModel;\r\n  validationSchema = new ValidationSchema(updateUserSchema);\r\n}\r\n```\r\n\r\nTo control the parameter used to fetch the document from database you can override `idParam`.\r\n\r\n```javascript\r\nclass UserUpdateController extends ApiUpdateController {\r\n  model = userModel;\r\n  validationSchema = new ValidationSchema(updateUserSchema);\r\n  // this will use req.params.userId to fetch the document from database\r\n  idParam = \"userId\";\r\n}\r\n```\r\n\r\nTo controller how the id is validated you can override `idParamIsInvalid()` and return a boolean indicating if the id is valid or not.\r\n\r\nIf the id is not valid the controller will return `404`.\r\n\r\n```javascript\r\nclass UserUpdateController extends ApiUpdateController {\r\n  ...\r\n  idParamIsInvalid() {\r\n    const id = this.req.params[this.idParam];\r\n    return !Number.isInteger(parseInt(id));\r\n  }\r\n}\r\n```\r\n\r\nBy default the updated document will be the result of the validation returned from validating the request body.\r\n\r\nThe controller only updates the values contained in the request body.\r\n\r\nIf the data is not valid `422` status code will be returned with error object in the response.\r\n\r\nTo customize the updated document or control the fields to be updated, you can override `getUpdateSet()`.\r\n\r\n```javascript\r\nclass UserUpdateController extends ApiUpdateController {\r\n  ...\r\n  getUpdateSet() {\r\n    const updateSet = this.validationResult.getValue(\"body\");\r\n    return {\r\n      ...updateSet,\r\n      role: \"default\"\r\n    };\r\n  }\r\n}\r\n```\r\n\r\nTo update a single document using query filter, you can set `updateOne` to true and override `getQueryFilter()` to return the filter used to get the document to be updated.\r\n\r\n```javascript\r\nclass UserUpdateController extends ApiUpdateController {\r\n  model = userModel;\r\n  validationSchema = new ValidationSchema(updateUserSchema);\r\n  updateOne = true;\r\n\r\n  getQueryFilter() {\r\n    return {\r\n      name: { $regex: /Mohamed/, $options: \"i\" }\r\n    };\r\n  }\r\n}\r\n```\r\n\r\nBy setting `upsert` to `true` if the document is not found in database, it will be created.\r\n\r\n```javascript\r\nclass UserUpdateController extends ApiUpdateController {\r\n  model = userModel;\r\n  validationSchema = new ValidationSchema(updateUserSchema);\r\n  upsert = true;\r\n}\r\n```\r\n\r\nTo control how data is updated you can override `getQueryResult()`.\r\n\r\n```javascript\r\nclass UserUpdateController extends ApiUpdateController {\r\n  ...\r\n  getQueryResult() {\r\n    const updateSet = this.getUpdateSet();\r\n    const id = this.req.params[this.idParam];\r\n    return this.model.findByIdAndUpdate(id, updateSet, { new: true, upsert: true });\r\n  }\r\n}\r\n```\r\n\r\nBy default the newly updated document will be returned in the response.\r\n\r\nTo return any additional data with the response you can override `getContextObject()`.\r\n\r\n```javascript\r\nclass UserUpdateController extends ApiUpdateController {\r\n  ...\r\n  async getContextObject() {\r\n    const context = await super.getContextObject();\r\n    // get any data you want to return in response\r\n    const additionalData = this.getAdditionalData();\r\n    return {\r\n      ...context,\r\n      ...additionalData\r\n    };\r\n  }\r\n}\r\n```\r\n\r\n## Delete Controller\r\n\r\nDelete controller is used to delete document(s) from database.\r\n\r\nTo control the parameter used to fetch the document from database you can override `idParam`.\r\n\r\n```javascript\r\nclass UserDeleteController extends ApiDeleteController {\r\n  model = userModel;\r\n  // this will use req.params.userId to fetch the document from database\r\n  idParam = \"userId\";\r\n}\r\n```\r\n\r\nTo controller how the id is validated you can override `idParamIsInvalid()` and return a boolean indicating if the id is valid or not.\r\n\r\nIf the id is not valid the controller will return `404`.\r\n\r\n```javascript\r\nclass UserDeleteController extends ApiDeleteController {\r\n  ...\r\n  idParamIsInvalid() {\r\n    const id = this.req.params[this.idParam];\r\n    return !Number.isInteger(parseInt(id));\r\n  }\r\n}\r\n```\r\n\r\nTo delete a single document using query filter, you can set `deleteOne` to `true` and override `getQueryFilter()` to return the filter used to get the document to be deleted.\r\n\r\n```javascript\r\nclass UserDeleteController extends ApiDeleteController {\r\n  model = userModel;\r\n  deleteOne = true;\r\n\r\n  getQueryFilter() {\r\n    return {\r\n      name: { $regex: /Mohamed/, $options: \"i\" }\r\n    };\r\n  }\r\n}\r\n```\r\n\r\nTo control how the document is deleted you can override `getQueryResult()`.\r\n\r\n```javascript\r\nclass UserDeleteController extends ApiDeleteController {\r\n  ...\r\n  getQueryResult() {\r\n    const id = this.req.params[this.idParam];\r\n    return this.model.findByIdAndDelete(id);\r\n  }\r\n}\r\n```\r\n\r\nBy default the deleted document will be returned in the response.\r\n\r\nTo return any additional data with the response you can override `getContextObject()`.\r\n\r\n```javascript\r\nclass UserDeleteController extends ApiDeleteController {\r\n  ...\r\n  async getContextObject() {\r\n    const context = await super.getContextObject();\r\n    // get any data you want to return in response\r\n    const additionalData = this.getAdditionalData();\r\n    return {\r\n      ...context,\r\n      ...additionalData\r\n    };\r\n  }\r\n}\r\n```\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmae776569%2Fxprevalent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmae776569%2Fxprevalent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmae776569%2Fxprevalent/lists"}