{"id":19691879,"url":"https://github.com/yviscool/egg-pig","last_synced_at":"2025-06-24T21:08:40.303Z","repository":{"id":57220710,"uuid":"129733934","full_name":"yviscool/egg-pig","owner":"yviscool","description":"nestjs in egg.","archived":false,"fork":false,"pushed_at":"2022-03-13T05:06:51.000Z","size":825,"stargazers_count":20,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-01T22:06:49.023Z","etag":null,"topics":["decorators","egg","egg-plugin","guard","interceptor","nest","pipe"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yviscool.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-04-16T11:43:39.000Z","updated_at":"2022-03-13T05:06:54.000Z","dependencies_parsed_at":"2022-08-29T04:01:38.802Z","dependency_job_id":null,"html_url":"https://github.com/yviscool/egg-pig","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/yviscool/egg-pig","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yviscool%2Fegg-pig","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yviscool%2Fegg-pig/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yviscool%2Fegg-pig/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yviscool%2Fegg-pig/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yviscool","download_url":"https://codeload.github.com/yviscool/egg-pig/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yviscool%2Fegg-pig/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261756768,"owners_count":23205159,"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":["decorators","egg","egg-plugin","guard","interceptor","nest","pipe"],"created_at":"2024-11-11T19:11:33.416Z","updated_at":"2025-06-24T21:08:40.265Z","avatar_url":"https://github.com/yviscool.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# egg-pig\nnest.js in egg.\n\n[![NPM version][npm-image]][npm-url]\n[![build status][travis-image]][travis-url]\n[![coverage][coverage-image]][coverage-url]\n\n[npm-image]: https://img.shields.io/npm/v/egg-pig.svg?style=flat-square\n[npm-url]: https://npmjs.org/package/egg-pig\n[travis-image]: https://travis-ci.org/yviscool/egg-pig.svg?branch=master\n[travis-url]: https://travis-ci.org/yviscool/egg-pig\n[coverage-url]: https://codecov.io/gh/yviscool/egg-pig\n[coverage-image]: https://codecov.io/gh/yviscool/egg-pig/branch/master/graph/badge.svg\n\n* [Installation](#installation)\n    - [Config](#Config)\n* [Usage](#usage)\n  + [Controller](#controller)\n  + [Return value](#return-value)\n  + [Param Decorators](#param-decorators)\n  + [Route name](#route-name)\n  + [Restful](#restful)\n  + [Multiple Middleware](#multiple-middleware)\n  + [Render Header](#render-header)\n* [Guard](#guard)\n* [Pipe](#pipe)\n  + [Build-in ValidationPipe](#build-in-balidationpipe)\n* [Interceptor](#interceptor)\n  + [Build-in interceptor](#build-in-interceptor)\n* [Filter](#filter)\n* [Tips](#tips)\n* [Global](#global)\n* [Custom Decorators](#custom-decorators)\n\n## Installation \n\n```bash\n$ npm i egg-pig --save\n```\n\n### Config\n\n```js\n// app/config/plugin.js\neggpig: {\n  enable: true,\n  package: 'egg-pig'\n}\n```\n\n## Usage \n\n### Controller\n\n```js\nimport { IService, EggAppConfig, Application, Context } from 'egg';\nimport { Controller, Get, Post } from 'egg-pig';\n\n@Controller('cats') // =\u003e /cats\nexport class CatsController {\n    \n    constructor(\n        private ctx: Context,\n        private app: Application,\n        private config: EggAppConfig,\n        private service: IService,\n    ) { }\n\n    @Get()  // =\u003e router.get('/cats', index)\n    async index() {\n        this.ctx.body = 'index';\n        // or return 'index'\n    }\n\n    @Get('get')   // =\u003e router.get('/cats/get', foo)\n    async foo() {\n        return 'add'\n        // or this.ctx.body = 'add'; \n    }\n\n    @Post('/add')   // =\u003e router.post('/cats/add', bar)\n    async bar(@Body() body) {\n        return body;\n        // or this.ctx.body = body;\n    }\n\n}\n```\n\nanother way \n\n```js\nimport { BaseContextClass } from 'egg';\nimport { Controller, Get, Post } from 'egg-pig';\n\n@Controller('cats') // =\u003e /cats\nexport class CatsController extends BaseContextClass{\n\n    @Get()\n    async foo() {\n        return await this.service.foo.bar();\n    }\n}\n```\n\n### return value\n\n```js\n@Controller('cats')\nexport class CatsController {\n\n    @Get('/add')  // router.get('/cats/add', foo)\n    async foo() {\n        return 'zjl'; // this.ctx.body = 'zjl;\n    }\n\n    @Get('bar')    // router.get('/cats/foo', bar)\n    async bar() {\n        return await this.service.xxx.yyy(); // this.ctx.body = '';\n    }\n}\n```\nuse return value replace ctx.body;\n\n\n### Param Decorators\n```js\nimport { Context, Request, Response, Param, Query, Body, Session, Headers, Res, Req, UploadedFile, UploadedFiles, UploadedFileStream, UploadedFilesStream } from 'egg-pig';\n\n@Controller('cats')\nexport class CatsController {\n    public async foo(\n        @Request() req,\n        @Response() res,\n        @Req() req, // alias\n        @Res() res,// alias\n        @Param() param,\n        @Query() query,\n        @Body() body,\n        @Session() session,\n        @Headers() headers,\n        @UploadedFile() file,\n        @UploadedFiles() fils,\n        @UploadedFileStream() stream,\n        @UploadedFilesStream() parts\n    ) {\n        // req=  this.ctx.request;\n        // res = this.ctx.response;\n        // param = this.ctx.params;\n        // query = this.ctx.query;\n        // body = this.ctx.request.body;\n        // session = this.ctx.session;\n        // headers = this.ctx.headers;\n        // file = this.ctx.request.files[0]\n        // files = this.ctx.request.files;\n        // stream = await this.ctx.getFileStream();\n        // parts = this.ctx.multipart();\n    }\n}\n```\n\n\n### route name\n\n```js\nimport { Controller, Get, Param } from 'egg-pig';\n\n@Controller('cats')\nexport class CatsController {\n\n    @Get(':id',{ routerName: 'cats'}) // router.get('cats', '/cats/:id', foo)\n    async foo(@Param('id') param) {\n        return param;\n    }\n}\n```\n\n### restful\n\n```js\nimport { Resources, Get } from 'egg-pig';\n\n@Resources('cats')    // =\u003e router.resources(''cats', /cats', CastController)\n// or @Restful('cats')\nexport class CatsController {\n\n    async index() {\n        return 'index';\n    }\n\n    async new() {\n        return 'new';\n    }\n\n    @Get('/add')    //  router.get('/cats/add', add)\n    async add() {\n        return 'add';\n    }\n\n}\n```\nYou can also use `@Restful()` Decorator, the same as Resources;\n\n### multiple-middleware\n\n\n1. use  decorator router options \n\n```ts\n@Controller('/', {middleware: ['homeMiddleware']})   //  this.app.middleware['homeMiddleware']\nexport class Test {\n    \n  @Get('/', {middleware: ['apiMiddleware']})  // this.app.middleware['apiMiddleware']\n  async index() {\n    const ctx = this.ctx;\n    return ctx.home + ctx.api;\n  }\n   \n}\n```\n\n2. use koa-router feature \n\n```js\n// router.ts\nexport default (app:Application) =\u003e {\n\n  const { router } = app;\n\n  router.get('/cats/add', async (_,next) =\u003e {\n    console.log('this is middleware');\n    return next();\n  });\n\n};\n\n\n// cats.ts\n@Controller('cats')\nexport class CatsController {\n\n  @Get('/add')\n  async foo(){\n    this.ctx.body = 'add'; \n  }\n}\n\n```\n\n### render-header\n\n```js\nimport { Render,Controller, Get, Header } from 'egg-pig';\n\n@Controller('home')\nexport class HomeController {\n\n  @Get()   // /home\n  @Render('list.tpl')\n  async foo() {\n    const dataList = {\n      list: [\n        { id: 1, title: 'this is news 1', url: '/news/1' },\n        { id: 2, title: 'this is news 2', url: '/news/2' }\n      ]\n    };\n    return dataList;\n  }\n\n  @Header('ETag','123')\n  @Get('etag')\n  async bar() {\n    ...\n  }\n\n  @Header({\n      'Etag': '1234',\n      'Last-Modified': new Date(),\n  })\n  @Get('other')\n  async baz() {\n      ...\n  }\n}\n```\n\n## use \nyou can see [nest.js](https://docs.nestjs.com/).\n\n### Guard\n\n```js\nimport { Injectable, CanActivate, ExecutionContext, UseGuards } from 'egg-pig';\nimport { Observable } from 'rxjs/Observable';\n\n@Injectable()\nclass XXGuard extends CanActivate{\n  canActivate(context: ExecutionContext)\n  : boolean | Promise\u003cboolean\u003e | Observable\u003cboolean\u003e {\n    return true;\n  }\n}\n\n@UseGuards(XXGuard)\nexport class HomeController {\n  // @UseGuards(XXGuard)\n  public async foo() {\n    // some logic\n  }\n}\n```\n\n\n### Pipe\n```js\nimport { PipeTransform, Injectable, ArgumentMetadata, UsePipes, Param, Query, Body  } from 'egg-pig';\n\n@Injectable()\nclass XXPipe extends PipeTransform{\n  async transform(value: any, metadata: ArgumentMetadata) {\n    return value;\n  }\n}\n\n@UsePipes(XXPipe)\nexport class HomeController {\n  // @UsePipes(XXPipe)\n  async foo(@Param('xx', XXPipe) param; @Body('xx', XXPipe) body, @Query(XXPipe) quey) {\n    // some logic\n  }\n}\n```\n\n#### Build-in ValidationPipe\n\n```js\nimport { ParseIntPipe, ValidationPipe } from 'egg-pig';\nimport { IsInt, IsString, Length } from \"class-validator\";\n\nclass User {\n\n    @IsInt()\n    age: number;\n\n    @Length(2, 10)\n    firstName: string;\n\n    @IsString()\n    lastName: string;\n\n    getName() {\n        return this.firstName + ' ' + this.lastName;\n    }\n\n}\n\n@Controller('pipetest')\nexport class PipetestController {\n\n    @Get('parseint')\n    async foo(@Query('id', ParseIntPipe) id) {\n        return id;\n    }\n\n    @Post('validation')\n    async bar(@Body(new ValidationPipe({ transform: true })) user: User) {\n        return user.getName();\n    }\n\n}\n```\n\nNotice You may find more information about the \n  [class-validator](https://github.com/typestack/class-validator)/\n  [class-transformer](https://github.com/typestack/class-transformer)\n\n\n### Interceptor\n\n```js\nimport { EggInterceptor, UseInterceptors, Interceptor} from 'egg-pig';\nimport { Injectable, EggInterceptor, ExecutionContext, CallHandler } from 'egg-pig';\nimport { Observable } from 'rxjs/Observable';\nimport { tap } from 'rxjs/operators';\n\n@Injectable()\nclass LoggingInterceptor extends EggInterceptor {\n  intercept(\n    context: ExecutionContext,\n    call$: CallHandler,\n  ): Observable\u003cany\u003e {\n    console.log('Before...');\n    const now = Date.now();\n    return call$.handle().pipe(\n      tap(() =\u003e console.log(`After... ${Date.now() - now}ms`)),\n    );\n  }\n}\n\n@UseInterceptors(LoggingInterceptor)\nexport class HomeController {\n\n  //@UseInterceptors(LoggingInterceptor)\n  public async foo() {\n    // some login\n  }\n}\n```\n\n#### Build-in interceptor \n\n```js\nimport { UseInterceptors, ClassSerializerInterceptor } from 'egg-pig';\n\nclass RoleEntity {\n    id: number;\n    name: string;\n    constructor(partial: Partial\u003cRoleEntity\u003e) {\n        Object.assign(this, partial);\n    }\n}\n\nclass UserEntity {\n    id: number;\n    firstName: string;\n    lastName: string;\n\n    @Exclude()\n    password: string;\n\n    @Expose()\n    get fullName() {\n        return `${this.firstName} ${this.lastName}`\n    }\n    @Transform(role =\u003e role.name)\n    role: RoleEntity\n\n    constructor(partial: Partial\u003cUserEntity\u003e) {\n        Object.assign(this, partial);\n    }\n}\n\n\n@Controller('serializer')\n@UseInterceptors(new ClassSerializerInterceptor())\nexport class SerializerController {\n\n    @Get()\n    async foo() {\n        return [new UserEntity({\n            id: 1,\n            firstName: 'jay',\n            lastName: 'chou',\n            password: '123456',\n            role: new RoleEntity({ id: 1, name: 'admin' })\n        }), new UserEntity({\n            id: 2,\n            firstName: 'kamic',\n            lastName: 'xxxla',\n            password: '45678',\n            role: new RoleEntity({ id: 2, name: 'user01' })\n        })]\n    }\n}\n```\n\n### filter \n\n```js\n\nimport { Controller, Get } from 'egg-pig';\n\n\n@Controller('cats')\nexport class CatsController {\n\n  @Get()\n  async foo(){\n    throw new Error('some ..')\n  }  \n}\n```\nWhen the client calls this endpoint,the eggjs will hanlde.\n\n```js\nimport {\n  Controller,\n  Get,\n  HttpException,\n  HttpStatus,\n} from 'egg-pig';\n\n@Controller('cats')\nexport class CatsController {\n  @Get()\n  async foo(){\n     throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);\n  }  \n}\n```\nWhen the client calls this endpoint, the response would look like this:\n```json\n{\n  \"statusCode\": 403,\n  \"message\": \"Forbidden\"\n}\n```\n\nanother way\n\n```js\n  async foo(){\n    throw new HttpException({\n     status: HttpStatus.FORBIDDEN,\n      error: 'This is a custom message',\n    }, 403);\n  }  \n```\n\n```js\nclass ForbiddenException extends HttpException {\n  constructor() {\n    super('Forbidden', HttpStatus.FORBIDDEN);\n  }\n}\n\nasync foo(){\n    throw new ForbiddenException()\n}  \n```\n\n**UseFilters**\n\n```js\nimport { Controller, Get, HttpException, HttpStatus, ExceptionFilter, UseFilters, Catch } from 'egg-pig';\n\n@Catch(HttpException)\nclass HttpExceptionFilter extends ExceptionFilter {\n  catch(exception) {\n    this.ctx.status = HttpStatus.FORBIDDEN;\n    this.ctx.body = {\n      statusCode: exception.getStatus(),\n      timestamp: new Date().toISOString(),\n      path: ctx.req.url\n    }\n  }\n}\n\nclass ForbiddenException extends HttpException {\n  constructor() {\n    super('Forbidden', HttpStatus.FORBIDDEN);\n  }\n}\n\n\n@Controller('cats')\n@UseFilters(HttpExceptionFilter)\nexport class CatsController {\n  @Get()\n  async foo(){\n    throw new ForbiddenException();\n  }  \n}\n```\n\n### tips\nCanActivate, EgggInterceptor, PipeTransform,  ExceptionFilter are all abstract class which extends `egg/BaseContextClass`, it means you can use this on methods . such as \n\n```js \nclass XXPipe extends PipeTransform{\n  async transform(value, metadata){\n    await this.service.foo.bar();\n    console.log(this.config)\n    this.foo(); \n    return value;\n  }\n  foo(){\n    // logic\n  }\n}\n```\n\n### global\n\nglobal prefix/guards/pipes/interceptors/filters\n\n```js\n// config.defalut.js\nexport default (appInfo: EggAppConfig) =\u003e {\n\n  config.globalPrefix = '/api/v1';\n\n  config.globalGuards = [new FooGuard(), FooGuard];\n\n  config.globalPipes = [new FooPipe(), FooPipe];\n\n  config.globalInterceptors = [new FooIn(), FooIn];\n\n  config.globalFilters = [new FooFilter(), FooFilter]\n\n  return config;\n};\n\n```\n\n### Custom Decorators\n\n```js \nimport { BaseContextClass } from 'egg';\nimport { Controller, Get, PipeTransform, Pipe, createParamDecorator } from 'egg-pig';\n\nconst User = createParamDecorator((data, ctx) =\u003e {\n  // data = 'test' =\u003e @User('test')\n  return ctx.user;\n});\n\n@Pipe()\nclass APipe extends PipeTransform {\n  transform(val, metadata) {\n    // val =\u003e ctx.user;\n    val \u0026\u0026 metadata;\n    return val;\n  }\n}\n\n\n@Controller('user')\nexport class HomeController {\n  @Get()\n  public async index(@User('test', APipe) user){\n    return user;\n  }\n}\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyviscool%2Fegg-pig","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyviscool%2Fegg-pig","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyviscool%2Fegg-pig/lists"}