{"id":13799677,"url":"https://github.com/giall/koa-joi-controllers","last_synced_at":"2025-04-12T05:10:05.957Z","repository":{"id":34858263,"uuid":"184929293","full_name":"giall/koa-joi-controllers","owner":"giall","description":"Controller decorators for Koa using koa-joi-router","archived":false,"fork":false,"pushed_at":"2023-01-06T01:50:03.000Z","size":1233,"stargazers_count":7,"open_issues_count":14,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-31T02:01:42.461Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/giall.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-05-04T18:12:41.000Z","updated_at":"2021-10-31T02:07:28.000Z","dependencies_parsed_at":"2023-01-15T09:36:59.596Z","dependency_job_id":null,"html_url":"https://github.com/giall/koa-joi-controllers","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/giall%2Fkoa-joi-controllers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/giall%2Fkoa-joi-controllers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/giall%2Fkoa-joi-controllers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/giall%2Fkoa-joi-controllers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/giall","download_url":"https://codeload.github.com/giall/koa-joi-controllers/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248287287,"owners_count":21078669,"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":[],"created_at":"2024-08-04T00:01:05.039Z","updated_at":"2025-04-12T05:10:05.899Z","avatar_url":"https://github.com/giall.png","language":"TypeScript","funding_links":[],"categories":["仓库"],"sub_categories":["中间件"],"readme":"# koa-joi-controllers\n\nController decorators for [Koa](https://koajs.com/) using [koa-joi-router](https://github.com/koajs/joi-router).\n\n[![npm version](https://img.shields.io/badge/npm-v1.2.3-blue.svg)](https://www.npmjs.com/package/koa-joi-controllers)\n[![Build Status](https://travis-ci.com/giall/koa-joi-controllers.svg?branch=master)](https://travis-ci.com/giall/koa-joi-controllers)\n[![codecov](https://codecov.io/gh/giall/koa-joi-controllers/branch/master/graph/badge.svg)](https://codecov.io/gh/giall/koa-joi-controllers)\n\n## Installation\n```sh\nnpm install koa-joi-controllers\n```\nIf you're using TypeScript, you should also install the type definitions for koa-joi-router:\n```sh\nnpm install --save-dev @types/koa-joi-router\n```\n\n## Usage\nCreate a controller class:\n\n```js\nimport { Get, Controller, KoaController } from 'koa-joi-controllers';\n\n@Controller('/v1')\nexport class MyController extends KoaController {\n  @Get('/hello')\n  async hello(ctx) {\n    ctx.body = 'Hello World';\n  }\n}\n```\n\nCreate a Koa app and configure the routes before running the server:\n```js\nimport Koa from 'koa'; // import * as Koa from 'koa'; for TypeScript projects\nimport { configureRoutes } from 'koa-joi-controllers';\n\nconst app = new Koa();\nconfigureRoutes(app, [\n  new MyController();\n], '/api'); // optional prefix for all routes\napp.listen(3000);\n\n// GET /api/v1/hello -\u003e 'Hello World'\n```\n\n# Overview\n\n- [Defining controllers](#controllers)\n- [HTTP method decorators](#method-decorators)\n- [Request parameters](#request-params)\n- [Request body](#request-body)\n- [Joi validation](#joi-validation)\n- [Named route parameter middleware](#param)\n- [Multiple middleware support](#middleware)\n- [Adding metadata](#metadata)\n- [Adding routes via the router](#router)\n- [Using with JavaScript](#javascript)\n\n\u003ca name=\"controllers\"\u003e\u003c/a\u003e\n## Defining controllers\n\nYou can create as many controllers as you want. Every controller needs to extend the `KoaController` class and have the `@Controller` decorator. The controller decorators accepts a string parameter, which is the prefix of all the routes in the controller class.\n\n```js\n@Controller('/koalas')\nexport class KoalaController extends KoaController {\n  @Get()\n  async all(ctx) {\n    ctx.body = Koala.all();\n  }\n\n  @Get('/:id')\n  async findById(ctx) {\n    ctx.body = Koala.findById(ctx.params.id);\n  }\n}\n```\n\n\u003ca name=\"method-decorators\"\u003e\u003c/a\u003e\n## HTTP method decorators\n\nYou can define a route with a `@Method` decorator, where Method is an Http method. (Get, Post, Put, Delete, Head or Options).\n\nThe method decorator accepts a string parameter which is the path of the route, which defaults to an empty string if omitted. The route path supports [RegExp](https://github.com/pillarjs/path-to-regexp) syntax.\n\nYou can add multiple method decorators as long as the path is the same, otherwise an exception is thrown when configuring the routes.\n\n```js\n@Post() @Put() // allowed\nasync myFunction(ctx) {\n  ctx.body = 'Success';\n}\n\n@Get('/options') @Options('/options') // allowed\nasync myFunction(ctx) {\n  ctx.body = 'Success';\n}\n\n@Delete() @Head('/head') // throws exception\nasync myFunction(ctx) {\n  ctx.body = 'Failure';\n}\n```\n\n\u003ca name=\"request-params\"\u003e\u003c/a\u003e\n## Request parameters\n\nRequest parameters in the route path can be defined by prefixing them with the ':' symbol, and can be accessed in the params field of the context.\n\n```js\n@Get('/users/:userId/koalas/:koalaId')\nasync findById(ctx) {\n  const userId = ctx.params.userId;\n  const koalaId = ctx.params.koalaId;\n  // do something...\n}\n```\n\n\u003ca name=\"request-body\"\u003e\u003c/a\u003e\n## Request body\n\nA request's body can be found in `ctx.request.body`, but the request has to be parsed first. In order for the request body to be parsed, you need to specify what type the incoming data is in by using the `@Json`, `@Form` or `@Multipart` decorators.\n\n```js\n@Post('/koalas')\n@Json()\nasync createKoala(ctx) {\n  const body = ctx.request.body; // incoming JSON data is in ctx.request.body\n  ctx.body = Koala.create(body);\n}\n```\n\nAlternatively, you can use the `@Validate` decorator.\n\n```js\n@Post('/koalas')\n@Validate({\n  type: 'json', // can also be 'form' or 'multipart'\n  failure: 403 // status code if validation fails\n})\nasync createKoala(ctx) {\n  const body = ctx.request.body; // incoming JSON data is in ctx.request.body\n  ctx.body = Koala.create(body);\n}\n```\n\nIf the incoming data does not match the expected type, validation will fail and the response status will be set to 400, or the `failure` value set in the `@Validate` decorator.\n\n\u003ca name=\"joi-validation\"\u003e\u003c/a\u003e\n## Joi validation\n\nThe `@Validate` decorator can enforce [Joi](https://github.com/hapijs/joi) validation on request body parameters. If validation fails, response status is set to 400 and the route handler is never called. If you want to handle the error, you can set the `continueOnError` (default: `false`) field to `true`.\n\n```js\nimport { Post, Validate, Validator } from 'koa-joi-controllers';\n\n@Post('/koalas')\n@Validate({\n  type: 'json',\n  body: {\n    name: Validator.Joi.string().max(40),\n    email: Validator.Joi.string().lowercase().email(),\n    password: Validator.Joi.string().max(40),\n    _csrf: Validator.Joi.string().token()\n  },\n  continueOnError: true // ctx.invalid is set to true if validation fails\n})\nasync createKoala(ctx) {\n  if (!ctx.invalid) {\n    Koala.create(ctx.request.body);\n  } else {\n    console.log('Validation failed!');\n  }\n}\n```\n\n\u003ca name=\"param\"\u003e\u003c/a\u003e\n## Named route parameter middleware\n\nYou can define middleware for named route parameters. This is useful for auto-loading or validation.\n\n```js\n@Param('id')\nasync param(id, ctx, next) {\n  ctx.koala = Koala.findById(id);\n  await next();\n}\n\n@Get('/:id')\nasync findById(ctx) {\n  ctx.body = ctx.koala; // ctx.koala was set by the @Param('id') middleware\n  ctx.status = ctx.koala ? 200 : 404;\n}\n```\n\n\u003ca name=\"middleware\"\u003e\u003c/a\u003e\n## Multiple middleware support\n\nYou can use the `@Pre` and `@Chain` decorators to add additional middleware to a specific route. The `Pre` middleware is called first, followed by the `Chain` middleware (can be multiple).\n\n```js\n@Get('/chain')\n@Pre(async (ctx, next) =\u003e {\n  ctx.body = [0];\n  await next();\n})\n@Chain(async (ctx, next) =\u003e {\n  ctx.body.push(1);\n  await next();\n})\n@Chain(async (ctx, next) =\u003e {\n  ctx.body.push(2);\n  await next();\n}, async (ctx, next) =\u003e {\n  ctx.body.push(3);\n  await next();\n})\nasync chain(ctx) {\n  ctx.body.push(4);}\n\n  // GET /chain -\u003e [0, 1, 2, 3, 4]\n  ```\n\n\u003ca name=\"metadata\"\u003e\u003c/a\u003e\n## Adding metadata\n\nYou can store metadata about a route. This isn't used but is stored along with all other route data.\n\n```js\n@Get('/hello')\n@Meta({\n  info: 'Hello World example',\n  other: {\n    data: 42\n  }\n})\nasync hello(ctx) {\n  ctx.body = 'Hello World';\n}\n```\n\n\u003ca name=\"router\"\u003e\u003c/a\u003e\n## Adding routes via the router\n\nIf you're looking for functionality that is not available with the current decorators, but is possible with [koa-joi-router](https://github.com/koajs/joi-router), you can achieve this by extending the `router()` method in your controller class.\n\n```js\n@Controller()\nexport class MyController extends KoaController {\n\n  router() {\n    let router = super.router(); // returns router with all routes defined with decorators\n\n    // add all your routes here\n    router.route({\n      path: '/hello',\n      method: 'get',\n      handler: async function (ctx) {\n        ctx.body = 'Hello World';\n      }\n    });\n\n    return router; // router must be returned\n  }\n\n}\n```\n\n\u003ca name=\"javascript\"\u003e\u003c/a\u003e\n## Using with JavaScript\n\nIn order to use ES6 imports and decorators in a JavaScript project, some additional configurations need to be made. Install the necessary `babel` dependencies:\n\n```sh\nnpm install --save-dev @babel/core @babel/preset-env @babel/node @babel/plugin-proposal-decorators\n```\n\nCreate a `.babelrc` file in your project root:\n```json\n{\n  \"presets\": [[\"@babel/preset-env\", {\"targets\": {\"node\": true}}]],\n  \"plugins\": [[\"@babel/plugin-proposal-decorators\", {\"legacy\": true}]]\n}\n```\nRun with:\n```sh\nnpx babel-node app.js\n```\n\n# License\n\n[MIT](https://github.com/giall/koa-joi-controllers/blob/master/LICENSE.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgiall%2Fkoa-joi-controllers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgiall%2Fkoa-joi-controllers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgiall%2Fkoa-joi-controllers/lists"}