Skip to content

Commit b2a6925

Browse files
Merge pull request #1092 from BitGo/DX-1373-add-a-tag-for-enumDescriptions
feat: require @description tags for enum comments
2 parents 5c17527 + b7531fe commit b2a6925

File tree

2 files changed

+128
-149
lines changed

2 files changed

+128
-149
lines changed

packages/openapi-generator/src/knownImports.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as E from 'fp-ts/Either';
22

33
import { isPrimitive, type Schema } from './ir';
44
import { errorLeft } from './error';
5+
import { parseCommentBlock } from './jsdoc';
56

67
export type DerefFn = (ref: Schema) => E.Either<string, Schema>;
78
export type KnownCodec = (
@@ -132,9 +133,12 @@ export const KNOWN_IMPORTS: KnownImports = {
132133

133134
for (const prop of enumValues) {
134135
const propertySchema = arg.properties[prop];
135-
if (propertySchema?.comment?.description) {
136-
enumDescriptions[prop] = propertySchema.comment.description;
137-
hasDescriptions = true;
136+
if (propertySchema?.comment) {
137+
const jsdoc = parseCommentBlock(propertySchema.comment);
138+
if (jsdoc.tags?.description) {
139+
enumDescriptions[prop] = jsdoc.tags.description;
140+
hasDescriptions = true;
141+
}
138142
}
139143
}
140144

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

Lines changed: 121 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -1441,179 +1441,98 @@ testCase(
14411441
},
14421442
);
14431443

1444-
const ROUTE_WITH_INDIVIDUAL_ENUM_DESCRIPTIONS = `
1444+
const ROUTE_WITH_ENUM_DESCRIPTIONS = `
14451445
import * as t from 'io-ts';
14461446
import * as h from '@api-ts/io-ts-http';
14471447
14481448
/**
1449-
* Transaction Request State Enum with individual descriptions
1449+
* Enum with @description tags - should generate x-enumDescriptions
14501450
*/
1451-
export const TransactionRequestState = t.keyof(
1451+
export const StatusWithDescriptions = t.keyof(
14521452
{
1453-
/** Transaction is waiting for approval from authorized users */
1453+
/**
1454+
* @description Transaction is waiting for approval from authorized users
1455+
*/
14541456
pendingApproval: 1,
1455-
/** Transaction was canceled by the user */
1457+
/**
1458+
* @description Transaction was canceled by the user
1459+
*/
14561460
canceled: 1,
1457-
/** Transaction was rejected by approvers */
1461+
/**
1462+
* @description Transaction was rejected by approvers
1463+
*/
14581464
rejected: 1,
1459-
/** Transaction has been initialized but not yet processed */
1460-
initialized: 1,
1461-
/** Transaction is ready to be delivered */
1462-
pendingDelivery: 1,
1463-
/** Transaction has been successfully delivered */
1464-
delivered: 1,
14651465
},
1466-
'TransactionRequestState',
1466+
'StatusWithDescriptions',
14671467
);
14681468
14691469
/**
1470-
* Route to test individual enum variant descriptions
1471-
*
1472-
* @operationId api.v1.enumVariantDescriptions
1473-
* @tag Test Routes
1470+
* Simple enum without any descriptions - should use standard format
14741471
*/
1475-
export const route = h.httpRoute({
1476-
path: '/transactions',
1477-
method: 'GET',
1478-
request: h.httpRequest({
1479-
query: {
1480-
states: t.array(TransactionRequestState),
1481-
},
1482-
}),
1483-
response: {
1484-
200: {
1485-
result: t.string
1486-
}
1472+
export const SimpleEnum = t.keyof(
1473+
{
1474+
value1: 1,
1475+
value2: 1,
1476+
value3: 1,
14871477
},
1488-
});
1489-
`;
1478+
'SimpleEnum',
1479+
);
14901480
1491-
testCase(
1492-
'individual enum variant descriptions use x-enumDescriptions extension',
1493-
ROUTE_WITH_INDIVIDUAL_ENUM_DESCRIPTIONS,
1481+
/**
1482+
* Enum with comments but no @description tags - should NOT generate x-enumDescriptions
1483+
*/
1484+
export const StatusWithComments = t.keyof(
14941485
{
1495-
openapi: '3.0.3',
1496-
info: {
1497-
title: 'Test',
1498-
version: '1.0.0',
1499-
},
1500-
paths: {
1501-
'/transactions': {
1502-
get: {
1503-
summary: 'Route to test individual enum variant descriptions',
1504-
operationId: 'api.v1.enumVariantDescriptions',
1505-
tags: ['Test Routes'],
1506-
parameters: [
1507-
{
1508-
name: 'states',
1509-
in: 'query',
1510-
required: true,
1511-
schema: {
1512-
type: 'array',
1513-
items: {
1514-
type: 'string',
1515-
enum: [
1516-
'pendingApproval',
1517-
'canceled',
1518-
'rejected',
1519-
'initialized',
1520-
'pendingDelivery',
1521-
'delivered',
1522-
],
1523-
'x-enumDescriptions': {
1524-
pendingApproval:
1525-
'Transaction is waiting for approval from authorized users',
1526-
canceled: 'Transaction was canceled by the user',
1527-
rejected: 'Transaction was rejected by approvers',
1528-
initialized:
1529-
'Transaction has been initialized but not yet processed',
1530-
pendingDelivery: 'Transaction is ready to be delivered',
1531-
delivered: 'Transaction has been successfully delivered',
1532-
},
1533-
description:
1534-
'Transaction Request State Enum with individual descriptions',
1535-
},
1536-
},
1537-
},
1538-
],
1539-
responses: {
1540-
200: {
1541-
description: 'OK',
1542-
content: {
1543-
'application/json': {
1544-
schema: {
1545-
type: 'object',
1546-
properties: {
1547-
result: {
1548-
type: 'string',
1549-
},
1550-
},
1551-
required: ['result'],
1552-
},
1553-
},
1554-
},
1555-
},
1556-
},
1557-
},
1558-
},
1559-
},
1560-
components: {
1561-
schemas: {
1562-
TransactionRequestState: {
1563-
title: 'TransactionRequestState',
1564-
description: 'Transaction Request State Enum with individual descriptions',
1565-
type: 'string',
1566-
enum: [
1567-
'pendingApproval',
1568-
'canceled',
1569-
'rejected',
1570-
'initialized',
1571-
'pendingDelivery',
1572-
'delivered',
1573-
],
1574-
'x-enumDescriptions': {
1575-
pendingApproval:
1576-
'Transaction is waiting for approval from authorized users',
1577-
canceled: 'Transaction was canceled by the user',
1578-
rejected: 'Transaction was rejected by approvers',
1579-
initialized: 'Transaction has been initialized but not yet processed',
1580-
pendingDelivery: 'Transaction is ready to be delivered',
1581-
delivered: 'Transaction has been successfully delivered',
1582-
},
1583-
},
1584-
},
1585-
},
1486+
/** processing = a case has been picked up by the Trust Committee Email Worker, and is being...processed */
1487+
processing: 1,
1488+
/** approved status */
1489+
approved: 1,
1490+
denied: 1,
15861491
},
1492+
'StatusWithComments',
15871493
);
15881494
1589-
const ROUTE_WITH_ENUM_WITHOUT_DESCRIPTIONS = `
1590-
import * as t from 'io-ts';
1591-
import * as h from '@api-ts/io-ts-http';
1592-
15931495
/**
1594-
* Simple enum without individual descriptions
1496+
* Enum with mixed comment types - only @description tags should be used
15951497
*/
1596-
export const SimpleEnum = t.keyof(
1498+
export const MixedCommentStatus = t.keyof(
15971499
{
1598-
value1: 1,
1599-
value2: 1,
1600-
value3: 1,
1500+
/**
1501+
* This is just an internal comment about pending status
1502+
*/
1503+
pending: 1,
1504+
/**
1505+
* processing = a case has been picked up by the Trust Committee Email Worker, and is being...processed
1506+
* @description Transaction is currently being processed by the system
1507+
*/
1508+
processing: 1,
1509+
/** approved by the team after review */
1510+
approved: 1,
1511+
/**
1512+
* @description Transaction was rejected due to validation failures
1513+
*/
1514+
rejected: 1,
1515+
/** denied without much explanation */
1516+
denied: 1,
16011517
},
1602-
'SimpleEnum',
1518+
'MixedCommentStatus',
16031519
);
16041520
16051521
/**
1606-
* Route to test enum without individual descriptions
1522+
* Route to test all enum description scenarios
16071523
*
1608-
* @operationId api.v1.simpleEnum
1524+
* @operationId api.v1.enumDescriptionScenarios
16091525
* @tag Test Routes
16101526
*/
16111527
export const route = h.httpRoute({
1612-
path: '/simple',
1528+
path: '/enum-scenarios',
16131529
method: 'GET',
16141530
request: h.httpRequest({
16151531
query: {
1616-
value: SimpleEnum,
1532+
withDescriptions: StatusWithDescriptions,
1533+
simple: SimpleEnum,
1534+
withComments: StatusWithComments,
1535+
mixed: MixedCommentStatus,
16171536
},
16181537
}),
16191538
response: {
@@ -1625,29 +1544,53 @@ export const route = h.httpRoute({
16251544
`;
16261545

16271546
testCase(
1628-
'enum without individual descriptions uses standard enum format',
1629-
ROUTE_WITH_ENUM_WITHOUT_DESCRIPTIONS,
1547+
'enum description scenarios - @description tags vs regular comments vs mixed',
1548+
ROUTE_WITH_ENUM_DESCRIPTIONS,
16301549
{
16311550
openapi: '3.0.3',
16321551
info: {
16331552
title: 'Test',
16341553
version: '1.0.0',
16351554
},
16361555
paths: {
1637-
'/simple': {
1556+
'/enum-scenarios': {
16381557
get: {
1639-
summary: 'Route to test enum without individual descriptions',
1640-
operationId: 'api.v1.simpleEnum',
1558+
summary: 'Route to test all enum description scenarios',
1559+
operationId: 'api.v1.enumDescriptionScenarios',
16411560
tags: ['Test Routes'],
16421561
parameters: [
16431562
{
1644-
name: 'value',
1563+
name: 'withDescriptions',
1564+
in: 'query',
1565+
required: true,
1566+
schema: {
1567+
$ref: '#/components/schemas/StatusWithDescriptions',
1568+
},
1569+
},
1570+
{
1571+
name: 'simple',
16451572
in: 'query',
16461573
required: true,
16471574
schema: {
16481575
$ref: '#/components/schemas/SimpleEnum',
16491576
},
16501577
},
1578+
{
1579+
name: 'withComments',
1580+
in: 'query',
1581+
required: true,
1582+
schema: {
1583+
$ref: '#/components/schemas/StatusWithComments',
1584+
},
1585+
},
1586+
{
1587+
name: 'mixed',
1588+
in: 'query',
1589+
required: true,
1590+
schema: {
1591+
$ref: '#/components/schemas/MixedCommentStatus',
1592+
},
1593+
},
16511594
],
16521595
responses: {
16531596
200: {
@@ -1672,11 +1615,43 @@ testCase(
16721615
},
16731616
components: {
16741617
schemas: {
1618+
StatusWithDescriptions: {
1619+
title: 'StatusWithDescriptions',
1620+
description:
1621+
'Enum with @description tags - should generate x-enumDescriptions',
1622+
type: 'string',
1623+
enum: ['pendingApproval', 'canceled', 'rejected'],
1624+
'x-enumDescriptions': {
1625+
pendingApproval:
1626+
'Transaction is waiting for approval from authorized users',
1627+
canceled: 'Transaction was canceled by the user',
1628+
rejected: 'Transaction was rejected by approvers',
1629+
},
1630+
},
16751631
SimpleEnum: {
16761632
title: 'SimpleEnum',
16771633
type: 'string',
16781634
enum: ['value1', 'value2', 'value3'],
1679-
description: 'Simple enum without individual descriptions',
1635+
description:
1636+
'Simple enum without any descriptions - should use standard format',
1637+
},
1638+
StatusWithComments: {
1639+
title: 'StatusWithComments',
1640+
type: 'string',
1641+
enum: ['processing', 'approved', 'denied'],
1642+
description:
1643+
'Enum with comments but no @description tags - should NOT generate x-enumDescriptions',
1644+
},
1645+
MixedCommentStatus: {
1646+
title: 'MixedCommentStatus',
1647+
type: 'string',
1648+
enum: ['pending', 'processing', 'approved', 'rejected', 'denied'],
1649+
'x-enumDescriptions': {
1650+
processing: 'Transaction is currently being processed by the system',
1651+
rejected: 'Transaction was rejected due to validation failures',
1652+
},
1653+
description:
1654+
'Enum with mixed comment types - only @description tags should be used',
16801655
},
16811656
},
16821657
},

0 commit comments

Comments
 (0)