@ffsm/napi
Version:
Napi - A framework using with Next.js for building APIs.
161 lines (160 loc) • 5.36 kB
JavaScript
import { NapiMethod } from "./enums";
import { ucfirst } from "./helpers";
export class NapiController {
constructor(targer) {
this.targer = targer;
this.routes = new Map();
this.params = new Map();
this.response = new Map();
}
setPrefix(options = "") {
let path = '';
if (typeof options === 'string') {
path = options;
}
else {
path = options.path || '';
}
this.prefix = path;
}
getPrefix() {
return this.prefix;
}
setRoute(method, route) {
this.routes.set(method, route);
return this;
}
getRoutes(method) {
if (method) {
return this.routes.get(method);
}
return this.routes;
}
setParam(method, payload) {
var _a;
const existing = ((_a = this.getParams(method)) !== null && _a !== void 0 ? _a : []).filter((param) => param.index !== payload.index);
this.params.set(method, [...existing, payload]);
return this;
}
getParams(method) {
return this.params.get(method);
}
setResponse(method, payload) {
var _a;
const res = Object.assign({}, (_a = this.response.get(method)) !== null && _a !== void 0 ? _a : {}, payload);
this.response.set(method, res);
return this;
}
getResponse(method) {
return this.response.get(method);
}
hasPrefix() {
return this.prefix !== undefined;
}
getName() {
return this.targer.constructor.name;
}
hasRoutes() {
return !!this.routes.size;
}
getInstance() {
if (!this.instance) {
const target = this.targer;
this.instance = new target();
}
return this.instance;
}
static from(target) {
if (this.decorators.has(target)) {
return this.decorators.get(target);
}
const controller = new NapiController(target);
this.decorators.set(target, controller);
return controller;
}
static createControllerDecorator() {
return (options) => {
return (target) => {
const controller = this.from(target);
controller.setPrefix(options);
return target;
};
};
}
static createMethodDecorator(handler) {
return (options) => {
return (target, propertyKey, descriptor) => {
const controller = NapiController.from(target.constructor);
handler(...[options, {
controller,
target,
propertyKey,
descriptor,
}]);
return descriptor;
};
};
}
static createParamDecorator(handle) {
return (options) => {
return (target, methodKey, index) => {
if (!methodKey) {
return;
}
const controller = NapiController.from(target.constructor);
controller.setParam(String(methodKey), {
handle,
options,
target,
index,
});
return index;
};
};
}
static has(controller) {
return this.decorators.has(controller);
}
static get(controller) {
return this.decorators.get(controller);
}
}
NapiController.decorators = new Map();
export const Controller = NapiController.createControllerDecorator();
export const createMethodDecorator = NapiController.createMethodDecorator;
export const createParamDecorator = NapiController.createParamDecorator;
export const { Get, Post, Put, Patch, Delete, Options, Head } = Object
.values(NapiMethod)
.filter((method) => typeof method === 'string')
.reduce((acc, method) => {
const capitalized = ucfirst(method);
acc[capitalized] = NapiController.createMethodDecorator((data, ctx) => {
const path = (typeof data === 'string' ? data : data === null || data === void 0 ? void 0 : data.path) || "/";
ctx.controller.setRoute(`${method}:${path}`, String(ctx.propertyKey));
});
return acc;
}, {});
const names = ['body', 'query', 'params', 'headers', 'cookies', 'files', 'session', 'res', 'req'];
export const { Body, Query, Params, Headers, Cookies, Files, Session, Res, Req, } = names.reduce((acc, name) => {
const capitalized = ucfirst(name);
acc[capitalized] = NapiController.createParamDecorator((_, ctx) => {
if (name === 'res') {
return ctx.getResponse();
}
if (name === 'req') {
return ctx.getRequest();
}
const router = ctx.getRouter();
return router[name];
});
return acc;
}, {});
export const HttpText = NapiController.createMethodDecorator((statusText, ctx) => {
ctx.controller.setResponse(String(ctx.propertyKey), { statusText });
});
export const HttpStatus = NapiController.createMethodDecorator((status, ctx) => {
ctx.controller.setResponse(String(ctx.propertyKey), { status });
});
export const SetHeaders = NapiController.createMethodDecorator((headers, ctx) => {
ctx.controller.setResponse(String(ctx.propertyKey), { headers });
});