UNPKG

rjweb-server

Version:

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

229 lines (228 loc) 8.3 kB
import { LoadPath, HTTPMethods, RoutedValidation, MiddlewareInitted } from "../../types/internal"; import Static from "../../types/static"; import HTTP from "../../types/http"; import WebSocket from "../../types/webSocket"; import { Content } from "../.."; import RouteWS from "./ws"; import RouteHTTP from "./http"; import RouteDefaultHeaders from "./defaultHeaders"; export default class RoutePath<GlobContext extends Record<any, any>, Middlewares extends MiddlewareInitted[] = [], Path extends string = '/'> { private externals; private validations; private headers; private parsedHeaders; private loadPaths; private statics; private routes; private webSockets; private httpPath; private hasCalledGet; /** Generate Route Block */ constructor( /** The Path of the Routes */ path: Path, /** The Validations to add */ validations?: RoutedValidation[], /** The Headers to add */ headers?: Record<string, Content>, /** The Contexts to add */ contexts?: HTTP['context']); /** * Add a Validation * @example * ``` * // The /api route will automatically check for correct credentials * // Obviously still putting the prefix (in this case / from the RoutePath in front) * const controller = new Server({ }) * * controller.path('/api', (path) => path * .validate(async(ctr, end) => { * if (!ctr.headers.has('Authorization')) return end(ctr.status(401).print('Unauthorized')) * if (ctr.headers.get('Authorization') !== 'key123 or db request ig') return end(ctr.status(401).print('Unauthorized')) * }) * .redirect('/pics', 'https://google.com/search?q=devil') * ) * ``` * @since 3.2.1 */ validate<Context extends Record<any, any> = {}, Body = unknown>( /** The Function to Validate the Request */ code: RoutedValidation<GlobContext & Context, Body, Middlewares, Path>): this; /** * Add a HTTP Route * @example * ``` * controller.path('/', (path) => path * .http('GET', '/hello', (ws) => ws * .onRequest(async(ctr) => { * ctr.print('Hello bro!') * }) * ) * ) * ``` * @since 6.0.0 */ http<Context extends Record<any, any> = {}, Body = unknown, LPath extends string = '/'>( /** The Request Method */ method: HTTPMethods, /** The Path on which this will be available */ path: LPath | RegExp, /** The Callback to handle the Endpoint */ callback: (path: RouteHTTP<GlobContext, Context, Body, Middlewares, `${Path}/${LPath}`>) => RouteHTTP<GlobContext, Context, Body, Middlewares, `${Path}/${LPath}`>): this; /** * Add a Websocket Route * @example * ``` * controller.path('/', (path) => path * .ws('/uptime', (ws) => ws * .onConnect(async(ctr) => { * console.log('Connected to ws!') * }) * .onMessage((ctr) => { * console.log('Received message', ctr.message) * }) * .onClose((ctr) => { * console.log('Disconnected from ws!') * }) * ) * ) * ``` * @since 5.4.0 */ ws<Context extends Record<any, any> = {}, Message = unknown, LPath extends string = '/'>( /** The Path on which this will be available */ path: LPath | RegExp, /** The Callback to handle the Endpoint */ callback: (path: RouteWS<GlobContext, Context, Message, Middlewares, `${Path}/${LPath}`>) => RouteWS<GlobContext, Context, Message, Middlewares, `${Path}/${LPath}`>): this; /** * Add Default Headers * @example * ``` * controller.path('/', (path) => path * .defaultHeaders((dH) => dH * .add('X-Api-Version', '1.0.0') * ) * ) * ``` * @since 6.0.0 */ defaultHeaders( /** The Callback to handle the Headers */ callback: (path: RouteDefaultHeaders) => RouteDefaultHeaders): this; /** * Add a Redirect * @example * ``` * // The /devil route will automatically redirect to google.com * // Obviously still putting the prefix (in this case / from the RoutePath in front) * const controller = new Server({ }) * * controller.path('/', (path) => path * .redirect('/devil', 'https://google.com') * .redirect('/devilpics', 'https://google.com/search?q=devil') * ) * ``` * @since 3.1.0 */ redirect( /** The Request Path to Trigger the Redirect on */ request: string, /** The Redirect Path to Redirect to */ redirect: string): this; /** * Serve Static Files * @example * ``` * // All Files in "./static" will be served dynamically so they wont be loaded as routes by default * // Due to the hideHTML Option being on files will be served differently, /index.html -> /; /about.html -> /about; /contributors/index.html -> /contributors * const controller = new Server({ }) * * controller.path('/', (path) => path * .static('./static', { * hideHTML: true, // If enabled will remove .html ending from files * addTypes: true, // If enabled will automatically add content-types to some file endings (including the custom ones defined in the main config) * }) * ) * ``` * @since 3.1.0 */ static( /** The Folder which will be used */ folder: string, /** Additional Configuration for Serving */ options?: { /** * Whether to automatically add Content-Type to some file endings * @default true * @since 3.1.0 */ addTypes?: boolean; /** * Whether to compress files when sending * @default true * @since 7.10.0 */ compress?: boolean; /** * Whether to automatically remove .html ending from files * @default false * @since 3.1.0 */ hideHTML?: boolean; }): this; /** * Load CJS Route Files * @example * ``` * // All Files in "./routes" ending with .js will be loaded as routes * const controller = new Server({ }) * * controller.path('/', (path) => path * .loadCJS('./routes') * ) * ``` * @since 3.1.0 */ loadCJS( /** The Folder which will be used */ folder: string, /** The Options */ options?: { /** * Whether to enable file based routing, works similarly to static file hideHTML * @default false * @since 7.5.0 */ fileBasedRouting?: boolean; }): this; /** * Load ESM Route Files * @example * ``` * // All Files in "./routes" ending with .js will be loaded as routes * const controller = new Server({ }) * * controller.path('/', (path) => path * .loadESM('./routes') * ) * ``` * @since 4.0.0 */ loadESM( /** The Folder which will be used */ folder: string, /** The Options */ options?: { /** * Whether to enable file based routing, works similarly to static file hideHTML * @default false * @since 7.5.0 */ fileBasedRouting?: boolean; }): this; /** * Add a new Block of Routes with a Prefix * @example * ``` * const controller = new Server({ }) * * controller.path('/', (path) => path * .http('GET', '/cool', (http) => http * .onRequest((ctr) => { * ctr.print('cool!') * }) * ) * .path('/api', (path) => path * .context({ * version: '1.0.0' * }) * .http('GET', '/', (http) => http * .onRequest((ctr) => { * ctr.print(`Welcome to the API!, Version ${ctr["@"].version}`) * }) * ) * ) * ) * ``` * @since 5.0.0 */ path<LPath extends string = `/${string}`>( /** The Path Prefix */ prefix: LPath, /** The Callback to handle the Prefix */ router: ((path: RoutePath<GlobContext, Middlewares, `${Path}/${LPath}`>) => RoutePath<GlobContext, Middlewares, `${Path}/${LPath}`>) | RoutePath<any, any>): this; /** * Internal Method for Generating Routes Object * @since 6.0.0 */ getData(): Promise<{ routes: HTTP[]; webSockets: WebSocket[]; statics: Static[]; loadPaths: LoadPath[]; }>; }