{"id":21063972,"url":"https://github.com/dolphjs/dolph","last_synced_at":"2025-05-16T02:32:12.102Z","repository":{"id":183098840,"uuid":"669540610","full_name":"dolphjs/dolph","owner":"dolphjs","description":"Write less code, ship faster 🔥🔥","archived":false,"fork":false,"pushed_at":"2025-03-10T18:54:44.000Z","size":1587,"stargazers_count":16,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"dev","last_synced_at":"2025-05-03T18:47:16.566Z","etag":null,"topics":["backend","dolph","dolphjs","nodejs","rest-api","typescript"],"latest_commit_sha":null,"homepage":"https://dolphjs.com","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dolphjs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-07-22T15:59:29.000Z","updated_at":"2025-04-09T10:26:06.000Z","dependencies_parsed_at":"2024-03-07T17:58:48.050Z","dependency_job_id":"15315393-6482-4d5e-b783-9161516a4558","html_url":"https://github.com/dolphjs/dolph","commit_stats":{"total_commits":118,"total_committers":1,"mean_commits":118.0,"dds":0.0,"last_synced_commit":"a411b9e83450a90139cb988a9ca59aff3239af6d"},"previous_names":["dolphjs/dolph"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dolphjs%2Fdolph","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dolphjs%2Fdolph/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dolphjs%2Fdolph/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dolphjs%2Fdolph/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dolphjs","download_url":"https://codeload.github.com/dolphjs/dolph/tar.gz/refs/heads/dev","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254183827,"owners_count":22028580,"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","dolph","dolphjs","nodejs","rest-api","typescript"],"created_at":"2024-11-19T17:47:53.538Z","updated_at":"2025-05-16T02:32:07.094Z","avatar_url":"https://github.com/dolphjs.png","language":"TypeScript","readme":"Looking for the `dolphjs/core` repo? here it is: https://github.com/dolphjs/core \nNote: docs has not yet been updated to fit newest version, docs is only correct for version o.o.2-beta\n\n# dolph.js\n\ndolphjs is a typescript backend framework built to ease development time and shorten code while retaining simplicity.\n\ndolphjs is built on the express.js framework and offers a wide range of classes, methods, functions and utility tools, from error handling middlewares to the best utiity loggers.\n\n## dolph_config file\n\nThe most important file in your dolphjs codebase is the `dolph_config.yaml` file which seats at the root directory of your project. Without this file, on running your dolph server you'll receive an error. In this file, you can define different  fields which helps automate your application. An example of the contents of this file is show below: \n\n```yaml\ndatabase:\n  mongo:\n    url: mongodb://127.0.0.1:27017/dolphjs\n    options:\n      useNewUrlParser: true\n  middlewares:\n    cors:\n      activate: true\n      origin: '*'\n      methods:\n        - GET\n        - POST\n        - PUT\n        - DELETE\n port: 3030\n```\n\nAs of current, the `dolphjs_config` file only accepts this fields:\n\n- **database** - this field should only be used if you want to connect to mongodb [support for other databases hasn't been added yet]. It takes an object of `mongo` as seen in the example above which also takes two objects as values, the `url` and `options` which do exactly what those fields do if using the `mongoose.connect` function manually. Dolphjs would detect this configuration on start and initialize the database as well as log info if successfully connected or not.\n\n-  **middlewares** - this field currently takes two optional fields: `cors` and `xss`. If the *activate* field on both **cors** and **xss** is set to true, then this middlewares are initialized by dolphjs and the other fields the cors object can take include: \n\n  ```ts\n    origin?: string | undefined;\n    allowedHeaders?: string[] | undefined | null;\n    maxAge?: number | undefined;\n    exposedHeaders?: string[] | null | undefined;\n    credentials?: boolean | undefined;\n    preflightContinue?: boolean | undefined;\n    optionsSuccessStatus: number | undefined;\n  ```\n\n- **port** - this is way you pass the port you want to dolphjs to server on. By default, dolphjs uses the port `3030` .\n\n***Note***: *all these are optional as they are alternative ways to initialize these in dolphjs by calling the appropriate functions which would all be discussed later in this docs. However, even if you don't use the `dolph_config.yaml` file to set your configurations, the absence of the file in your root directory would make the dolphjs engine to scream at you with errors. So it's better to leave it empty than not include it.* \n\n## Starting The Server\n\nThis is probably the easiest thing to do in dolphjs. It is as easy as this:\n\n```ts\nimport { DolphFactory } from \"@dolphjs/dolph\"\n\nconst routes = [];\nconst middlewares = [];\nconst dolph = new DolphFactory(routes, middlewares);\n\ndolph.start();\n\n```\n\nThis 5 lines of code starts the dolphjs server, initializes middlewares and database (assuming you used the dolph_config.yaml file to setup configurations) and exposes the dolph engine which is of type `express`. \n\n## Routing\n\nThe `routes` options of the **DolphFactory** class takes an array of routes. An example would look like this:\n\n```ts\nimport { Router } from \"@dolphjs/core\";\n\nconst router = Router();\nconst appRoutes = {\n  path: \"/\",\n  router,\n};\n\nconst routes = [appRoutes];\n\nconst dolph = new DolphFactory(routes);\n```\n\nThe sample code shown above shows how to setup your router in dolphjs but this method is not recommended, despite not having any performance set-backs but because it doesn't let you enjoy the full power of dolphjs. Here is how a router should look like to harness the power of dolphjs:\n\n```ts\nimport { DolphRouteHandler } from '@dolphjs/dolph/classes';\nimport { AppController } from './app.controller';\nimport { Dolph } from '@dolphjs/dolph/common';\n\nclass AppRouter extends DolphRouteHandler\u003cDolph\u003e {\n  constructor() {\n    super();\n    this.initRoutes();\n  }\n\n  public readonly path: string = '/app';\n  // where AppController is your controller class\n  controller: AppController = new AppController();\n\n  initRoutes() {\n  }\n}\n\nconst routes = [new AppRouter()]\n\nconst dolph = new DolphFactory(routes);\n```\n\nFrom the above code, you utilize the strengths of dolphjs and follow the code pattern enforced by dolphjs to enhance clean code, scalability and readability. Now that we have established this, you might be wandering how we'll use our controller in this code above to process requests and send response. Unlike in the former which can be done like this: \n\n```ts\nconst router = Router();\n\nrouter.get(\"/app\", (req:Drequest, res:DResponse) =\u003e {})\nconst appRoutes = {\n  path: \"/\",\n  router,\n};\n```\n\nto use the later, we do it this way:\n\n```ts\nclass AppRouter extends DolphRouteHandler\u003cDolph\u003e {\n  constructor() {\n    super();\n    this.initRoutes();\n  }\n\n  public readonly path: string = '/app';\n  controller: AppController = new AppController();\n\n  initRoutes() {\n    this.router.get(`${this.path}`, (req:DRequest, res:DResponse) =\u003e {});\n  }\n}\n```\n\nor by using the controller class:\n\n```ts\nclass AppRouter extends DolphRouteHandler\u003cDolph\u003e {\n  constructor() {\n    super();\n    this.initRoutes();\n  }\n\n  public readonly path: string = '/app';\n  controller: AppController = new AppController();\n\n  initRoutes() {\n    this.router.get(`${this.path}`, this.controller.sendGreeting());\n  }\n}\n```\n\nWhere `sendGreeting` is a method on the `AppController` class that acts as a handler.\n\n## Controllers\n\nWe will illustrate the two ways of setting up controllers whereby the first can be used with the first way of setting up a router and the second for the second way of setting up a router.\n\n### Using the first method (functional paradigm)\n\n```ts\nconst { TryCatchAsyncFn, SuccessResponse } = require(\"@dolphjs/dolph/common\");\n\nexport const sendGreeting = ((req, res) =\u003e {\n  SuccessResponse({ res, msg: \"Hey there !\" });\n});\n\n```\n\nWith this method, it is just as you are using express.js but the second method let's you leverage the strengths of dolphjs. \n\n### Using the second method (Object oriented paradigm)\n\n```ts\nimport { DolphControllerHandler } from '@dolphjs/dolph/classes';\nimport { Dolph, SuccessResponse, DRequest, DResponse } from '@dolphjs/dolph/common';\n\nexport class AppController extends DolphControllerHandler\u003cDolph\u003e {\n  constructor() {\n    super();\n  }\n    \n  public async sendGreeting(req: DRequest, res: DResponse){\n    SuccessResponse({ res, msg: \"Hey there !\" });\n  };\n}\n```\n\nCurrently, you are probably wondering why anyone would use the second over the first method but as you go deeper into the docs to see the kind of control and simplicity being offered by the second, you'll love it. Dolphjs offers more functionalities when using the OOP approach.\n\n***Note***: *It is recommended to use OOP approach when working with a medium-scale or large-scale code bases and the functional approach for small projects* \n\n## Services\n\nWhen working with a large code base, you'll most likely want to divide your code into reusable components called services which can be used for several things with the most likely being to distribute code written in controllers.\n\nHere is what a service looks like:\n\n```ts\nimport { DolphServiceHandler } from '@dolphjs/dolph/classes';\nimport { Dolph } from '@dolphjs/dolph/common';\n\nexport class UserService extends DolphServiceHandler\u003cDolph\u003e {\n\n  constructor() {\n    super('userService');\n  }\n    \n  public readonly newUser = async (userData: userDataDTO) =\u003e {\n      return {newUser};\n  }\n}\n```\n\n## Manually Initializing Database\n\nYou might not want to make use of the `dolph_config.yaml` file to initialize your mongodb or you might want to use another database. Here's how to do that for mongodb and MySQL.\n\n### mongodb \n\ndolphjs also offers easier ways to manually initialize mongodb database without the config file and these are shown below:\n\n***autoInitMongo*** - \n\n```ts\nimport { autoInitMongo } from \"@dolphjs/dolph/packages\";\n\nautoInitMongo({url: \"mongodb://localhost:127017/dolphjs\", options: {}});\n```\n\nThis method is what is ran behind the scene when you configure mongodb in the config file.\n\n***initMongo*** -\n\n```ts\nimport { initMongo } from \"@dolphjs/dolph/packages\";\n\ninitMongo({url, options}).then(res =\u003e {\n    console.log(\"MongoDb Running\")\n}).catch(e=\u003e {\n    console.error(e)\n});\n```\n\nAs you can see, this method requires you to call the `.then` \u0026 `.catch` to handle the promise but the former does this for you by calling this function and handling the promise.\n\n### mysql\n\ndolphjs also offers an easier way to manually initialize mysql database without the config file by using sequelize under the hood.\n\n```ts\nimport { autoInitMysql, initMysql } from \"@dolphjs/dolph/packages\";\n\nconst mysql = initMySql('dolph', 'root', 'password', 'localhost');\n\nautoInitMySql(mysql);\n```\n\nIn case you don't want to use another ORM like prisma then avoid using this function but setup your configuration as you would do in an express application.\n\n## Inject MySQL \u0026 MongoDB model In DolphServiceHandler\n\nIf you are using the dolphjs offered way (which is recommended) in configuring your MySQL or MongoDb database and the OOP approach then dolphjs provides a way for injecting models in your service handlers. Here is an example of a full application flow using using this :\n\n```ts\n// app.model.ts\n\nimport mongoose, { Schema, Document } from 'mongoose';\n\nexport interface IUser extends Document {\n  name: string;\n  email: string;\n  age: string;\n  work: string;\n  height: string;\n}\n\nconst UserSchema = new Schema({\n  name: String,\n  email: String,\n  age: Number,\n  work: String,\n  height: String,\n});\n\nexport const userModel = mongoose.model\u003cIUser\u003e('User', UserSchema);\n\n```\n\n\n\n```ts\n//app.schema.ts\n\nimport { INTEGER, STRING } from 'sequelize';\nimport { mysql } from './sqlDb';\n\nexport const User = mysql.define('user', {\n  id: {\n    type: INTEGER,\n    allowNull: false,\n    primaryKey: true,\n    autoIncrement: true,\n  },\n  username: {\n    type: STRING,\n    allowNull: false,\n  },\n  age: INTEGER,\n});\n```\n\n\n\n```ts\n// sqlDb.ts\n\nimport { initMySql } from '@dolphjs/dolph/packages';\n\nexport const mysql = initMySql('dolph', 'root', 'password', 'localhost');\n\n```\n\n\n\n```ts\n//app.service.ts\n\nimport { InjectMongo, InjectMySQL } from '@dolphjs/dolph/decorators';\nimport { DolphServiceHandler } from '@dolphjs/dolph/classes';\nimport { IUser, userModel } from './app.model';\nimport { Model } from 'mongoose';\nimport { User } from './app.schema';\nimport { ModelStatic, Model as SqlModel } from 'sequelize';\nimport { Dolph } from '@dolphjs/dolph/common';\n\n@InjectMongo('userModel', userModel)\n@InjectMySQL('userMySqlModel', User)\nexport class AppService extends DolphServiceHandler\u003cDolph\u003e {\n  userModel!: Model\u003cIUser\u003e;\n  userMySqlModel!: ModelStatic\u003cSqlModel\u003cany, any\u003e\u003e;\n\n  constructor() {\n    super('appService');\n  }\n\n  createUser = async (body: any) =\u003e {\n    const data = await this.userModel.create(body);\n    return data;\n  };\n\n  createSQLUser = async (body: { username: string; age: string }) =\u003e {\n    return this.userMySqlModel.create(body);\n  };\n}\n```\n\n```ts\n// app.controller.ts\n\nimport { DolphControllerHandler, DolphServiceHandler } from '@dolphjs/dolph/classes';\nimport { TryCatchAsyncDec, DRequest, DResponse } from '@dolphjs/dolph/common';\nimport { AppService } from './app.service';\nimport { BadRequestException, Dolph, SuccessResponse } from '@dolphjs/dolph/common';\nimport { InjectServiceHandler } from '@dolphjs/dolph/decorators';\n\n@InjectServiceHandler([{ serviceHandler: AppService, serviceName: 'appService' }])\nclass ControllerService {\n  appService!: AppService;\n}\n\nconst controllerServices = new ControllerService();\nexport class AppController extends DolphControllerHandler\u003cDolph\u003e {\n  constructor() {\n    super();\n  }\n\n  @TryCatchAsyncDec\n  public async createUser(req: DRequest, res: DResponse) {\n    const { body, file } = req;\n    if (body.height \u003c 1.7) throw new \n    BadRequestException('sorry, you are too short for this \tprogram');\n    const data = await controllerServices.appService.createUser(body);\n    SuccessResponse({ res, body: data });\n  }\n\n  @TryCatchAsyncDec\n  public async createUserMysql(req: DRequest, res: DResponse) {\n    const { username, age } = req.body;\n    const result = await controllerServices.appService.createSQLUser({ username, age });\n    SuccessResponse({ res, body: result });\n  }\n}\n\n```\n\n```ts\n// app.router.ts\n\nimport { DolphRouteHandler } from '@dolphjs/dolph/classes';\nimport { AppController } from './app.controller';\nimport { Dolph } from '@dolphjs/dolph/common';\n\nexport class AppRouter extends DolphRouteHandler\u003cDolph\u003e {\n  constructor() {\n    super();\n    this.initRoutes();\n  }\n\n  public readonly path: string = '/app';\n  controller: AppController = new AppController();\n\n  initRoutes() {\n    this.router.post(`${this.path}/user`, this.controller.createUser);\n    this.router.post(`${this.path}/user-sql`, this.controller.createUserMysql);\n  }\n}\n```\n\n\n\nThis is how a sample basic flow looks like. We'll discuss later on the foreign functions you see in the codes above like: **SuccessResponse**, **BadRequestException**, **InjectServiceHandler** and the rest.\n\n## Decorators\n\nDecorators are used to make things easier when building with typescript. There are a couple of decorators provided by dolphjs for specific use cases which would be discussed in details below:\n\n- TryCatchAsyncDec - this decorator is used to wrap the method with try-catch and handles exceptions. It should be used as a top level decorator which means that if there are more than one decorator attached to a method, it should be the on top of the others. Here is an example:\n\n  ```typescript\n  @TryCatchAsyncDec\n  @JWTAuthVerifyDec('random_secret')\n  @MediaParser({ fieldname: 'upload', type: 'single', extensions: ['.png'] })\n  ```\n\n  there are three decorators abpve but it is placed on top of the three.\n\n  The equivalent of this decorator in the javascript environment is the `TryCatchAsyncFn` which is called as a function which wraps the method as seen below:\n\n  ```typescript\n   register = TryCatchAsyncFn(async (req, res, next) =\u003e {\n      const { username } = req.body;\n      SuccessResponse({ res, body: username });\n    });\n  ```\n\n- TryCatchDec - work like the `TryCatchAsyncDec` but unlike it, this decorator is used for synchronous code, it doesn't handle asynchronous code. The javascript equivalent can be seen below:\n\n  ```javascript\n   register = TryCatchDec((req, res, next) =\u003e {\n      const { username } = req.body;\n      SuccessResponse({ res, body: username });\n    });\n  ```\n\n- JWTAuthVerifyDec -  this decorator handles JWT authorization and sets the payload object to the payload object provided by DRequest. It takes one parameter which is the secret or path to private key depending on the method of authentication used. This is how it works:\n\n  ```typescript\n   @JWTAuthVerifyDec('random_secret')\n   public async createUser(req: DRequest, res: DResponse) {\n     const { body, file } = req;\n     if (body.height \u003c 1.7) throw new BadRequestException('sorry, you are too short for   this program');\n     SuccessResponse({ res, body: { body, payload: req.payload } });\n   }\n  ```\n\n  the `req.payload` holds the payload object that wa enctypted to the JWT secret.\n\n  The javascript equivalent of this is the `JwtAuthMiddleware` function. It would be called as a middleware function on thr route by calling the `Verify` method on the `JwtBasicAuth` class which is passed as a parameter to it. Like this:\n\n  ```javascript\n  router.post(\"/user\", JwtAuthMiddleware(new JwtBasicAuth(\"secret\")), controller);\n  ```\n\n- CookieAuthVerifyDec -  this works like the JwtAuthVerifyDec but it is used when cookies are used for authorization not tokens. In order to use this decorator, the cookie name has to be \"xAuthToken\". It also accepts a parameter of the secret used for the cookie. An example:\n\n  ```typescript\n  @CookieAuthVerifyDec('random_secret')\n  public async createUser(req: DRequest, res: DResponse) {\n    const { body, file } = req;\n    if (body.height \u003c 1.7) throw new BadRequestException('sorry, you are too short for   this program');\n    SuccessResponse({ res, body: { body, payload: req.payload } });\n   }\n  ```\n\n  currently, there is no javascript equivalent for this decorator.\n\n- InjectMySQL -  this is a very important decorator which is used for injecting the MySQL model instance into the service class. Here is an example:\n\n  ```typescript\n  @InjectMySQL('userModel', User)\n  class AppService extends DolphServiceHandler\u003cDolph\u003e {\n    userModel!: ModelStatic\u003cSqlModel\u003cany, any\u003e\u003e;\n  \n    constructor() {\n      super('app');\n    }\n    \n    createUser = async (body: any) =\u003e {\n      const data = await this.userModel.create(body);\n      return data;\n    };\n  }\n  ```\n\n  \n\nIt accepts two parameters: the name of the instance and the mySQL model. Note: the name (firs paremter) should be the exact name used to attribute it's type else dolphjs wouldn't be able to set typings.\n\n- InjectMongo -  works like the `InjectMySQL` decorator but for mogodb databases.\n\n- InjectServiceHandler -  this decorator is used for injecting dolphjs service handlers into a class, it takes a parameter or type `DolphServicemapping` which looks like this: \n\n  ```typescript\n  type DolphServiceMapping\u003cT\u003e = {\n    serviceName: keyof T;\n    serviceHandler: DolphConstructor\u003cT\u003e;\n  };\n  ```\n\n  this is how it is being used:\n\n  ```typescript\n  @InjectServiceHandler([{ serviceHandler: AppService, serviceName: 'appservice' }])\n  class Service {\n    appservice!: AppService;\n  }\n  ```\n\n  \n\nwhere `AppService` is a class which extends `DolphServiceHandler`.\n\n- MediaParser - this is a very useful decorator which is used for processing files, it uses the **multer** library behind the scene to handle file processing. It accepts a parameter of type `IMediaParserOptions`. Here is an example of it's use case:\n\n  ```typescript\n   @TryCatchAsyncDec\n    @JWTAuthVerifyDec('random_secret')\n    @MediaParser({ fieldname: 'upload', type: 'single', extensions: ['.png'] })\n    public async createUser(req: DRequest, res: DResponse) {\n      const { body, file } = req;\n      if (body.height \u003c 1.7) throw new BadRequestException('sorry, you are too short for this program');\n      const data = await controllerServices.appservice.createUser(body);\n      SuccessResponse({ res, body: { data, file: file, payload: req.payload } });\n    }\n  ```\n\n\n\n## Interfaces \u0026 Types\n\nThere are a several interfaces and types which would be needful when writing code with dolphjs.\n\n- DolphConfig - \n\n  ```typescript\n   interface DolphConfig {\n    database?: DolphConfigDbOption;\n    middlewares?: DolphConfigMiddlewares;\n    port?: dolphPort;\n    routing?: DolphConfigRouting;\n    env?: dolphEnv;\n    jsonLimit?: string;\n  }\n  ```\n\n  this is the interface for the `dolph_config` file. Where `jsonLimit` takes the limit for json request in this form: \"5mb\"\n\n- DolphConfigDbOption - \n\n  ```typescript\n   interface DolphConfigDbOption {\n    mongo: MongooseConfig;\n    mysql: MySqlConfig;\n  }\n  ```\n\n- MySqlConfig - \n\n  ```typescript\n  interface MySqlConfig {\n    host: string;\n    database: string;\n    user: string;\n    pass?: string | null;\n  }\n  ```\n\n- DolphConfigMiddleware - \n\n  ```typescript\n  interface DolphConfigMiddlewares {\n    cors?: DolphMiddlewareOption;\n  }\n  ```\n\n- IPayload -\n\n  ```typescript\n  interface IPayload {\n    sub: string | object | Buffer;\n    iat: number;\n    exp: number;\n    info?: string | object | Array\u003cany\u003e;\n  }\n  ```\n\n- IMediaParserOptions -\n\n  ```typescript\n  interface IMediaParserOptions {\n    extensions?: string[];\n    type: mediaType;\n    storage?: multer.DiskStorageOptions;\n    fieldname: string;\n    limit?: number;\n  }\n  ```\n\n- MongooseConfig - \n\n  ```typescript\n  interface MongooseConfig {\n    url: string;\n    options?: mongoose.ConnectOptions;\n  }\n  ```\n\n- DolphMiddlewareOption - \n\n  ```typescript\n  type DolphMiddlewareOption = {\n    activate?: boolean | undefined;\n    origin?: string | undefined;\n    allowedHeaders?: string[] | undefined | null;\n    maxAge?: number | undefined;\n    exposedHeaders?: string[] | null | undefined;\n    credentials?: boolean | undefined;\n    preflightContinue?: boolean | undefined;\n    optionsSuccessStatus: number | undefined;\n  };\n  ```\n\n- DolphServiceMapping - \n\n  ```typescript\n  type DolphServiceMapping\u003cT\u003e = {\n    serviceName: keyof T;\n    serviceHandler: DolphConstructor\u003cT\u003e;\n  };\n  ```\n\n- argonHashParam -\n\n  ```typescript\n  type argonHahsParam = {\n    pureString: string;\n    timeCost?: number;\n    memoryCost?: number;\n    parallelism?: number;\n    type?: 0 | 1 | 2;\n    version?: number;\n    salt?: Buffer;\n    saltLength?: number;\n    raw?: true;\n    secret?: Buffer;\n  };\n  ```\n\n- ResponseType - \n\n  ```typescript\n  type ResponseType\u003cT = any\u003e = {\n    res: DResponse;\n    status?: number;\n    msg?: string;\n    body?: T;\n  };\n  ```\n\n## Logger\n\nDolphjs has a custom built logger which has three levels:\n\n- error - this is used to log an error to the console\n\n- warn - this is used to log a warning to the console\n\n- info - this is used to log an info to the console\n\n- debug - this is used to log a debug message to the console\n\n  ```typescript\n  logger.info();\n  logger.error();\n  logger.warn();\n  logger.debug();\n  ```\n\n## Validation\n\nDolphjs offers out of the box support for request valions.\n\n* Request Validation: dolphjs provides a middleware function which can be used with Joi [https://github.com/joi] to perform request validation. This function is the `reqValidatorMiddleware` function which can be used i this way to check a request param, body or query satisfies the requirements before it passes to the controller:\n\n  ```typescript\n  this.router.post(`${this.path}/user`, reqValidatorMiddleware(createUser), this.controller.createUser);\n  ```\n\n  and to setup the Joi object which is passed as a param to `reqValidatorMiddleware` as seen above, we have:\n\n  ```typescript\n  import Joi from 'joi';\n  \n  const createUser = {\n    body: Joi.object().keys({\n      name: Joi.string().required(),\n      age: Joi.number().required().min(15),\n      work: Joi.string().required(),\n      height: Joi.number().required(),\n    }),\n  };\n  ```\n\n  as we can see, the request validation is checking for the json body that's why body is the key. If it were query then we would have:\n\n  ```typescript\n  import Joi from 'joi';\n  \n  const createUser = {\n    query: Joi.object().keys({\n      name: Joi.string().required(),\n      age: Joi.number().required().min(15),\n      work: Joi.string().required(),\n      height: Joi.number().required(),\n    }),\n  };\n  ```\n\n  and for param:\n\n  ```typescript\n  import Joi from 'joi';\n  \n  const createUser = {\n    param: Joi.object().keys({\n      name: Joi.string().required(),\n      age: Joi.number().required().min(15),\n      work: Joi.string().required(),\n      height: Joi.number().required(),\n    }),\n  };\n  ```\n\n## Exceptions\n\nExceptions are thrown when there is an error. The dolphjs engine handles exceptions in two ways and this depends on the environment. When application is in development environment, dolphjs add the stack to the error sent to the client and logs the stack alongside error messages to the console but when in production environment, dolphjs omits the stack and only send error message, code and any other relevant info needed and logs only the error message to console.\n\nThere are pre-defined exception classes for each major http status code and a general exception for errors.\n\n- **ErrorException** - accepts two parameters: message and status code\n- **BadGatewayException** - accepts only the message and sends a 502 status code\n- **BadRequestException** - accepts only the message and sends a 400 status code\n- **ConflictException** - accepts only the message and sends a 409 status code\n- **ForbiddenException** - accepts only the message and sends a 403 status code\n- **GoneException** - accepts only the message and sends a 410 status code\n- **HttpVersionUnSupportedException** - accepts only the message and sends a 505 status code\n- **ImTeaPotException** - accepts only the message and sends a 418 status code\n- **InternalServerErrorException** - accepts only the message and sends a 500 status code\n- **MethodNotAllowedException** - accepts only the message and sends a 405 status code\n- **MisDirectedException** - accepts only the message and sends a 421 status code\n- **NotAcceptableException** - accepts the message and sends a 406 status code\n- **NotFoundException** - accepts the message and sends a 404 status code\n- **NotImplementedException** - accepts the message and sends a 501 status code\n- **NotModifiedException** - accepts the message and sends a 304 status code\n- **PaymentRequiredException** - accepts the message and sends a 402 status code\n- **ServiceUnavaliableException** -  accepts the message and sends a 503 status code\n- **TimeOutException** -  accepts the message and sends a 504 status code\n- **UnauthorizedException** - accepts the message and sends a 401 status code\n- **UnSupportedMediaException** - accepts the message and sends a 415 status code\n\n## Responses\n\nIn dolphjs, a response is just a function which executes something similar to `res.status().send()`. However, there are two types of responses: the **ErrorResponse** and **SuccessResponse**.\n\n* **ErrorResponse** - takes a parameter of type `ResponseType`\n* **SuccessResponse** - takes a parameter of type `ResponseType`\n\n## Utilities\n\n- **pick** -  the pick util is used for creating objects from choosing fields in another object. \n\n  ```typescript\n  const filter = pick(req.query, ['limit', 'page']);\n  ```\n\n  The code snippet above creates a filter object by pciking the `limit` and `page` fields of the `req.query` object.\n\n- hashWithBcrypt - used for hashing strings (mostly passwords) using bcryptjs. It takes a parameter of `bcryptHashParam`.\n\n  ```typescript\n  const hashedPassword = await hashWithBcrypt({pureString: \"password\", salt: 10});\n  ```\n\n- compareWithBcryptHash - compares a hashed string against a pure string. Accepts a parameter of type `bcryptCompareParam`. It returns a boolean.\n\n  ```typescript\n  const isSame = compareWithBcryptHash({pureString: \"password\", hashString: \"xxxx\"});\n  ```\n\n- hashWithArgon - used for hashing strings (mostly passwords) using argon2. It takes a parameter of type `argonHahsParam`.\n\n- verifyArgonHash -  compares a hashed string against a pure string. Accepts a parameter of type `bcryptCompareParam`. It returns a boolean.\n\n- uniqueFiveDigitsCode - a function which implements the `generateRandomCode` function and returns 5 random digits code. Can be used for otp generation.\n\n- uniqueSixDigitsCode - a function which implements the `generateRandomCode` function and returns 6 random digits code. Can be used for otp generation.\n\n- uniqueSevenDigitsCode - a function which implements the `generateRandomCode` function and returns 7 random digits code. Can be used for otp generation.\n\n- generateJWTwithHMAC - a function that accepts the payload of type `IPayload` and secret of type `string` . It generates and returns a  JWT token using the **HMAC** algorithm.\n\n- verifyJWTwithHMAC - a function that accepts the token of type `string` and secret of type `string` . It verifies a JWT token and returns an error or the payload using the **HMAC** algorithm.\n\n- generateJWTwithRSA -  a function that accepts the  private key path of type **string** and payload of type **IPayload** . It  generates and returns a JWT token using the **RSA** algorithm.\n\n- verifyJWTwithRSA - a function that accepts the public key path of type **string** and token of type **string**. It verifies a JWT token and returns an error or the payload using the **RSA** algorithm.\n\n- toJSON - a function that transforms all mongoose documents a collection. It replaces the **_id** field with **id** and removes the **__v** field when returning to user. Pass it as a plugin to your mongoose schema in order to use:\n\n  ```typescript\n  const userSchema = new Schema({\n    name: String,\n    email: String,\n    age: Number,\n    work: String,\n    height: String,\n  });\n  \n  userSchema.plugin(toJSON)\n  ```\n\n## How To Configure A JWT Payload\n\nIn dolphjs, JWT payloads of type `IPayload` can be generated only by using **moment**. Here is an example:\n\n```typescript\nconst token = generateJWTwithHMAC({\n   payload: {\n     exp: moment().add(30000, 'seconds').unix(),\n     iat: moment().unix(),\n     sub: username,\n   },\n   secret: 'random_secret',\n});\n```\n\n\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdolphjs%2Fdolph","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdolphjs%2Fdolph","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdolphjs%2Fdolph/lists"}