server router prefix

This commit is contained in:
Sergey Yarkov 2026-03-10 14:58:46 +03:00
parent 57e62272e9
commit 611a42a249
6 changed files with 58 additions and 19 deletions

View File

@ -51,7 +51,10 @@ export function createServer(options) {
return {
listen(port = 3000, cb) {
server.listen(port, cb);
return { router };
},
router: {
prefix: router.prefix,
define: router.define
}
};
}

View File

@ -1,18 +1,23 @@
import { serializeError } from "serialize-error";
import formidable from "formidable";
import { BadRequestError, HttpError, MethodNotAllowedError, NotFoundError } from "./errors.js";
import * as utils from "./utils/index.js";
/**
* @returns {import("./types/http-server.js").HttpRouter}
*/
export function createRouter() {
/** @type {import("./types/http-server.js").HttpRoute[]} */
const routes = [];
let prefixNameGroup = "";
return {
routes: [],
async handle(ctx) {
const { req, res } = ctx;
try {
for (const route of this.routes) {
for (const route of routes) {
const patternResult = route.pattern.exec(req.url.pathname);
if (!patternResult) continue;
@ -69,9 +74,18 @@ export function createRouter() {
);
}
},
prefix(name, cb) {
const prevPrefix = prefixNameGroup;
prefixNameGroup += name;
cb(this);
prefixNameGroup = prevPrefix;
},
define(method, pathname, handler, options = {}) {
if (!utils.matchRoutePathname(pathname)) throw new Error(`Incorrect pathname "${pathname}"`);
if (prefixNameGroup) pathname = utils.formatRoutePathname(prefixNameGroup + pathname);
/** @type {import("./types/http-server.js").HttpRoute} */
this.routes.push({ method, pattern: new URLPattern({ pathname }), handler, options });
routes.push({ method, pattern: new URLPattern({ pathname }), handler, options });
console.log("defined:", pathname);
}
};
}

View File

@ -3,7 +3,8 @@ import type IncomingForm from "formidable/Formidable.js";
import formidable from "formidable";
export interface HttpServer {
listen: (port: number, cb: () => void) => { router: HttpRouter };
listen: (port: number, cb: () => void) => void;
router: Pick<HttpRouter, "prefix" | "define">;
}
export interface HttpServerOptions {
@ -26,9 +27,10 @@ export interface HttpRoute {
handler: HttpRouteHandler;
options: HttpRouteOptions;
}
export interface HttpRouter {
routes: Array<HttpRoute>;
handle: (ctx: HttpContext) => Promise<void>;
prefix: (name: string, cb: (router: HttpRouter) => void) => void;
define: (
method: HttpMethod,
pathname: string,

View File

@ -0,0 +1 @@
export * from "./string.js";

View File

@ -0,0 +1,14 @@
/**
* @param {string} pathname
*/
export function matchRoutePathname(pathname) {
return pathname.match(/(^\/[^/].*$|^\/$)/g);
}
/**
* @param {string} pathname
*/
export function formatRoutePathname(pathname) {
if (pathname[0] !== "/") pathname = "/" + pathname;
return pathname.replaceAll(/\/{2,}/g, "/");
}

View File

@ -17,15 +17,17 @@ const cors = {
headers: "Content-Type,Accept"
};
const server = createServer({ cors }).listen(SERVER_PORT, async () => {
const server = createServer({ cors });
server.listen(SERVER_PORT, async () => {
console.log(`Service ${packageJson.name} is running at port ${SERVER_PORT}.`);
await fsp.mkdir(path.join(process.cwd(), "/uploads"), { recursive: true });
await db.connect().then(() => console.log("Database connected!"));
});
server.router.define("GET", "/", ({ res }) => res.sendText("Сервис инструментов таблицы АСУ."));
server.router.define("GET", "/api/reports_status_parse", reportsHandlers.statusParseHandler);
server.router.define("POST", "/api/reports_excel_file_parse", reportsHandlers.parseExcelHandler, {
server.router.prefix("/api", (router) => {
router.define("GET", "/reports_status_parse", reportsHandlers.statusParseHandler);
router.define("POST", "/reports_excel_file_parse", reportsHandlers.parseExcelHandler, {
incomingForm: {
maxFields: 1,
maxFiles: 1,
@ -34,5 +36,8 @@ server.router.define("POST", "/api/reports_excel_file_parse", reportsHandlers.pa
uploadDir: path.join(process.cwd(), "./uploads"),
filter: ({ mimetype }) => !!mimetype && mimetype.includes("application/vnd.ms-excel")
}
});
router.define("POST", "/reports_sync", reportsHandlers.syncParsedHandler);
});
server.router.define("POST", "/api/reports_sync", reportsHandlers.syncParsedHandler);
server.router.define("GET", "/", ({ res }) => res.sendText("Сервис инструментов таблицы АСУ."));