import { Argv } from "yargs" ; import { copySync , existsSync } from "fs-extra" ; import { join , normalize } from "path" ; import { eachSeries } from "async" ; import packlist = require ( "npm-packlist" ) ; import { Package } from "../Package" ; import { TspScriptsOptions , tspScriptsOptions } from "../tspScriptsOptions" ; import { tspHandler } from "../tspHandler" ; import { CliError , cliOptions , log , PackageNotFoundError , } from "@jtbennett/ts-project-cli-utils" ; import { getPaths } from "../paths" ; import { execSync } from "child_process" ; const NODE_MODULES = "node_modules" ; const copyNodeModules = ( src , dest , skip ? ) => { if ( existsSync ( src ) ) { log . verbose ( `  Copying ${ src } to ${ dest }` ) ; const filter = skip && skip ?. length > 0 ? ( src ) => ! skip . some ( ( pkg ) => src . endsWith ( join ( NODE_MODULES , normalize ( pkg . name ) ) ) ) : undefined ; copySync ( src , dest , { overwrite : false , errorOnExist : true , filter } ) ; } else { log . verbose ( `  Directory to copy does not exist: "${ src }"` ) ; } } ; const copyWorkspaceFiles = async ( workspace , dest ) => { log . info ( `Copying ${ workspace . name } to ${ dest }` ) ; const filesToCopy = await packlist ( { path : workspace . path } ) ; filesToCopy . forEach ( ( file ) => { log . verbose ( `  Copying ${ file }` ) ; copySync ( join ( workspace . path , file ) , join ( dest , file ) ) ; } ) ; copyNodeModules ( join ( workspace . path , NODE_MODULES ) , join ( dest , NODE_MODULES ) ) ; } ; const handler = tspHandler < TspScriptsOptions & { appName : string ; outDir : string ; } > ( async ( args ) => { const allPackages = Package . loadAll ( ) ; const app = allPackages . find ( ( pkg ) => pkg . packageJson && pkg . packageJson . name === args . appName ) ; if ( ! app ) { throw new PackageNotFoundError ( args . appName ) ; } if ( existsSync ( args . outDir ) ) { throw new CliError ( `Out directory already exists: ${ args . outDir }` ) ; } if ( args . yarn ) { log . info ( `Removing dependencies not used by ${ args . appName } and all devDependencies.` ) ; execSync ( `yarn workspaces focus --production ${ args . appName }` , { stdio : "inherit" , } ) ; } else { log . warn ( "Yarn was not run. node_modules in --out-dir may be missing required dependencies and/or " + "include devDependencies or other unnecessary dependencies." ) ; } copyNodeModules ( join ( getPaths ( ) . rootPath , NODE_MODULES ) , join ( args . outDir , NODE_MODULES ) , allPackages ) ; await copyWorkspaceFiles ( app , join ( args . outDir , app . dir ) ) ; const workspacesToCopy = new Map < string , Package > ( ) ; const addWorkspacesToCopy = ( pkg ) => { if ( ! workspacesToCopy . has ( pkg . name ) ) { pkg . loadDependencies ( ) . forEach ( ( dep ) => { workspacesToCopy . set ( dep . name , dep ) ; addWorkspacesToCopy ( dep ) ; } ) ; } } ; addWorkspacesToCopy ( app ) ; await eachSeries ( workspacesToCopy . values ( ) , async ( workspace ) => { await copyWorkspaceFiles ( workspace , join ( args . outDir , NODE_MODULES , normalize ( workspace . name ) ) ) ; } ) ; args . yarn = args . yarn && process . env . CI !== "true" ; } ) ; export const bundle = { command : "bundle <app-name>" , describe : "Prepare an app for deployment" , builder : ( yargs ) => yargs . usage ( "Usage: $0 bundle <app-name> --out-dir <out-dir>" ) . positional ( "app-name" , { desc : "Name of the app to bundle." , type : "string" , } ) . options ( { outDir : { alias : "o" , describe : "Path where the bundled application will be output." , demand : true , } , ... cliOptions , ... tspScriptsOptions , } ) , handler , } ;