Last active
July 27, 2022 06:03
-
-
Save WEEFAA/7dd5c1ffb2f5c54e4a1417cf9fb06aa6 to your computer and use it in GitHub Desktop.
[NextJS] custom controller class
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { NextApiHandler, NextApiRequest, NextApiResponse } from "next" | |
| // checkout NextJS 'NextApiResponse' generic, | |
| // TL;DR | |
| // calling response.send & response.json can be type, NextApiResponse<your_interface_or_type> | |
| interface API_Response { | |
| ok: boolean, | |
| status?: number, | |
| data?: any | |
| } | |
| interface ControllerConstructor { | |
| new (req: NextApiRequest, res: NextApiResponse<API_Response>): IController | |
| } | |
| // instance | |
| interface IController { | |
| req: NextApiRequest, | |
| res: NextApiResponse, | |
| controls: IControlTypes, | |
| exec(): Promise<any>, | |
| setControls(controls: IControlTypes): void | |
| } | |
| // to execute | |
| export type IControlFunction = NextApiHandler<API_Response> | |
| // supported http verbs | |
| type IControlMethods = 'GET' | 'POST' | 'UPDATE' | 'DELETE' | 'PUT' | 'PATCH' | 'OPTIONS' | |
| // available controls | |
| type IControlTypes = { | |
| [methods in IControlMethods]?: IControlFunction; | |
| } | |
| export const Controller: ControllerConstructor = class Controller implements IController { | |
| controls: IControlTypes = {}; | |
| // constructor | |
| constructor(public req: NextApiRequest, public res: NextApiResponse<API_Response>){} | |
| // run single controller, [e.g. GET /api/users ] | |
| async exec() { | |
| try{ | |
| const { method } = this.req | |
| // get the controller according to http verb | method | |
| const control = this.controls[method as IControlMethods] | |
| if(!control){ | |
| // method not supported, end the request | |
| return this.res.status(405).end() | |
| } | |
| // execute the target control | |
| return await control(this.req,this.res) | |
| }catch(e){ | |
| // reject the request | |
| return this.res.status(500).json({ | |
| ok: false, | |
| status: 500, | |
| data: {} | |
| }) | |
| } | |
| } | |
| // set controllers, | |
| // controllers must be set before calling `await this.exec()` | |
| setControls(controls: IControlTypes){ | |
| this.controls = controls | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { Controller, API_Response, IControlFunction } from "./path/to/controller" | |
| import { NextApiRequest, NextApiResponse } from "next" | |
| // these controllers can be at different source file too | |
| const get_handler:IControlFunction = async (req,res) => { | |
| // do some stuff... | |
| res.json({ | |
| ok: true, | |
| data: { message: "@sfx_one" } | |
| }) | |
| } | |
| const post_handler: IControlFunction = async (req,res) => { | |
| // process some stuff... | |
| res.json({ | |
| ok: true, | |
| data: { | |
| subscriber_id: "@sfx_one" | |
| } | |
| }) | |
| } | |
| const api_handler = async (req: NextApiRequest,res: NextApiResponse<API_Response>) => { | |
| const controller = new Controller(req,res) | |
| // must set controls first | |
| controller.setControls({ | |
| GET: get_handler, | |
| POST: post_handler | |
| }) | |
| // do more stuff here... | |
| // call exec | |
| // exec returns a promise, make sure to 'await' it. | |
| await controller.exec() | |
| } | |
| export default api_handler |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment