UNPKG

projen

Version:

CDK for software projects

821 lines • 125 kB
"use strict"; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.NodeProject = exports.AutoRelease = void 0; const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const path_1 = require("path"); const bundler_1 = require("./bundler"); const jest_1 = require("./jest"); const license_checker_1 = require("./license-checker"); const node_package_1 = require("./node-package"); const projenrc_1 = require("./projenrc"); const build_1 = require("../build"); const consts_1 = require("../build/private/consts"); const common_1 = require("../common"); const dependencies_1 = require("../dependencies"); const github_1 = require("../github"); const biome_1 = require("./biome/biome"); const util_1 = require("./util"); const constants_1 = require("../github/constants"); const util_2 = require("../github/private/util"); const workflows_model_1 = require("../github/workflows-model"); const ignore_file_1 = require("../ignore-file"); const javascript_1 = require("../javascript"); const license_1 = require("../license"); const projenrc_json_1 = require("../projenrc-json"); const release_1 = require("../release"); const runner_options_1 = require("../runner-options"); const util_3 = require("../util"); const path_2 = require("../util/path"); const PROJEN_SCRIPT = "projen"; /** * Automatic bump modes */ var AutoRelease; (function (AutoRelease) { /** * Automatically bump & release a new version for every commit to "main" */ AutoRelease[AutoRelease["EVERY_COMMIT"] = 0] = "EVERY_COMMIT"; /** * Automatically bump & release a new version on a daily basis. */ AutoRelease[AutoRelease["DAILY"] = 1] = "DAILY"; })(AutoRelease || (exports.AutoRelease = AutoRelease = {})); /** * Node.js project. * * @pjid node */ class NodeProject extends github_1.GitHubProject { /** * The .npmrc file */ get npmrc() { if (!this._npmrc) { this._npmrc = new javascript_1.NpmConfig(this, { omitEmpty: true }); } return this._npmrc; } /** * @deprecated use `package.allowLibraryDependencies` */ get allowLibraryDependencies() { return this.package.allowLibraryDependencies; } /** * @deprecated use `package.entrypoint` */ get entrypoint() { return this.package.entrypoint; } /** * The minimum node version required by this package to function. * * This value indicates the package is incompatible with older versions. */ get minNodeVersion() { return this.package.minNodeVersion; } /** * Maximum node version supported by this package. * * The value indicates the package is incompatible with newer versions. */ get maxNodeVersion() { return this.package.maxNodeVersion; } /** * The package manager to use. * * @deprecated use `package.packageManager` */ get packageManager() { return this.package.packageManager; } /** * @deprecated use `package.addField(x, y)` */ get manifest() { return this.package.manifest; } constructor(options) { super({ ...options, // Node projects have the specific projen version locked via lockfile, so we can skip the @<VERSION> part of the top-level project projenCommand: options.projenCommand ?? "npx projen", }); this.package = new node_package_1.NodePackage(this, options); this.workflowBootstrapSteps = options.workflowBootstrapSteps ?? []; this.workflowGitIdentity = options.workflowGitIdentity ?? constants_1.DEFAULT_GITHUB_ACTIONS_USER; this.workflowPackageCache = options.workflowPackageCache ?? false; this.artifactsDirectory = options.artifactsDirectory ?? consts_1.DEFAULT_ARTIFACTS_DIRECTORY; (0, util_2.ensureNotHiddenPath)(this.artifactsDirectory, "artifactsDirectory"); const normalizedArtifactsDirectory = (0, util_3.normalizePersistedPath)(this.artifactsDirectory); this.artifactsJavascriptDirectory = path_1.posix.join(normalizedArtifactsDirectory, "js"); this.runScriptCommand = (() => { switch (this.packageManager) { case node_package_1.NodePackageManager.NPM: return "npm run"; case node_package_1.NodePackageManager.YARN: case node_package_1.NodePackageManager.YARN2: case node_package_1.NodePackageManager.YARN_CLASSIC: case node_package_1.NodePackageManager.YARN_BERRY: return "yarn run"; case node_package_1.NodePackageManager.PNPM: return "pnpm run"; case node_package_1.NodePackageManager.BUN: return "bun run"; default: throw new Error(`unexpected package manager ${this.packageManager}`); } })(); const envCommand = (() => { switch (this.packageManager) { case node_package_1.NodePackageManager.PNPM: return '$(pnpm -c exec "node --print process.env.PATH")'; case node_package_1.NodePackageManager.BUN: return '$(bun --eval "console.log(process.env.PATH)")'; default: return '$(npx -c "node --print process.env.PATH")'; } })(); this.nodeVersion = options.workflowNodeVersion ?? this.package.minNodeVersion; // add PATH for all tasks which includes the project's npm .bin list this.tasks.addEnvironment("PATH", envCommand); this.addLicense(options); if (options.npmignoreEnabled ?? true) { this.npmignore = new ignore_file_1.IgnoreFile(this, ".npmignore", options.npmIgnoreOptions); } this.addDefaultGitIgnore(); if (options.gitignore?.length) { for (const i of options.gitignore) { this.gitignore.exclude(i); } } if (options.npmignore?.length) { if (!this.npmignore) { throw new Error('.npmignore is not defined for an APP project type. Add "npmIgnore: true" to override this'); } for (const i of options.npmignore) { this.npmignore.exclude(i); } } if (!this.ejected) { this.setScript(PROJEN_SCRIPT, this.package.projenCommand); } this.npmignore?.exclude(`/${common_1.PROJEN_DIR}/`); const projen = options.projenDevDependency ?? (this.parent ? false : true); if (projen && !this.ejected) { const postfix = options.projenVersion ? `@${options.projenVersion}` : ""; this.addDevDeps(`projen${postfix}`); if (!this.deps.isDependencySatisfied("constructs", dependencies_1.DependencyType.BUILD, "^10.0.0")) { this.addDevDeps(`constructs@^10.0.0`); } } if (!options.defaultReleaseBranch) { throw new Error('"defaultReleaseBranch" is temporarily a required option while we migrate its default value from "master" to "main"'); } const buildEnabled = options.buildWorkflow ?? (this.parent ? false : true); // configure jest if enabled // must be before the build/release workflows if (options.jest ?? true) { this.jest = new jest_1.Jest(this, options.jestOptions); } const workflowPermissions = { idToken: this.determineIdTokenPermissions(options), }; const buildWorkflowOptions = options.buildWorkflowOptions ?? {}; if (buildEnabled && (this.github || github_1.GitHub.of(this.root))) { this.buildWorkflow = new build_1.BuildWorkflow(this, { buildTask: this.buildTask, artifactsDirectory: this.artifactsDirectory, containerImage: options.workflowContainerImage, gitIdentity: this.workflowGitIdentity, mutableBuild: options.mutableBuild, workflowTriggers: options.buildWorkflowTriggers, permissions: workflowPermissions, ...buildWorkflowOptions, preBuildSteps: this.renderWorkflowSetup({ installStepConfiguration: { workingDirectory: this.determineInstallWorkingDirectory(), }, mutable: buildWorkflowOptions.mutableBuild ?? options.mutableBuild ?? true, }).concat(buildWorkflowOptions.preBuildSteps ?? []), postBuildSteps: [...(options.postBuildSteps ?? [])], ...(0, runner_options_1.filteredRunsOnOptions)(options.workflowRunsOn, options.workflowRunsOnGroup), }); this.buildWorkflow.addPostBuildSteps(...this.renderUploadCoverageJobStep(options)); this.maybeAddCodecovIgnores(options); } // Build release tasks array const releaseTasks = []; // Add security audit before release if enabled if (options.auditDeps) { const auditTask = this.addAuditTask(options); const runOn = options.auditDepsOptions?.runOn ?? "build"; if (runOn === "release") { releaseTasks.push(auditTask); } else if (runOn === "build") { this.preCompileTask.spawn(auditTask); } // "manual" mode doesn't add to any task } const release = options.release ?? options.releaseWorkflow ?? (this.parent ? false : true); if (release) { // Add build task releaseTasks.push(this.buildTask); this.release = new release_1.Release(this, { versionFile: "package.json", // this is where "version" is set after bump tasks: releaseTasks, branch: options.defaultReleaseBranch ?? "main", ...options, artifactsDirectory: this.artifactsDirectory, releaseWorkflowSetupSteps: [ ...this.renderWorkflowSetup({ installStepConfiguration: { workingDirectory: this.determineInstallWorkingDirectory(), }, mutable: false, }), ...(options.releaseWorkflowSetupSteps ?? []), ], postBuildSteps: [ ...(options.postBuildSteps ?? []), ...this.renderUploadCoverageJobStep(options), ], workflowNodeVersion: this.nodeVersion, workflowPermissions, }); this.maybeAddCodecovIgnores(options); this.publisher = this.release.publisher; const nodePackageToReleaseCodeArtifactAuthProviderMapping = { [node_package_1.CodeArtifactAuthProvider.ACCESS_AND_SECRET_KEY_PAIR]: release_1.CodeArtifactAuthProvider.ACCESS_AND_SECRET_KEY_PAIR, [node_package_1.CodeArtifactAuthProvider.GITHUB_OIDC]: release_1.CodeArtifactAuthProvider.GITHUB_OIDC, }; if (options.releaseToNpm ?? false) { const codeArtifactOptions = (0, release_1.isAwsCodeArtifactRegistry)(this.package.npmRegistry) ? { accessKeyIdSecret: options.codeArtifactOptions?.accessKeyIdSecret, secretAccessKeySecret: options.codeArtifactOptions?.secretAccessKeySecret, roleToAssume: options.codeArtifactOptions?.roleToAssume, authProvider: options.codeArtifactOptions?.authProvider ? nodePackageToReleaseCodeArtifactAuthProviderMapping[options.codeArtifactOptions.authProvider] : release_1.CodeArtifactAuthProvider.ACCESS_AND_SECRET_KEY_PAIR, } : {}; this.release.publisher.publishToNpm({ registry: this.package.npmRegistry, npmTokenSecret: this.package.npmTokenSecret, npmProvenance: this.package.npmProvenance, trustedPublishing: options.npmTrustedPublishing ?? false, codeArtifactOptions, }); } } else { // validate that no release options are selected if the release workflow is disabled. if (options.releaseToNpm) { throw new Error('"releaseToNpm" is not supported if "release" is not set'); } if (options.releaseEveryCommit) { throw new Error('"releaseEveryCommit" is not supported if "release" is not set'); } if (options.releaseSchedule) { throw new Error('"releaseSchedule" is not supported if "release" is not set'); } } if ((options.autoMerge ?? true) && this.github?.mergify && this.buildWorkflow?.buildJobIds) { this.autoMerge = new github_1.AutoMerge(this.github, options.autoMergeOptions); this.autoMerge.addConditionsLater({ render: () => this.buildWorkflow?.buildJobIds.map((id) => `status-success=${id}`) ?? [], }); } const dependabot = options.dependabot ?? false; const depsUpgrade = options.depsUpgrade ?? !dependabot; if (dependabot && depsUpgrade) { throw new Error("'dependabot' cannot be configured together with 'depsUpgrade'"); } const depsAutoApprove = options.autoApproveUpgrades ?? false; if (depsAutoApprove && !this.autoApprove && this.github) { throw new Error("Automatic approval of dependencies upgrades requires configuring `autoApproveOptions`"); } const autoApproveLabel = (condition) => condition && this.autoApprove?.label ? [this.autoApprove.label] : undefined; if (dependabot) { const defaultOptions = { labels: autoApproveLabel(depsAutoApprove), }; this.github?.addDependabot((0, util_3.deepMerge)([defaultOptions, options.dependabotOptions ?? {}])); } if (depsUpgrade) { const defaultOptions = { workflowOptions: { container: options.workflowContainerImage ? { image: options.workflowContainerImage, } : undefined, labels: autoApproveLabel(depsAutoApprove), gitIdentity: this.workflowGitIdentity, permissions: workflowPermissions, }, }; this.upgradeWorkflow = new javascript_1.UpgradeDependencies(this, (0, util_3.deepMerge)([defaultOptions, options.depsUpgradeOptions ?? {}])); } if (options.pullRequestTemplate ?? true) { this.github?.addPullRequestTemplate(...(options.pullRequestTemplateContents ?? [])); } const projenrcJs = options.projenrcJs ?? !options.projenrcJson; if (!this.parent && projenrcJs) { const projenrcJsFile = new projenrc_1.Projenrc(this, options.projenrcJsOptions); this.npmignore?.exclude(`/${projenrcJsFile.filePath}`); } else if (options.projenrcJson) { const projenrcJsonFile = projenrc_json_1.ProjenrcJson.of(this); if (projenrcJsonFile) { this.npmignore?.exclude(`/${projenrcJsonFile.filePath}`); } } // add a bundler component - this enables things like Lambda bundling and in the future web bundling. this.bundler = new bundler_1.Bundler(this, options.bundlerOptions); const shouldPackage = options.package ?? true; if (release && !shouldPackage) { this.logger.warn("When `release` is enabled, `package` must also be enabled as it is required by release. Force enabling `package`."); } if (release || shouldPackage) { this.packageTask.exec(`mkdir -p ${this.artifactsJavascriptDirectory}`); const pkgMgr = this.package.packageManager === node_package_1.NodePackageManager.PNPM ? "pnpm" : "npm"; this.packageTask.exec(`${pkgMgr} pack --pack-destination ${this.artifactsJavascriptDirectory}`); } if ((0, util_3.multipleSelected)([options.biome, options.prettier])) { throw new Error("Only one of biome and prettier can be enabled."); } if (options.biome ?? false) { this.biome = new biome_1.Biome(this, { ...options.biomeOptions }); } if (options.prettier ?? false) { this.prettier = new javascript_1.Prettier(this, { ...options.prettierOptions }); } // For PNPM, the default resolution mode is "lowest", which leads to any non-versioned (ie '*') dependencies being // resolved to the lowest available version, which is unlikely to be expected behaviour for users. We set resolution // mode to "highest" to match the behaviour of yarn and npm. if (this.package.packageManager === node_package_1.NodePackageManager.PNPM) { this.npmrc.addConfig("resolution-mode", "highest"); } if (options.checkLicenses) { new license_checker_1.LicenseChecker(this, options.checkLicenses); } } determineInstallWorkingDirectory() { if (this.parent) { return (0, path_2.ensureRelativePathStartsWithDot)((0, path_1.relative)(".", this.root.outdir)); } return; } determineIdTokenPermissions(options) { const { codeCovTokenSecret, scopedPackagesOptions, codeArtifactOptions } = options; const useCodeCoveOidc = this.useCodecov(options) && !codeCovTokenSecret; const hasScopedPackages = (scopedPackagesOptions ?? []).length > 0; const useCodeArtifactOidc = codeArtifactOptions?.authProvider === release_1.CodeArtifactAuthProvider.GITHUB_OIDC; if (useCodeCoveOidc || (useCodeArtifactOidc && hasScopedPackages)) { return workflows_model_1.JobPermission.WRITE; } return undefined; } useCodecov(options) { // Use Codecov when it is enabled or if or a secret token name is passed in // AND jest must be configured return (options.codeCov || options.codeCovTokenSecret) && this.jest?.config; } maybeAddCodecovIgnores(options) { if (this.useCodecov(options)) { this.addGitIgnore("codecov"); this.addGitIgnore("codecov.*"); } } renderUploadCoverageJobStep(options) { // run codecov if enabled or a secret token name is passed in // AND jest must be configured if (this.useCodecov(options)) { return [ { name: "Upload coverage to Codecov", uses: "codecov/codecov-action@v5", with: options.codeCovTokenSecret ? { token: `\${{ secrets.${options.codeCovTokenSecret} }}`, directory: this.jest?.config.coverageDirectory, } : { directory: this.jest?.config.coverageDirectory, use_oidc: true, }, }, ]; } else { return []; } } addBins(bins) { this.package.addBin(bins); } /** * Replaces the contents of an npm package.json script. * * @param name The script name * @param command The command to execute */ setScript(name, command) { this.package.setScript(name, command); } /** * Replaces the contents of multiple npm package.json scripts. * @param scripts The scripts to set */ addScripts(scripts) { for (const [name, command] of Object.entries(scripts)) { this.package.setScript(name, command); } } /** * Removes the npm script (always successful). * @param name The name of the script. */ removeScript(name) { this.package.removeScript(name); } /** * Indicates if a script by the name name is defined. * @param name The name of the script * @deprecated Use `project.tasks.tryFind(name)` */ hasScript(name) { return this.package.hasScript(name); } /** * DEPRECATED * @deprecated use `project.compileTask.exec()` */ addCompileCommand(...commands) { for (const c of commands) { this.compileTask.exec(c); } } /** * DEPRECATED * @deprecated use `project.testTask.exec()` */ addTestCommand(...commands) { for (const c of commands) { this.testTask.exec(c); } } /** * Directly set fields in `package.json`. * @param fields The fields to set */ addFields(fields) { for (const [name, value] of Object.entries(fields)) { this.package.addField(name, value); } } /** * Adds keywords to package.json (deduplicated) * @param keywords The keywords to add */ addKeywords(...keywords) { this.package.addKeywords(...keywords); } /** * Get steps for scoped package access * * @param codeArtifactOptions Details of logging in to AWS * @returns array of job steps required for each private scoped packages */ getScopedPackageSteps(codeArtifactOptions) { const parsedCodeArtifactOptions = { accessKeyIdSecret: codeArtifactOptions?.accessKeyIdSecret ?? "AWS_ACCESS_KEY_ID", secretAccessKeySecret: codeArtifactOptions?.secretAccessKeySecret ?? "AWS_SECRET_ACCESS_KEY", roleToAssume: codeArtifactOptions?.roleToAssume, authProvider: codeArtifactOptions?.authProvider, }; if (parsedCodeArtifactOptions.authProvider === node_package_1.CodeArtifactAuthProvider.GITHUB_OIDC) { return [ { name: "Configure AWS Credentials", uses: "aws-actions/configure-aws-credentials@v5", with: { "aws-region": "us-east-2", "role-to-assume": parsedCodeArtifactOptions.roleToAssume, "role-duration-seconds": 900, }, }, { name: "AWS CodeArtifact Login", run: `${this.runScriptCommand} ca:login`, }, ]; } if (parsedCodeArtifactOptions.roleToAssume) { return [ { name: "Configure AWS Credentials", uses: "aws-actions/configure-aws-credentials@v5", with: { "aws-access-key-id": (0, util_2.secretToString)(parsedCodeArtifactOptions.accessKeyIdSecret), "aws-secret-access-key": (0, util_2.secretToString)(parsedCodeArtifactOptions.secretAccessKeySecret), "aws-region": "us-east-2", "role-to-assume": parsedCodeArtifactOptions.roleToAssume, "role-duration-seconds": 900, }, }, { name: "AWS CodeArtifact Login", run: `${this.runScriptCommand} ca:login`, }, ]; } return [ { name: "AWS CodeArtifact Login", run: `${this.runScriptCommand} ca:login`, env: { AWS_ACCESS_KEY_ID: (0, util_2.secretToString)(parsedCodeArtifactOptions.accessKeyIdSecret), AWS_SECRET_ACCESS_KEY: (0, util_2.secretToString)(parsedCodeArtifactOptions.secretAccessKeySecret), }, }, ]; } /** * Returns the set of workflow steps which should be executed to bootstrap a * workflow. * * @param options Options. * @returns Job steps */ renderWorkflowSetup(options = {}) { const install = new Array(); // first run the workflow bootstrap steps install.push(...this.workflowBootstrapSteps); if (this.package.packageManager === node_package_1.NodePackageManager.PNPM) { install.push({ name: "Setup pnpm", uses: "pnpm/action-setup@v4", with: { version: this.package.pnpmVersion }, }); } else if (this.package.packageManager === node_package_1.NodePackageManager.BUN) { install.push({ name: "Setup bun", uses: "oven-sh/setup-bun@v2", with: { "bun-version": this.package.bunVersion }, }); } if (this.package.packageManager !== node_package_1.NodePackageManager.BUN) { if (this.nodeVersion || this.workflowPackageCache) { const pm = this.package.packageManager; const cache = (0, util_1.isYarnClassic)(pm) || (0, util_1.isYarnBerry)(pm) ? "yarn" : pm === node_package_1.NodePackageManager.PNPM ? "pnpm" : "npm"; install.push({ name: "Setup Node.js", uses: "actions/setup-node@v5", with: { ...(this.nodeVersion && { "node-version": this.nodeVersion, }), ...(this.workflowPackageCache && { cache, }), }, }); } } const mutable = options.mutable ?? false; if (this.package.scopedPackagesOptions) { install.push(...this.getScopedPackageSteps(this.package.codeArtifactOptions)); } install.push({ name: "Install dependencies", run: mutable ? this.package.installAndUpdateLockfileCommand : this.package.installCommand, ...(options.installStepConfiguration ?? {}), }); return install; } /** * Defines normal dependencies. * * @param deps Names modules to install. By default, the the dependency will * be installed in the next `npx projen` run and the version will be recorded * in your `package.json` file. You can upgrade manually or using `yarn * add/upgrade`. If you wish to specify a version range use this syntax: * `module@^7`. */ addDeps(...deps) { return this.package.addDeps(...deps); } /** * Defines development/test dependencies. * * @param deps Names modules to install. By default, the the dependency will * be installed in the next `npx projen` run and the version will be recorded * in your `package.json` file. You can upgrade manually or using `yarn * add/upgrade`. If you wish to specify a version range use this syntax: * `module@^7`. */ addDevDeps(...deps) { return this.package.addDevDeps(...deps); } /** * Defines peer dependencies. * * When adding peer dependencies, a devDependency will also be added on the * pinned version of the declared peer. This will ensure that you are testing * your code against the minimum version required from your consumers. * * @param deps Names modules to install. By default, the the dependency will * be installed in the next `npx projen` run and the version will be recorded * in your `package.json` file. You can upgrade manually or using `yarn * add/upgrade`. If you wish to specify a version range use this syntax: * `module@^7`. */ addPeerDeps(...deps) { return this.package.addPeerDeps(...deps); } /** * Defines bundled dependencies. * * Bundled dependencies will be added as normal dependencies as well as to the * `bundledDependencies` section of your `package.json`. * * @param deps Names modules to install. By default, the the dependency will * be installed in the next `npx projen` run and the version will be recorded * in your `package.json` file. You can upgrade manually or using `yarn * add/upgrade`. If you wish to specify a version range use this syntax: * `module@^7`. */ addBundledDeps(...deps) { return this.package.addBundledDeps(...deps); } /** * Adds patterns to be ignored by npm. * * @param pattern The pattern to ignore. * * @remarks * If you are having trouble getting an ignore to populate, try using your construct or component's preSynthesize method to properly delay calling this method. */ addPackageIgnore(pattern) { this.npmignore?.addPatterns(pattern); } addLicense(options) { if (this.package.license) { new license_1.License(this, { spdx: this.package.license, copyrightOwner: options.copyrightOwner ?? options.authorName, copyrightPeriod: options.copyrightPeriod, }); } } addDefaultGitIgnore() { this.gitignore.exclude("# Logs", "logs", "*.log", "npm-debug.log*", "yarn-debug.log*", "yarn-error.log*", "lerna-debug.log*", "# Diagnostic reports (https://nodejs.org/api/report.html)", "report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json", "# Runtime data", "pids", "*.pid", "*.seed", "*.pid.lock", "# Directory for instrumented libs generated by jscoverage/JSCover", "lib-cov", "# Coverage directory used by tools like istanbul", "coverage", "*.lcov", "# nyc test coverage", ".nyc_output", "# Compiled binary addons (https://nodejs.org/api/addons.html)", "build/Release", "# Dependency directories", "node_modules/", "jspm_packages/", "# TypeScript cache", "*.tsbuildinfo", "# Optional eslint cache", ".eslintcache", "# Output of 'npm pack'", "*.tgz", "# Yarn Integrity file", ".yarn-integrity", "# parcel-bundler cache (https://parceljs.org/)", ".cache"); } /** * Returns the shell command to execute in order to run a task. This will * typically be `npx projen TASK`. * * @param task The task for which the command is required */ runTaskCommand(task) { return `${this.package.projenCommand} ${task.name}`; } /** * The job ID of the build workflow. */ get buildWorkflowJobId() { return this.buildWorkflow?.buildJobIds[0]; } /** * Adds a security audit task. */ addAuditTask(options) { const auditLevel = options.auditDepsOptions?.level ?? "high"; const auditProdOnly = options.auditDepsOptions?.prodOnly ?? false; // Create audit task const auditTask = this.tasks.addTask("audit", { description: "Run security audit", }); // Add package manager specific audit command const auditCommand = this.getAuditCommand(auditLevel, auditProdOnly); auditTask.exec(auditCommand); return auditTask; } /** * Gets the appropriate audit command for the package manager. */ getAuditCommand(level, prodOnly) { const levelFlag = this.getAuditLevelFlag(level); const prodFlag = prodOnly ? this.getAuditProdFlag() : ""; switch (this.packageManager) { case node_package_1.NodePackageManager.NPM: return `npm audit${levelFlag}${prodFlag}`; case node_package_1.NodePackageManager.YARN: case node_package_1.NodePackageManager.YARN_CLASSIC: // Use Node.js to call yarn and handle exit code cross-platform const threshold = this.getYarnClassicThreshold(level); return `node -e "const { execSync } = require('child_process'); try { execSync('yarn audit${levelFlag}${prodFlag}', {stdio: 'inherit'}); } catch(e) { process.exit(e.status < ${threshold} ? 0 : 1); }"`; case node_package_1.NodePackageManager.YARN2: case node_package_1.NodePackageManager.YARN_BERRY: return `yarn npm audit --recursive${levelFlag}${prodFlag}`; case node_package_1.NodePackageManager.PNPM: return `pnpm audit${levelFlag}${prodFlag}`; case node_package_1.NodePackageManager.BUN: return `bun audit${levelFlag}${prodFlag}`; default: throw new Error(`Unsupported package manager: ${this.packageManager}`); } } /** * Gets the threshold value for yarn classic based on vulnerability level. */ getYarnClassicThreshold(level) { switch (level) { case "low": return 2; // Pass for exit code < 2, fail for >= 2 (LOW and above) case "moderate": return 4; // Pass for exit code < 4, fail for >= 4 (MODERATE and above) case "high": return 8; // Pass for exit code < 8, fail for >= 8 (HIGH and above) case "critical": return 16; // Pass for exit code < 16, fail for >= 16 (CRITICAL) default: return 2; } } /** * Gets the audit level flag for the package manager. */ getAuditLevelFlag(level) { switch (this.packageManager) { case node_package_1.NodePackageManager.NPM: return ` --audit-level=${level}`; case node_package_1.NodePackageManager.YARN: case node_package_1.NodePackageManager.YARN_CLASSIC: return ` --level ${level}`; case node_package_1.NodePackageManager.YARN2: case node_package_1.NodePackageManager.YARN_BERRY: return ` --severity ${level}`; case node_package_1.NodePackageManager.PNPM: return ` --audit-level ${level}`; case node_package_1.NodePackageManager.BUN: return ` --audit-level ${level}`; default: return ""; } } /** * Gets the production-only flag for the package manager. */ getAuditProdFlag() { switch (this.packageManager) { case node_package_1.NodePackageManager.NPM: return " --omit=dev"; case node_package_1.NodePackageManager.YARN: case node_package_1.NodePackageManager.YARN_CLASSIC: return " --groups dependencies"; case node_package_1.NodePackageManager.YARN2: case node_package_1.NodePackageManager.YARN_BERRY: return " --environment production"; case node_package_1.NodePackageManager.PNPM: return " --prod"; case node_package_1.NodePackageManager.BUN: return " --production"; default: return ""; } } } exports.NodeProject = NodeProject; _a = JSII_RTTI_SYMBOL_1; NodeProject[_a] = { fqn: "projen.javascript.NodeProject", version: "0.98.32" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZS1wcm9qZWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2phdmFzY3JpcHQvbm9kZS1wcm9qZWN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsK0JBQXVDO0FBQ3ZDLHVDQUFvRDtBQUNwRCxpQ0FBMkM7QUFDM0MsdURBQTBFO0FBQzFFLGlEQU13QjtBQUN4Qix5Q0FBdUQ7QUFDdkQsb0NBQXFFO0FBQ3JFLG9EQUFzRTtBQUN0RSxzQ0FBdUM7QUFDdkMsa0RBQWlEO0FBQ2pELHNDQU9tQjtBQUNuQix5Q0FBb0Q7QUFDcEQsaUNBQW9EO0FBQ3BELG1EQUFrRTtBQUNsRSxpREFBNkU7QUFDN0UsK0RBTW1DO0FBQ25DLGdEQUErRDtBQUMvRCw4Q0FNdUI7QUFDdkIsd0NBQXFDO0FBQ3JDLG9EQUFnRDtBQUNoRCx3Q0FRb0I7QUFDcEIsc0RBQTBEO0FBRTFELGtDQUE4RTtBQUM5RSx1Q0FBK0Q7QUFFL0QsTUFBTSxhQUFhLEdBQUcsUUFBUSxDQUFDO0FBMlcvQjs7R0FFRztBQUNILElBQVksV0FVWDtBQVZELFdBQVksV0FBVztJQUNyQjs7T0FFRztJQUNILDZEQUFZLENBQUE7SUFFWjs7T0FFRztJQUNILCtDQUFLLENBQUE7QUFDUCxDQUFDLEVBVlcsV0FBVywyQkFBWCxXQUFXLFFBVXRCO0FBRUQ7Ozs7R0FJRztBQUNILE1BQWEsV0FBWSxTQUFRLHNCQUFhO0lBVzVDOztPQUVHO0lBQ0gsSUFBVyxLQUFLO1FBQ2QsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNqQixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksc0JBQVMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUN6RCxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQ3JCLENBQUM7SUFHRDs7T0FFRztJQUNILElBQVcsd0JBQXdCO1FBQ2pDLE9BQU8sSUFBSSxD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