hunk.code_window: const Task = require('../ember-cli/lib/models/task');
  
hunk.labels: keep add keep
hunk.after_edit: const MemoryFS = require('memory-fs');
  
hunk.file_path: packages/@angular/cli/tasks/extract-i18n.ts
hunk.type: add
file: const webpackMerge = require('webpack-merge');
  import { CliConfig } from './config';
  import { BuildOptions } from './build-options';
  import {
    getBrowserConfig,
    getCommonConfig,
    getDevConfig,
    getProdConfig,
    getStylesConfig,
    getNonAotConfig,
    getAotConfig
  } from './webpack-configs';
  
  const path = require('path');
  
  export interface WebpackConfigOptions {
    projectRoot: string;
    buildOptions: BuildOptions;
    appConfig: any;
  }
  
  export class NgCliWebpackConfig {
    public config: any;
    public wco: WebpackConfigOptions;
    constructor(buildOptions: BuildOptions, appConfig: any) {
  
      this.validateBuildOptions(buildOptions);
  
      const configPath = CliConfig.configFilePath();
      const projectRoot = path.dirname(configPath);
  
      appConfig = this.addAppConfigDefaults(appConfig);
      buildOptions = this.addTargetDefaults(buildOptions);
      buildOptions = this.mergeConfigs(buildOptions, appConfig);
  
      this.wco = { projectRoot, buildOptions, appConfig };
    }
  
    public buildConfig() {
      let webpackConfigs = [
        getCommonConfig(this.wco),
        getBrowserConfig(this.wco),
        getStylesConfig(this.wco),
        this.getTargetConfig(this.wco)
      ];
  
      if (this.wco.appConfig.main || this.wco.appConfig.polyfills) {
        const typescriptConfigPartial = this.wco.buildOptions.aot
          ? getAotConfig(this.wco)
          : getNonAotConfig(this.wco);
        webpackConfigs.push(typescriptConfigPartial);
      }
  
      this.config = webpackMerge(webpackConfigs);
      return this.config;
    }
  
    public getTargetConfig(webpackConfigOptions: WebpackConfigOptions): any {
      switch (webpackConfigOptions.buildOptions.target) {
        case 'development':
          return getDevConfig(webpackConfigOptions);
        case 'production':
          return getProdConfig(webpackConfigOptions);
      }
    }
  
    // Validate build options
    public validateBuildOptions(buildOptions: BuildOptions) {
      buildOptions.target = buildOptions.target || 'development';
      if (buildOptions.target !== 'development' && buildOptions.target !== 'production') {
        throw new Error("Invalid build target. Only 'development' and 'production' are available.");
      }
    }
  
    // Fill in defaults for build targets
    public addTargetDefaults(buildOptions: BuildOptions): BuildOptions {
      const targetDefaults: { [target: string]: BuildOptions } = {
        development: {
          environment: 'dev',
          outputHashing: 'media',
          sourcemaps: true,
          extractCss: false
        },
        production: {
          environment: 'prod',
          outputHashing: 'all',
          sourcemaps: false,
          extractCss: true,
          aot: true
        }
      };
  
      return Object.assign({}, targetDefaults[buildOptions.target], buildOptions);
    }
  
    // Fill in defaults from .angular-cli.json
    public mergeConfigs(buildOptions: BuildOptions, appConfig: any) {
      const mergeableOptions = {
        outputPath: appConfig.outDir,
        deployUrl: appConfig.deployUrl
      };
  
      return Object.assign({}, mergeableOptions, buildOptions);
    }
  
    public addAppConfigDefaults(appConfig: any) {
      const appConfigDefaults: any = {
        testTsconfig: appConfig.tsconfig,
        scripts: [],
        styles: []
      };
  
      // can't use Object.assign here because appConfig has a lot of getters/setters
      for (let key of Object.keys(appConfigDefaults)) {
        appConfig[key] = appConfig[key] || appConfigDefaults[key];
      }
  
      return appConfig;
    }
  }
  