Comparing version 2.1.0 to 2.1.1
@@ -7,2 +7,3 @@ #!/usr/bin/env node | ||
const _ = require("lodash"); | ||
const chalk_1 = require("chalk"); | ||
const parallelshell_1 = require("./parallelshell"); | ||
@@ -29,2 +30,3 @@ const workspace_1 = require("./workspace"); | ||
const excludeMissing = yargs_1.argv.excludeMissing || false; | ||
const showReport = yargs_1.argv.report || false; | ||
const cmd = yargs_1.argv._[0]; | ||
@@ -35,3 +37,5 @@ const pkgName = yargs_1.argv._[1]; | ||
} | ||
const workspaceGlobs = JSON.parse(fs.readFileSync('./package.json', 'utf8')).workspace || [ | ||
const packageJsonWorkspaces = JSON.parse(fs.readFileSync('./package.json', 'utf8')).workspaces; | ||
const packageJsonWorkspacesNohoistFormat = packageJsonWorkspaces && packageJsonWorkspaces.packages; | ||
const workspaceGlobs = packageJsonWorkspacesNohoistFormat || packageJsonWorkspaces || [ | ||
'packages/*' | ||
@@ -52,9 +56,19 @@ ]; | ||
excludeMissing, | ||
showReport, | ||
workspacePath: process.cwd() | ||
}, pkgPaths); | ||
let cycle = runner.detectCycles(); | ||
if (cycle.length > 0) { | ||
console.error('\nERROR: Dependency cycle detected:\n', ' ', cycle.join(' <- '), '\n'); | ||
process.exit(1); | ||
} | ||
let runlist = yargs_1.argv._.slice(1); | ||
runner.run(cmd, runlist.length > 0 ? runlist : undefined).catch(err => { | ||
console.error('Aborting execution due to previous error'); | ||
process.exit(1); | ||
runner.run(cmd, runlist.length > 0 ? runlist : undefined).then(hadError => { | ||
if (hadError && fastExit) { | ||
console.error(chalk_1.default.red(`\nAborting execution and cancelling running scripts because an error occurred executing \`${cmd}\` for one of the packages.`)); | ||
console.error(' Run wsrun without option --fast-exit to keep going despite errors or with option --report to see which package caused the error.\n'); | ||
console.error(); | ||
} | ||
process.exit(hadError ? 1 : 0); | ||
}); | ||
//# sourceMappingURL=index.js.map |
@@ -44,2 +44,3 @@ /// <reference types="node" /> | ||
excludeMissing: boolean; | ||
showReport: boolean; | ||
} | ||
@@ -55,2 +56,3 @@ export declare class RunGraph { | ||
private runList; | ||
private resultMap; | ||
private throat; | ||
@@ -62,5 +64,7 @@ prefixer: (basePath: string, pkg: string, line: string) => string; | ||
private allDeps(pkg); | ||
detectCycles(): string[]; | ||
private makeCmd(cmd, pkg); | ||
private runOne(cmd, pkg); | ||
run(cmd: string, pkgs?: string[]): Promise<undefined>; | ||
private checkResultsAndReport(cmd, pkgs); | ||
run(cmd: string, pkgs?: string[]): Promise<boolean>; | ||
} |
@@ -135,2 +135,8 @@ "use strict"; | ||
const lodash_1 = require("lodash"); | ||
var ResultSpecialValues; | ||
(function (ResultSpecialValues) { | ||
ResultSpecialValues["Pending"] = "PENDING"; | ||
ResultSpecialValues["Excluded"] = "EXCLUDED"; | ||
ResultSpecialValues["MissingScript"] = "MISSING_SCRIPT"; | ||
})(ResultSpecialValues || (ResultSpecialValues = {})); | ||
class RunGraph { | ||
@@ -144,2 +150,3 @@ constructor(pkgJsons, opts, pkgPaths) { | ||
this.runList = new Set(); | ||
this.resultMap = new Map(); | ||
this.throat = passThrough; | ||
@@ -155,2 +162,4 @@ this.prefixer = new Prefixer(this.opts.workspacePath).prefixer; | ||
}; | ||
this.checkResultsAndReport = this.checkResultsAndReport.bind(this); | ||
this.closeAll = this.closeAll.bind(this); | ||
pkgJsons.forEach(j => this.jsonMap.set(j.name, j)); | ||
@@ -176,2 +185,29 @@ this.children = []; | ||
} | ||
detectCycles() { | ||
let topLevelPkgs = {}; | ||
for (let key of this.jsonMap.keys()) { | ||
topLevelPkgs[key] = '*'; | ||
} | ||
let top = { name: '$', dependencies: topLevelPkgs }; | ||
let self = this; | ||
function deepCycle(json, pathLookup) { | ||
let newPathLookup = pathLookup.concat([json.name]); | ||
let index = pathLookup.indexOf(json.name); | ||
if (index >= 0) { | ||
return newPathLookup.slice(index); | ||
} | ||
let currentDeps = Object.keys(json.dependencies || {}).concat(Object.keys(json.devDependencies || {})); | ||
for (let name of currentDeps) { | ||
let d = self.jsonMap.get(name); | ||
if (!d) | ||
continue; | ||
let res = deepCycle(d, newPathLookup); | ||
if (res.length) | ||
return res; | ||
} | ||
return []; | ||
} | ||
let res = deepCycle(top, []); | ||
return res; | ||
} | ||
makeCmd(cmd, pkg) { | ||
@@ -186,4 +222,6 @@ return `${this.opts.bin} ${cmd}`; | ||
return myDeps.then(() => { | ||
this.resultMap.set(pkg, ResultSpecialValues.Pending); | ||
if (this.opts.exclude.indexOf(pkg) >= 0) { | ||
console.log(chalk_1.default.bold(pkg), 'in exclude list, skipping'); | ||
this.resultMap.set(pkg, ResultSpecialValues.Excluded); | ||
return Promise.resolve(); | ||
@@ -193,2 +231,3 @@ } | ||
console.log(chalk_1.default.bold(pkg), 'has no ', cmd, 'script, skipping missing'); | ||
this.resultMap.set(pkg, ResultSpecialValues.MissingScript); | ||
return Promise.resolve(); | ||
@@ -204,3 +243,3 @@ } | ||
}); | ||
child.exitCode.then(code => code > 0 && this.closeAll.bind(this)); | ||
child.exitCode.then(code => this.resultMap.set(pkg, code)); | ||
this.children.push(child); | ||
@@ -211,8 +250,55 @@ let finished = this.throat(() => { | ||
}); | ||
return this.opts.mode != 'parallel' ? finished : Promise.resolve(); | ||
return finished; | ||
}); | ||
} | ||
checkResultsAndReport(cmd, pkgs) { | ||
const pkgsInError = []; | ||
const pkgsSuccessful = []; | ||
const pkgsPending = []; | ||
const pkgsSkipped = []; | ||
const pkgsMissingScript = []; | ||
this.resultMap.forEach((result, pkg) => { | ||
switch (result) { | ||
case ResultSpecialValues.Excluded: | ||
pkgsSkipped.push(pkg); | ||
break; | ||
case ResultSpecialValues.MissingScript: | ||
pkgsMissingScript.push(pkg); | ||
break; | ||
case ResultSpecialValues.Pending: | ||
pkgsPending.push(pkg); | ||
break; | ||
case 0: | ||
pkgsSuccessful.push(pkg); | ||
break; | ||
default: | ||
pkgsInError.push(pkg); | ||
break; | ||
} | ||
}); | ||
if (this.opts.showReport) { | ||
const formatPkgs = (pgks) => pgks.join(', '); | ||
const pkgsNotStarted = pkgs.filter(pkg => !this.resultMap.has(pkg)); | ||
console.log(chalk_1.default.bold('\nReport:')); | ||
if (pkgsInError.length) | ||
console.log(chalk_1.default.red(` ${pkgsInError.length} packages finished \`${cmd}\` with error: ${formatPkgs(pkgsInError)}`)); | ||
if (pkgsSuccessful.length) | ||
console.log(chalk_1.default.green(` ${pkgsSuccessful.length} packages finished \`${cmd}\` successfully: ${formatPkgs(pkgsSuccessful)}`)); | ||
if (pkgsPending.length) | ||
console.log(chalk_1.default.white(` ${pkgsPending.length} packages have been cancelled running \`${cmd}\`: ${formatPkgs(pkgsPending)}`)); | ||
if (pkgsNotStarted.length) | ||
console.log(chalk_1.default.white(` ${pkgsNotStarted.length} packages have not started running \`${cmd}\`: ${formatPkgs(pkgsNotStarted)}`)); | ||
if (pkgsMissingScript.length) | ||
console.log(chalk_1.default.gray(` ${pkgsMissingScript.length} packages are missing script \`${cmd}\`: ${formatPkgs(pkgsMissingScript)}`)); | ||
if (pkgsSkipped.length) | ||
console.log(chalk_1.default.gray(` ${pkgsSkipped.length} packages have been skipped: ${formatPkgs(pkgsSkipped)}`)); | ||
console.log(); | ||
} | ||
return pkgsInError.length > 0; | ||
} | ||
run(cmd, pkgs = this.pkgJsons.map(p => p.name)) { | ||
this.runList = new Set(pkgs); | ||
return Promise.all(pkgs.map(pkg => this.lookupOrRun(cmd, pkg))).thenReturn(void 0); | ||
return Promise.all(pkgs.map(pkg => this.lookupOrRun(cmd, pkg))) | ||
.catch(err => this.opts.fastExit && this.closeAll()) | ||
.then(() => this.checkResultsAndReport(cmd, pkgs)); | ||
} | ||
@@ -219,0 +305,0 @@ } |
{ | ||
"name": "wsrun", | ||
"version": "2.1.0", | ||
"version": "2.1.1", | ||
"description": "executes commands on packages in parallel, but is aware of the dependencies between them", | ||
@@ -5,0 +5,0 @@ "main": "./build/index.js", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
52811
729
0
1