import { model } from "amf-client-js" ; import { resolveApiModel , parseRamlFile , getAllDataTypes , } from "../common/amfParser" ; import { Name } from "../common/structures/name" ; import { RestApi } from "../download/exchangeTypes" ; import path from "path" ; import fs from "fs-extra" ; import { ramlToolLogger } from "../common/logger" ; import _ from "lodash" ; import { ApiMetadata } from "./" ; /**
 * An API represented as an AMF model. Includes the extracted data types
 * defined in the spec. Common transformations of the name are cached for
 * reference in templates and for use in assembling file paths.
 */ export class ApiModel extends ApiMetadata { model : model . document . Document ; dataTypes : model . domain . CustomDomainProperty [ ] = [ ] ; metadata : RestApi ; main : string ; path : string ; param { string } name param { string } filepath param { ApiMetadata [ ] } children memberof constructor ( name , filepath , children = [ ] ) { super ( name , filepath , children ) ; if ( path . extname ( filepath ) === ".raml" || path . extname ( filepath ) === ".rml" ) { this . main = filepath ; this . path = path . basename ( filepath ) ; } else if ( fs . lstatSync ( filepath ) . isDirectory ( ) && fs . existsSync ( path . join ( filepath , "exchange.json" ) ) ) { const exchangeConfig = fs . readJSONSync ( path . join ( filepath , "exchange.json" ) ) ; this . main = exchangeConfig [ "main" ] ; this . path = filepath ; } else { throw new Error ( "No exchange.json or no raml file provided, can't load api" ) ; } } description memberof public updateName ( ) { if ( ! this . model ) { throw new Error ( "Cannot update the name before the model is loaded" ) ; } this . name = new Name ( ( this . model . encodes as model . domain . WebApi ) ?. name . value ( ) ) ; } description param { boolean } updateName returns { Promise < void > } memberof public async loadModel ( updateName = true ) { ramlToolLogger . info ( `Loading model for ${ this . name . original }` ) ; const tmpModel = await parseRamlFile ( path . join ( this . path , this . main ) ) ; this . dataTypes = getAllDataTypes ( _ . cloneDeep ( tmpModel ) ) ; this . model = resolveApiModel ( tmpModel , "editing" ) ; if ( updateName ) { this . updateName ( ) ; } } description param { boolean } updateName returns { Promise < void > } memberof public async init ( updateName = true ) { await this . loadModel ( updateName ) ; await super . init ( ) ; } description returns { Promise < void > } memberof public async renderThis ( ) { if ( ! this . model ) { await this . loadModel ( ) ; } ramlToolLogger . info ( `Rendering templates for ${ this . name . original }` ) ; const promises = this . templates . map ( async ( template ) => { try { await fs . ensureDir ( path . dirname ( template . outputFile ) ) ; await fs . writeFile ( template . outputFile , template . handlebarTemplate ( this , { allowProtoPropertiesByDefault : true , allowProtoMethodsByDefault : true , } ) ) ; } catch ( err ) { ramlToolLogger . error ( `Error while rendering ${ template . outputFile }:` , err ) ; } } ) ; await Promise . all ( promises ) ; } }