Skip to content

Commit 46ca0ef

Browse files
authored
Merge pull request #770 from BitGo/DX352-optout
feat(openapi-generator): add unknown jsdoc tags to openapi json output
2 parents 752863f + c0b52b2 commit 46ca0ef

File tree

2 files changed

+160
-1
lines changed

2 files changed

+160
-1
lines changed

packages/openapi-generator/src/openapi.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,26 @@ function routeToOpenAPI(route: Route): [string, string, OpenAPIV3.OperationObjec
126126
const isUnstable = jsdoc.tags?.unstable !== undefined;
127127
const example = jsdoc.tags?.example;
128128

129+
const knownTags = new Set([
130+
'operationId',
131+
'summary',
132+
'private',
133+
'unstable',
134+
'example',
135+
'tag',
136+
'description',
137+
'url',
138+
]);
139+
const unknownTagsObject = Object.entries(jsdoc.tags ?? {}).reduce(
140+
(acc, [key, value]) => {
141+
if (!knownTags.has(key)) {
142+
return { ...acc, [key]: value || true };
143+
}
144+
return acc;
145+
},
146+
{},
147+
);
148+
129149
const requestBody =
130150
route.body === undefined
131151
? {}
@@ -147,6 +167,9 @@ function routeToOpenAPI(route: Route): [string, string, OpenAPIV3.OperationObjec
147167
...(tag !== '' ? { tags: [tag] } : {}),
148168
...(isInternal ? { 'x-internal': true } : {}),
149169
...(isUnstable ? { 'x-unstable': true } : {}),
170+
...(Object.keys(unknownTagsObject).length > 0
171+
? { 'x-unknown-tags': unknownTagsObject }
172+
: {}),
150173
parameters: route.parameters.map((p) => {
151174
// Array types not allowed here
152175
const schema = schemaToOpenAPI(p.schema);

packages/openapi-generator/test/openapi.test.ts

Lines changed: 137 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ import {
1616
async function testCase(
1717
description: string,
1818
src: string,
19-
expected: OpenAPIV3_1.Document<{ 'x-internal'?: boolean; 'x-unstable'?: boolean }>,
19+
expected: OpenAPIV3_1.Document<{
20+
'x-internal'?: boolean;
21+
'x-unstable'?: boolean;
22+
'x-unknown-tags'?: object;
23+
}>,
2024
expectedErrors: string[] = [],
2125
) {
2226
test(description, async () => {
@@ -1192,3 +1196,135 @@ testCase(
11921196
},
11931197
},
11941198
);
1199+
1200+
const ROUTE_WITH_UNKNOWN_TAG = `
1201+
import * as t from 'io-ts';
1202+
import * as h from '@api-ts/io-ts-http';
1203+
1204+
/**
1205+
* A simple route
1206+
*
1207+
* @operationId api.v1.test
1208+
* @tag Test Routes
1209+
* @optout true
1210+
*/
1211+
export const route = h.httpRoute({
1212+
path: '/foo',
1213+
method: 'GET',
1214+
request: h.httpRequest({}),
1215+
response: {
1216+
200: {
1217+
test: t.string
1218+
}
1219+
},
1220+
});
1221+
`;
1222+
1223+
testCase('route with unknown tag', ROUTE_WITH_UNKNOWN_TAG, {
1224+
openapi: '3.0.3',
1225+
info: {
1226+
title: 'Test',
1227+
version: '1.0.0',
1228+
},
1229+
paths: {
1230+
'/foo': {
1231+
get: {
1232+
summary: 'A simple route',
1233+
operationId: 'api.v1.test',
1234+
tags: ['Test Routes'],
1235+
'x-unknown-tags': {
1236+
optout: 'true',
1237+
},
1238+
parameters: [],
1239+
responses: {
1240+
200: {
1241+
description: 'OK',
1242+
content: {
1243+
'application/json': {
1244+
schema: {
1245+
type: 'object',
1246+
properties: {
1247+
test: {
1248+
type: 'string',
1249+
},
1250+
},
1251+
required: ['test'],
1252+
},
1253+
},
1254+
},
1255+
},
1256+
},
1257+
},
1258+
},
1259+
},
1260+
components: {
1261+
schemas: {},
1262+
},
1263+
});
1264+
1265+
const ROUTE_WITH_MULTIPLE_UNKNOWN_TAGS = `
1266+
import * as t from 'io-ts';
1267+
import * as h from '@api-ts/io-ts-http';
1268+
1269+
/**
1270+
* A simple route
1271+
*
1272+
* @operationId api.v1.test
1273+
* @tag Test Routes
1274+
* @optout true
1275+
* @critical false
1276+
*/
1277+
export const route = h.httpRoute({
1278+
path: '/foo',
1279+
method: 'GET',
1280+
request: h.httpRequest({}),
1281+
response: {
1282+
200: {
1283+
test: t.string
1284+
}
1285+
},
1286+
});
1287+
`;
1288+
1289+
testCase('route with multiple unknown tags', ROUTE_WITH_MULTIPLE_UNKNOWN_TAGS, {
1290+
openapi: '3.0.3',
1291+
info: {
1292+
title: 'Test',
1293+
version: '1.0.0',
1294+
},
1295+
paths: {
1296+
'/foo': {
1297+
get: {
1298+
summary: 'A simple route',
1299+
operationId: 'api.v1.test',
1300+
tags: ['Test Routes'],
1301+
'x-unknown-tags': {
1302+
optout: 'true',
1303+
critical: 'false',
1304+
},
1305+
parameters: [],
1306+
responses: {
1307+
200: {
1308+
description: 'OK',
1309+
content: {
1310+
'application/json': {
1311+
schema: {
1312+
type: 'object',
1313+
properties: {
1314+
test: {
1315+
type: 'string',
1316+
},
1317+
},
1318+
required: ['test'],
1319+
},
1320+
},
1321+
},
1322+
},
1323+
},
1324+
},
1325+
},
1326+
},
1327+
components: {
1328+
schemas: {},
1329+
},
1330+
});

0 commit comments

Comments
 (0)