rjweb-server
Version:
Easy and Robust Way to create a Web Server with Many Easy-to-use Features in NodeJS
175 lines (174 loc) • 6.65 kB
TypeScript
import Route from "../Route";
import { Method } from "../../types/global";
import Http from "./Http";
import { UsableMiddleware } from "../Middleware";
import { UsableValidator } from "../Validator";
import { RateLimitConfig } from "../../types/internal";
import RateLimit from "./RateLimit";
import GlobalContext from "../../types/internal/classes/GlobalContext";
import { ArrayOrNot } from "@rjweb/utils";
import Ws from "./Ws";
import { OperationObject } from "openapi3-ts/oas31";
export default class Path<Middlewares extends UsableMiddleware[], Validators extends UsableValidator[] = [], Context extends Record<string, any> = {}, Excluded extends (keyof Path<Middlewares>)[] = []> {
private validators;
protected routesHttp: Route<'http'>[];
protected routesStatic: Route<'static'>[];
protected routesWS: Route<'ws'>[];
protected _httpRatelimit: RateLimitConfig;
protected _wsRatelimit: RateLimitConfig;
protected promises: Promise<any>[];
protected openApi: OperationObject;
private _global;
private prefix;
private computePath;
/**
* Create a new Path
* @since 6.0.0
*/ constructor(prefix: string, global: GlobalContext, validators?: Validators, ratelimits?: [RateLimitConfig, RateLimitConfig], promises?: Promise<any>[], openApi?: OperationObject);
/**
* Add OpenAPI Documentation to all HTTP Endpoints in this Path (and all children)
* @since 9.0.0
*/ document(item: OperationObject): Omit<Path<Middlewares, Validators, Context, [...Excluded, 'document']>, Excluded[number] | 'document'>;
/**
* Add a Ratelimit to all HTTP Endpoints in this Path (and all children)
*
* When a User requests an Endpoint, that will count against their hit count, if
* the hits exceeds the `<maxHits>` in `<timeWindow>ms`, they wont be able to access
* the route for `<penalty>ms`.
* @example
* ```
* import { time } from "@rjweb/utils"
*
* server.path('/', (path) => path
* .httpRateLimit((limit) => limit
* .hits(5)
* .window(time(20).s())
* .penalty(0)
* ) // This will allow 5 requests every 20 seconds
* .http('GET', '/hello', (ws) => ws
* .onRequest(async(ctr) => {
* ctr.print('Hello bro!')
* })
* )
* )
*
* server.rateLimit('httpRequest', (ctr) => {
* ctr.print(`Please wait ${ctr.getRateLimit()?.resetIn}ms!!!!!`)
* })
* ```
* @since 8.6.0
*/ httpRatelimit(callback: (limit: RateLimit) => any): Omit<Path<Middlewares, Validators, Context, Excluded>, Excluded[number] | 'httpRatelimit'>;
/**
* Add a Ratelimit to all WebSocket Endpoints in this Path (and all children)
*
* When a User sends a message to a Socket, that will count against their hit count, if
* the hits exceeds the `<maxHits>` in `<timeWindow>ms`, they wont be able to access
* the route for `<penalty>ms`.
* @example
* ```
* import { time } from "@rjweb/utils"
*
* server.path('/', (path) => path
* .httpRateLimit((limit) => limit
* .hits(5)
* .window(time(20).s())
* .penalty(0)
* ) // This will allow 5 messages every 20 seconds
* .ws('/echo', (ws) => ws
* .onMessage(async(ctr) => {
* ctr.print(await ctr.rawMessageBytes())
* })
* )
* )
*
* server.rateLimit('wsMessage', (ctr) => {
* ctr.print(`Please wait ${ctr.getRateLimit()?.resetIn}ms!!!!!`)
* })
* ```
* @since 8.6.0
*/ wsRatelimit(callback: (limit: RateLimit) => any): Omit<Path<Middlewares, Validators, Context, Excluded>, Excluded[number] | 'wsRatelimit'>;
/**
* Create a redirection route
* @example
* ```
* const server = new Server(...)
*
* server.path('/', (path) => path
* .redirect('/google', 'https://google.com')
* )
* ```
* @since 3.10.0
*/ redirect(path: ArrayOrNot<string | RegExp>, redirect: string, type?: 'temporary' | 'permanent'): this;
/**
* Create a subpath of this Path
* @since 6.0.0
*/ path(prefix: string, callback: (path: Path<Middlewares, Validators, Context>) => any): this;
/**
* Use a Validator on all Endpoints in this Path
*
* This will attach a Validator to all Endpoints in this Path
* @since 9.0.0
*/ validate<_Validator extends UsableValidator<any>>(validator: _Validator): Path<Middlewares, [...Validators, _Validator], Context, Excluded>;
/**
* Serve Static Files
* @example
* ```
* // All Files in "./public" will be served dynamically so they wont be loaded as routes by default
* // Due to the stripHtmlEnding Option being on files will be served differently, /index.html -> /; /about.html -> /about; /contributors/index.html -> /contributors
* const server = new Server(...)
*
* server.path('/', (path) => path
* .static('./public', {
* stripHtmlEnding: true // If enabled will remove .html ending from files
* })
* )
* ```
* @since 3.1.0
*/ static(folder: string, options?: {
/**
* Whether to automatically remove .html ending from files
* @default false
* @since 9.0.0
*/ stripHtmlEnding?: boolean;
/**
* Whether to pre-process the files before serving them,
* this will force you to restart the server every time
* you add or remove a file.
* @warning THIS WILL RECURSIVELY WALK THROUGH ALL FILES IN THE FOLDER, USE WITH CAUTION
* @default false
* @since 9.0.0
*/ preProcessFiles?: boolean;
}): this;
/**
* Add a new HTTP Route
* @example
* ```
* const server = new Server(...)
*
* server.path('/', (path) => path
* .http('GET', '/hello', (ws) => ws
* .onRequest((ctr) => {
* ctr.print('Hello!')
* })
* )
* )
* ```
* @since 6.0.0
*/ http<_Method extends Method>(method: _Method, path: ArrayOrNot<string | RegExp>, callback: (http: Http<_Method, Middlewares, Validators, Context>) => any): this;
/**
* Add a new WebSocket Route
* @example
* ```
* const server = new Server(...)
*
* server.path('/', (path) => path
* .ws('/echo', (ws) => ws
* .onMessage((ctr) => {
* ctr.print(ctr.rawMessageBytes())
* })
* )
* )
* ```
* @since 6.0.0
*/ ws(path: ArrayOrNot<string | RegExp>, callback: (ws: Ws<Middlewares, Validators, Context>) => any): this;
}