import { unixEOL , unique } from '@sap-cloud-sdk/util' ; import { ModuleDeclarationStructure , StructureKind , VariableDeclarationKind , VariableStatementStructure , OptionalKind , VariableDeclarationStructure } from 'ts-morph' ; import { getGenericParameters , linkClass } from '../generator-utils' ; import { prependPrefix } from '../internal-prefix' ; import { getStaticNavPropertyDescription , getStaticPropertyDescription , addLeadingNewline } from '../typedoc' ; import { VdmEntity , VdmNavigationProperty , VdmProperty , VdmServiceMetadata } from '../vdm-types' ; internal export function entityNamespace ( entity , service ) { return { kind : StructureKind . Module , name : entity . className , isExported : true , statements : [ fieldBuilderInitializer ( entity ) , ... properties ( entity ) , ... navigationProperties ( entity , service ) , allFields ( entity , service ) , allFieldSelector ( entity ) , keyFields ( entity ) , keys ( entity ) ] } ; } function fieldBuilderInitializer ( entity ) { return { kind : StructureKind . VariableStatement , declarationKind : VariableDeclarationKind . Const , declarations : [ { name : '_fieldBuilder' , type : `FieldBuilder<Constructable<${ entity . className }>>` , initializer : `new FieldBuilder(${ entity . className })` } ] , isExported : false } ; } function properties ( entity ) { return entity . properties . map ( prop => property ( prop ) ) ; } function getFieldInitializer ( prop ) { return { name : prop . staticPropertyName , initializer : createPropertyFieldInitializerForEntity ( prop ) } ; } export function createPropertyFieldInitializerForEntity ( prop , fieldBuilderName = '_fieldBuilder' ) { if ( prop . isCollection ) { if ( prop . isComplex ) { return `${ fieldBuilderName }.buildCollectionField('${ prop . originalName }', ${ prop . jsType }, ${ prop . nullable })` ; } if ( prop . isEnum ) { return `${ fieldBuilderName }.buildCollectionField('${ prop . originalName }', ${ prop . jsType }, ${ prop . nullable })` ; } return `${ fieldBuilderName }.buildCollectionField('${ prop . originalName }', '${ prop . edmType }', ${ prop . nullable })` ; } if ( prop . isComplex ) { return `${ fieldBuilderName }.buildComplexTypeField('${ prop . originalName }', ${ prop . fieldType }, ${ prop . nullable })` ; } if ( prop . isEnum ) { return `${ fieldBuilderName }.buildEnumField('${ prop . originalName }', ${ prop . jsType }, ${ prop . nullable })` ; } return `${ fieldBuilderName }.buildEdmTypeField('${ prop . originalName }', '${ prop . edmType }', ${ prop . nullable })` ; } export function getPropertyFieldType ( entity , prop , fieldBuilderName = '_fieldBuilder' ) { if ( prop . isCollection ) { if ( prop . isComplex ) { return `CollectionField<${ entity . className }, DeSerializersT, ${ prop . jsType }, ${ prop . nullable }, true>` ; } if ( prop . isEnum ) { return `CollectionField<${ entity . className }, DeSerializersT, string, ${ prop . nullable }, true>` ; } return `CollectionField<${ entity . className }, DeSerializersT, DeSerializedType<DeSerializersT,, ${ prop . nullable }, true>` ; } if ( prop . isComplex ) { return 'Comple' ; return `${ fieldBuilderName }.buildComplexTypeField('${ prop . originalName }', ${ prop . fieldType }, ${ prop . nullable })` ; } if ( prop . isEnum ) { return `${ fieldBuilderName }.buildEnumField('${ prop . originalName }', ${ prop . jsType }, ${ prop . nullable })` ; } return `${ fieldBuilderName }.buildEdmTypeField('${ prop . originalName }', '${ prop . edmType }', ${ prop . nullable })` ; } function property ( prop ) { return { kind : StructureKind . VariableStatement , declarationKind : VariableDeclarationKind . Const , declarations : [ getFieldInitializer ( prop ) ] , docs : [ getStaticPropertyDescription ( prop ) ] , isExported : true } ; } function navigationProperties ( entity , service ) { return entity . navigationProperties . map ( navProp => navigationProperty ( navProp , entity , service ) ) ; } function navigationProperty ( navProp , entity , service ) { const matchedEntity = service . entities . find ( e => e . entitySetName === navProp . to ) ; if ( ! matchedEntity ) { throw Error ( `Failed to find the entity from the service: ${ JSON . stringify ( service ) } for nav property ${ navProp }` ) ; } const toEntity = matchedEntity . className ; return { kind : StructureKind . VariableStatement , declarationKind : VariableDeclarationKind . Const , declarations : [ { name : navProp . staticPropertyName , type : `${ linkClass ( navProp , service . oDataVersion ) }<${ entity . className },${ toEntity }>` , initializer : `new ${ linkClass ( navProp , service . oDataVersion ) }('${ navProp . originalName }', ${ entity . className }, ${ toEntity })` } ] , docs : [ getStaticNavPropertyDescription ( navProp ) ] , isExported : true } ; } function allFields ( entity , service ) { const fieldTypes = unique ( [ ... entity . properties . map ( p => `${ p . fieldType }<${ getGenericParameters ( entity . className , p , true ) }>` ) , ... entity . navigationProperties . map ( p => `${ linkClass ( p , service . oDataVersion ) }<${ entity . className },${ p . toEntityClassName }>` ) ] ) ; return { kind : StructureKind . VariableStatement , declarationKind : VariableDeclarationKind . Const , declarations : [ { name : prependPrefix ( 'allFields' ) , type : `Array<${ fieldTypes . join ( ' | ' ) }>` , initializer : `[
          ${ entity . properties . map ( prop => prop . staticPropertyName ) . concat ( entity . navigationProperties . map ( navProp => navProp . staticPropertyName ) ) . map ( name => `${ entity . className }.${ name }` ) . join ( `, ${ unixEOL }` ) }
          ]` } ] , docs : [ addLeadingNewline ( `All fields of the ${ entity . className } entity.` ) ] , isExported : true } ; } function allFieldSelector ( entity ) { return { kind : StructureKind . VariableStatement , declarationKind : VariableDeclarationKind . Const , declarations : [ { name : 'ALL_FIELDS' , type : `AllFields<${ entity . className }>` , initializer : `new AllFields('*', ${ entity . className })` } ] , docs : [ addLeadingNewline ( 'All fields selector.' ) ] , isExported : true } ; } function keyFields ( entity ) { return { kind : StructureKind . VariableStatement , declarationKind : VariableDeclarationKind . Const , declarations : [ { name : prependPrefix ( 'keyFields' ) , type : `Array<Field<${ entity . className }, boolean, boolean>>` , initializer : '[' + entity . keys . map ( key => `${ entity . className }.${ key . staticPropertyName }` ) . join ( ', ' ) + ']' } ] , docs : [ addLeadingNewline ( `All key fields of the ${ entity . className } entity.` ) ] , isExported : true } ; } function keys ( entity ) { return { kind : StructureKind . VariableStatement , declarationKind : VariableDeclarationKind . Const , declarations : [ { name : prependPrefix ( 'keys' ) , type : `{[keys: string]: Field<${ entity . className }, boolean, boolean>}` , initializer : `${ entity . className }.${ prependPrefix ( 'keyFields' ) }.reduce((acc: {[keys: string]: Field<${ entity . className }, boolean, boolean>}, field: Field<${ entity . className }, boolean, boolean>) => {
          acc[field._fieldName] = field;
          return acc;
        }, {})` } ] , docs : [ addLeadingNewline ( `Mapping of all key field names to the respective static field property ${ entity . className }.` ) ] , isExported : true } ; }