Skip to content

Commit 5e35eb3

Browse files
Merge pull request #826 from BitGo/DX-531
feat: add support for array examples with the @arrayExample tag
2 parents 6515011 + 374a19f commit 5e35eb3

File tree

2 files changed

+125
-2
lines changed

2 files changed

+125
-2
lines changed

packages/openapi-generator/src/openapi.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ import type { Route } from './route';
77
import type { Schema } from './ir';
88
import { Block } from 'comment-parser';
99

10+
type ExtendedOpenApiSchema = OpenAPIV3.SchemaObject & {
11+
arrayExample?: string;
12+
};
13+
1014
function schemaToOpenAPI(
1115
schema: Schema,
1216
): OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject | undefined {
@@ -50,7 +54,14 @@ function schemaToOpenAPI(
5054
if (innerSchema === undefined) {
5155
return undefined;
5256
}
53-
return { type: 'array', items: { ...innerSchema, ...defaultOpenAPIObject } };
57+
58+
const { arrayExample, ...rest } = defaultOpenAPIObject;
59+
60+
return {
61+
type: 'array',
62+
...(arrayExample ? { example: JSON.parse(arrayExample) } : {}), // Add example to array if it exists
63+
items: { ...innerSchema, ...rest },
64+
};
5465
case 'object':
5566
return {
5667
type: 'object',
@@ -173,7 +184,7 @@ function schemaToOpenAPI(
173184
}
174185
};
175186

176-
function buildDefaultOpenAPIObject(schema: Schema): OpenAPIV3.SchemaObject {
187+
function buildDefaultOpenAPIObject(schema: Schema): ExtendedOpenApiSchema {
177188
const emptyBlock: Block = { description: '', tags: [], source: [], problems: [] };
178189
const jsdoc = parseCommentBlock(schema.comment ?? emptyBlock);
179190

@@ -196,6 +207,7 @@ function schemaToOpenAPI(
196207
const writeOnly = jsdoc?.tags?.writeOnly ?? schema.writeOnly;
197208
const format = jsdoc?.tags?.format ?? schema.format ?? schema.format;
198209
const title = jsdoc?.tags?.title ?? schema.title;
210+
const arrayExample = jsdoc?.tags?.arrayExample ?? '';
199211

200212
const deprecated =
201213
Object.keys(jsdoc?.tags || {}).includes('deprecated') || !!schema.deprecated;
@@ -223,7 +235,9 @@ function schemaToOpenAPI(
223235
...(writeOnly ? { writeOnly: true } : {}),
224236
...(format ? { format } : {}),
225237
...(title ? { title } : {}),
238+
...(arrayExample ? { arrayExample } : {}),
226239
};
240+
227241
return defaultOpenAPIObject;
228242
}
229243

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

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3567,3 +3567,112 @@ testCase("route with titles in request bodies", SCHEMA_WITH_TITLES_IN_REQUEST_BO
35673567
}
35683568
}
35693569
});
3570+
3571+
3572+
const ROUTE_WITH_ARRAY_EXAMPLE = `
3573+
import * as t from 'io-ts';
3574+
import * as h from '@api-ts/io-ts-http';
3575+
3576+
export const route = h.httpRoute({
3577+
path: '/foo',
3578+
method: 'POST',
3579+
request: h.httpRequest({
3580+
params: {},
3581+
body: t.type({
3582+
/**
3583+
* @example "btc"
3584+
*/
3585+
array1: t.array(t.string),
3586+
/**
3587+
* @example "btc"
3588+
* @arrayExample ["btc", "eth"]
3589+
*/
3590+
array2: t.array(t.string),
3591+
objectWithArray: t.type({
3592+
/**
3593+
* @arrayExample ["btc", "eth"]
3594+
*/
3595+
nestedArray: t.array(t.string)
3596+
})
3597+
})
3598+
}),
3599+
response: {
3600+
200: t.literal('OK'),
3601+
},
3602+
});`
3603+
3604+
testCase("route with array examples", ROUTE_WITH_ARRAY_EXAMPLE, {
3605+
openapi: '3.0.3',
3606+
info: {
3607+
title: 'Test',
3608+
version: '1.0.0'
3609+
},
3610+
paths: {
3611+
'/foo': {
3612+
post: {
3613+
parameters: [],
3614+
requestBody: {
3615+
content: {
3616+
'application/json': {
3617+
schema: {
3618+
type: 'object',
3619+
properties: {
3620+
array1: {
3621+
type: 'array',
3622+
items: {
3623+
type: 'string',
3624+
example: '"btc"'
3625+
},
3626+
},
3627+
array2: {
3628+
type: 'array',
3629+
example: ['btc', 'eth'],
3630+
items: {
3631+
type: 'string',
3632+
example: '"btc"'
3633+
},
3634+
},
3635+
objectWithArray: {
3636+
properties: {
3637+
nestedArray: {
3638+
example: [
3639+
'btc',
3640+
'eth'
3641+
],
3642+
items: {
3643+
type: 'string'
3644+
},
3645+
type: 'array'
3646+
}
3647+
},
3648+
required: [
3649+
'nestedArray'
3650+
],
3651+
type: 'object'
3652+
},
3653+
},
3654+
required: [ 'array1', 'array2', 'objectWithArray' ],
3655+
},
3656+
}
3657+
}
3658+
},
3659+
responses: {
3660+
'200': {
3661+
description: 'OK',
3662+
content: {
3663+
'application/json': {
3664+
schema: {
3665+
type: 'string',
3666+
enum: [ 'OK' ]
3667+
}
3668+
}
3669+
}
3670+
}
3671+
}
3672+
}
3673+
}
3674+
},
3675+
components: {
3676+
schemas: {}
3677+
}
3678+
});

0 commit comments

Comments
 (0)