aws-cdk-lib
Version:
Version 2 of the AWS Cloud Development Kit library
3 lines (2 loc) • 9.68 kB
JavaScript
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Bundling=void 0;const os=require("os"),path=require("path"),aws_lambda_1=require("../../aws-lambda"),cdk=require("../../core"),package_installation_1=require("./package-installation"),package_manager_1=require("./package-manager"),types_1=require("./types"),util_1=require("./util"),ESBUILD_MAJOR_VERSION="0";class Bundling{constructor(props){if(this.props=props,this.packageManager=package_manager_1.PackageManager.fromLockFile(props.depsLockFilePath,props.logLevel),Bundling.esbuildInstallation=Bundling.esbuildInstallation??package_installation_1.PackageInstallation.detect("esbuild"),Bundling.tscInstallation=Bundling.tscInstallation??package_installation_1.PackageInstallation.detect("typescript"),this.projectRoot=props.projectRoot,this.relativeEntryPath=path.relative(this.projectRoot,path.resolve(props.entry)),this.relativeDepsLockFilePath=path.relative(this.projectRoot,path.resolve(props.depsLockFilePath)),this.relativeDepsLockFilePath.includes(".."))throw new Error(`Expected depsLockFilePath: ${props.depsLockFilePath} to be under projectRoot: ${this.projectRoot} (${this.relativeDepsLockFilePath})`);if(props.tsconfig&&(this.relativeTsconfigPath=path.relative(this.projectRoot,path.resolve(props.tsconfig))),props.preCompilation&&!/\.tsx?$/.test(props.entry))throw new Error("preCompilation can only be used with typescript files");if(props.format===types_1.OutputFormat.ESM&&(props.runtime===aws_lambda_1.Runtime.NODEJS_10_X||props.runtime===aws_lambda_1.Runtime.NODEJS_12_X))throw new Error(`ECMAScript module output format is not supported by the ${props.runtime.name} runtime`);this.externals=[...props.externalModules??(isSdkV2Runtime(props.runtime)?["aws-sdk"]:["@aws-sdk/*"]),...props.nodeModules??[]];const shouldBuildImage=props.forceDockerBundling||!Bundling.esbuildInstallation;this.image=shouldBuildImage?props.dockerImage??cdk.DockerImage.fromBuild(path.join(__dirname,"../lib"),{buildArgs:{...props.buildArgs??{},IMAGE:props.runtime.bundlingImage.image,ESBUILD_VERSION:props.esbuildVersion??ESBUILD_MAJOR_VERSION},platform:props.architecture.dockerPlatform}):cdk.DockerImage.fromRegistry("dummy");const bundlingCommand=this.createBundlingCommand({inputDir:cdk.AssetStaging.BUNDLING_INPUT_DIR,outputDir:cdk.AssetStaging.BUNDLING_OUTPUT_DIR,esbuildRunner:"esbuild",tscRunner:"tsc",osPlatform:"linux"});this.command=props.command??["bash","-c",bundlingCommand],this.environment=props.environment,this.workingDirectory=props.workingDirectory??"/",this.entrypoint=props.entrypoint,this.volumes=props.volumes,this.volumesFrom=props.volumesFrom,this.user=props.user,this.securityOpt=props.securityOpt,this.network=props.network,this.bundlingFileAccess=props.bundlingFileAccess,props.forceDockerBundling||(this.local=this.getLocalBundlingProvider())}static bundle(options){return aws_lambda_1.Code.fromAsset(options.projectRoot,{assetHash:options.assetHash,assetHashType:options.assetHash?cdk.AssetHashType.CUSTOM:cdk.AssetHashType.OUTPUT,bundling:new Bundling(options)})}static clearEsbuildInstallationCache(){this.esbuildInstallation=void 0}static clearTscInstallationCache(){this.tscInstallation=void 0}createBundlingCommand(options){const pathJoin=osPathJoin(options.osPlatform);let relativeEntryPath=pathJoin(options.inputDir,this.relativeEntryPath),tscCommand="";if(this.props.preCompilation){const tsconfig=this.props.tsconfig??util_1.findUp("tsconfig.json",path.dirname(this.props.entry));if(!tsconfig)throw new Error("Cannot find a `tsconfig.json` but `preCompilation` is set to `true`, please specify it via `tsconfig`");const compilerOptions=util_1.getTsconfigCompilerOptions(tsconfig);tscCommand=`${options.tscRunner} "${relativeEntryPath}" ${compilerOptions}`,relativeEntryPath=relativeEntryPath.replace(/\.ts(x?)$/,".js$1")}const loaders=Object.entries(this.props.loader??{}),defines=Object.entries(this.props.define??{});if(this.props.sourceMap===!1&&this.props.sourceMapMode)throw new Error("sourceMapMode cannot be used when sourceMap is false");const sourceMapEnabled=this.props.sourceMapMode??this.props.sourceMap,sourceMapValue=(this.props.sourceMapMode??types_1.SourceMapMode.DEFAULT)===types_1.SourceMapMode.DEFAULT?"":`=${this.props.sourceMapMode}`,sourcesContent=this.props.sourcesContent??!0,outFile=this.props.format===types_1.OutputFormat.ESM?"index.mjs":"index.js",esbuildCommand=[options.esbuildRunner,"--bundle",`"${relativeEntryPath}"`,`--target=${this.props.target??toTarget(this.props.runtime)}`,"--platform=node",...this.props.format?[`--format=${this.props.format}`]:[],`--outfile="${pathJoin(options.outputDir,outFile)}"`,...this.props.minify?["--minify"]:[],...sourceMapEnabled?[`--sourcemap${sourceMapValue}`]:[],...sourcesContent?[]:[`--sources-content=${sourcesContent}`],...this.externals.map(external=>`--external:${external}`),...loaders.map(([ext,name])=>`--loader:${ext}=${name}`),...defines.map(([key,value])=>`--define:${key}=${JSON.stringify(value)}`),...this.props.logLevel?[`--log-level=${this.props.logLevel}`]:[],...this.props.keepNames?["--keep-names"]:[],...this.relativeTsconfigPath?[`--tsconfig=${pathJoin(options.inputDir,this.relativeTsconfigPath)}`]:[],...this.props.metafile?[`--metafile=${pathJoin(options.outputDir,"index.meta.json")}`]:[],...this.props.banner?[`--banner:js=${JSON.stringify(this.props.banner)}`]:[],...this.props.footer?[`--footer:js=${JSON.stringify(this.props.footer)}`]:[],...this.props.charset?[`--charset=${this.props.charset}`]:[],...this.props.mainFields?[`--main-fields=${this.props.mainFields.join(",")}`]:[],...this.props.inject?this.props.inject.map(i=>`--inject:${i}`):[],...this.props.esbuildArgs?[toCliArgs(this.props.esbuildArgs)]:[]];let depsCommand="";if(this.props.nodeModules){const pkgPath=util_1.findUp("package.json",path.dirname(this.props.entry));if(!pkgPath)throw new Error("Cannot find a `package.json` in this project. Using `nodeModules` requires a `package.json`.");const dependencies=util_1.extractDependencies(pkgPath,this.props.nodeModules),osCommand=new OsCommand(options.osPlatform),lockFilePath=pathJoin(options.inputDir,this.relativeDepsLockFilePath??this.packageManager.lockFile),isPnpm=this.packageManager.lockFile===package_manager_1.LockFile.PNPM;depsCommand=chain([isPnpm?osCommand.write(pathJoin(options.outputDir,"pnpm-workspace.yaml"),""):"",osCommand.writeJson(pathJoin(options.outputDir,"package.json"),{dependencies}),osCommand.copy(lockFilePath,pathJoin(options.outputDir,this.packageManager.lockFile)),osCommand.changeDirectory(options.outputDir),this.packageManager.installCommand.join(" "),isPnpm?osCommand.remove(pathJoin(options.outputDir,"node_modules",".modules.yaml")):""])}return chain([...this.props.commandHooks?.beforeBundling(options.inputDir,options.outputDir)??[],tscCommand,esbuildCommand.join(" "),...(this.props.nodeModules&&this.props.commandHooks?.beforeInstall(options.inputDir,options.outputDir))??[],depsCommand,...this.props.commandHooks?.afterBundling(options.inputDir,options.outputDir)??[]])}getLocalBundlingProvider(){const osPlatform=os.platform(),createLocalCommand=(outputDir,esbuild,tsc)=>this.createBundlingCommand({inputDir:this.projectRoot,outputDir,esbuildRunner:esbuild.isLocal?this.packageManager.runBinCommand("esbuild"):"esbuild",tscRunner:tsc&&(tsc.isLocal?this.packageManager.runBinCommand("tsc"):"tsc"),osPlatform}),environment=this.props.environment??{},cwd=this.projectRoot;return{tryBundle(outputDir){if(!Bundling.esbuildInstallation)return process.stderr.write(`esbuild cannot run locally. Switching to Docker bundling.
`),!1;if(!Bundling.esbuildInstallation.version.startsWith(`${ESBUILD_MAJOR_VERSION}.`))throw new Error(`Expected esbuild version ${ESBUILD_MAJOR_VERSION}.x but got ${Bundling.esbuildInstallation.version}`);const localCommand=createLocalCommand(outputDir,Bundling.esbuildInstallation,Bundling.tscInstallation);return util_1.exec(osPlatform==="win32"?"cmd":"bash",[osPlatform==="win32"?"/c":"-c",localCommand],{env:{...process.env,...environment},stdio:["ignore",process.stderr,"inherit"],cwd,windowsVerbatimArguments:osPlatform==="win32"}),!0}}}}exports.Bundling=Bundling;class OsCommand{constructor(osPlatform){this.osPlatform=osPlatform}write(filePath,data){return this.osPlatform==="win32"?data?`echo ^${data}^ > "${filePath}"`:`echo. > "${filePath}"`:`echo '${data}' > "${filePath}"`}writeJson(filePath,data){const stringifiedData=JSON.stringify(data);return this.write(filePath,stringifiedData)}copy(src,dest){return this.osPlatform==="win32"?`copy "${src}" "${dest}"`:`cp "${src}" "${dest}"`}changeDirectory(dir){return`cd "${dir}"`}remove(filePath){return this.osPlatform==="win32"?`del "${filePath}"`:`rm "${filePath}"`}}function chain(commands){return commands.filter(c=>!!c).join(" && ")}function osPathJoin(platform){return function(...paths){const joined=path.join(...paths);return os.platform()==="win32"&&platform!=="win32"?joined.replace(/\\/g,"/"):joined}}function toTarget(runtime){const match=runtime.name.match(/nodejs(\d+)/);if(!match)throw new Error("Cannot extract version from runtime.");return`node${match[1]}`}function toCliArgs(esbuildArgs){const args=[];for(const[key,value]of Object.entries(esbuildArgs))value===!0||value===""?args.push(key):value&&args.push(`${key}="${value}"`);return args.join(" ")}function isSdkV2Runtime(runtime){return[aws_lambda_1.Runtime.NODEJS,aws_lambda_1.Runtime.NODEJS_4_3,aws_lambda_1.Runtime.NODEJS_6_10,aws_lambda_1.Runtime.NODEJS_8_10,aws_lambda_1.Runtime.NODEJS_10_X,aws_lambda_1.Runtime.NODEJS_12_X,aws_lambda_1.Runtime.NODEJS_14_X,aws_lambda_1.Runtime.NODEJS_16_X].some(r=>r.family===runtime.family&&r.name===runtime.name)}