UNPKG

ufiber

Version:

Next-gen webserver for node-js developer

178 lines (176 loc) 5.14 kB
const require_consts = require('../consts.cjs'); const require_url = require('../utils/url.cjs'); const require_smart = require('./smart.cjs'); const require_index = require('./trie-tree/index.cjs'); const require_index$1 = require('./reg-exp/index.cjs'); const require_compose = require('./compose.cjs'); //#region src/router/index.ts const onNotFound = (ctx) => ctx.status(404).json({ message: `Cannot ${ctx.url} on ${ctx.method}` }); const onError = (err, ctx) => { console.error(err); ctx.text("Internal Server Error", 500); }; const kNotFound = Symbol("notFound"); const kErrorHandler = Symbol("errorHandler"); /** * Lightweight, router built on top of a RegExp/Trie based matcher. * Supports single or multiple route matchers (Trie, RegExp, or both). * like multi-router delegation and single-router optimization. */ var Router = class { routes = []; #basePath = "/"; #path = "/"; router; [kNotFound] = onNotFound; [kErrorHandler] = onError; /** Register a GET route. */ get; /** Register a POST route. */ post; /** Register a PUT route. */ put; /** Register a DELETE route. */ delete; /** Register a PATCH route. */ patch; /** Register a HEAD route. */ head; /** Register an OPTIONS route. */ options; /** Register a route matching any HTTP method. */ all; constructor() { [...require_consts.METHODS, require_consts.METHOD_NAME_ALL_LOWERCASE].forEach((method) => { this[method] = (arg1, ...args) => { const path = typeof arg1 === "string" ? arg1 : this.#path; if (typeof arg1 !== "string") this.#addRoute(method, path, arg1); args.forEach((handler) => this.#addRoute(method, path, handler)); return this; }; }); this.router = new require_smart.SmartRouter({ routers: [new require_index$1.RegExpRouter(), new require_index.TrieRouter()] }); } /** * Register a route for one or more HTTP methods and paths. * * @param method - A single method or an array of methods (e.g. `'get'`, `'post'`). * @param path - A single path or an array of paths. * @param handlers - One or more handlers to attach. * @returns This router instance (for chaining). * * @example * ```ts * router.on(['get', 'post'], ['/user', '/account'], handler); * ``` */ on = (method, path, ...handlers) => { for (const p of [path].flat()) { this.#path = p; for (const m of [method].flat()) handlers.forEach((handler) => this.#addRoute(m.toUpperCase(), this.#path, handler)); } return this; }; /** * Registers middleware handlers. * Works similarly to `app.use()` in Express. * * @param arg1 - Path string or the first handler function. * @param handlers - Additional handler functions. * @returns This router instance. * * @example * ```ts * router.use(authMiddleware); * router.use('/api', apiMiddleware); * ``` */ use = (arg1, ...handlers) => { if (typeof arg1 === "string") this.#path = arg1; else { this.#path = "*"; handlers.unshift(arg1); } handlers.forEach((handler) => this.#addRoute(require_consts.METHOD_NAME_ALL, this.#path, handler)); return this; }; /** * `.onError()` handles an error and returns a customized Response. * * @param {ErrorHandler} handler - request Handler for error * @returns {Hono} changed Hono instance * * @example * ```ts * app.onError((err, c) => { * console.error(`${err}`) * return c.text('Custom Error Message', 500) * }) * ``` */ onError = (handler) => { this[kErrorHandler] = handler; return this; }; /** * `.notFound()` allows you to customize a Not Found Response. * * @param {$404Handler} handler - request handler for not-found * @returns {Hono} changed Hono instance * * @example * ```ts * app.notFound((c) => { * return c.text('Custom 404 Message', 404) * }) * ``` */ notFound = (handler) => { this[kNotFound] = handler; return this; }; /** * `.route()` allows grouping other Fiber instance in routes. * * @param {string} path - base Path * @param {Router} router - other Router instance * @returns {Router} routed Router instance * * @example * ```ts * const app = new Router() * const app2 = new Router() * * app2.get("/user", (c) => c.text("user")) * app.route("/api", app2) // GET /api/user * ``` */ route(path, router) { if (router === this) throw new Error("Cannot mount router onto itself"); const base = require_url.mergePath(this.#basePath, path); router.routes.forEach((r) => { let handler; if (router[kErrorHandler] === onError) handler = r.handler; else handler = async (c, next) => await require_compose.compose([], { onError: router[kErrorHandler] })(c, () => r.handler(c, next)); this.#addRoute(r.method, require_url.mergePath(base, r.path), handler); }); } /** * Internal method that registers a route into the internal matcher. */ #addRoute(method, path, handler) { method = method.toUpperCase(); const r = { path: require_url.mergePath(this.#basePath, path), method, handler, basePath: this.#basePath }; this.router.add(method, path, [handler, r]); this.routes.push(r); } }; //#endregion exports.Router = Router; exports.kErrorHandler = kErrorHandler; exports.kNotFound = kNotFound;