import { SchemaObject , OpenAPIObject } from 'openapi3-ts' ; import { EnumValue } from './enum-value' ; import { GenType } from './gen-type' ; import { tsComments , tsType , unqualifiedName } from './gen-utils' ; import { Options } from './options' ; import { Property } from './property' ; /**
 * Context to generate a model
 */ export class Model extends GenType { isSimple : boolean ; isEnum : boolean ; isObject : boolean ; simpleType : string ; enumValues : EnumValue [ ] ; elementType : string ; properties : Property [ ] ; additionalPropertiesType : string ; constructor ( public openApi , name , public schema , options ) { super ( name , unqualifiedName , options ) ; const description = schema . description || '' ; this . tsComments = tsComments ( description , 0 , schema . deprecated ) ; const type = schema . type || 'any' ; if ( options . enumStyle !== 'alias' && ( schema . enum || [ ] ) . length > 0 && [ 'string' , 'number' , 'integer' ] . includes ( type ) ) { const names = schema [ 'x-enumNames' ] as string [ ] || [ ] ; const values = schema . enum || [ ] ; this . enumValues = [ ] ; for ( let i = 0 ; i < values . length ; i ++ ) { const enumValue = new EnumValue ( type , names [ i ] , values [ i ] , options ) ; this . enumValues . push ( enumValue ) ; } } this . isObject = ( type === 'object' || ! ! schema . properties ) && ! schema . nullable ; this . isEnum = ( this . enumValues || [ ] ) . length > 0 ; this . isSimple = ! this . isObject && ! this . isEnum ; if ( this . isObject ) { const propertiesByName = new Map < string , Property > ( ) ; this . collectObject ( schema , propertiesByName ) ; const sortedNames = [ ... propertiesByName . keys ( ) ] ; sortedNames . sort ( ) ; this . properties = sortedNames . map ( propName => propertiesByName . get ( propName ) as Property ) ; } else { this . simpleType = tsType ( schema , options , openApi ) ; } this . collectImports ( schema ) ; this . updateImports ( ) ; } protected pathToModels ( ) { if ( this . namespace ) { const depth = this . namespace . split ( '/' ) . length ; let path = '' ; for ( let i = 0 ; i < depth ; i ++ ) { path += '../' ; } return path ; } return './' ; } protected skipImport ( name ) { return this . name === name ; } private collectObject ( schema , propertiesByName ) { if ( schema . type === 'object' || ! ! schema . properties ) { const properties = schema . properties || { } ; const required = schema . required || [ ] ; const propNames = Object . keys ( properties ) ; const propTypes = new Set < string > ( ) ; const appendType = ( type ) => { if ( type . startsWith ( 'null | ' ) ) { propTypes . add ( 'null' ) ; propTypes . add ( type . substr ( 'null | ' . length ) ) ; } else { propTypes . add ( type ) ; } } ; for ( const propName of propNames ) { const prop = new Property ( this , propName , properties [ propName ] , required . includes ( propName ) , this . options , this . openApi ) ; propertiesByName . set ( propName , prop ) ; appendType ( prop . type ) ; if ( ! prop . required ) { propTypes . add ( 'undefined' ) ; } } if ( schema . additionalProperties === true ) { this . additionalPropertiesType = 'any' ; } else if ( schema . additionalProperties ) { const propType = tsType ( schema . additionalProperties , this . options , this . openApi ) ; appendType ( propType ) ; this . additionalPropertiesType = [ ... propTypes ] . sort ( ) . join ( ' | ' ) ; } } if ( schema . allOf ) { schema . allOf . forEach ( s => this . collectObject ( s , propertiesByName ) ) ; } } }