Skip to content

Commit

Permalink
feat: support x-enum-varnames
Browse files Browse the repository at this point in the history
  • Loading branch information
Chaim Lev-Ari committed Dec 18, 2023
1 parent c8d4ead commit ad84671
Show file tree
Hide file tree
Showing 11 changed files with 317 additions and 19 deletions.
1 change: 1 addition & 0 deletions e2e/kubb.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const schemas = [
['requestBody', './schemas/requestBody.yaml'],
['box', './schemas/box.json'],
['digitalocean', './schemas/digitalocean.yaml'],
['enums', './schemas/enums.yaml']
]

/** @type {import('@kubb/core').KubbUserConfig} */
Expand Down
39 changes: 39 additions & 0 deletions e2e/schemas/enums.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
definitions:
enumVarNames.Type:
enum:
- 0
- 1
type: integer
x-enum-varnames:
- Pending
- Received
enumNames.Type:
enum:
- 0
- 1
x-enumNames:
- Pending
- Received
swagger: "2.0"
info:
title: test
version: "1.0.0"
paths:
/var-names:
get:
consumes:
- application/json
responses:
200:
description: Success
schema:
$ref: '#/definitions/enumVarNames.Type'
/names:
get:
consumes:
- application/json
responses:
200:
description: Success
schema:
$ref: '#/definitions/enumNames.Type'
21 changes: 14 additions & 7 deletions packages/swagger-faker/src/FakerGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,15 +243,22 @@ export class FakerGenerator extends Generator<PluginOptions['resolvedOptions'],
}

