Skip to content

Commit 240cecf

Browse files
committed
feat: add 3.1 oneOf+const structure as enum
1 parent abab307 commit 240cecf

File tree

5 files changed

+186
-2
lines changed

5 files changed

+186
-2
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// https://json-schema.org/draft/2020-12/json-schema-core.html#name-non-json-instances
2+
3+
export interface JsonCustomVocabulary {
4+
const?: string | number;
5+
}

src/openApi/v3/interfaces/OpenApiSchema.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { Dictionary } from '../../../utils/types';
22
import type { WithEnumExtension } from './Extensions/WithEnumExtension';
3+
import type { JsonCustomVocabulary } from './JsonCustomVocabulary';
34
import type { OpenApiDiscriminator } from './OpenApiDiscriminator';
45
import type { OpenApiExternalDocs } from './OpenApiExternalDocs';
56
import type { OpenApiReference } from './OpenApiReference';
@@ -8,7 +9,7 @@ import type { OpenApiXml } from './OpenApiXml';
89
/**
910
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#schemaObject
1011
*/
11-
export interface OpenApiSchema extends OpenApiReference, WithEnumExtension {
12+
export interface OpenApiSchema extends OpenApiReference, WithEnumExtension, JsonCustomVocabulary {
1213
title?: string;
1314
multipleOf?: number;
1415
maximum?: number;

src/openApi/v3/parser/getModel.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Enum } from '../../../client/interfaces/Enum';
12
import type { Model } from '../../../client/interfaces/Model';
23
import { getPattern } from '../../../utils/getPattern';
34
import type { OpenApi } from '../interfaces/OpenApi';
@@ -68,6 +69,7 @@ export const getModel = (
6869
model.base = 'string';
6970
model.enum.push(...extendedEnumerators);
7071
model.default = getModelDefault(definition, model);
72+
7173
return model;
7274
}
7375
}
@@ -118,7 +120,39 @@ export const getModel = (
118120
}
119121
}
120122

