fix: response schema is now inferred from each endpoint's sample JSON
This commit is contained in:
1 parent
d2af39da61
commit
9ab98fd50c
1 file changed
+51
-1
@@ -212,6 +212,53 @@ function parseExample(response: string) {
|
||||
}
|
||||
}
|
||||
|
||||
type Schema = Record<string, unknown>
|
||||
|
||||
function mergeSchemas(schemas: Schema[]): Schema {
|
||||
const unique = [...new Map(schemas.map((schema) => [JSON.stringify(schema), schema])).values()]
|
||||
if (unique.length === 1) return unique[0]
|
||||
const objects = unique.filter((schema) => schema.type === 'object')
|
||||
if (objects.length > 1 && objects.length === unique.length) {
|
||||
const keys = [...new Set(objects.flatMap((schema) => Object.keys(schema.properties as Schema)))]
|
||||
return {
|
||||
type: 'object',
|
||||
properties: Object.fromEntries(
|
||||
keys.map((key) => [
|
||||
key,
|
||||
mergeSchemas(
|
||||
objects
|
||||
.map((schema) => (schema.properties as Record<string, Schema>)[key])
|
||||
.filter((schema) => schema !== undefined),
|
||||
),
|
||||
]),
|
||||
),
|
||||
required: keys.filter((key) =>
|
||||
objects.every((schema) => key in (schema.properties as Schema)),
|
||||
),
|
||||
}
|
||||
}
|
||||
return { anyOf: unique }
|
||||
}
|
||||
|
||||
function inferSchema(value: unknown): Schema {
|
||||
if (value === null) return { type: 'null' }
|
||||
if (Array.isArray(value)) {
|
||||
return value.length === 0
|
||||
? { type: 'array', items: {} }
|
||||
: { type: 'array', items: mergeSchemas(value.map(inferSchema)) }
|
||||
}
|
||||
if (typeof value === 'object') {
|
||||
const entries = Object.entries(value as Record<string, unknown>)
|
||||
return {
|
||||
type: 'object',
|
||||
properties: Object.fromEntries(entries.map(([key, child]) => [key, inferSchema(child)])),
|
||||
required: entries.map(([key]) => key),
|
||||
}
|
||||
}
|
||||
if (typeof value === 'number') return { type: Number.isInteger(value) ? 'integer' : 'number' }
|
||||
return { type: typeof value }
|
||||
}
|
||||
|
||||
function operation(item: ApiEndpoint) {
|
||||
const pathParameters = [...item.path.matchAll(/\{(\w+)\}/g)].map((match) => ({
|
||||
name: match[1],
|
||||
@@ -234,7 +281,10 @@ function operation(item: ApiEndpoint) {
|
||||
: {
|
||||
description: 'Success',
|
||||
content: {
|
||||
'application/json': { schema: {}, ...(example === undefined ? {} : { example }) },
|
||||
'application/json': {
|
||||
schema: example === undefined ? {} : inferSchema(example),
|
||||
...(example === undefined ? {} : { example }),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user