feat: v3 requests example working
This commit is contained in:
committed by
Andrew Bastin
parent
721a201e7a
commit
bc2f81ff25
@@ -0,0 +1,62 @@
|
||||
import { OpenAPIV3 } from "openapi-types"
|
||||
import { pipe } from "fp-ts/function"
|
||||
import * as A from "fp-ts/Array"
|
||||
import * as O from "fp-ts/Option"
|
||||
|
||||
type SchemaType = OpenAPIV3.ArraySchemaObjectType | OpenAPIV3.NonArraySchemaObjectType
|
||||
|
||||
type PrimitiveSchemaType = Exclude<SchemaType, "array" | "object">
|
||||
|
||||
type PrimitiveRequestBodyExampleType = string | number | boolean | null
|
||||
|
||||
type RequestBodyExampleType = PrimitiveRequestBodyExampleType | Array<RequestBodyExampleType> | { [name: string]: RequestBodyExampleType }
|
||||
|
||||
const isSchemaTypePrimitive = (schemaType: SchemaType) : schemaType is PrimitiveSchemaType => !["array", "object"].includes(schemaType)
|
||||
|
||||
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
|
||||
// TODO(agarwal): Use Enum values, if any
|
||||
const generatePrimitiveRequestBodyExample = (schemaObject: OpenAPIV3.NonArraySchemaObject) : RequestBodyExampleType =>
|
||||
getPrimitiveTypePlaceholder(schemaObject.type as PrimitiveSchemaType)
|
||||
|
||||
// Use carefully, call only when type is object
|
||||
const generateObjectRequestBodyExample = (schemaObject: OpenAPIV3.NonArraySchemaObject) : RequestBodyExampleType =>
|
||||
pipe(
|
||||
schemaObject.properties,
|
||||
O.fromNullable,
|
||||
O.map((properties) => Object.entries(properties) as [string, OpenAPIV3.SchemaObject][]),
|
||||
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 =>
|
||||
Array.of(generateRequestBodyExampleFromSchemaObject(schemaObject.items as OpenAPIV3.SchemaObject))
|
||||
|
||||
const generateRequestBodyExampleFromSchemaObject = (schemaObject: OpenAPIV3.SchemaObject) : RequestBodyExampleType => {
|
||||
// TODO: Handle schema objects with oneof or anyof
|
||||
if(schemaObject.example) return schemaObject.example as RequestBodyExampleType
|
||||
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 => {
|
||||
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) : ""
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import { OpenAPIV3_1 as OpenAPIV31 } from "openapi-types"
|
||||
import { pipe } from "fp-ts/function"
|
||||
import * as O from "fp-ts/Option"
|
||||
import * as A from "fp-ts/Array"
|
||||
|
||||
type MixedArraySchemaType = (OpenAPIV31.ArraySchemaObjectType | OpenAPIV31.NonArraySchemaObjectType)[]
|
||||
|
||||
type SchemaType = OpenAPIV31.ArraySchemaObjectType | OpenAPIV31.NonArraySchemaObjectType | MixedArraySchemaType
|
||||
|
||||
type PrimitiveSchemaType = Exclude<OpenAPIV31.NonArraySchemaObjectType, "object">
|
||||
|
||||
type PrimitiveRequestBodyExampleType = string | number | boolean | null
|
||||
|
||||
type RequestBodyExampleType = PrimitiveRequestBodyExampleType | Array<RequestBodyExampleType> | { [name: string]: RequestBodyExampleType }
|
||||
|
||||
const isSchemaTypePrimitive = (schemaType: SchemaType) : schemaType is PrimitiveSchemaType => !Array.isArray(schemaType) && !["array", "object"].includes(schemaType)
|
||||
|
||||
const getPrimitiveTypePlaceholder = (primitiveType: PrimitiveSchemaType) : PrimitiveRequestBodyExampleType => {
|
||||
switch(primitiveType) {
|
||||
case "number": return 0.0
|
||||
case "integer": return 0
|
||||
case "string": return "string"
|
||||
case "boolean": return true
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// Use carefully, the schema type should necessarily be primitive
|
||||
// TODO(agarwal): Use Enum values, if any
|
||||
const generatePrimitiveRequestBodyExample = (schemaObject: OpenAPIV31.NonArraySchemaObject) : RequestBodyExampleType =>
|
||||
getPrimitiveTypePlaceholder(schemaObject.type as PrimitiveSchemaType)
|
||||
|
||||
// Use carefully, the schema type should necessarily be object
|
||||
const generateObjectRequestBodyExample = (schemaObject: OpenAPIV31.NonArraySchemaObject) : RequestBodyExampleType =>
|
||||
pipe(
|
||||
schemaObject.properties,
|
||||
O.fromNullable,
|
||||
O.map((properties) => Object.entries(properties) as [string, OpenAPIV31.SchemaObject][]),
|
||||
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
|
||||
const generateMixedArrayRequestBodyEcample = (schemaObject: OpenAPIV31.SchemaObject) : RequestBodyExampleType =>
|
||||
pipe(
|
||||
schemaObject,
|
||||
schemaObject => schemaObject.type as MixedArraySchemaType,
|
||||
A.reduce(
|
||||
[] as Array<RequestBodyExampleType>,
|
||||
(aggregatedExample, itemType) => {
|
||||
// TODO: Figure out how to include non-primitive types as well
|
||||
if(isSchemaTypePrimitive(itemType)) {
|
||||
aggregatedExample.push(getPrimitiveTypePlaceholder(itemType))
|
||||
}
|
||||
return aggregatedExample
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
const generateArrayRequestBodyExample = (schemaObject: OpenAPIV31.ArraySchemaObject) : RequestBodyExampleType =>
|
||||
Array.of(generateRequestBodyExampleFromSchemaObject(schemaObject.items as OpenAPIV31.SchemaObject))
|
||||
|
||||
const generateRequestBodyExampleFromSchemaObject = (schemaObject: OpenAPIV31.SchemaObject) : RequestBodyExampleType => {
|
||||
// TODO: Handle schema objects with oneof or anyof
|
||||
if(schemaObject.example) return schemaObject.example as RequestBodyExampleType
|
||||
if(schemaObject.examples) return schemaObject.examples[0] as RequestBodyExampleType
|
||||
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 => {
|
||||
if(mediaObject.example) return mediaObject.example as RequestBodyExampleType
|
||||
if(mediaObject.examples) return mediaObject.examples[0] as RequestBodyExampleType
|
||||
return mediaObject.schema ? generateRequestBodyExampleFromSchemaObject(mediaObject.schema) : ""
|
||||
}
|
||||
@@ -24,8 +24,10 @@ import * as S from "fp-ts/string"
|
||||
import * as O from "fp-ts/Option"
|
||||
import * as TE from "fp-ts/TaskEither"
|
||||
import * as RA from "fp-ts/ReadonlyArray"
|
||||
import { step } from "../steps"
|
||||
import { defineImporter, IMPORTER_INVALID_FILE_FORMAT } from "."
|
||||
import { step } from "../../steps"
|
||||
import { defineImporter, IMPORTER_INVALID_FILE_FORMAT } from "../"
|
||||
import { generateRequestBodyExampleFromMediaObject as generateExampleV31 } from "./exampleV31"
|
||||
import { generateRequestBodyExampleFromMediaObject as generateExampleV3 } from "./exampleV3"
|
||||
|
||||
export const OPENAPI_DEREF_ERROR = "openapi/deref_error" as const
|
||||
|
||||
@@ -366,7 +368,8 @@ const generateRequestBodyExampleFromOpenAPIV2Body = (
|
||||
)
|
||||
|
||||
const parseOpenAPIV3Body = (
|
||||
op: OpenAPIV3.OperationObject | OpenAPIV31.OperationObject
|
||||
op: OpenAPIV3.OperationObject | OpenAPIV31.OperationObject,
|
||||
isV31Request: boolean
|
||||
): HoppRESTReqBody => {
|
||||
const objs = Object.entries(
|
||||
(
|
||||
@@ -385,11 +388,19 @@ const parseOpenAPIV3Body = (
|
||||
OpenAPIV3.MediaTypeObject | OpenAPIV31.MediaTypeObject
|
||||
] = objs[0]
|
||||
|
||||
const exampleBody = JSON.stringify(
|
||||
isV31Request
|
||||
? generateExampleV31(media as OpenAPIV31.MediaTypeObject)
|
||||
: generateExampleV3(media as OpenAPIV3.MediaTypeObject),
|
||||
null,
|
||||
"\t"
|
||||
)
|
||||
|
||||
return contentType in knownContentTypes
|
||||
? contentType === "multipart/form-data" ||
|
||||
contentType === "application/x-www-form-urlencoded"
|
||||
? parseOpenAPIV3BodyFormData(contentType, media)
|
||||
: { contentType: contentType as any, body: "" }
|
||||
: { contentType: contentType as any, body: exampleBody }
|
||||
: { contentType: null, body: null }
|
||||
}
|
||||
|
||||
@@ -401,12 +412,20 @@ const isOpenAPIV3Operation = (
|
||||
typeof doc.openapi === "string" &&
|
||||
doc.openapi.startsWith("3.")
|
||||
|
||||
const isOpenAPIV31Operation = (
|
||||
doc: OpenAPI.Document,
|
||||
op: OpenAPIOperationType
|
||||
): op is OpenAPIV31.OperationObject =>
|
||||
objectHasProperty(doc, "openapi") &&
|
||||
typeof doc.openapi === "string" &&
|
||||
doc.openapi.startsWith("3.1")
|
||||
|
||||
const parseOpenAPIBody = (
|
||||
doc: OpenAPI.Document,
|
||||
op: OpenAPIOperationType
|
||||
): HoppRESTReqBody =>
|
||||
isOpenAPIV3Operation(doc, op)
|
||||
? parseOpenAPIV3Body(op)
|
||||
? parseOpenAPIV3Body(op, isOpenAPIV31Operation(doc, op))
|
||||
: parseOpenAPIV2Body(op)
|
||||
|
||||
const resolveOpenAPIV3SecurityObj = (
|
||||
Reference in New Issue
Block a user