Skip to content

Commit 02269a1

Browse files
committed
Add support for x-enum-varnames and x-enum-descriptions
1 parent ea65d72 commit 02269a1

File tree

4 files changed

+113
-13
lines changed

4 files changed

+113
-13
lines changed

.changeset/chilled-news-design.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"openapi-typescript": major
3+
---
4+
5+
Add support for x-enum-varnames and x-enum-descriptions

packages/openapi-typescript/src/lib/ts.ts

+35-13
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ export function tsDedupe(types: ts.TypeNode[]): ts.TypeNode[] {
229229
export function tsEnum(
230230
name: string,
231231
members: (string | number)[],
232+
membersNames?: string[],
233+
membersDescriptions?: string[],
232234
options?: { readonly?: boolean; export?: boolean },
233235
) {
234236
let enumName = name.replace(JS_ENUM_INVALID_CHARS_RE, (c) => {
@@ -249,28 +251,48 @@ export function tsEnum(
249251
})
250252
: undefined,
251253
/* name */ enumName,
252-
/* members */ members.map(tsEnumMember),
254+
/* members */ members.map((value, i) =>
255+
tsEnumMember(value, membersNames?.[i], membersDescriptions?.[i]),
256+
),
253257
);
254258
}
255259

256260
/** Sanitize TS enum member expression */
257-
export function tsEnumMember(value: string | number) {
258-
if (typeof value === "number") {
259-
return ts.factory.createEnumMember(
260-
`Value${String(value)}`.replace(".", "_"), // don’t forget decimals
261-
ts.factory.createNumericLiteral(value),
262-
);
263-
}
264-
let name = value;
261+
export function tsEnumMember(
262+
value: string | number,
263+
memberName?: string,
264+
description?: string,
265+
) {
266+
let name = memberName ?? String(value);
265267
if (!JS_PROPERTY_INDEX_RE.test(name)) {
266268
if (Number(name[0]) >= 0) {
267-
name = `Value${name}`;
269+
name = `Value${name}`.replace(".", "_"); // don't forged decimals;
268270
}
269271
name = name.replace(JS_PROPERTY_INDEX_INVALID_CHARS_RE, "_");
270272
}
271-
return ts.factory.createEnumMember(
272-
name,
273-
ts.factory.createStringLiteral(value),
273+
274+
let member;
275+
if (typeof value === "number") {
276+
member = ts.factory.createEnumMember(
277+
name,
278+
ts.factory.createNumericLiteral(value),
279+
);
280+
} else {
281+
member = ts.factory.createEnumMember(
282+
name,
283+
ts.factory.createStringLiteral(value),
284+
);
285+
}
286+
287+
if (description == undefined) {
288+
return member;
289+
}
290+
291+
return ts.addSyntheticLeadingComment(
292+
member,
293+
ts.SyntaxKind.SingleLineCommentTrivia,
294+
" ".concat(description.trim()),
295+
true,
274296
);
275297
}
276298

packages/openapi-typescript/src/transform/schema-object.ts

+2
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ export function transformSchemaObjectWithComposition(
127127
const enumType = tsEnum(
128128
enumName,
129129
schemaObject.enum as (string | number)[],
130+
schemaObject["x-enum-varnames"],
131+
schemaObject["x-enum-descriptions"],
130132
{ export: true, readonly: options.ctx.immutable },
131133
);
132134
options.ctx.injectFooter.push(enumType);

packages/openapi-typescript/test/lib/ts.test.ts

+71
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,77 @@ describe("tsEnum", () => {
127127
Value100 = 100,
128128
Value101 = 101,
129129
Value102 = 102
130+
}`);
131+
});
132+
133+
it("number members with x-enum-descriptions", () => {
134+
expect(
135+
astToString(
136+
tsEnum(".Error.code.", [100, 101, 102], undefined, [
137+
"Code 100",
138+
"Code 101",
139+
"Code 102",
140+
]),
141+
).trim(),
142+
).toBe(`enum ErrorCode {
143+
// Code 100
144+
Value100 = 100,
145+
// Code 101
146+
Value101 = 101,
147+
// Code 102
148+
Value102 = 102
149+
}`);
150+
});
151+
152+
it("x-enum-varnames", () => {
153+
expect(
154+
astToString(
155+
tsEnum(
156+
".Error.code.",
157+
[100, 101, 102],
158+
["Unauthorized", "NotFound", "PermissionDenied"],
159+
),
160+
).trim(),
161+
).toBe(`enum ErrorCode {
162+
Unauthorized = 100,
163+
NotFound = 101,
164+
PermissionDenied = 102
165+
}`);
166+
});
167+
168+
it("x-enum-varnames with numeric prefix", () => {
169+
expect(
170+
astToString(
171+
tsEnum(".Error.code.", [100, 101, 102], ["0a", "1b", "2c"]),
172+
).trim(),
173+
).toBe(`enum ErrorCode {
174+
Value0a = 100,
175+
Value1b = 101,
176+
Value2c = 102
177+
}`);
178+
});
179+
180+
it("x-enum-descriptions with x-enum-varnames", () => {
181+
expect(
182+
astToString(
183+
tsEnum(
184+
".Error.code.",
185+
[100, 101, 102],
186+
["Unauthorized", "NotFound", "PermissionDenied"],
187+
[
188+
"User is unauthorized",
189+
"Item not found",
190+
"User doesn't have permissions",
191+
],
192+
),
193+
).trim(),
194+
).toBe(`enum ErrorCode {
195+
// User is unauthorized
196+
Unauthorized = 100,
197+
// Item not found
198+
NotFound = 101,
199+
// User doesn't have permissions
200+
PermissionDenied = 102
130201
}`);
131202
});
132203
});

0 commit comments

Comments
 (0)