-
Notifications
You must be signed in to change notification settings - Fork 69
Expand file tree
/
Copy pathinit-public-api-swagger.ts
More file actions
122 lines (99 loc) · 4.07 KB
/
init-public-api-swagger.ts
File metadata and controls
122 lines (99 loc) · 4.07 KB
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import {OpenApiGeneratorV31} from '@asteasolutions/zod-to-openapi';
import type {OpenAPIObjectConfigV31} from '@asteasolutions/zod-to-openapi/dist/v3.1/openapi-generator';
import type {ExpressKit} from '@gravity-ui/expresskit';
import swaggerUi from 'swagger-ui-express';
import {objectKeys} from '../../../../shared';
import {registry} from '../../../registry';
import {
OPEN_API_VERSION_HEADER_COMPONENT_NAME,
PUBLIC_API_LATEST_VERSION,
PUBLIC_API_VERSION_HEADER,
} from '../constants';
export const initPublicApiSwagger = (app: ExpressKit) => {
const {config} = app;
const installationText = `Installation – <b>${config.appInstallation}</b>`;
const envText = `Env – <b>${config.appEnv}</b>`;
const {baseConfig, securitySchemes, biOpenapiSchemas} = registry.getPublicApiConfig();
setImmediate(() => {
const versionToDocument = Object.entries(baseConfig).reduce<
Record<string, ReturnType<OpenApiGeneratorV31['generateDocument']>>
>((acc, [version, {openApi}]) => {
if (securitySchemes) {
Object.keys(securitySchemes).forEach((securityType) => {
openApi.registry.registerComponent('securitySchemes', securityType, {
...securitySchemes[securityType],
});
});
}
openApi.registry.registerComponent(
'parameters',
OPEN_API_VERSION_HEADER_COMPONENT_NAME,
{
name: PUBLIC_API_VERSION_HEADER,
in: 'header',
required: true,
schema: {
type: 'string',
const: version,
example: version,
},
description: `API version header.`,
},
);
const generator = new OpenApiGeneratorV31(openApi.registry.definitions);
const generateDocumentParams: OpenAPIObjectConfigV31 = {
openapi: '3.1.0',
info: {
version,
title: `DataLens API `,
description: [installationText, envText].join('<br />'),
},
servers: [{url: '/'}],
};
acc[version] = generator.generateDocument(generateDocumentParams);
return acc;
}, {});
const versions = objectKeys(baseConfig).map(Number);
versions.forEach((version) => {
const openApiDocument = versionToDocument[version];
openApiDocument.components = openApiDocument.components ?? {};
openApiDocument.components.schemas = {
...openApiDocument.components?.schemas,
...biOpenapiSchemas,
};
const versionPath = `/${version}/`;
const isLatest = version === PUBLIC_API_LATEST_VERSION;
const addSwaggerRoutes = (basePath: string) => {
const jsonPath = `${basePath}json/`;
app.express.get(jsonPath, (req, res) => {
const host = req.get('host');
const serverUrl = `https://${host}`;
openApiDocument.servers = [{url: serverUrl}];
return res.json(openApiDocument);
});
const swaggerOptions = {
url: jsonPath,
validatorUrl: null,
tagsSorter: 'alpha',
operationsSorter: 'alpha',
};
app.express.use(
basePath,
swaggerUi.serveFiles(undefined, {
swaggerOptions,
}),
);
app.express.get(
basePath,
swaggerUi.setup(null, {
swaggerOptions,
}),
);
};
addSwaggerRoutes(versionPath);
if (isLatest) {
addSwaggerRoutes('/');
}
});
});
};