fix(oas): support additional props, fix circular references patch, and other fixes (#9213)

* chore(oas): support additional props, fix circular references patch, and other fixes

* fix description

* description fixes
This commit is contained in:
Shahed Nasser
2024-09-20 17:22:19 +03:00
committed by GitHub
parent 3084008fc9
commit 6a2a105cf8
8 changed files with 197 additions and 36 deletions

View File

@@ -69,9 +69,16 @@ class OasSchemaHelper {
// check if schema has child schemas
// and convert those
if (schema.properties) {
Object.keys(schema.properties).forEach((property) => {
const propertySchema = schema.properties![property]
const properties = schema.properties
? schema.properties
: schema.additionalProperties &&
typeof schema.additionalProperties !== "boolean" &&
!this.isRefObject(schema.additionalProperties)
? schema.additionalProperties.properties
: undefined
if (properties) {
Object.keys(properties).forEach((property) => {
const propertySchema = properties![property]
if ("$ref" in propertySchema) {
return
}
@@ -105,7 +112,7 @@ class OasSchemaHelper {
})
}
schema.properties![property] =
properties![property] =
this.namedSchemaToReference(
propertySchema as OpenApiSchema,
level + 1
@@ -178,6 +185,28 @@ class OasSchemaHelper {
this.namedSchemaToReference(transformedProperty) ||
transformedProperty
})
} else if (
clonedSchema.additionalProperties &&
typeof clonedSchema.additionalProperties !== "boolean" &&
!this.isRefObject(clonedSchema.additionalProperties) &&
clonedSchema.additionalProperties.properties
) {
const additionalProps = schema.additionalProperties as OpenApiSchema
Object.entries(clonedSchema.additionalProperties.properties).forEach(
([key, property]) => {
if (this.isRefObject(property)) {
return
}
const transformedProperty = this.schemaChildrenToRefs(
property,
level + 1
)
additionalProps.properties![key] =
this.namedSchemaToReference(transformedProperty) ||
transformedProperty
}
)
}
return clonedSchema
@@ -186,10 +215,17 @@ class OasSchemaHelper {
isSchemaEmpty(schema: OpenApiSchema): boolean {
switch (schema.type) {
case "object":
return (
const isPropertiesEmpty =
schema.properties === undefined ||
Object.keys(schema.properties).length === 0
)
const isAdditionalPropertiesEmpty =
schema.additionalProperties === undefined ||
typeof schema.additionalProperties === "boolean" ||
(!this.isRefObject(schema.additionalProperties) &&
(schema.additionalProperties.properties === undefined ||
Object.keys(schema.additionalProperties.properties).length == 0))
return isPropertiesEmpty && isAdditionalPropertiesEmpty
case "array":
return (
!this.isRefObject(schema.items) && this.isSchemaEmpty(schema.items)
@@ -350,6 +386,7 @@ class OasSchemaHelper {
| OpenApiSchema
| OpenAPIV3.RequestBodyObject
| OpenAPIV3.ResponseObject
| OpenAPIV3.ParameterObject
| undefined
): schema is OpenAPIV3.ReferenceObject {
return schema !== undefined && "$ref" in schema

View File

@@ -1512,10 +1512,6 @@ class OasKindGenerator extends FunctionKindGenerator {
case itemType.isClassOrInterface() ||
itemType.isTypeParameter() ||
(itemType as ts.Type).flags === ts.TypeFlags.Object:
const properties: Record<
string,
OpenApiSchema | OpenAPIV3.ReferenceObject
> = {}
const requiredProperties: string[] = []
const baseType = itemType.getBaseTypes()?.[0]
@@ -1535,8 +1531,26 @@ class OasKindGenerator extends FunctionKindGenerator {
required: undefined,
}
const properties: Record<
string,
OpenApiSchema | OpenAPIV3.ReferenceObject
> = {}
let isAdditionalProperties = false
if (level + 1 <= this.MAX_LEVEL) {
itemType.getProperties().forEach((property) => {
let itemProperties = itemType.getProperties()
if (
!itemProperties.length &&
itemType.aliasTypeArguments?.length === 2 &&
itemType.aliasTypeArguments[0].flags === ts.TypeFlags.String
) {
// object has dynamic keys, so put the properties under additionalProperties
itemProperties = itemType.aliasTypeArguments[1].getProperties()
isAdditionalProperties = true
}
itemProperties.forEach((property) => {
if (
(allowedChildren && !allowedChildren.includes(property.name)) ||
(disallowedChildren && disallowedChildren.includes(property.name))
@@ -1624,7 +1638,14 @@ class OasKindGenerator extends FunctionKindGenerator {
}
if (Object.values(properties).length) {
objSchema.properties = properties
if (isAdditionalProperties) {
objSchema.additionalProperties = {
type: "object",
properties,
}
} else {
objSchema.properties = properties
}
}
objSchema.required =
@@ -1987,6 +2008,26 @@ class OasKindGenerator extends FunctionKindGenerator {
oldSchemaObj!.properties = newSchemaObj.properties
} else if (!newSchemaObj?.properties) {
delete oldSchemaObj!.properties
// check if additionalProperties should be updated
if (
!oldSchemaObj!.additionalProperties &&
newSchemaObj.additionalProperties
) {
oldSchemaObj!.additionalProperties = newSchemaObj.additionalProperties
} else if (!newSchemaObj.additionalProperties) {
delete oldSchemaObj!.additionalProperties
} else if (
typeof oldSchemaObj!.additionalProperties !== "boolean" &&
typeof newSchemaObj!.additionalProperties !== "boolean"
) {
oldSchemaObj!.additionalProperties =
this.updateSchema({
oldSchema: oldSchemaObj!.additionalProperties,
newSchema: newSchemaObj.additionalProperties,
level: level + 1,
}) || oldSchemaObj!.additionalProperties
}
} else {
// update existing properties
Object.entries(oldSchemaObj!.properties!).forEach(

View File

@@ -175,6 +175,30 @@ export default async function () {
})
// collect schemas
oas.parameters?.forEach((parameter) => {
if (oasSchemaHelper.isRefObject(parameter)) {
referencedSchemas.add(
oasSchemaHelper.normalizeSchemaName(parameter.$ref)
)
return
}
if (!parameter.schema) {
return
}
if (oasSchemaHelper.isRefObject(parameter.schema)) {
referencedSchemas.add(
oasSchemaHelper.normalizeSchemaName(parameter.schema.$ref)
)
return
}
testAndFindReferenceSchema(parameter.schema)
})
if (oas.requestBody) {
if (oasSchemaHelper.isRefObject(oas.requestBody)) {
referencedSchemas.add(