UNPKG

ts-json-schema-generator

Version:

Generate JSON schema from your Typescript sources

97 lines (85 loc) 4.14 kB
import type { Definition } from "../Schema/Definition.js"; import type { RawTypeName } from "../Schema/RawType.js"; import type { BaseType } from "../Type/BaseType.js"; import type { TypeFormatter } from "../TypeFormatter.js"; import { uniqueArray } from "./uniqueArray.js"; import { deepMerge } from "./deepMerge.js"; import { derefType } from "./derefType.js"; // TODO: Can we do this at parse time? See heritage clause in interfaces. // TODO: We really only need this if the children use additionalProperties: false. export function getAllOfDefinitionReducer(childTypeFormatter: TypeFormatter) { // combine object instead of using allOf because allOf does not work well with additional properties return (definition: Definition, baseType: BaseType): Definition => { const other = childTypeFormatter.getDefinition(derefType(baseType)); definition.properties = deepMerge(other.properties || {}, definition.properties || {}); function additionalPropsDefinition(props?: boolean | Definition): props is Definition { return props !== undefined && props !== true; } if ( additionalPropsDefinition(definition.additionalProperties) && additionalPropsDefinition(other.additionalProperties) ) { // additional properties is false only if all children also set additional properties to false // collect additional properties and merge into a single definition let additionalProps: Definition[] = []; let additionalTypes: RawTypeName[] = []; const addAdditionalProps: (addProps: Definition) => void = (addProps: Definition) => { if (addProps) { if (addProps.anyOf) { for (const prop of addProps.anyOf as Definition[]) { if (prop.type) { additionalTypes = additionalTypes.concat( Array.isArray(prop.type) ? prop.type : [prop.type], ); } else { additionalProps.push(prop); } } } else if (addProps.type) { additionalTypes = additionalTypes.concat( Array.isArray(addProps.type) ? addProps.type : [addProps.type], ); } else { additionalProps.push(addProps); } } }; addAdditionalProps(definition.additionalProperties); addAdditionalProps(other.additionalProperties); additionalTypes = uniqueArray(additionalTypes); additionalProps = uniqueArray(additionalProps); if (additionalTypes.length > 1) { additionalProps.push({ type: additionalTypes, }); } else if (additionalTypes.length === 1) { additionalProps.push({ type: additionalTypes[0], }); } if (additionalProps.length > 1) { definition.additionalProperties = { anyOf: additionalProps, }; } else if (additionalProps.length === 1) { if (Object.keys(additionalProps[0]).length === 0) { delete definition.additionalProperties; } else { definition.additionalProperties = additionalProps[0]; } } else { definition.additionalProperties = false; } } if (other.required) { definition.required = uniqueArray((definition.required || []).concat(other.required)).sort(); } if ( (other.additionalProperties || other.additionalProperties === undefined) && definition.additionalProperties == false ) { delete definition.additionalProperties; } return definition; }; }