/* Copyright IBM Corp. 2017 */ import { join, normalize, parse, resolve } from 'path'; import { combineLatest, merge, Observable, of } from 'rxjs'; import { filter, map, mergeMap, shareReplay, tap } from 'rxjs/operators'; import { getDistDir } from '../utils/angular.utils'; import { firstOf } from '../utils/file.utils'; import { CMD_COPY, OPTION_DATA, OPTION_NAME, OPTION_ROOT, OPTION_SOURCE, OPTION_VERBOSE } from './../constants'; import { Options } from './../options'; import { configIndexDirFromContextRoot, configTrimSlashes } from './../utils/config'; import { rxCopyDir } from './../utils/rx.copy'; import { rxDeleteDir } from './../utils/rx.delete'; import { rxMoveFile } from './../utils/rx.move'; import { AbstractCommand } from './abstract.command'; import { Command } from './command'; import { HELP_APPLICATION_NAME, HELP_CONTEXT_ROOT, HELP_COPY_SOURCE, HELP_DATA_DIRECTORY, HELP_VERBOSE } from './help'; const ROOT_RESOURCE: { [key: string]: boolean } = { 'index.html': true, 'favicon.ico': true }; function _isRootResource(aFilename: string): boolean { const parsed = parse(aFilename); return !!ROOT_RESOURCE[parsed.base]; } /** * Copies the build output to the correct location */ export class CopyBuildCommand extends AbstractCommand implements Command { static readonly TYPE = 'build'; static readonly COMMAND = CMD_COPY; constructor(options: Options) { super(options); } printHelp(): void { // log the command line console.log(CopyBuildCommand.COMMAND, CopyBuildCommand.TYPE, `--${OPTION_SOURCE} `, `--${OPTION_DATA} `, `--${OPTION_NAME} `, `[--${OPTION_ROOT} ]`, `[--${OPTION_VERBOSE}]`); // log the parameters console.log(`--${OPTION_SOURCE} `, ':', HELP_COPY_SOURCE); console.log(`--${OPTION_DATA} `, ':', HELP_DATA_DIRECTORY); console.log(`--${OPTION_NAME} `, ':', HELP_APPLICATION_NAME); console.log(`--${OPTION_ROOT}`, ':', HELP_CONTEXT_ROOT); console.log(`--${OPTION_VERBOSE}`, ':', HELP_VERBOSE); } process(): Observable { // the options const opts = this.getOptions(); const appName = opts.name || this.getAppName(); const contextRoot = `/${configTrimSlashes(opts.root || this.getContextRoot(appName))}`; // logger const logger = this.getLogger(); // the directories const dataDir = this.getDataDir(); // source directory is the build output const firstSrc = firstOf(opts.src); const rxSrcDir = firstSrc ? of(resolve(firstSrc)) : this.getAngularCliConfig().pipe( map(getDistDir), map(dir => resolve(dir)) ); // name of the target directory for the main files const assetDir = resolve(normalize(join(dataDir, 'assets', appName))); // directory for index file const idxDir = configIndexDirFromContextRoot(contextRoot, dataDir); // delete the files in the asset dir const rxDeletedAssets = rxDeleteDir(assetDir); // copy files into the assets directory const rxCopiedAssets = combineLatest(rxSrcDir, rxDeletedAssets).pipe( tap(([srcDir, dstDir]) => logger.next(`Copying from [${srcDir}] to [${dstDir}].`)), mergeMap(([srcDir, dstDir]) => rxCopyDir(srcDir, dstDir)), shareReplay() ); // copy some selected files to the context root dir const rxRoot = rxCopiedAssets.pipe( filter(_isRootResource) ); const rxApp = rxCopiedAssets.pipe( filter(res => !_isRootResource(res)) ); // move the root resources const rxMovedRoot = rxRoot.pipe( mergeMap(file => rxMoveFile(file, join(idxDir, parse(file).base))) ); // merge const rxResult = merge(rxApp, rxMovedRoot); return rxResult; } }