refactor: examplev2 created and lintfix
This commit is contained in:
@@ -0,0 +1,184 @@
|
|||||||
|
import { OpenAPIV2 } from "openapi-types"
|
||||||
|
import * as O from "fp-ts/Option"
|
||||||
|
import { pipe, flow } from "fp-ts/function"
|
||||||
|
import * as A from "fp-ts/Array"
|
||||||
|
|
||||||
|
type PrimitiveSchemaType = "string" | "integer" | "number" | "boolean"
|
||||||
|
|
||||||
|
type SchemaType = "array" | "object" | PrimitiveSchemaType
|
||||||
|
|
||||||
|
type PrimitiveRequestBodyExampleType = number | string | boolean
|
||||||
|
|
||||||
|
type RequestBodyExampleType =
|
||||||
|
| { [name: string]: RequestBodyExampleType }
|
||||||
|
| Array<RequestBodyExampleType>
|
||||||
|
| PrimitiveRequestBodyExampleType
|
||||||
|
|
||||||
|
const getPrimitiveTypePlaceholder = (
|
||||||
|
schemaType: PrimitiveSchemaType
|
||||||
|
): PrimitiveRequestBodyExampleType => {
|
||||||
|
switch (schemaType) {
|
||||||
|
case "string":
|
||||||
|
return "string"
|
||||||
|
case "integer":
|
||||||
|
case "number":
|
||||||
|
return 1
|
||||||
|
case "boolean":
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getSchemaTypeFromSchemaObject = (
|
||||||
|
schema: OpenAPIV2.SchemaObject
|
||||||
|
): O.Option<SchemaType> =>
|
||||||
|
pipe(
|
||||||
|
schema.type,
|
||||||
|
O.fromNullable,
|
||||||
|
O.map(
|
||||||
|
(schemaType) =>
|
||||||
|
(Array.isArray(schemaType) ? schemaType[0] : schemaType) as SchemaType
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
const isSchemaTypePrimitive = (
|
||||||
|
schemaType: string
|
||||||
|
): schemaType is PrimitiveSchemaType =>
|
||||||
|
["string", "integer", "number", "boolean"].includes(schemaType)
|
||||||
|
|
||||||
|
const isSchemaTypeArray = (schemaType: string): schemaType is "array" =>
|
||||||
|
schemaType === "array"
|
||||||
|
|
||||||
|
const isSchemaTypeObject = (schemaType: string): schemaType is "object" =>
|
||||||
|
schemaType === "object"
|
||||||
|
|
||||||
|
const getSampleEnumValueOrPlaceholder = (
|
||||||
|
schema: OpenAPIV2.SchemaObject
|
||||||
|
): RequestBodyExampleType => {
|
||||||
|
const enumValue = pipe(
|
||||||
|
schema.enum,
|
||||||
|
O.fromNullable,
|
||||||
|
O.map((enums) => enums[0] as RequestBodyExampleType)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (O.isSome(enumValue)) return enumValue.value
|
||||||
|
|
||||||
|
return pipe(
|
||||||
|
schema,
|
||||||
|
getSchemaTypeFromSchemaObject,
|
||||||
|
O.filter(isSchemaTypePrimitive),
|
||||||
|
O.map(getPrimitiveTypePlaceholder),
|
||||||
|
O.getOrElseW(() => "")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const generateExampleArrayFromOpenAPIV2ItemsObject = (
|
||||||
|
items: OpenAPIV2.ItemsObject
|
||||||
|
): RequestBodyExampleType => {
|
||||||
|
// ItemsObject can not hold type "object"
|
||||||
|
// https://swagger.io/specification/v2/#itemsObject
|
||||||
|
|
||||||
|
// TODO : Handle array of objects
|
||||||
|
// https://stackoverflow.com/questions/60490974/how-to-define-an-array-of-objects-in-openapi-2-0
|
||||||
|
|
||||||
|
const primitivePlaceholder = pipe(
|
||||||
|
items,
|
||||||
|
O.fromPredicate(
|
||||||
|
flow((items) => items.type as SchemaType, isSchemaTypePrimitive)
|
||||||
|
),
|
||||||
|
O.map(getSampleEnumValueOrPlaceholder)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (O.isSome(primitivePlaceholder))
|
||||||
|
return Array.of(primitivePlaceholder.value, primitivePlaceholder.value)
|
||||||
|
|
||||||
|
// If the type is not primitive, it is "array"
|
||||||
|
// items property is required if type is array
|
||||||
|
return Array.of(
|
||||||
|
generateExampleArrayFromOpenAPIV2ItemsObject(
|
||||||
|
items.items as OpenAPIV2.ItemsObject
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const generateRequestBodyExampleFromOpenAPIV2BodySchema = (
|
||||||
|
schema: OpenAPIV2.SchemaObject
|
||||||
|
): RequestBodyExampleType => {
|
||||||
|
if (schema.example) return schema.example as RequestBodyExampleType
|
||||||
|
|
||||||
|
const primitiveTypeExample = pipe(
|
||||||
|
schema,
|
||||||
|
O.fromPredicate(
|
||||||
|
flow(
|
||||||
|
getSchemaTypeFromSchemaObject,
|
||||||
|
O.map(isSchemaTypePrimitive),
|
||||||
|
O.getOrElseW(() => false) // No schema type found in the schema object, assume non-primitive
|
||||||
|
)
|
||||||
|
),
|
||||||
|
O.map(getSampleEnumValueOrPlaceholder) // Use enum or placeholder to populate primitive field
|
||||||
|
)
|
||||||
|
|
||||||
|
if (O.isSome(primitiveTypeExample)) return primitiveTypeExample.value
|
||||||
|
|
||||||
|
const arrayTypeExample = pipe(
|
||||||
|
schema,
|
||||||
|
O.fromPredicate(
|
||||||
|
flow(
|
||||||
|
getSchemaTypeFromSchemaObject,
|
||||||
|
O.map(isSchemaTypeArray),
|
||||||
|
O.getOrElseW(() => false) // No schema type found in the schema object, assume type to be different from array
|
||||||
|
)
|
||||||
|
),
|
||||||
|
O.map((schema) => schema.items as OpenAPIV2.ItemsObject),
|
||||||
|
O.map(generateExampleArrayFromOpenAPIV2ItemsObject)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (O.isSome(arrayTypeExample)) return arrayTypeExample.value
|
||||||
|
|
||||||
|
return pipe(
|
||||||
|
schema,
|
||||||
|
O.fromPredicate(
|
||||||
|
flow(
|
||||||
|
getSchemaTypeFromSchemaObject,
|
||||||
|
O.map(isSchemaTypeObject),
|
||||||
|
O.getOrElseW(() => false)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
O.chain((schema) =>
|
||||||
|
pipe(
|
||||||
|
schema.properties,
|
||||||
|
O.fromNullable,
|
||||||
|
O.map(
|
||||||
|
(properties) =>
|
||||||
|
Object.entries(properties) as [string, OpenAPIV2.SchemaObject][]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
O.getOrElseW(() => [] as [string, OpenAPIV2.SchemaObject][]),
|
||||||
|
A.reduce(
|
||||||
|
{} as { [name: string]: RequestBodyExampleType },
|
||||||
|
(aggregatedExample, property) => {
|
||||||
|
const example = generateRequestBodyExampleFromOpenAPIV2BodySchema(
|
||||||
|
property[1]
|
||||||
|
)
|
||||||
|
aggregatedExample[property[0]] = example
|
||||||
|
return aggregatedExample
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const generateRequestBodyExampleFromOpenAPIV2Body = (
|
||||||
|
op: OpenAPIV2.OperationObject
|
||||||
|
): string =>
|
||||||
|
pipe(
|
||||||
|
(op.parameters ?? []) as OpenAPIV2.Parameter[],
|
||||||
|
A.findFirst((param) => param.in === "body"),
|
||||||
|
O.map(
|
||||||
|
flow(
|
||||||
|
(parameter) => parameter.schema,
|
||||||
|
generateRequestBodyExampleFromOpenAPIV2BodySchema
|
||||||
|
)
|
||||||
|
),
|
||||||
|
O.getOrElse(() => "" as RequestBodyExampleType),
|
||||||
|
(requestBodyExample) => JSON.stringify(requestBodyExample, null, "\t") // Using a tab character mimics standard pretty-print appearance
|
||||||
|
)
|
||||||
@@ -3,60 +3,106 @@ import { pipe } from "fp-ts/function"
|
|||||||
import * as A from "fp-ts/Array"
|
import * as A from "fp-ts/Array"
|
||||||
import * as O from "fp-ts/Option"
|
import * as O from "fp-ts/Option"
|
||||||
|
|
||||||
type SchemaType = OpenAPIV3.ArraySchemaObjectType | OpenAPIV3.NonArraySchemaObjectType
|
type SchemaType =
|
||||||
|
| OpenAPIV3.ArraySchemaObjectType
|
||||||
|
| OpenAPIV3.NonArraySchemaObjectType
|
||||||
|
|
||||||
type PrimitiveSchemaType = Exclude<SchemaType, "array" | "object">
|
type PrimitiveSchemaType = Exclude<SchemaType, "array" | "object">
|
||||||
|
|
||||||
type PrimitiveRequestBodyExampleType = string | number | boolean | null
|
type PrimitiveRequestBodyExampleType = string | number | boolean | null
|
||||||
|
|
||||||
type RequestBodyExampleType = PrimitiveRequestBodyExampleType | Array<RequestBodyExampleType> | { [name: string]: RequestBodyExampleType }
|
type RequestBodyExampleType =
|
||||||
|
| PrimitiveRequestBodyExampleType
|
||||||
const isSchemaTypePrimitive = (schemaType: SchemaType) : schemaType is PrimitiveSchemaType => !["array", "object"].includes(schemaType)
|
| Array<RequestBodyExampleType>
|
||||||
|
| { [name: string]: RequestBodyExampleType }
|
||||||
|
|
||||||
const getPrimitiveTypePlaceholder = (primitiveType: PrimitiveSchemaType) : PrimitiveRequestBodyExampleType => {
|
const isSchemaTypePrimitive = (
|
||||||
switch(primitiveType) {
|
schemaType: SchemaType
|
||||||
case "number": return 0.0
|
): schemaType is PrimitiveSchemaType =>
|
||||||
case "integer": return 0
|
!["array", "object"].includes(schemaType)
|
||||||
case "string": return "string"
|
|
||||||
case "boolean": return true
|
const getPrimitiveTypePlaceholder = (
|
||||||
}
|
primitiveType: PrimitiveSchemaType
|
||||||
|
): PrimitiveRequestBodyExampleType => {
|
||||||
|
switch (primitiveType) {
|
||||||
|
case "number":
|
||||||
|
return 0.0
|
||||||
|
case "integer":
|
||||||
|
return 0
|
||||||
|
case "string":
|
||||||
|
return "string"
|
||||||
|
case "boolean":
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use carefully, call only when type is primitive
|
// Use carefully, call only when type is primitive
|
||||||
// TODO(agarwal): Use Enum values, if any
|
// TODO(agarwal): Use Enum values, if any
|
||||||
const generatePrimitiveRequestBodyExample = (schemaObject: OpenAPIV3.NonArraySchemaObject) : RequestBodyExampleType =>
|
const generatePrimitiveRequestBodyExample = (
|
||||||
getPrimitiveTypePlaceholder(schemaObject.type as PrimitiveSchemaType)
|
schemaObject: OpenAPIV3.NonArraySchemaObject
|
||||||
|
): RequestBodyExampleType =>
|
||||||
|
getPrimitiveTypePlaceholder(schemaObject.type as PrimitiveSchemaType)
|
||||||
|
|
||||||
// Use carefully, call only when type is object
|
// Use carefully, call only when type is object
|
||||||
const generateObjectRequestBodyExample = (schemaObject: OpenAPIV3.NonArraySchemaObject) : RequestBodyExampleType =>
|
const generateObjectRequestBodyExample = (
|
||||||
pipe(
|
schemaObject: OpenAPIV3.NonArraySchemaObject
|
||||||
schemaObject.properties,
|
): RequestBodyExampleType =>
|
||||||
O.fromNullable,
|
pipe(
|
||||||
O.map((properties) => Object.entries(properties) as [string, OpenAPIV3.SchemaObject][]),
|
schemaObject.properties,
|
||||||
O.getOrElseW(() => [] as [string, OpenAPIV3.SchemaObject][]),
|
O.fromNullable,
|
||||||
A.reduce(
|
O.map(
|
||||||
{} as {[name: string]: RequestBodyExampleType},
|
(properties) =>
|
||||||
(aggregatedExample, property) => {
|
Object.entries(properties) as [string, OpenAPIV3.SchemaObject][]
|
||||||
aggregatedExample[property[0]] = generateRequestBodyExampleFromSchemaObject(property[1])
|
),
|
||||||
return aggregatedExample
|
O.getOrElseW(() => [] as [string, OpenAPIV3.SchemaObject][]),
|
||||||
}
|
A.reduce(
|
||||||
)
|
{} as { [name: string]: RequestBodyExampleType },
|
||||||
|
(aggregatedExample, property) => {
|
||||||
|
aggregatedExample[property[0]] =
|
||||||
|
generateRequestBodyExampleFromSchemaObject(property[1])
|
||||||
|
return aggregatedExample
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
const generateArrayRequestBodyExample = (schemaObject: OpenAPIV3.ArraySchemaObject) : RequestBodyExampleType =>
|
const generateArrayRequestBodyExample = (
|
||||||
Array.of(generateRequestBodyExampleFromSchemaObject(schemaObject.items as OpenAPIV3.SchemaObject))
|
schemaObject: OpenAPIV3.ArraySchemaObject
|
||||||
|
): RequestBodyExampleType =>
|
||||||
|
Array.of(
|
||||||
|
generateRequestBodyExampleFromSchemaObject(
|
||||||
|
schemaObject.items as OpenAPIV3.SchemaObject
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
const generateRequestBodyExampleFromSchemaObject = (schemaObject: OpenAPIV3.SchemaObject) : RequestBodyExampleType => {
|
const generateRequestBodyExampleFromSchemaObject = (
|
||||||
// TODO: Handle schema objects with oneof or anyof
|
schemaObject: OpenAPIV3.SchemaObject
|
||||||
if(schemaObject.example) return schemaObject.example as RequestBodyExampleType
|
): RequestBodyExampleType => {
|
||||||
if(!schemaObject.type) return ""
|
// TODO: Handle schema objects with oneof or anyof
|
||||||
if(isSchemaTypePrimitive(schemaObject.type)) return generatePrimitiveRequestBodyExample(schemaObject as OpenAPIV3.NonArraySchemaObject)
|
if (schemaObject.example)
|
||||||
if(schemaObject.type === "object") return generateObjectRequestBodyExample(schemaObject as OpenAPIV3.NonArraySchemaObject)
|
return schemaObject.example as RequestBodyExampleType
|
||||||
return generateArrayRequestBodyExample(schemaObject as OpenAPIV3.ArraySchemaObject)
|
if (!schemaObject.type) return ""
|
||||||
|
if (isSchemaTypePrimitive(schemaObject.type))
|
||||||
|
return generatePrimitiveRequestBodyExample(
|
||||||
|
schemaObject as OpenAPIV3.NonArraySchemaObject
|
||||||
|
)
|
||||||
|
if (schemaObject.type === "object")
|
||||||
|
return generateObjectRequestBodyExample(
|
||||||
|
schemaObject as OpenAPIV3.NonArraySchemaObject
|
||||||
|
)
|
||||||
|
return generateArrayRequestBodyExample(
|
||||||
|
schemaObject as OpenAPIV3.ArraySchemaObject
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const generateRequestBodyExampleFromMediaObject = (mediaObject: OpenAPIV3.MediaTypeObject) : RequestBodyExampleType => {
|
export const generateRequestBodyExampleFromMediaObject = (
|
||||||
if(mediaObject.example) return mediaObject.example as RequestBodyExampleType
|
mediaObject: OpenAPIV3.MediaTypeObject
|
||||||
if(mediaObject.examples) return mediaObject.examples[0] as RequestBodyExampleType
|
): RequestBodyExampleType => {
|
||||||
return mediaObject.schema ? generateRequestBodyExampleFromSchemaObject(mediaObject.schema as OpenAPIV3.SchemaObject) : ""
|
if (mediaObject.example) return mediaObject.example as RequestBodyExampleType
|
||||||
}
|
if (mediaObject.examples)
|
||||||
|
return mediaObject.examples[0] as RequestBodyExampleType
|
||||||
|
return mediaObject.schema
|
||||||
|
? generateRequestBodyExampleFromSchemaObject(
|
||||||
|
mediaObject.schema as OpenAPIV3.SchemaObject
|
||||||
|
)
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,82 +3,133 @@ import { pipe } from "fp-ts/function"
|
|||||||
import * as O from "fp-ts/Option"
|
import * as O from "fp-ts/Option"
|
||||||
import * as A from "fp-ts/Array"
|
import * as A from "fp-ts/Array"
|
||||||
|
|
||||||
type MixedArraySchemaType = (OpenAPIV31.ArraySchemaObjectType | OpenAPIV31.NonArraySchemaObjectType)[]
|
type MixedArraySchemaType = (
|
||||||
|
| OpenAPIV31.ArraySchemaObjectType
|
||||||
|
| OpenAPIV31.NonArraySchemaObjectType
|
||||||
|
)[]
|
||||||
|
|
||||||
type SchemaType = OpenAPIV31.ArraySchemaObjectType | OpenAPIV31.NonArraySchemaObjectType | MixedArraySchemaType
|
type SchemaType =
|
||||||
|
| OpenAPIV31.ArraySchemaObjectType
|
||||||
|
| OpenAPIV31.NonArraySchemaObjectType
|
||||||
|
| MixedArraySchemaType
|
||||||
|
|
||||||
type PrimitiveSchemaType = Exclude<OpenAPIV31.NonArraySchemaObjectType, "object">
|
type PrimitiveSchemaType = Exclude<
|
||||||
|
OpenAPIV31.NonArraySchemaObjectType,
|
||||||
|
"object"
|
||||||
|
>
|
||||||
|
|
||||||
type PrimitiveRequestBodyExampleType = string | number | boolean | null
|
type PrimitiveRequestBodyExampleType = string | number | boolean | null
|
||||||
|
|
||||||
type RequestBodyExampleType = PrimitiveRequestBodyExampleType | Array<RequestBodyExampleType> | { [name: string]: RequestBodyExampleType }
|
type RequestBodyExampleType =
|
||||||
|
| PrimitiveRequestBodyExampleType
|
||||||
|
| Array<RequestBodyExampleType>
|
||||||
|
| { [name: string]: RequestBodyExampleType }
|
||||||
|
|
||||||
const isSchemaTypePrimitive = (schemaType: SchemaType) : schemaType is PrimitiveSchemaType => !Array.isArray(schemaType) && !["array", "object"].includes(schemaType)
|
const isSchemaTypePrimitive = (
|
||||||
|
schemaType: SchemaType
|
||||||
|
): schemaType is PrimitiveSchemaType =>
|
||||||
|
!Array.isArray(schemaType) && !["array", "object"].includes(schemaType)
|
||||||
|
|
||||||
const getPrimitiveTypePlaceholder = (primitiveType: PrimitiveSchemaType) : PrimitiveRequestBodyExampleType => {
|
const getPrimitiveTypePlaceholder = (
|
||||||
switch(primitiveType) {
|
primitiveType: PrimitiveSchemaType
|
||||||
case "number": return 0.0
|
): PrimitiveRequestBodyExampleType => {
|
||||||
case "integer": return 0
|
switch (primitiveType) {
|
||||||
case "string": return "string"
|
case "number":
|
||||||
case "boolean": return true
|
return 0.0
|
||||||
}
|
case "integer":
|
||||||
return null
|
return 0
|
||||||
|
case "string":
|
||||||
|
return "string"
|
||||||
|
case "boolean":
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use carefully, the schema type should necessarily be primitive
|
// Use carefully, the schema type should necessarily be primitive
|
||||||
// TODO(agarwal): Use Enum values, if any
|
// TODO(agarwal): Use Enum values, if any
|
||||||
const generatePrimitiveRequestBodyExample = (schemaObject: OpenAPIV31.NonArraySchemaObject) : RequestBodyExampleType =>
|
const generatePrimitiveRequestBodyExample = (
|
||||||
getPrimitiveTypePlaceholder(schemaObject.type as PrimitiveSchemaType)
|
schemaObject: OpenAPIV31.NonArraySchemaObject
|
||||||
|
): RequestBodyExampleType =>
|
||||||
|
getPrimitiveTypePlaceholder(schemaObject.type as PrimitiveSchemaType)
|
||||||
|
|
||||||
// Use carefully, the schema type should necessarily be object
|
// Use carefully, the schema type should necessarily be object
|
||||||
const generateObjectRequestBodyExample = (schemaObject: OpenAPIV31.NonArraySchemaObject) : RequestBodyExampleType =>
|
const generateObjectRequestBodyExample = (
|
||||||
pipe(
|
schemaObject: OpenAPIV31.NonArraySchemaObject
|
||||||
schemaObject.properties,
|
): RequestBodyExampleType =>
|
||||||
O.fromNullable,
|
pipe(
|
||||||
O.map((properties) => Object.entries(properties) as [string, OpenAPIV31.SchemaObject][]),
|
schemaObject.properties,
|
||||||
O.getOrElseW(() => [] as [string, OpenAPIV31.SchemaObject][]),
|
O.fromNullable,
|
||||||
A.reduce(
|
O.map(
|
||||||
{} as {[name: string]: RequestBodyExampleType},
|
(properties) =>
|
||||||
(aggregatedExample, property) => {
|
Object.entries(properties) as [string, OpenAPIV31.SchemaObject][]
|
||||||
aggregatedExample[property[0]] = generateRequestBodyExampleFromSchemaObject(property[1])
|
),
|
||||||
return aggregatedExample
|
O.getOrElseW(() => [] as [string, OpenAPIV31.SchemaObject][]),
|
||||||
}
|
A.reduce(
|
||||||
)
|
{} as { [name: string]: RequestBodyExampleType },
|
||||||
|
(aggregatedExample, property) => {
|
||||||
|
aggregatedExample[property[0]] =
|
||||||
|
generateRequestBodyExampleFromSchemaObject(property[1])
|
||||||
|
return aggregatedExample
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
// Use carefully, the schema type should necessarily be mixed array
|
// Use carefully, the schema type should necessarily be mixed array
|
||||||
const generateMixedArrayRequestBodyEcample = (schemaObject: OpenAPIV31.SchemaObject) : RequestBodyExampleType =>
|
const generateMixedArrayRequestBodyEcample = (
|
||||||
pipe(
|
schemaObject: OpenAPIV31.SchemaObject
|
||||||
schemaObject,
|
): RequestBodyExampleType =>
|
||||||
schemaObject => schemaObject.type as MixedArraySchemaType,
|
pipe(
|
||||||
A.reduce(
|
schemaObject,
|
||||||
[] as Array<RequestBodyExampleType>,
|
(schemaObject) => schemaObject.type as MixedArraySchemaType,
|
||||||
(aggregatedExample, itemType) => {
|
A.reduce(
|
||||||
// TODO: Figure out how to include non-primitive types as well
|
[] as Array<RequestBodyExampleType>,
|
||||||
if(isSchemaTypePrimitive(itemType)) {
|
(aggregatedExample, itemType) => {
|
||||||
aggregatedExample.push(getPrimitiveTypePlaceholder(itemType))
|
// TODO: Figure out how to include non-primitive types as well
|
||||||
}
|
if (isSchemaTypePrimitive(itemType)) {
|
||||||
return aggregatedExample
|
aggregatedExample.push(getPrimitiveTypePlaceholder(itemType))
|
||||||
}
|
}
|
||||||
)
|
return aggregatedExample
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
const generateArrayRequestBodyExample = (schemaObject: OpenAPIV31.ArraySchemaObject) : RequestBodyExampleType =>
|
const generateArrayRequestBodyExample = (
|
||||||
Array.of(generateRequestBodyExampleFromSchemaObject(schemaObject.items as OpenAPIV31.SchemaObject))
|
schemaObject: OpenAPIV31.ArraySchemaObject
|
||||||
|
): RequestBodyExampleType =>
|
||||||
|
Array.of(
|
||||||
|
generateRequestBodyExampleFromSchemaObject(
|
||||||
|
schemaObject.items as OpenAPIV31.SchemaObject
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
const generateRequestBodyExampleFromSchemaObject = (schemaObject: OpenAPIV31.SchemaObject) : RequestBodyExampleType => {
|
const generateRequestBodyExampleFromSchemaObject = (
|
||||||
// TODO: Handle schema objects with oneof or anyof
|
schemaObject: OpenAPIV31.SchemaObject
|
||||||
if(schemaObject.example) return schemaObject.example as RequestBodyExampleType
|
): RequestBodyExampleType => {
|
||||||
if(schemaObject.examples) return schemaObject.examples[0] as RequestBodyExampleType
|
// TODO: Handle schema objects with oneof or anyof
|
||||||
if(!schemaObject.type) return ""
|
if (schemaObject.example)
|
||||||
if(isSchemaTypePrimitive(schemaObject.type)) return generatePrimitiveRequestBodyExample(schemaObject as OpenAPIV31.NonArraySchemaObject)
|
return schemaObject.example as RequestBodyExampleType
|
||||||
if(schemaObject.type === "object") return generateObjectRequestBodyExample(schemaObject)
|
if (schemaObject.examples)
|
||||||
if(schemaObject.type === "array") return generateArrayRequestBodyExample(schemaObject)
|
return schemaObject.examples[0] as RequestBodyExampleType
|
||||||
return generateMixedArrayRequestBodyEcample(schemaObject)
|
if (!schemaObject.type) return ""
|
||||||
|
if (isSchemaTypePrimitive(schemaObject.type))
|
||||||
|
return generatePrimitiveRequestBodyExample(
|
||||||
|
schemaObject as OpenAPIV31.NonArraySchemaObject
|
||||||
|
)
|
||||||
|
if (schemaObject.type === "object")
|
||||||
|
return generateObjectRequestBodyExample(schemaObject)
|
||||||
|
if (schemaObject.type === "array")
|
||||||
|
return generateArrayRequestBodyExample(schemaObject)
|
||||||
|
return generateMixedArrayRequestBodyEcample(schemaObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const generateRequestBodyExampleFromMediaObject = (mediaObject: OpenAPIV31.MediaTypeObject) : RequestBodyExampleType => {
|
export const generateRequestBodyExampleFromMediaObject = (
|
||||||
if(mediaObject.example) return mediaObject.example as RequestBodyExampleType
|
mediaObject: OpenAPIV31.MediaTypeObject
|
||||||
if(mediaObject.examples) return mediaObject.examples[0] as RequestBodyExampleType
|
): RequestBodyExampleType => {
|
||||||
return mediaObject.schema ? generateRequestBodyExampleFromSchemaObject(mediaObject.schema) : ""
|
if (mediaObject.example) return mediaObject.example as RequestBodyExampleType
|
||||||
}
|
if (mediaObject.examples)
|
||||||
|
return mediaObject.examples[0] as RequestBodyExampleType
|
||||||
|
return mediaObject.schema
|
||||||
|
? generateRequestBodyExampleFromSchemaObject(mediaObject.schema)
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import { step } from "../../steps"
|
|||||||
import { defineImporter, IMPORTER_INVALID_FILE_FORMAT } from "../"
|
import { defineImporter, IMPORTER_INVALID_FILE_FORMAT } from "../"
|
||||||
import { generateRequestBodyExampleFromMediaObject as generateExampleV31 } from "./exampleV31"
|
import { generateRequestBodyExampleFromMediaObject as generateExampleV31 } from "./exampleV31"
|
||||||
import { generateRequestBodyExampleFromMediaObject as generateExampleV3 } from "./exampleV3"
|
import { generateRequestBodyExampleFromMediaObject as generateExampleV3 } from "./exampleV3"
|
||||||
|
import { generateRequestBodyExampleFromOpenAPIV2Body } from "./exampleV2"
|
||||||
|
|
||||||
const OPENAPI_DEREF_ERROR = "openapi/deref_error" as const
|
const OPENAPI_DEREF_ERROR = "openapi/deref_error" as const
|
||||||
|
|
||||||
@@ -183,190 +184,6 @@ const parseOpenAPIV3BodyFormData = (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type PrimitiveSchemaType = "string" | "integer" | "number" | "boolean"
|
|
||||||
|
|
||||||
type SchemaType = "array" | "object" | PrimitiveSchemaType
|
|
||||||
|
|
||||||
type PrimitiveRequestBodyExampleType = number | string | boolean
|
|
||||||
|
|
||||||
type RequestBodyExampleType =
|
|
||||||
| { [name: string]: RequestBodyExampleType }
|
|
||||||
| Array<RequestBodyExampleType>
|
|
||||||
| PrimitiveRequestBodyExampleType
|
|
||||||
|
|
||||||
const getPrimitiveTypePlaceholder = (
|
|
||||||
schemaType: PrimitiveSchemaType
|
|
||||||
): PrimitiveRequestBodyExampleType => {
|
|
||||||
switch (schemaType) {
|
|
||||||
case "string":
|
|
||||||
return "string"
|
|
||||||
case "integer":
|
|
||||||
case "number":
|
|
||||||
return 1
|
|
||||||
case "boolean":
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getSchemaTypeFromSchemaObject = (
|
|
||||||
schema: OpenAPIV2.SchemaObject
|
|
||||||
): O.Option<SchemaType> =>
|
|
||||||
pipe(
|
|
||||||
schema.type,
|
|
||||||
O.fromNullable,
|
|
||||||
O.map(
|
|
||||||
(schemaType) =>
|
|
||||||
(Array.isArray(schemaType) ? schemaType[0] : schemaType) as SchemaType
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
const isSchemaTypePrimitive = (
|
|
||||||
schemaType: string
|
|
||||||
): schemaType is PrimitiveSchemaType =>
|
|
||||||
["string", "integer", "number", "boolean"].includes(schemaType)
|
|
||||||
|
|
||||||
const isSchemaTypeArray = (schemaType: string): schemaType is "array" =>
|
|
||||||
schemaType === "array"
|
|
||||||
|
|
||||||
const isSchemaTypeObject = (schemaType: string): schemaType is "object" =>
|
|
||||||
schemaType === "object"
|
|
||||||
|
|
||||||
const getSampleEnumValueOrPlaceholder = (
|
|
||||||
schema: OpenAPIV2.SchemaObject
|
|
||||||
): RequestBodyExampleType => {
|
|
||||||
const enumValue = pipe(
|
|
||||||
schema.enum,
|
|
||||||
O.fromNullable,
|
|
||||||
O.map((enums) => enums[0] as RequestBodyExampleType)
|
|
||||||
)
|
|
||||||
|
|
||||||
if (O.isSome(enumValue)) return enumValue.value
|
|
||||||
|
|
||||||
return pipe(
|
|
||||||
schema,
|
|
||||||
getSchemaTypeFromSchemaObject,
|
|
||||||
O.filter(isSchemaTypePrimitive),
|
|
||||||
O.map(getPrimitiveTypePlaceholder),
|
|
||||||
O.getOrElseW(() => "")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const generateExampleArrayFromOpenAPIV2ItemsObject = (
|
|
||||||
items: OpenAPIV2.ItemsObject
|
|
||||||
): RequestBodyExampleType => {
|
|
||||||
// ItemsObject can not hold type "object"
|
|
||||||
// https://swagger.io/specification/v2/#itemsObject
|
|
||||||
|
|
||||||
// TODO : Handle array of objects
|
|
||||||
// https://stackoverflow.com/questions/60490974/how-to-define-an-array-of-objects-in-openapi-2-0
|
|
||||||
|
|
||||||
const primitivePlaceholder = pipe(
|
|
||||||
items,
|
|
||||||
O.fromPredicate(
|
|
||||||
flow((items) => items.type as SchemaType, isSchemaTypePrimitive)
|
|
||||||
),
|
|
||||||
O.map(getSampleEnumValueOrPlaceholder)
|
|
||||||
)
|
|
||||||
|
|
||||||
if (O.isSome(primitivePlaceholder))
|
|
||||||
return Array.of(primitivePlaceholder.value, primitivePlaceholder.value)
|
|
||||||
|
|
||||||
// If the type is not primitive, it is "array"
|
|
||||||
// items property is required if type is array
|
|
||||||
return Array.of(
|
|
||||||
generateExampleArrayFromOpenAPIV2ItemsObject(
|
|
||||||
items.items as OpenAPIV2.ItemsObject
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const generateRequestBodyExampleFromOpenAPIV2BodySchema = (
|
|
||||||
schema: OpenAPIV2.SchemaObject
|
|
||||||
): RequestBodyExampleType => {
|
|
||||||
if (schema.example) return schema.example as RequestBodyExampleType
|
|
||||||
|
|
||||||
const primitiveTypeExample = pipe(
|
|
||||||
schema,
|
|
||||||
O.fromPredicate(
|
|
||||||
flow(
|
|
||||||
getSchemaTypeFromSchemaObject,
|
|
||||||
O.map(isSchemaTypePrimitive),
|
|
||||||
O.getOrElseW(() => false) // No schema type found in the schema object, assume non-primitive
|
|
||||||
)
|
|
||||||
),
|
|
||||||
O.map(getSampleEnumValueOrPlaceholder) // Use enum or placeholder to populate primitive field
|
|
||||||
)
|
|
||||||
|
|
||||||
if (O.isSome(primitiveTypeExample)) return primitiveTypeExample.value
|
|
||||||
|
|
||||||
const arrayTypeExample = pipe(
|
|
||||||
schema,
|
|
||||||
O.fromPredicate(
|
|
||||||
flow(
|
|
||||||
getSchemaTypeFromSchemaObject,
|
|
||||||
O.map(isSchemaTypeArray),
|
|
||||||
O.getOrElseW(() => false) // No schema type found in the schema object, assume type to be different from array
|
|
||||||
)
|
|
||||||
),
|
|
||||||
O.map((schema) => schema.items as OpenAPIV2.ItemsObject),
|
|
||||||
O.map(generateExampleArrayFromOpenAPIV2ItemsObject)
|
|
||||||
)
|
|
||||||
|
|
||||||
if (O.isSome(arrayTypeExample)) return arrayTypeExample.value
|
|
||||||
|
|
||||||
return pipe(
|
|
||||||
schema,
|
|
||||||
O.fromPredicate(
|
|
||||||
flow(
|
|
||||||
getSchemaTypeFromSchemaObject,
|
|
||||||
O.map(isSchemaTypeObject),
|
|
||||||
O.getOrElseW(() => false)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
O.chain((schema) =>
|
|
||||||
pipe(
|
|
||||||
schema.properties,
|
|
||||||
O.fromNullable,
|
|
||||||
O.map(
|
|
||||||
(properties) =>
|
|
||||||
Object.entries(properties) as [string, OpenAPIV2.SchemaObject][]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
O.getOrElseW(() => [] as [string, OpenAPIV2.SchemaObject][]),
|
|
||||||
A.reduce(
|
|
||||||
{} as { [name: string]: RequestBodyExampleType },
|
|
||||||
(aggregatedExample, property) => {
|
|
||||||
const example = generateRequestBodyExampleFromOpenAPIV2BodySchema(
|
|
||||||
property[1]
|
|
||||||
)
|
|
||||||
aggregatedExample[property[0]] = example
|
|
||||||
return aggregatedExample
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const getSchemaFromOpenAPIV2Parameter = (
|
|
||||||
parameter: OpenAPIV2.Parameter
|
|
||||||
): OpenAPIV2.SchemaObject => parameter.schema
|
|
||||||
|
|
||||||
const generateRequestBodyExampleFromOpenAPIV2Body = (
|
|
||||||
op: OpenAPIV2.OperationObject
|
|
||||||
): string =>
|
|
||||||
pipe(
|
|
||||||
(op.parameters ?? []) as OpenAPIV2.Parameter[],
|
|
||||||
A.findFirst((param) => param.in === "body"),
|
|
||||||
O.map(
|
|
||||||
flow(
|
|
||||||
getSchemaFromOpenAPIV2Parameter,
|
|
||||||
generateRequestBodyExampleFromOpenAPIV2BodySchema
|
|
||||||
)
|
|
||||||
),
|
|
||||||
O.getOrElse(() => "" as RequestBodyExampleType),
|
|
||||||
(requestBodyExample) => JSON.stringify(requestBodyExample, null, "\t") // Using a tab character mimics standard pretty-print appearance
|
|
||||||
)
|
|
||||||
|
|
||||||
const parseOpenAPIV3Body = (
|
const parseOpenAPIV3Body = (
|
||||||
op: OpenAPIV3.OperationObject | OpenAPIV31.OperationObject,
|
op: OpenAPIV3.OperationObject | OpenAPIV31.OperationObject,
|
||||||
isV31Request: boolean
|
isV31Request: boolean
|
||||||
|
|||||||
Reference in New Issue
Block a user