/**
 * Additional angular.json specific tool functions that are not part of normal project.ts
 */ import { SchematicContext , SchematicsException , Tree } from '@angular-devkit/schematics' ; import { ProjectType , WorkspaceProject , WorkspaceSchema } from '../../schematics-core/utility/workspace-models' ; import { OptionsAfterSetup } from './options-after-setup' ; import { xliffmergeBuilderName , xliffmergeBuilderSpec } from './constants' ; import { buildConfigurationForLanguage , serveConfigurationForLanguage } from './common-functions' ; import { IXliffMergeOptions } from '@ngx-i18nsupport/ngx-i18nsupport' ; /**
 * Read and edit functionality on angular.json
 * It allows multiple changes on angular.json file.
 * At the end we call commit() to write angular.json.
 */ export class WorkspaceSnaphot { private readonly workspace : WorkspaceSchema ; param host param context throws constructor ( private host , private context ? ) { this . workspace = this . readAngularJson ( ) ; } /**
     * Commit all changes done on workspace.
     * (writes angular.json)
     */ public commit ( ) { const newAngularJsonContent = JSON . stringify ( this . workspace , null , 2 ) ; this . host . overwrite ( '/angular.json' , newAngularJsonContent ) ; } param projectName throws public getProjectByName ( projectName ) { const projects = this . workspace . projects ; if ( ! projects ) { throw new SchematicsException ( 'angular.json does not contain projects' ) ; } const project = projects [ projectName ] ; if ( ! project ) { throw new SchematicsException ( 'angular.json does not contain project ' + projectName ) ; } return project ; } /**
     * Return all projects.
     */ public getAllProjects ( ) { return Object . keys ( this . workspace . projects ) . map ( projectName => { return { name : projectName , project : this . workspace . projects [ projectName ] } ; } ) ; } /**
     * Return name of default project.
     */ public getDefaultProjectName ( ) { return this . workspace . defaultProject ; } param projectName param configurationName param configuration public addArchitectBuildConfigurationToProject ( projectName , configurationName , configuration ) { return this . addObjectToProjectPath ( projectName , 'build configuration' , [ 'architect' , 'build' , 'configurations' ] , configurationName , configuration ) ; } param projectName param configurationName param configuration public addArchitectServeConfigurationToProject ( projectName , configurationName , configuration ) { return this . addObjectToProjectPath ( projectName , 'serve configuration' , [ 'architect' , 'serve' , 'configurations' ] , configurationName , configuration ) ; } param projectName param builderName param builder param options param configuration public addArchitectBuilderToProject ( projectName , builderName , builder , options , configuration ? ) { const builderSpec = { builder : builder , options : options } ; if ( configuration ) { builderSpec . configuration = configuration ; } return this . addObjectToProjectPath ( projectName , 'architect builder' , [ 'architect' ] , builderName , builderSpec ) ; } param options param language public addLanguageConfigurationToProject ( options , language ) { this . addArchitectBuildConfigurationToProject ( options . project , language , buildConfigurationForLanguage ( options , language ) ) ; if ( this . context ) { this . context . logger . info ( `added build configuration for language "${ language }" to project "${ options . project }"` ) ; } this . addArchitectServeConfigurationToProject ( options . project , language , serveConfigurationForLanguage ( options , language ) ) ; if ( this . context ) { this . context . logger . info ( `added serve configuration for language "${ language }" to project "${ options . project }"` ) ; } } param options public addBuilderConfigurationToProject ( options ) { const baseDir = ( options . isDefaultProject ) ? '' : `projects/${ options . project }/` ; const builderOptions = { xliffmergeOptions : { i18nFormat : options . i18nFormat , srcDir : `${ baseDir }${ options . srcDir }` , genDir : `${ baseDir }${ options . genDir }` , defaultLanguage : options . parsedLanguages [ 0 ] , languages : options . parsedLanguages } } ; this . addArchitectBuilderToProject ( options . project , xliffmergeBuilderName , xliffmergeBuilderSpec , builderOptions ) ; if ( this . context ) { this . context . logger . info ( `added builder xliffmerge to project "${ options . project }"` ) ; } } param projectName public getActualXliffmergeConfigFromWorkspace ( projectName ) { if ( ! projectName ) { return null ; } const project = this . getProjectByName ( projectName ) ; if ( ! project || ! project . architect ) { return null ; } const xliffmergeBuilder = project . architect [ 'xliffmerge' ] ; if ( ! xliffmergeBuilder || ! xliffmergeBuilder . options ) { return null ; } if ( xliffmergeBuilder . options && xliffmergeBuilder . options . xliffmergeOptions ) { return xliffmergeBuilder . options ; } else if ( xliffmergeBuilder . options . profile ) { const content = this . host . read ( xliffmergeBuilder . options . profile ) ; if ( ! content ) { return null ; } const contentString = content . toString ( 'UTF-8' ) ; const profileContent = JSON . parse ( contentString ) as { xliffmergeOptions : IXliffMergeOptions ; } ; return { xliffmergeOptions : profileContent . xliffmergeOptions , profile : xliffmergeBuilder . options . profile } ; } else { return null ; } } param objectType param projectName param path param objectName param objectToAdd private addObjectToProjectPath ( projectName , objectType , path , objectName , objectToAdd ) { const projects = this . workspace . projects ; if ( ! projects ) { throw new SchematicsException ( 'angular.json does not contain projects' ) ; } const project = projects [ projectName ] ; if ( ! project ) { throw new SchematicsException ( 'angular.json does not contain project ' + projectName ) ; } const container = this . getObjectFromProjectUsingPath ( projectName , project , path ) ; const addedOrChanged = ( container [ objectName ] ) ? 'changed' : 'added' ; container [ objectName ] = objectToAdd ; if ( this . context ) { this . context . logger . info ( `${ addedOrChanged } ${ objectType } ${ objectName } to project ${ projectName }` ) ; } } param projectName param project param path return throws private getObjectFromProjectUsingPath ( projectName , project , path ) { let object = project ; let currentPath = '' ; for ( let i = 0 ; i < path . length ; i ++ ) { currentPath = currentPath + '.' + path [ i ] ; object = object [ path [ i ] ] ; if ( ! object ) { throw new SchematicsException ( 'angular.json does not contain ' + currentPath + ' in project ' + projectName ) ; } } return object ; } private readAngularJson ( ) { const noAngularJsonMsg = 'file angular.json not found' ; if ( this . host . exists ( '/angular.json' ) ) { const content = this . host . read ( '/angular.json' ) ; if ( ! content ) { throw new SchematicsException ( noAngularJsonMsg ) ; } const sourceText = content . toString ( 'utf-8' ) ; return JSON . parse ( sourceText ) ; } else { throw new SchematicsException ( noAngularJsonMsg ) ; } } }