tezx
Version:
TezX is a modern, ultra-lightweight, and high-performance JavaScript framework built specifically for Bun. It provides a minimal yet powerful API, seamless environment management, and a high-concurrency HTTP engine for building fast, scalable web applicat
196 lines (195 loc) • 6.83 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Router = void 0;
const url_js_1 = require("../utils/url.js");
class Router {
router;
routes = [];
staticFile = Object.create(null);
basePath;
constructor({ basePath = "/" } = {}) {
this.basePath = basePath;
this.get = this.get.bind(this);
this.post = this.post.bind(this);
this.put = this.put.bind(this);
this.delete = this.delete.bind(this);
this.all = this.all.bind(this);
this.addRouter = this.addRouter.bind(this);
this.group = this.group.bind(this);
}
static(serveStatic) {
if (Array.isArray(serveStatic?.files)) {
const strong = serveStatic?.options?.strongEtag ?? true;
const disabled = serveStatic?.options?.disableEtag;
if (disabled) {
serveStatic?.files.forEach((s) => {
this.staticFile[`GET ${s?.route}`] = async (ctx) => {
if (serveStatic?.options?.cacheControl) {
ctx.setHeader("Cache-Control", serveStatic?.options.cacheControl);
}
return ctx.sendFile(s.fileSource, {
headers: serveStatic?.options?.headers,
});
};
});
}
else {
serveStatic?.files.forEach((s) => {
this.staticFile[`GET ${s?.route}`] = async (ctx) => {
if (serveStatic?.options?.cacheControl) {
ctx.setHeader("Cache-Control", serveStatic?.options.cacheControl);
}
const stat = await Bun.file(s?.fileSource).stat();
const raw = `${stat.size}-${Math.floor(stat.mtimeMs ?? Date.now())}`;
let etagVal = strong ? `"${raw}"` : `W/"${raw}"`;
ctx.headers.set("Etag", etagVal);
const ifNoneMatch = ctx.req.header("if-none-match");
if (ifNoneMatch === etagVal) {
return new Response(null, {
status: 304,
headers: { "ETag": etagVal },
});
}
return ctx.sendFile(s.fileSource, {
headers: serveStatic?.options?.headers,
});
};
});
}
}
return this;
}
get(path, ...args) {
this.#registerRoute("GET", path, ...args);
return this;
}
post(path, ...args) {
this.#registerRoute("POST", path, ...args);
return this;
}
put(path, ...args) {
this.#registerRoute("PUT", path, ...args);
return this;
}
patch(path, ...args) {
this.#registerRoute("PATCH", path, ...args);
return this;
}
delete(path, ...args) {
this.#registerRoute("DELETE", path, ...args);
return this;
}
options(path, ...args) {
this.#registerRoute("OPTIONS", path, ...args);
return this;
}
all(path, ...args) {
this.#registerRoute("ALL", path, ...args);
return this;
}
when(methods, path, ...args) {
const methodList = Array.isArray(methods) ? methods : [methods];
for (const method of methodList) {
this.#registerRoute(method.toUpperCase(), path, ...args);
}
return this;
}
addRouter(path, router) {
return this.#addRouterInstance(path, router);
}
group(prefix, callback) {
const router = new Router({
basePath: prefix,
});
callback(router);
this.#addRouterInstance("/", router);
return this;
}
use(...args) {
let path = "/";
let middlewares = [];
let router;
if (typeof args[0] === "string") {
path = args[0];
if (Array.isArray(args[1])) {
middlewares = args[1];
router = args[2];
}
else if (typeof args[1] === "function") {
middlewares = [args[1]];
router = args[2];
}
else {
router = args[1];
}
}
else if (typeof args[0] === "function") {
if (args.length === 1) {
middlewares = [args[0]];
}
else {
middlewares = [args[0]];
router = args[1];
}
}
else if (Array.isArray(args[0])) {
middlewares = args[0];
router = args[1];
}
else if (args[0] instanceof Router) {
router = args[0];
}
if (middlewares?.length) {
this.#addRoute("ALL", path, middlewares);
}
if (router && router instanceof Router) {
this.addRouter(path, router);
}
return this;
}
#addRoute(method, path, handlers) {
let pattern = `/${(0, url_js_1.sanitizePathSplitBasePath)(this.basePath, path).join("/")}`;
this.router?.addRoute?.(method, pattern, handlers);
this.routes.push({
method: method,
pattern: pattern,
handlers: handlers,
});
}
#registerRoute(method, path, ...args) {
if (args.length === 0) {
throw new Error("At least one handler is required.");
}
let middlewares = [];
let callback;
if (args.length > 1) {
if (Array.isArray(args[0])) {
middlewares = args[0];
}
else if (typeof args[0] === "function") {
middlewares = [args[0]];
}
callback = args[args.length - 1];
}
else {
callback = args[0];
}
if (typeof callback !== "function") {
throw new Error("Route callback function is missing or invalid.");
}
if (!middlewares.every((middleware) => typeof middleware === "function")) {
throw new Error("Middleware must be a function or an array of functions.");
}
this.#addRoute(method, path, [...middlewares, callback]);
}
#addRouterInstance(path, router) {
if (!(router instanceof Router)) {
throw new Error("Router instance is required.");
}
router.routes.forEach((r) => {
this.#addRoute(r?.method, `/${(0, url_js_1.sanitizePathSplitBasePath)(path, r?.pattern).join("/")}`, r?.handlers);
});
Object.assign(this.staticFile, router.staticFile);
}
}
exports.Router = Router;