/**
 * Code taken from the utils of @schematics/angular
 */ export interface Host { write ( path , content ) : Promise < void > ; read ( path ) : Promise < string > ; } export interface Change { readonly path : string | null ; readonly order : number ; readonly description : string ; apply ( host ) : Promise < void > ; } /**
 * An operation that does nothing.
 */ export class NoopChange implements Change { description = 'No operation.' ; order = Infinity ; path = null ; apply ( ) { return Promise . resolve ( ) ; } } /**
 * Will add text to the source code.
 */ export class InsertChange implements Change { order : number ; description : string ; constructor ( public path , public pos , public toAdd ) { if ( pos < 0 ) { throw new Error ( 'Negative positions are invalid' ) ; } this . description = `Inserted ${ toAdd } into position ${ pos } of ${ path }` ; this . order = pos ; } /**
     * This method does not insert spaces if there is none in the original string.
     */ apply ( host ) { return host . read ( this . path ) . then ( ( content ) => { const prefix = content . substring ( 0 , this . pos ) ; const suffix = content . substring ( this . pos ) ; return host . write ( this . path , `${ prefix }${ this . toAdd }${ suffix }` ) ; } ) ; } } /**
 * Will remove text from the source code.
 */ export class RemoveChange implements Change { order : number ; description : string ; constructor ( public path , private pos , private toRemove ) { if ( pos < 0 ) { throw new Error ( 'Negative positions are invalid' ) ; } this . description = `Removed ${ toRemove } into position ${ pos } of ${ path }` ; this . order = pos ; } apply ( host ) { return host . read ( this . path ) . then ( ( content ) => { const prefix = content . substring ( 0 , this . pos ) ; const suffix = content . substring ( this . pos + this . toRemove . length ) ; return host . write ( this . path , `${ prefix }${ suffix }` ) ; } ) ; } } /**
 * Will replace text from the source code.
 */ export class ReplaceChange implements Change { order : number ; description : string ; constructor ( public path , private pos , private oldText , private newText ) { if ( pos < 0 ) { throw new Error ( 'Negative positions are invalid' ) ; } this . description = `Replaced ${ oldText } into position ${ pos } ` + `of ${ path } with ${ newText }` ; this . order = pos ; } apply ( host ) { return host . read ( this . path ) . then ( ( content ) => { const prefix = content . substring ( 0 , this . pos ) ; const suffix = content . substring ( this . pos + this . oldText . length ) ; const text = content . substring ( this . pos , this . pos + this . oldText . length ) ; if ( text !== this . oldText ) { return Promise . reject ( new Error ( `Invalid replace: "${ text }" != "${ this . oldText }".` ) ) ; } return host . write ( this . path , `${ prefix }${ this . newText }${ suffix }` ) ; } ) ; } }