import { writeFile } from 'fs/promises' ; import { join } from 'path' ; import stringify from 'safe-stable-stringify' ; import { Model } from './model/metamodel' ; import { compileEndpoints , compileSpecification } from './model/build-model' ; import buildJsonSpec , { JsonSpec } from './model/json-spec' ; import { ValidationErrors } from './validation-errors' ; type StepFunction = ( model : Model , restSpec : Map < string , JsonSpec > , errors : ValidationErrors ) => Promise < Model > ; /**
 * The main job of the compiler is to generate the Model and write it on disk.
 * If needed you can add one or more intermediate steps between the
 * model generation and the disk write. This can be done by using
 * the `step` method.
 * Each steps takes as input the model and the rest-api-spec,
 * and must return the model, even if it wasn't changed.
 */ export default class Compiler { queue : StepFunction [ ] ; model : Model ; jsonSpec : Map < string , JsonSpec > ; errors : ValidationErrors ; constructor ( ) { this . queue = [ ] ; this . errors = new ValidationErrors ( ) ; } generateModel ( ) { this . jsonSpec = buildJsonSpec ( ) ; const endpoints = compileEndpoints ( ) ; this . model = compileSpecification ( endpoints ) ; return this ; } async write ( ) { for ( const step of this . queue ) { this . model = await step ( this . model , this . jsonSpec , this . errors ) ; } await writeFile ( join ( __dirname , '..' , '..' , 'output' , 'schema' , 'schema.json' ) , stringify ( this . model , null , 2 ) , 'utf8' ) ; this . errors . log ( ) ; await writeFile ( join ( __dirname , '..' , '..' , 'output' , 'schema' , 'validation-errors.json' ) , stringify ( this . errors , null , 2 ) , 'utf8' ) ; } step ( step ) { this . queue . push ( step ) ; return this ; } }