import * as path from 'path' ; import { Command , flags } from '@oclif/command' ; import * as glob from 'fast-glob' ; import * as Listr from 'listr' ; import { copyFile , rm , mkdir , boxMessage , checkOldDependencies , getWarnings , parsePackageJson } from '../utils' ; interface Context { parsed : { flags : any ; args : any ; } ; outputDir : string ; projectDir : string ; } export default class Package extends Command { static description = 'Copies the specified files to the deployment folder' ; static examples = [ '$ sap-cloud-sdk package' , '$ sap-cloud-sdk package -i="index.html"' , '$ sap-cloud-sdk package --include="package.json,package-lock.json,index.js,dist/**/*" --exclude="**/*.java"' ] ; static flags = { help : flags . help ( { char : 'h' , description : 'Show help for the package command.' } ) , output : flags . string ( { char : 'o' , default : 'deployment' , description : 'Output and deployment folder' } ) , ci : flags . boolean ( { default : false , description : 'Add node_modules in production environments to respect the `build once` principle.' } ) , include : flags . string ( { char : 'i' , default : 'package.json,package-lock.json,index.js,dist/**/*' , description : 'Comma seperated list of files or globs to include' } ) , exclude : flags . string ( { char : 'e' , default : '' , description : 'Comma separated list of files or globs to exclude' } ) , verbose : flags . boolean ( { char : 'v' , description : 'Show more detailed output.' } ) } ; static args = [ { name : 'projectDir' , description : 'Path to the project directory that shall be packaged.' } ] ; async run ( ) { const parsed = this . parse ( Package ) ; const projectDir = parsed . args . projectDir || '.' ; const outputDir = path . resolve ( projectDir , parsed . flags . output ) ; const tasks = new Listr ( [ { title : 'Read flags' , task : ctx => { ctx . parsed = parsed ; ctx . projectDir = projectDir ; ctx . outputDir = outputDir ; } } , { title : `Overwrite ${ parsed . flags . output }` , task : this . overwrite } , { title : 'Copying files' , task : this . copyFiles } , { title : 'Copying node_modules for ci' , enabled : ( ) => parsed . flags . ci , task : this . copyNodeModules } , { title : 'Check the SAP Cloud SDK dependencies' , task : this . checkSDKDependencies } ] ) ; await tasks . run ( ) ; this . printSuccessMessage ( ) ; } async overwrite ( ctx ) { try { await rm ( ctx . outputDir ) ; await mkdir ( ctx . outputDir ) ; } catch ( error ) { this . error ( error , { exit : 1 } ) ; } } async copyFiles ( ctx ) { const include = await glob ( ctx . parsed . flags . include . split ( ',' ) , { dot : true , absolute : true , cwd : ctx . projectDir } ) ; const exclude = ctx . parsed . flags . exclude . length > 0 ? await glob ( ctx . parsed . flags . exclude . split ( ',' ) , { dot : true , absolute : true , cwd : ctx . projectDir } ) : [ ] ; const filtered = include . filter ( filepath => ! exclude . includes ( filepath ) ) ; await copyFilesTo ( filtered , ctx . outputDir , ctx . projectDir ) ; } async copyNodeModules ( ctx ) { const nodeModuleFiles = await glob ( 'node_modules/**/*' , { dot : true , absolute : true , cwd : ctx . projectDir } ) ; await copyFilesTo ( nodeModuleFiles , ctx . outputDir , ctx . projectDir ) ; } async checkSDKDependencies ( ctx ) { const { dependencies , devDependencies } = await parsePackageJson ( ctx . projectDir ) ; checkOldDependencies ( dependencies ) ; checkOldDependencies ( devDependencies ) ; } printSuccessMessage ( ) { const warnings = getWarnings ( ) ; const body = [ '🚀 Please migrate to new packages.' , 'Please find how to migrate here:' , 'https://sap.github.io/cloud-sdk/docs/js/guides/migrate-to-open-source-version-of-cloud-sdk-for-javascript-typescript/' ] ; if ( warnings ) { if ( this . hasOldSDKWarnings ( warnings ) ) { this . log ( boxMessage ( [ '⚠️ Package finished with warnings:' , ... warnings , '' , ... body ] ) ) ; } else { this . log ( boxMessage ( [ '⚠️ Package finished with warnings:' , ... warnings ] ) ) ; } } else { this . log ( boxMessage ( [ '✅ Package finished successfully.' ] ) ) ; } } hasOldSDKWarnings ( warnings ) { const regex = new RegExp ( 'Old SAP Cloud SDK: .* is detected.' ) ; return ( warnings . map ( warning => regex . test ( warning ) ) . filter ( value => value ) . length > 0 ) ; } } async function copyFilesTo ( filePaths , outputDir , projectDir ) { return Promise . all ( filePaths . map ( async ( filepath ) => { const outputFilePath = path . resolve ( outputDir , path . relative ( projectDir , filepath ) ) ; await mkdir ( path . dirname ( outputFilePath ) , { recursive : true } ) ; await copyFile ( filepath , outputFilePath ) ; } ) ) ; }