-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathOpenApiRouterResolver.ts
70 lines (64 loc) · 2.87 KB
/
OpenApiRouterResolver.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import { Request, RequestHandler } from 'express';
import { ApiControllerFactory } from './ApiControllerFactory';
import { ServerUtils } from './ServerUtils';
/**
* Information provided by the open api validator when resolving the router.
*/
export interface OpenApiRoute {
basePath: string;
expressRoute: string;
openApiRoute: string;
method: string;
pathParams: unknown[];
}
/**
*
* It handles the Rosetta specific requests delegating the request to the right api controller method.
*/
export class OpenApiRouterResolver {
constructor(private readonly apiControllerFactory: ApiControllerFactory) {}
public static camelize(str: string): string {
return str
.trim()
.replace(/^\w|[A-Z]|\b\w/g, function (word, index) {
return index === 0 ? word.toLowerCase() : word.toUpperCase();
})
.replace(/\s+/g, '');
}
public resolver(route: OpenApiRoute): RequestHandler {
const { serviceMethodName, serviceClassName, method } = this.resolveServiceMethod(route.openApiRoute);
return ServerUtils.asyncMiddleware(async (req) => {
const response = await method(req);
if (!response) {
throw new Error(`Response is required. Have you implemented ${serviceClassName}.${serviceMethodName}()?`);
}
return response;
});
}
public resolveServiceMethod(openApiRoute: string): {
serviceMethodName: string;
serviceClassName: string;
method: (req: Request) => Promise<unknown>;
} {
const { serviceName, serviceMethodName } = OpenApiRouterResolver.resolveServiceAndMethodNames(openApiRoute);
const serviceFactoryName = this.apiControllerFactory.constructor.name;
const factoryMethod = (this.apiControllerFactory as any)[serviceName].bind(this.apiControllerFactory);
if (!factoryMethod) {
throw new Error(`There is no factory method name ${serviceName}. Have you implemented ${serviceFactoryName}.${serviceName}`);
}
const service = factoryMethod();
if (!service) {
throw new Error(
`There is no service method name ${serviceName}. Is ${serviceFactoryName}.${serviceName} returning an ${serviceName}ApiService implementation?`,
);
}
const method = service[serviceMethodName].bind(service);
return { serviceMethodName: serviceMethodName, serviceClassName: service.constructor.name, method };
}
public static resolveServiceAndMethodNames(openApiRoute: string): { serviceName: string; serviceMethodName: string } {
const serviceSplit = openApiRoute.split('/').join(' ').trim();
const serviceName = serviceSplit.split(' ')[0];
const serviceMethodName = OpenApiRouterResolver.camelize(serviceSplit);
return { serviceName, serviceMethodName };
}
}