mirror of
https://github.com/KwiTsukasa/kt-template-online-api.git
synced 2026-05-27 15:44:54 +08:00
86 lines
2.2 KiB
TypeScript
86 lines
2.2 KiB
TypeScript
import { RequestMethod, Type } from '@nestjs/common';
|
|
import { METHOD_METADATA, PATH_METADATA } from '@nestjs/common/constants';
|
|
|
|
export interface ControllerRoute {
|
|
controllerName: string;
|
|
handlerName: string;
|
|
method: string;
|
|
path: string;
|
|
}
|
|
|
|
const requestMethodMap: Partial<Record<RequestMethod, string>> = {
|
|
[RequestMethod.GET]: 'GET',
|
|
[RequestMethod.POST]: 'POST',
|
|
[RequestMethod.PUT]: 'PUT',
|
|
[RequestMethod.DELETE]: 'DELETE',
|
|
[RequestMethod.PATCH]: 'PATCH',
|
|
};
|
|
|
|
const toPaths = (path?: string | string[]): string[] => {
|
|
if (path === undefined) {
|
|
return [''];
|
|
}
|
|
|
|
return Array.isArray(path) ? path : [path];
|
|
};
|
|
|
|
const normalizePath = (...segments: string[]) => {
|
|
const path = segments
|
|
.map((segment) => `${segment}`.replace(/^\/+|\/+$/g, ''))
|
|
.filter(Boolean)
|
|
.join('/');
|
|
|
|
return path ? `/${path}` : '/';
|
|
};
|
|
|
|
export const collectControllerRoutes = (
|
|
controllers: Type<unknown>[],
|
|
): ControllerRoute[] => {
|
|
return controllers
|
|
.flatMap((ControllerClass) => {
|
|
const controllerPaths = toPaths(
|
|
Reflect.getMetadata(PATH_METADATA, ControllerClass),
|
|
);
|
|
const prototype = ControllerClass.prototype;
|
|
|
|
return Object.getOwnPropertyNames(prototype).flatMap((handlerName) => {
|
|
if (handlerName === 'constructor') {
|
|
return [];
|
|
}
|
|
|
|
const handler = prototype[handlerName];
|
|
const requestMethod: RequestMethod | undefined = Reflect.getMetadata(
|
|
METHOD_METADATA,
|
|
handler,
|
|
);
|
|
|
|
if (requestMethod === undefined) {
|
|
return [];
|
|
}
|
|
|
|
const method = requestMethodMap[requestMethod];
|
|
|
|
if (!method) {
|
|
return [];
|
|
}
|
|
|
|
const routePaths = toPaths(Reflect.getMetadata(PATH_METADATA, handler));
|
|
|
|
return controllerPaths.flatMap((controllerPath) =>
|
|
routePaths.map((routePath) => ({
|
|
controllerName: ControllerClass.name,
|
|
handlerName,
|
|
method,
|
|
path: normalizePath(controllerPath, routePath),
|
|
})),
|
|
);
|
|
});
|
|
})
|
|
.sort((a, b) => routeKey(a).localeCompare(routeKey(b)));
|
|
};
|
|
|
|
export const routeKey = ({
|
|
method,
|
|
path,
|
|
}: Pick<ControllerRoute, 'method' | 'path'>) => `${method} ${path}`;
|