if (schema.enum) {
if ('x-enumNames' in schema) {
return [
{
keyword: fakerKeywords.enum,
args: [`[${[...new Set(schema['x-enumNames'] as string[])].map((value) => `\`${value}\``).join(', ')}]`],
},
]
const extensionEnums = (['x-enumNames', 'x-enum-varnames'] as Array<keyof typeof schema>)
.filter(extensionKey => extensionKey in schema)
.map((extensionKey) => {
return [
{
keyword: fakerKeywords.enum,
args: [`[${[...new Set(schema[extensionKey] as string[])].map((value) => `\`${value}\``).join(', ')}]`],
},
]
})

if (extensionEnums.length > 0 && extensionEnums[0]) {
return extensionEnums[0]
}


if (schema.type === 'number' || schema.type === 'integer') {
return [
{
Expand Down
39 changes: 39 additions & 0 deletions packages/swagger-ts/mocks/enums.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
definitions:
enumVarNames.Type:
enum:
- 0
- 1
type: integer
x-enum-varnames:
- Pending
- Received
enumNames.Type:
enum:
- 0
- 1
x-enumNames:
- Pending
- Received
swagger: "2.0"
info:
title: test
version: "1.0.0"
paths:
/var-names:
get:
consumes:
- application/json
responses:
200:
description: Success
schema:
$ref: '#/definitions/enumVarNames.Type'
/names:
get:
consumes:
- application/json
responses:
200:
description: Success
schema:
$ref: '#/definitions/enumNames.Type'
44 changes: 44 additions & 0 deletions packages/swagger-ts/src/TypeGenerator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,3 +314,47 @@ describe('TypeGenerator with discriminators', async () => {
expect(ast_output).toMatchSnapshot()
})
})


describe('TypeGenerator enums', async () => {
const schemaPath = path.resolve(__dirname, '../mocks/enums.yaml')
const oas = await new OasManager().parse(schemaPath)
const generator = new TypeGenerator({
usedEnumNames: {},
enumType: 'asConst',
dateType: 'string',
optionalType: 'questionToken',
transformers: {},
oasType: false,
}, {
oas,
pluginManager: mockedPluginManager,
})

const schemas = oas.getDefinition().components?.schemas


test('generate x-enum-varnames types', async () => {


const node = generator.build({ schema: schemas?.['enumVarNames.Type'] as OasTypes.SchemaObject, baseName: 'enumVarNames' })

const output = print(node, undefined)

expect(output).toBeDefined()

expect(await format(output)).toMatchSnapshot()
})

test('generate x-enumNames types', async () => {


const node = generator.build({ schema: schemas?.['enumNames.Type'] as OasTypes.SchemaObject, baseName: 'enumNames' })

const output = print(node, undefined)

expect(output).toBeDefined()

expect(await format(output)).toMatchSnapshot()
})
})
14 changes: 11 additions & 3 deletions packages/swagger-ts/src/TypeGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,12 +280,20 @@ export class TypeGenerator extends Generator<PluginOptions['resolvedOptions'], C

let enums: [key: string, value: string | number][] = [...new Set(schema.enum)].map((key) => [key, key])

if ('x-enumNames' in schema) {
enums = [...new Set(schema['x-enumNames'] as string[])].map((key: string, index) => {
return [key, schema.enum?.[index] as string]
const extensionEnums : Array<typeof enums> = (['x-enumNames', 'x-enum-varnames'] as Array<keyof typeof schema>)
.filter(extensionKey => extensionKey in schema)
.map((extensionKey) => {
return [...new Set(schema[extensionKey] as string[])].map((key, index) => {
return [key, schema.enum?.[index] as string] as const
})
})

if (extensionEnums.length > 0 && extensionEnums[0]) {
enums = extensionEnums[0]
}



this.extraNodes.push(
...factory.createEnumDeclaration({
name: transformers.camelCase(enumName),
Expand Down
23 changes: 23 additions & 0 deletions packages/swagger-ts/src/__snapshots__/TypeGenerator.test.ts.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`TypeGenerator enums > generate x-enum-varnames types 1`] = `
"export const enumVarNames = {
Pending: 0,
Received: 1,
} as const
export type enumVarNames = (typeof enumVarNames)[keyof typeof enumVarNames]
"
`;

exports[`TypeGenerator enums > generate x-enumNames types 1`] = `
"export const enumVarNames = {
Pending: 0,
Received: 1,
} as const
export type enumVarNames = (typeof enumVarNames)[keyof typeof enumVarNames]
export const enumNames = {
Pending: 0,
Received: 1,
} as const
export type enumNames = (typeof enumNames)[keyof typeof enumNames]
"
`;

exports[`TypeGenerator simple > generate type for Pet with optionalType \`questionToken\` 1`] = `
"export type Pet = {
/**
Expand Down
39 changes: 39 additions & 0 deletions packages/swagger-zod/mocks/enums.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
definitions:
enumVarNames.Type:
enum:
- 0
- 1
type: integer
x-enum-varnames:
- Pending
- Received
enumNames.Type:
enum:
- 0
- 1
x-enumNames:
- Pending
- Received
swagger: "2.0"
info:
title: test
version: "1.0.0"
paths:
/var-names:
get:
consumes:
- application/json
responses:
200:
description: Success
schema:
$ref: '#/definitions/enumVarNames.Type'
/names:
get:
consumes:
- application/json
responses:
200:
description: Success
schema:
$ref: '#/definitions/enumNames.Type'
33 changes: 32 additions & 1 deletion packages/swagger-zod/src/ZodGenerator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ describe('ZodGenerator simple', async () => {
})
})

describe('TypeGenerator with const', async () => {
describe('ZodGenerator with const', async () => {
const discriminatorPath = path.resolve(__dirname, '../mocks/constCases.yaml')
const oas = await new OasManager().parse(discriminatorPath)
const generator = new ZodGenerator({
Expand Down Expand Up @@ -124,3 +124,34 @@ describe('ZodGenerator lazy import', async () => {
expect(node).toMatchSnapshot()
})
})



describe('ZodGenerator enums', async () => {
const schemaPath = path.resolve(__dirname, '../mocks/enums.yaml')
const oas = await new OasManager().parse(schemaPath)
const generator = new ZodGenerator({
exclude: undefined,
include: undefined,
override: undefined,
transformers: {},
}, {
oas,
pluginManager: mockedPluginManager,
})

const schemas = oas.getDefinition().components?.schemas


test('generate x-enum-varnames types', async () => {
const node = generator.build({ schema: schemas?.['enumVarNames.Type'] as OasTypes.SchemaObject, baseName: 'enumVarNames' })

expect(node).toMatchSnapshot()
})

test('generate x-enumNames types', async () => {
const node = generator.build({ schema: schemas?.['enumNames.Type'] as OasTypes.SchemaObject, baseName: 'enumNames' })

expect(node).toMatchSnapshot()
})
})
23 changes: 15 additions & 8 deletions packages/swagger-zod/src/ZodGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,16 +249,23 @@ export class ZodGenerator extends Generator<PluginOptions['resolvedOptions'], Co
}

if (schema.enum) {
if ('x-enumNames' in schema) {
return [
{
keyword: zodKeywords.enum,
args: [...new Set(schema['x-enumNames'] as string[])].map((value: string) => `\`${value}\``),
},
...baseItems,
]
const extensionEnums = (['x-enumNames', 'x-enum-varnames'] as Array<keyof typeof schema>)
.filter(extensionKey => extensionKey in schema)
.map((extensionKey) => {
return [
{
keyword: zodKeywords.enum,
args: [...new Set(schema[extensionKey] as string[])].map((value: string) => `\`${value}\``),
},
...baseItems,
]
})

if (extensionEnums.length > 0 && extensionEnums[0]) {
return extensionEnums[0]
}


if (schema.type === 'number' || schema.type === 'integer') {
// we cannot use z.enum when enum type is number/integer
return [
Expand Down
Loading

0 comments on commit ad84671

Please sign in to comment.