0.1.10 ⢠Published 3 years ago
nextjs-decorators v0.1.10
a simple and lightweight collection of decorators to create APIs in an elegant way in DI pattern
Prerequisites
- node >=10
Install
npm i nextjs-decorators
Usage
Step 1: Define a controller with @Controller decorator
// pages/api/hello.ts
import { Controller } from 'nextjs-decorators'
@Controller('api/hello') // <--this should match with the route's url generated by Next.js
class MyAwesomeController {
}
Step 2: Defined a route with @{Method} decorator
// pages/api/hello.ts
import { Controller, Get, Post, Param, Body } from 'nextjs-decorators'
@Controller('api/hello')
class MyAwesomeController {
@Get(':id') // <-- this will match with route GET api/hello/{id}
findById(@Param('id')id:string){ // <-- get the param from url
return someDatabaseClient.findById(id) // <-- Promise will be automatically resolved
}
@Post('') // <-- this will match with route POST api/hello
findById(@Body()body: BodyInterface){ // <-- get the body from request
return someDatabaseClient.create(body) // <-- Promise will be automatically resolved
}
}
Step 3: Register the controller
// pages/api/hello
import { Controller, Get, Post, Param, Body, registerController } from 'nextjs-decorators'
@Controller('api/hello')
class MyAwesomeController {
@Get(':id')
findById(@Param('id')id:string){
return someDatabaseClient.findById(id)
}
@Post('')
findById(@Body()body: BodyInterface){
return someDatabaseClient.create(body)
}
}
export default registerController(MyAwesomeController) // <--- all routes will be registered
Dependency Injection(DI)
// page/api/service.ts
export class MyService{
sayHello(){
return { message: "you are awesome" }
}
}
// page/api/hello.ts
import { Get, Controller, AutoInject, registerController } from 'nextjs-decorators'
import { MyService } from './service.ts';
@AutoInject() // <-- automatically inject list of dependencies in constructor
@Controller('/api/hello')
class MyAwesomeController{
constructor(private service: MyService){}
@Get()
getMessage(){
return this.service.sayHello()
}
}
export default registerController(MyAwesomeController)
Middleware
Basic usage
// pages/api/hello.ts
import { UseMiddleware, Controller, Get, registerController } from 'nextjs-decorators'
@UseMiddleware((req, res) => {
/** do something like logic stuffs */
/** Middleware at class level will apply its logic to all route in class */
console.log(`${new Date()} - IP: ${req.ip} URL: ${req.URL}`)
})
@Controller("api/hello")
class MyAwesomeController{
@Get()
@UseMiddleware(()=> {
console.log("route middleware get executed")
})
saySomethingObvious(){
return { message: "you are awesome" }
}
}
export default registerController(MyAwesomeController)
WARNING: return statement in middleware will return immediately to the client, for example
// pages/api/hello.ts
import { UseMiddleware, Controller, Get, registerController } from 'nextjs-decorators'
@Controller("api/hello")
class MyAwesomeController{
@Get()
@UseMiddleware(()=> {
return { message: "return at middleware" } // <-- this is the result which client will receive
})
saySomethingObvious(){
return { message: "you are awesome" } // <-- in fact this will never get executed
}
}
export default registerController(MyAwesomeController)
Guard
Guard is pretty much like Middleware, how ever it accept return type of boolean, if falsy value is returned it will throw an Unauthorize exception, and cannot access the desired route
// pages/api/hello.ts
import { UseGuard, Controller, Get, registerController, Request } from 'nextjs-decorators'
import { NextApiRequest } from 'next'
@UseGuard((req: Request)=> {
const user = database.user.findOne({ id: req.query.id })
req.user = user
return user;// <- throw Unauthorize exception if user not found in database
})
@Controller("api/hello")
class MyAwesomeController{
@Get()
@UseGuard(()=> user.role !== 'admin' /** access the user from the request we've set above */)
adminRoute(){
return { message: "Hi admin" }
}
}
export default registerController(MyAwesomeController)
Author
š¤ tienpvse(Phan Van Tien)
- Twitter: @Tin38662979
- Github: @tienpvse1
- LinkedIn: @tienpvse
Show your support
Give a āļø if this project helped you!