121-
if (definition.oneOf?.length) {
123+
if (
124+
definition.oneOf?.length &&
125+
(definition.type === 'integer' || definition.type === 'string') &&
126+
(typeof definition.oneOf?.at(0)?.const === 'number' || typeof definition.oneOf?.at(0)?.const === 'string')
127+
) {
128+
const enumerator: Enum[] = definition.oneOf.reduce((acc, item) => {
129+
if (typeof item.const === 'number') {
130+
acc.push({
131+
value: String(item.const),
132+
name: `${item.title}` || `'_${item.const}'`,
133+
type: 'number',
134+
description: item.description || item.title || null,
135+
});
136+
} else {
137+
acc.push({
138+
value: `'${item.const}'`,
139+
name: `${item.title}` || `'${item.const}'`,
140+
type: 'string',
141+
description: item.description || item.title || null,
142+
});
143+
}
144+
return acc;
145+
}, [] as Enum[]);
146+
if (enumerator.length) {
147+
model.export = 'enum';
148+
model.type = 'string';
149+
model.base = 'string';
150+
model.enum.push(...enumerator);
151+
model.default = getModelDefault(definition, model);
152+
153+
return model;
154+
}
155+
} else if (definition.oneOf?.length) {
122156
const composition = getModelComposition(openApi, definition, definition.oneOf, 'one-of', getModel);
123157
model.export = composition.type;
124158
model.imports.push(...composition.imports);

test/__snapshots__/index.spec.ts.snap

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3639,6 +3639,8 @@ export type { DictionaryWithProperties } from './models/DictionaryWithProperties
36393639
export type { DictionaryWithReference } from './models/DictionaryWithReference';
36403640
export type { DictionaryWithString } from './models/DictionaryWithString';
36413641
export type { EnumFromDescription } from './models/EnumFromDescription';
3642+
export { EnumViaOneOfNumeric } from './models/EnumViaOneOfNumeric';
3643+
export { EnumViaOneOfString } from './models/EnumViaOneOfString';
36423644
export { EnumWithExtensions } from './models/EnumWithExtensions';
36433645
export { EnumWithNumbers } from './models/EnumWithNumbers';
36443646
export { EnumWithStrings } from './models/EnumWithStrings';
@@ -3704,6 +3706,8 @@ export { $DictionaryWithProperties } from './schemas/$DictionaryWithProperties';
37043706
export { $DictionaryWithReference } from './schemas/$DictionaryWithReference';
37053707
export { $DictionaryWithString } from './schemas/$DictionaryWithString';
37063708
export { $EnumFromDescription } from './schemas/$EnumFromDescription';
3709+
export { $EnumViaOneOfNumeric } from './schemas/$EnumViaOneOfNumeric';
3710+
export { $EnumViaOneOfString } from './schemas/$EnumViaOneOfString';
37073711
export { $EnumWithExtensions } from './schemas/$EnumWithExtensions';
37083712
export { $EnumWithNumbers } from './schemas/$EnumWithNumbers';
37093713
export { $EnumWithStrings } from './schemas/$EnumWithStrings';
@@ -4247,6 +4251,82 @@ export type EnumFromDescription = number;
42474251
"
42484252
`;
42494253

4254+
exports[`v3 should generate: ./test/generated/v3/models/EnumLike.ts 1`] = `
4255+
"/* istanbul ignore file */
4256+
/* tslint:disable */
4257+
/* eslint-disable */
4258+
4259+
/**
4260+
* OpenApi 3.1 style numeric enum
4261+
*/
4262+
export enum EnumLike {
4263+
/**
4264+
* Success
4265+
* /
4266+
SUCCESS = 0,
4267+
/**
4268+
* Warning
4269+
*/
4270+
'WARNING' = 1,
4271+
/**
4272+
* Error
4273+
*/
4274+
'ERROR' = 3,
4275+
};
4276+
4277+
"
4278+
`;
4279+
4280+
exports[`v3 should generate: ./test/generated/v3/models/EnumViaOneOfNumeric.ts 1`] = `
4281+
"/* istanbul ignore file */
4282+
/* tslint:disable */
4283+
/* eslint-disable */
4284+
4285+
/**
4286+
* OpenApi 3.1 style numeric enum
4287+
*/
4288+
export enum EnumViaOneOfNumeric {
4289+
/**
4290+
* Success
4291+
*/
4292+
SUCCESS = 0,
4293+
/**
4294+
* Warning
4295+
*/
4296+
WARNING = 1,
4297+
/**
4298+
* Error
4299+
*/
4300+
ERROR = 3,
4301+
}
4302+
"
4303+
`;
4304+
4305+
exports[`v3 should generate: ./test/generated/v3/models/EnumViaOneOfString.ts 1`] = `
4306+
"/* istanbul ignore file */
4307+
/* tslint:disable */
4308+
/* eslint-disable */
4309+
4310+
/**
4311+
* OpenApi 3.1 style numeric enum
4312+
*/
4313+
export enum EnumViaOneOfString {
4314+
/**
4315+
* Success
4316+
*/
4317+
SUCCESS = 'SUCCESS',
4318+
/**
4319+
* Warning
4320+
*/
4321+
WARNING = 'SUCCESS',
4322+
/**
4323+
* Error
4324+
*/
4325+
ERROR = 'SUCCESS',
4326+
}
4327+
"
4328+
`;
4329+
42504330
exports[`v3 should generate: ./test/generated/v3/models/EnumWithExtensions.ts 1`] = `
42514331
"/* istanbul ignore file */
42524332
/* tslint:disable */
@@ -4281,6 +4361,7 @@ exports[`v3 should generate: ./test/generated/v3/models/EnumWithNumbers.ts 1`] =
42814361
* This is a simple enum with numbers
42824362
*/
42834363
export enum EnumWithNumbers {
4364+
'_0' = 0,
42844365
'_1' = 1,
42854366
'_2' = 2,
42864367
'_3' = 3,
@@ -5447,6 +5528,26 @@ export const $EnumFromDescription = {
54475528
"
54485529
`;
54495530

5531+
exports[`v3 should generate: ./test/generated/v3/schemas/$EnumViaOneOfNumeric.ts 1`] = `
5532+
"/* istanbul ignore file */
5533+
/* tslint:disable */
5534+
/* eslint-disable */
5535+
export const $EnumViaOneOfNumeric = {
5536+
type: 'Enum',
5537+
} as const;
5538+
"
5539+
`;
5540+
5541+
exports[`v3 should generate: ./test/generated/v3/schemas/$EnumViaOneOfString.ts 1`] = `
5542+
"/* istanbul ignore file */
5543+
/* tslint:disable */
5544+
/* eslint-disable */
5545+
export const $EnumViaOneOfString = {
5546+
type: 'Enum',
5547+
} as const;
5548+
"
5549+
`;
5550+
54505551
exports[`v3 should generate: ./test/generated/v3/schemas/$EnumWithExtensions.ts 1`] = `
54515552
"/* istanbul ignore file */
54525553
/* tslint:disable */

test/spec/v3.json

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,6 +1567,7 @@
15671567
"EnumWithNumbers": {
15681568
"description": "This is a simple enum with numbers",
15691569
"enum": [
1570+
0,
15701571
1,
15711572
2,
15721573
3,
@@ -1606,6 +1607,48 @@
16061607
"Used when the status of something has an error"
16071608
]
16081609
},
1610+
"EnumViaOneOfNumeric": {
1611+
"description": "OpenApi 3.1 style numeric enum",
1612+
"type": "integer",
1613+
"oneOf": [
1614+
{
1615+
"const": 0,
1616+
"title": "SUCCESS",
1617+
"description": "Success"
1618+
},
1619+
{
1620+
"const": 1,
1621+
"title": "WARNING",
1622+
"description": "Warning"
1623+
},
1624+
{
1625+
"const": 3,
1626+
"title": "ERROR",
1627+
"description": "Error"
1628+
}
1629+
]
1630+
},
1631+
"EnumViaOneOfString": {
1632+
"description": "OpenApi 3.1 style numeric enum",
1633+
"type": "integer",
1634+
"oneOf": [
1635+
{
1636+
"const": "SUCCESS",
1637+
"title": "SUCCESS",
1638+
"description": "Success"
1639+
},
1640+
{
1641+
"const": "SUCCESS",
1642+
"title": "WARNING",
1643+
"description": "Warning"
1644+
},
1645+
{
1646+
"const": "SUCCESS",
1647+
"title": "ERROR",
1648+
"description": "Error"
1649+
}
1650+
]
1651+
},
16091652
"ArrayWithNumbers": {
16101653
"description": "This is a simple array with numbers",
16111654
"type": "array",

0 commit comments

Comments
 (0)