file copyright author Vivek M. Chawla <@VivekMChawla>
 *  summary description version license import * as core from '@salesforce/core' ; import { JsonMap } from '@salesforce/ts-types' ; import * as path from 'path' ; import { SfdxFalconDebug } from '../../modules/sfdx-falcon-debug' ; import { SfdxFalconError } from '../../modules/sfdx-falcon-error' ; import { SfdxFalconProject } from '../../modules/sfdx-falcon-project' ; import { SfdxFalconResult } from '../../modules/sfdx-falcon-result' ; import { SfdxFalconResultType } from '../../modules/sfdx-falcon-result' ; import { AppxRecipeEngine } from './engines/appx' ; import { AppxDemoConfigEngine } from './engines/appx/demo-config' ; import { RecipeType } from './types' ; import { CompileOptions } from './types' ; import { ExecutionOptions } from './types' ; const dbgNs = 'RECIPE:sfdx-falcon-recipe:' ; interface description export interface SfdxFalconRecipeJson { recipeName : string ; description : string ; recipeType : string ; recipeVersion : string ; schemaVersion : string ; options : JsonMap ; recipeStepGroups : JsonMap [ ] ; handlers : JsonMap [ ] ; } class summary description version public export class SfdxFalconRecipe { method param { SfdxFalconProject } sfdxFPO param { string } recipeFile description public static async public static async read ( sfdxFPO , recipeFile ) { const recipePath = sfdxFPO . configPath ; const recipe = await SfdxFalconRecipe . resolveSfdxFalconRecipe ( recipePath , recipeFile ) ; try { SfdxFalconRecipe . validate ( recipe ) ; } catch ( error ) { const combinedPath = path . join ( recipePath , recipeFile ) ; throw new SfdxFalconError ( `Recipe file '${ combinedPath }' is invalid.  ${ error . message }` , `InvalidRecipe` , `${ dbgNs }read` , error ) ; } const sfdxFR = new SfdxFalconRecipe ( ) ; sfdxFR . _recipeName = recipe . recipeName ; sfdxFR . _description = recipe . description ; sfdxFR . _recipeType = recipe . recipeType as RecipeType ; sfdxFR . _recipeVersion = recipe . recipeVersion ; sfdxFR . _schemaVersion = recipe . schemaVersion ; sfdxFR . _options = recipe . options ; sfdxFR . _recipeStepGroups = recipe . recipeStepGroups ; sfdxFR . _handlers = recipe . handlers ; sfdxFR . _validated = true ; sfdxFR . _projectContext = sfdxFPO ; sfdxFR . _falconRecipeResult = new SfdxFalconResult ( sfdxFR . recipeName , SfdxFalconResultType . RECIPE , { startNow : false , bubbleError : true , bubbleFailure : true } ) ; sfdxFR . _falconRecipeResultDetail = { projectContext : sfdxFR . _projectContext , recipeEngine : null , recipeName : sfdxFR . recipeName , recipeDescription : sfdxFR . _description , recipeType : sfdxFR . _recipeType , recipeVersion : sfdxFR . _recipeVersion , recipeSchemaVersion : sfdxFR . _schemaVersion , recipeOptions : sfdxFR . _options , recipeStepGroups : sfdxFR . _recipeStepGroups , recipeHandlers : sfdxFR . _handlers } ; return sfdxFR ; } method param { string } recipePath param { string } recipeFile returns { Promise < object > } description private static async private static async resolveSfdxFalconRecipe ( recipePath , recipeFile ) { const configOptions = { rootFolder : recipePath , filename : recipeFile , isGlobal : false , isState : false } ; const combinedPath = path . join ( configOptions . rootFolder , configOptions . filename ) ; SfdxFalconDebug . obj ( `${ dbgNs }resolveSfdxFalconRecipe:configOptions:` , configOptions , `configOptions: ` ) ; const sfdxFalconRecipeFile = await core . ConfigFile . create ( configOptions ) . catch ( error => { throw new SfdxFalconError ( `Recipe file '${ combinedPath }' is invalid.  Reason: ${ error . message }` , `InvalidRecipe` , `${ dbgNs }resolveSfdxFalconRecipe` , error ) ; } ) ; if ( await sfdxFalconRecipeFile . exists ( ) === false ) { throw new SfdxFalconError ( `Recipe file '${ combinedPath }' does not exist.` , `RecipeNotFound` , `${ dbgNs }resolveSfdxFalconRecipe` ) ; } SfdxFalconDebug . obj ( `${ dbgNs }resolveSfdxFalconRecipe:sfdxFalconRecipeFile:` , sfdxFalconRecipeFile , `sfdxFalconRecipeFile: ` ) ; const sfdxFalconRecipe = sfdxFalconRecipeFile . toObject ( ) as unknown as SfdxFalconRecipeJson ; SfdxFalconDebug . obj ( `${ dbgNs }resolveSfdxFalconRecipe:sfdxFalconRecipe:` , sfdxFalconRecipe , `sfdxFalconRecipe: ` ) ; return sfdxFalconRecipe ; } method param { SfdxFalconRecipeJson } sfdxFalconRecipeJson returns { void } description version private static private static validate ( sfdxFalconRecipeJson ) { SfdxFalconRecipe . validateTopLevelProperties ( sfdxFalconRecipeJson ) ; switch ( sfdxFalconRecipeJson . recipeType ) { case RecipeType . APPX_DEMO : AppxDemoConfigEngine . validateRecipe ( sfdxFalconRecipeJson ) ; break ; case RecipeType . APPX_PACKAGE : break ; default : throw new SfdxFalconError ( `Recipe type '${ sfdxFalconRecipeJson . recipeType }' does not exist.` , `InvalidRecipe` , `${ dbgNs }validate` ) ; } } method param { SfdxFalconRecipeJson } sfdxFalconRecipe returns { void } description private static private static validateTopLevelProperties ( sfdxFalconRecipe ) { const invalidConfigKeys = new Array < string > ( ) ; if ( ! sfdxFalconRecipe . recipeName ) invalidConfigKeys . push ( 'recipeName' ) ; if ( ! sfdxFalconRecipe . description ) invalidConfigKeys . push ( 'description' ) ; if ( ! sfdxFalconRecipe . recipeType ) invalidConfigKeys . push ( 'recipeType' ) ; if ( ! sfdxFalconRecipe . recipeVersion ) invalidConfigKeys . push ( 'recipeVersion' ) ; if ( ! sfdxFalconRecipe . schemaVersion ) invalidConfigKeys . push ( 'schemaVersion' ) ; if ( ! sfdxFalconRecipe . options ) invalidConfigKeys . push ( 'options' ) ; if ( ! sfdxFalconRecipe . recipeStepGroups ) invalidConfigKeys . push ( 'recipeStepGroups' ) ; if ( ! sfdxFalconRecipe . handlers ) invalidConfigKeys . push ( 'handlers' ) ; if ( invalidConfigKeys . length > 0 ) { throw new SfdxFalconError ( `Recipe has missing/invalid settings (${ invalidConfigKeys }).` , `InvalidRecipe` , `${ dbgNs }validateTopLevelProperties` ) ; } } private _recipeName : string ; get recipeName ( ) : string { return this . _recipeName ; } private _description : string ; get description ( ) : string { return this . _description ; } private _recipeType : RecipeType ; get recipeType ( ) : RecipeType { return this . _recipeType ; } private _recipeVersion : string ; get recipeVersion ( ) : string { return this . _recipeVersion ; } private _schemaVersion : string ; get schemaVersion ( ) : string { return this . _schemaVersion ; } private _options : JsonMap ; get options ( ) : JsonMap { return this . _options ; } private _recipeStepGroups : JsonMap [ ] ; get recipeStepGroups ( ) : JsonMap [ ] { return this . _recipeStepGroups ; } private _handlers : JsonMap [ ] ; get handlers ( ) : JsonMap [ ] { return this . _handlers ; } private _compiled : boolean ; get compiled ( ) : boolean { return this . _compiled ; } private _projectContext : SfdxFalconProject ; get projectContext ( ) : SfdxFalconProject { return this . _projectContext ; } private _recipeEngine : AppxRecipeEngine ; get recipeEngine ( ) : AppxRecipeEngine { return this . _recipeEngine ; } private _falconRecipeResult : SfdxFalconResult ; get falconRecipeResult ( ) : SfdxFalconResult { return this . _falconRecipeResult ; } private _falconRecipeResultDetail : any ; get falconRecipeResultDetail ( ) : any { return this . _falconRecipeResultDetail ; } private _validated : boolean ; get validated ( ) : boolean { return this . _validated ; } constructs description private private constructor ( ) { } method param { CompileOptions } compileOptions description public async public async compile ( compileOptions = { } ) { SfdxFalconDebug . obj ( `${ dbgNs }compile:compileOptions:` , compileOptions , `compileOptions: ` ) ; switch ( this . _recipeType ) { case RecipeType . APPX_DEMO : this . _recipeEngine = await AppxDemoConfigEngine . compileRecipe ( this , compileOptions ) ; break ; case RecipeType . APPX_PACKAGE : break ; default : throw new SfdxFalconError ( `Recipe type '${ this . _recipeType }' is invalid.` , `InvalidRecipe` , `${ dbgNs }compile` ) ; } this . _compiled = true ; this . _falconRecipeResultDetail . recipeEngine = this . _recipeEngine ; return ; } method param { any } executionOptions returns { Promise < SfdxFalconResult > } description public async public async execute ( executionOptions = { } ) { if ( this . _compiled !== true ) { throw new Error ( `ERROR_RECIPE_NOT_COMPILED: The compile() method must be called before you can  ` + `execute this recipe` ) ; } await this . _recipeEngine . execute ( executionOptions ) . then ( engineSuccessResponse => { this . onSuccess ( engineSuccessResponse ) ; } ) . catch ( engineFailureResponse => { this . onError ( engineFailureResponse ) ; } ) ; SfdxFalconDebug . obj ( `${ dbgNs }execute:_falconRecipeResult:` , this . _falconRecipeResult , `this._falconRecipeResult: ` ) ; this . renderSuccessMessage ( ) ; return this . _falconRecipeResult ; } method param { SfdxFalconResult } engineError returns { void } description private private onError ( engineError ) { const falconEngineResult = SfdxFalconResult . wrapRejectedPromise ( engineError , SfdxFalconResultType . ENGINE , `EngineResult (REJECTED)` ) ; SfdxFalconDebug . obj ( `${ dbgNs }onError:falconEngineResult:` , falconEngineResult , `falconEngineResult: ` ) ; this . _falconRecipeResult . addChild ( falconEngineResult ) ; SfdxFalconDebug . obj ( `${ dbgNs }onError:falconRecipeResult:` , this . falconRecipeResult , `this.falconRecipeResult: ` ) ; throw this . _falconRecipeResult ; } method param { SfdxFalconResult } falconEngineResult returns { void } description private private onSuccess ( falconEngineResult ) { SfdxFalconDebug . obj ( `${ dbgNs }onSuccess:falconEngineResult:` , falconEngineResult , `falconEngineResult: ` ) ; this . _falconRecipeResult . addChild ( falconEngineResult ) ; this . _falconRecipeResult . success ( ) ; return ; } method returns { void } description private private renderSuccessMessage ( ) { console . log ( `Recipe Executed Successfully` ) ; } }