UNPKG

rjweb-server

Version:

Easy and Robust Way to create a Web Server with Many Easy-to-use Features in NodeJS

115 lines (114 loc) 5.04 kB
import { DataContext, EndFn, RealAny } from "../types/internal"; import { UsableMiddleware } from "./Middleware"; import HttpRequestContext from "./request/HttpRequestContext"; import WsOpenContext from "./request/WsOpenContext"; import WsMessageContext from "./request/WsMessageContext"; import WsCloseContext from "./request/WsCloseContext"; import { OperationObject } from "openapi3-ts/oas31"; type Listeners<Data extends Record<string, any>, Context extends Record<string, any>, Middlewares extends UsableMiddleware[] = []> = { httpRequest: ((ctr: DataContext<'HttpRequest', 'POST', HttpRequestContext<Context>, Middlewares>, end: EndFn, data: Data) => RealAny)[]; wsOpen: ((ctr: DataContext<'WsOpen', 'GET', WsOpenContext<'open', Context>, Middlewares>, end: EndFn, data: Data) => RealAny)[]; wsMessage: ((ctr: DataContext<'WsMessage', 'GET', WsMessageContext<Context>, Middlewares>, end: EndFn, data: Data) => RealAny)[]; wsClose: ((ctr: DataContext<'WsClose', 'GET', WsCloseContext<Context>, Middlewares>, end: EndFn, data: Data) => RealAny)[]; }; export default class Validator<Data extends Record<string, any> = {}, Context extends Record<string, any> = {}, Middlewares extends UsableMiddleware[] = []> { private openApi; private openApiFn; private listeners; /** * Create a new Validator * @example * ``` * import { Server, Channel } from "rjweb-server" * import { Runtime } from "@rjweb/runtime-generic" * import { network, number } from "@rjweb/utils" * * const echo = new Channel<string>() * * const server = new Server(Runtime, { * port: 8000 * }) * * const authorize = new server.Validator<{ password: string }>() * .http((ctr, end, data) => { * if (!ctr.headers.has('authorization')) return end(ctr.status(ctr.$status.BAD_REQUEST).print('Authorization Required')) * if (ctr.headers.get('authorization') !== data.password) return end(ctr.status(ctr.$status.UNAUTHORIZED).print('Authorization Required')) * }) * * const authorizeLast = new server.Validator<{ allowedIP: network.IPAddress }>() * .extend(authorize) * .context<{ * random: number * }>() * .http((ctr, end, data) => { * if (!ctr.client.ip.equals(data.allowedIP)) return end(ctr.status(ctr.$status.UNAUTHORIZED).print('Invalid IP')) * * ctr["@"].random = number.generate(0, 100) * }) * * server.path('/', (path) => path * .ws('/echo', (ws) => ws * .validate(authorize.use({ password: '123' })) * .onConnect((ctr) => { * ctr.subscribe(echo) * }) * .onMessage((ctr) => { * echo.send(ctr.rawMessage()) // will send the message to all subscribed sockets * }) * ) * .http('GET', '/last-echo', (http) => http * .validate(authorizeLast.use({ password: '123', allowedIP: new network.IPAddress('127.1') })) * .onRequest((ctr) => { * return ctr.print( * echo.last() + * `\n${ctr["@"].random}` * ) * }) * ) * ) * * server.start().then(() => console.log('Server Started!')) * ``` * @since 9.0.0 */ constructor(); /** * Add OpenAPI Documentation to all Endpoints using this Validator * @since 9.0.0 */ document(item: OperationObject | ((data: Data) => OperationObject)): this; /** * Add context variables to the validator, typescript only * @since 9.0.0 */ context<NewContext extends Record<string, any>>(): Validator<Data, Context & NewContext, Middlewares>; /** * Extend on another validator * @since 9.0.0 */ extend<V extends Validator<any, any, any>, _Data extends [any, any] = V extends Validator<infer Data, infer Context> ? [Data, Context] : [{}, {}]>(validator: V): Validator<Data & _Data[0], Context & _Data[1]>; /** * Add a validation step for an http event * @since 9.0.0 */ httpRequest(handler: Listeners<Data, Context, Middlewares>['httpRequest'][number]): this; /** * Add a validation step for a websocket open event * @since 9.0.0 */ wsOpen(handler: Listeners<Data, Context, Middlewares>['wsOpen'][number]): this; /** * Add a validation step for a websocket message event * @since 9.0.0 */ wsMessage(handler: Listeners<Data, Context, Middlewares>['wsMessage'][number]): this; /** * Add a validation step for a websocket close event * @since 9.0.0 */ wsClose(handler: Listeners<Data, Context, Middlewares>['wsClose'][number]): this; /** * Use the Validator * @since 9.0.0 */ use(data: Data): UsableValidator<Context>; } export type UsableValidator<Context extends Record<string, any> = {}> = { NOTICE: 'DO NOT CALL MANUALLY, THIS IS FOR RJWEB INTERNALLY'; data: Record<string, any>; listeners: Listeners<any, any, any>; context: Context; openApi: OperationObject; }; export {};