1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-04 00:18:01 +01:00
unleash.unleash/src/lib/services/openapi-service.ts
2023-02-22 13:10:29 +01:00

97 lines
2.7 KiB
TypeScript

import openapi, { IExpressOpenApi } from '@unleash/express-openapi';
import { Express, RequestHandler, Response } from 'express';
import { IUnleashConfig } from '../types/option';
import {
createOpenApiSchema,
JsonSchemaProps,
removeJsonSchemaProps,
SchemaId,
} from '../openapi';
import { ApiOperation } from '../openapi/util/api-operation';
import { Logger } from '../logger';
import { validateSchema } from '../openapi/validate';
import { IFlagResolver } from '../types';
export class OpenApiService {
private readonly config: IUnleashConfig;
private readonly logger: Logger;
private readonly api: IExpressOpenApi;
private flagResolver: IFlagResolver;
constructor(config: IUnleashConfig) {
this.config = config;
this.flagResolver = config.flagResolver;
this.logger = config.getLogger('openapi-service.ts');
this.api = openapi(
this.docsPath(),
createOpenApiSchema(config.server),
{ coerce: true, extendRefs: true },
);
}
validPath(op: ApiOperation): RequestHandler {
return this.api.validPath(op);
}
useDocs(app: Express): void {
app.use(this.api);
app.use(this.docsPath(), this.api.swaggerui);
}
docsPath(): string {
const { baseUriPath = '' } = this.config.server ?? {};
return `${baseUriPath}/docs/openapi`;
}
registerCustomSchemas<T extends JsonSchemaProps>(
schemas: Record<string, T>,
): void {
Object.entries(schemas).forEach(([name, schema]) => {
this.api.schema(name, removeJsonSchemaProps(schema));
});
}
useErrorHandler(app: Express): void {
app.use((err, req, res, next) => {
if (err && err.status && err.validationErrors) {
res.status(err.status).json({
error: err.message,
validation: err.validationErrors,
});
} else {
next(err);
}
});
}
respondWithValidation<T, S = SchemaId>(
status: number,
res: Response<T>,
schema: S,
data: T,
headers: { [header: string]: string } = {},
): void {
const errors = validateSchema<S>(schema, data);
if (errors) {
this.logger.debug(
'Invalid response:',
JSON.stringify(errors, null, 4),
);
if (this.flagResolver.isEnabled('strictSchemaValidation')) {
throw new Error(JSON.stringify(errors, null, 4));
}
}
Object.entries(headers).forEach(([header, value]) =>
res.header(header, value),
);
res.status(status).json(data);
}
}