concurrently
Advanced tools
Comparing version 7.2.2 to 7.3.0
@@ -38,3 +38,3 @@ #!/usr/bin/env node | ||
// Find argument separator (double dash) | ||
const argsSepIdx = cleanArgs.findIndex((arg) => arg === '--'); | ||
const argsSepIdx = cleanArgs.findIndex(arg => arg === '--'); | ||
// Arguments before separator | ||
@@ -61,3 +61,3 @@ const argsBeforeSep = argsSepIdx >= 0 ? cleanArgs.slice(0, argsSepIdx) : cleanArgs; | ||
}, | ||
'names': { | ||
names: { | ||
alias: 'n', | ||
@@ -73,3 +73,3 @@ describe: 'List of custom names to be used in prefix template.\n' + | ||
}, | ||
'success': { | ||
success: { | ||
alias: 's', | ||
@@ -87,3 +87,3 @@ describe: 'Which command(s) must exit with code 0 in order for concurrently exit with ' + | ||
}, | ||
'raw': { | ||
raw: { | ||
alias: 'r', | ||
@@ -100,3 +100,3 @@ describe: 'Output only raw output of processes, disables prettifying ' + | ||
}, | ||
'hide': { | ||
hide: { | ||
describe: 'Comma-separated list of processes to hide the output.\n' + | ||
@@ -107,3 +107,3 @@ 'The processes can be identified by their name or index.', | ||
}, | ||
'group': { | ||
group: { | ||
alias: 'g', | ||
@@ -113,3 +113,3 @@ describe: 'Order the output as if the commands were run sequentially.', | ||
}, | ||
'timings': { | ||
timings: { | ||
describe: 'Show timing information for all processes.', | ||
@@ -137,3 +137,3 @@ type: 'boolean', | ||
// Prefix | ||
'prefix': { | ||
prefix: { | ||
alias: 'p', | ||
@@ -216,3 +216,5 @@ describe: 'Prefix used in logging for each process.\n' + | ||
? ['success', 'failure'] | ||
: (args.killOthersOnFail ? ['failure'] : []), | ||
: args.killOthersOnFail | ||
? ['failure'] | ||
: [], | ||
maxProcesses: args.maxProcesses, | ||
@@ -219,0 +221,0 @@ raw: args.raw, |
@@ -36,13 +36,7 @@ "use strict"; | ||
description: 'Send input to specific child identified by index', | ||
example: [ | ||
'$ $0 --handle-input "npm run watch-js" nodemon', | ||
'1:rs', | ||
].join('\n'), | ||
example: ['$ $0 --handle-input "npm run watch-js" nodemon', '1:rs'].join('\n'), | ||
}, | ||
{ | ||
description: 'Send input to specific child identified by name', | ||
example: [ | ||
'$ $0 --handle-input -n js,srv "npm run watch-js" nodemon', | ||
'srv:rs', | ||
].join('\n'), | ||
example: ['$ $0 --handle-input -n js,srv "npm run watch-js" nodemon', 'srv:rs'].join('\n'), | ||
}, | ||
@@ -62,22 +56,29 @@ { | ||
{ | ||
description: 'Passthrough some additional arguments via \'{<number>}\' placeholder', | ||
description: "Passthrough some additional arguments via '{<number>}' placeholder", | ||
example: '$ $0 -P "echo {1}" -- foo', | ||
}, | ||
{ | ||
description: 'Passthrough all additional arguments via \'{@}\' placeholder', | ||
description: "Passthrough all additional arguments via '{@}' placeholder", | ||
example: '$ $0 -P "npm:dev-* -- {@}" -- --watch --noEmit', | ||
}, | ||
{ | ||
description: 'Passthrough all additional arguments combined via \'{*}\' placeholder', | ||
description: "Passthrough all additional arguments combined via '{*}' placeholder", | ||
example: '$ $0 -P "npm:dev-* -- {*}" -- --watch --noEmit', | ||
}, | ||
]; | ||
const examplesString = examples | ||
.map(({ example, description }) => [ | ||
` - ${description}`, | ||
example | ||
.split('\n') | ||
.map(line => ` ${line}`) | ||
.join('\n'), | ||
].join('\n\n')) | ||
.join('\n\n'); | ||
exports.epilogue = ` | ||
Examples: | ||
${examples.map(({ example, description }) => ` | ||
- ${description} | ||
${example.split('\n').map(line => ` ${line}`).join('\n')} | ||
`).join('')} | ||
${examplesString} | ||
For more details, visit https://github.com/open-cli-tools/concurrently | ||
`; |
@@ -9,5 +9,9 @@ import { CommandInfo } from '../command'; | ||
constructor(additionalArguments: string[]); | ||
parse(commandInfo: CommandInfo): CommandInfo & { | ||
parse(commandInfo: CommandInfo): { | ||
command: string; | ||
name: string; | ||
env?: Record<string, unknown>; | ||
cwd?: string; | ||
prefixColor?: string; | ||
}; | ||
} |
@@ -13,6 +13,6 @@ "use strict"; | ||
parse(commandInfo) { | ||
const command = commandInfo.command.replace(/\\?\{([@\*]|[1-9][0-9]*)\}/g, (match, placeholderTarget) => { | ||
const command = commandInfo.command.replace(/\\?\{([@*]|[1-9][0-9]*)\}/g, (match, placeholderTarget) => { | ||
// Don't replace the placeholder if it is escaped by a backslash. | ||
if (match.startsWith('\\')) { | ||
return match.substring(1); | ||
return match.slice(1); | ||
} | ||
@@ -36,7 +36,5 @@ // Replace numeric placeholder if value exists in additional arguments. | ||
}); | ||
return Object.assign({}, commandInfo, { | ||
command, | ||
}); | ||
return { ...commandInfo, command }; | ||
} | ||
} | ||
exports.ExpandArguments = ExpandArguments; |
@@ -13,9 +13,9 @@ "use strict"; | ||
} | ||
return Object.assign({}, commandInfo, { | ||
return { | ||
...commandInfo, | ||
name: commandInfo.name || cmdName, | ||
command: `${npmCmd} run ${cmdName}${args}`, | ||
}); | ||
}; | ||
} | ||
} | ||
exports.ExpandNpmShortcut = ExpandNpmShortcut; | ||
; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ExpandNpmWildcard = void 0; | ||
const fs = __importStar(require("fs")); | ||
const _ = __importStar(require("lodash")); | ||
const OMISSION = /\(!([^\)]+)\)/; | ||
const fs_1 = __importDefault(require("fs")); | ||
const lodash_1 = __importDefault(require("lodash")); | ||
const OMISSION = /\(!([^)]+)\)/; | ||
/** | ||
@@ -40,3 +20,3 @@ * Finds wildcards in npm/yarn/pnpm run commands and replaces them with all matching scripts in the | ||
try { | ||
const json = fs.readFileSync('package.json', { encoding: 'utf-8' }); | ||
const json = fs_1.default.readFileSync('package.json', { encoding: 'utf-8' }); | ||
return JSON.parse(json); | ||
@@ -61,4 +41,4 @@ } | ||
const cmdNameSansOmission = cmdName.replace(OMISSION, ''); | ||
const preWildcard = _.escapeRegExp(cmdNameSansOmission.substr(0, wildcardPosition)); | ||
const postWildcard = _.escapeRegExp(cmdNameSansOmission.substr(wildcardPosition + 1)); | ||
const preWildcard = lodash_1.default.escapeRegExp(cmdNameSansOmission.slice(0, wildcardPosition)); | ||
const postWildcard = lodash_1.default.escapeRegExp(cmdNameSansOmission.slice(wildcardPosition + 1)); | ||
const wildcardRegex = new RegExp(`^${preWildcard}(.*?)${postWildcard}$`); | ||
@@ -76,3 +56,4 @@ const currentName = commandInfo.name || ''; | ||
if (match) { | ||
return Object.assign({}, commandInfo, { | ||
return { | ||
...commandInfo, | ||
command: `${npmCmd} run ${script}${args}`, | ||
@@ -82,3 +63,3 @@ // Will use an empty command name if command has no name and the wildcard match is empty, | ||
name: currentName + match[1], | ||
}); | ||
}; | ||
} | ||
@@ -90,2 +71,1 @@ }) | ||
exports.ExpandNpmWildcard = ExpandNpmWildcard; | ||
; |
@@ -7,5 +7,9 @@ import { CommandInfo } from '../command'; | ||
export declare class StripQuotes implements CommandParser { | ||
parse(commandInfo: CommandInfo): CommandInfo & { | ||
parse(commandInfo: CommandInfo): { | ||
command: string; | ||
name: string; | ||
env?: Record<string, unknown>; | ||
cwd?: string; | ||
prefixColor?: string; | ||
}; | ||
} |
@@ -12,8 +12,7 @@ "use strict"; | ||
if (/^"(.+?)"$/.test(command) || /^'(.+?)'$/.test(command)) { | ||
command = command.substring(1, command.length - 1); | ||
command = command.slice(1, command.length - 1); | ||
} | ||
return Object.assign({}, commandInfo, { command }); | ||
return { ...commandInfo, command }; | ||
} | ||
} | ||
exports.StripQuotes = StripQuotes; | ||
; |
/// <reference types="node" /> | ||
/// <reference types="node" /> | ||
/// <reference types="node" /> | ||
/// <reference types="node" /> | ||
import { ChildProcess as BaseChildProcess, SpawnOptions } from 'child_process'; | ||
@@ -21,3 +24,3 @@ import * as Rx from 'rxjs'; | ||
*/ | ||
env?: Record<string, any>; | ||
env?: Record<string, unknown>; | ||
/** | ||
@@ -80,3 +83,3 @@ * The current working directory of the process when spawned. | ||
/** @inheritdoc */ | ||
readonly env: Record<string, any>; | ||
readonly env: Record<string, unknown>; | ||
/** @inheritdoc */ | ||
@@ -83,0 +86,0 @@ readonly cwd?: string; |
@@ -80,3 +80,3 @@ "use strict"; | ||
endDate, | ||
durationSeconds: durationSeconds + (durationNanoSeconds / 1e9), | ||
durationSeconds: durationSeconds + durationNanoSeconds / 1e9, | ||
}, | ||
@@ -100,3 +100,2 @@ }); | ||
exports.Command = Command; | ||
; | ||
/** | ||
@@ -103,0 +102,0 @@ * Pipes all events emitted by `stream` into `subject`. |
@@ -15,7 +15,7 @@ import * as Rx from 'rxjs'; | ||
* Provides logic to determine whether lists of commands ran successfully. | ||
*/ | ||
*/ | ||
export declare class CompletionListener { | ||
private readonly successCondition; | ||
private readonly scheduler?; | ||
constructor({ successCondition, scheduler }: { | ||
constructor({ successCondition, scheduler, }: { | ||
/** | ||
@@ -22,0 +22,0 @@ * How this instance will define that a list of commands ran successfully. |
@@ -31,5 +31,5 @@ "use strict"; | ||
* Provides logic to determine whether lists of commands ran successfully. | ||
*/ | ||
*/ | ||
class CompletionListener { | ||
constructor({ successCondition = 'all', scheduler }) { | ||
constructor({ successCondition = 'all', scheduler, }) { | ||
this.successCondition = successCondition; | ||
@@ -54,12 +54,10 @@ this.scheduler = scheduler; | ||
const nameOrIndex = commandSyntaxMatch[1]; | ||
const targetCommandsEvents = events.filter(({ command, index }) => (command.name === nameOrIndex | ||
|| index === Number(nameOrIndex))); | ||
const targetCommandsEvents = events.filter(({ command, index }) => command.name === nameOrIndex || index === Number(nameOrIndex)); | ||
if (this.successCondition.startsWith('!')) { | ||
// All commands except the specified ones must exit succesfully | ||
return events.every((event) => (targetCommandsEvents.includes(event) | ||
|| event.exitCode === 0)); | ||
return events.every(event => targetCommandsEvents.includes(event) || event.exitCode === 0); | ||
} | ||
// Only the specified commands must exit succesfully | ||
return targetCommandsEvents.length > 0 | ||
&& targetCommandsEvents.every(event => event.exitCode === 0); | ||
return (targetCommandsEvents.length > 0 && | ||
targetCommandsEvents.every(event => event.exitCode === 0)); | ||
} | ||
@@ -73,4 +71,3 @@ /** | ||
const closeStreams = commands.map(command => command.close); | ||
return Rx.lastValueFrom(Rx.merge(...closeStreams) | ||
.pipe((0, operators_1.bufferCount)(closeStreams.length), (0, operators_1.switchMap)(exitInfos => this.isSuccess(exitInfos) | ||
return Rx.lastValueFrom(Rx.merge(...closeStreams).pipe((0, operators_1.bufferCount)(closeStreams.length), (0, operators_1.switchMap)(exitInfos => this.isSuccess(exitInfos) | ||
? Rx.of(exitInfos, this.scheduler) | ||
@@ -81,2 +78,1 @@ : Rx.throwError(exitInfos, this.scheduler)), (0, operators_1.take)(1))); | ||
exports.CompletionListener = CompletionListener; | ||
; |
@@ -50,7 +50,8 @@ "use strict"; | ||
// Use documented behaviour of repeating last color when specifying more commands than colors | ||
lastColor = options.prefixColors && options.prefixColors[index] || lastColor; | ||
return new command_1.Command(Object.assign({ | ||
lastColor = (options.prefixColors && options.prefixColors[index]) || lastColor; | ||
return new command_1.Command({ | ||
index, | ||
prefixColor: lastColor, | ||
}, command), (0, get_spawn_opts_1.getSpawnOpts)({ | ||
...command, | ||
}, (0, get_spawn_opts_1.getSpawnOpts)({ | ||
raw: options.raw, | ||
@@ -70,3 +71,3 @@ env: command.env, | ||
commands = handleResult.commands; | ||
if (options.logger) { | ||
if (options.logger && options.outputStream) { | ||
const outputWriter = new output_writer_1.OutputWriter({ | ||
@@ -87,3 +88,3 @@ outputStream: options.outputStream, | ||
.finally(() => { | ||
handleResult.onFinishCallbacks.forEach((onFinish) => onFinish()); | ||
handleResult.onFinishCallbacks.forEach(onFinish => onFinish()); | ||
}); | ||
@@ -96,3 +97,2 @@ return { | ||
exports.concurrently = concurrently; | ||
; | ||
function mapToCommandInfo(command) { | ||
@@ -107,3 +107,3 @@ if (typeof command === 'string') { | ||
} | ||
return Object.assign({ | ||
return { | ||
command: command.command, | ||
@@ -113,5 +113,8 @@ name: command.name || '', | ||
cwd: command.cwd || '', | ||
}, command.prefixColor ? { | ||
prefixColor: command.prefixColor, | ||
} : {}); | ||
...(command.prefixColor | ||
? { | ||
prefixColor: command.prefixColor, | ||
} | ||
: {}), | ||
}; | ||
} | ||
@@ -118,0 +121,0 @@ function parseCommand(command, parsers) { |
@@ -20,3 +20,3 @@ /// <reference types="node" /> | ||
private readonly pauseInputStreamOnFinish; | ||
constructor({ defaultInputTarget, inputStream, pauseInputStreamOnFinish, logger }: { | ||
constructor({ defaultInputTarget, inputStream, pauseInputStreamOnFinish, logger, }: { | ||
inputStream: Readable; | ||
@@ -23,0 +23,0 @@ logger: Logger; |
@@ -40,3 +40,3 @@ "use strict"; | ||
class InputHandler { | ||
constructor({ defaultInputTarget, inputStream, pauseInputStreamOnFinish, logger }) { | ||
constructor({ defaultInputTarget, inputStream, pauseInputStreamOnFinish, logger, }) { | ||
this.logger = logger; | ||
@@ -57,4 +57,4 @@ this.defaultInputTarget = defaultInputTarget || defaults.defaultInputTarget; | ||
const input = dataParts[1] || data; | ||
const command = commands.find(command => (command.name === targetId || | ||
command.index.toString() === targetId.toString())); | ||
const command = commands.find(command => command.name === targetId || | ||
command.index.toString() === targetId.toString()); | ||
if (command && command.stdin) { | ||
@@ -79,2 +79,1 @@ command.stdin.write(input); | ||
exports.InputHandler = InputHandler; | ||
; |
@@ -25,3 +25,3 @@ "use strict"; | ||
const exitCode = caughtSignal === 'SIGINT' ? 0 : exitInfo.exitCode; | ||
return Object.assign({}, exitInfo, { exitCode }); | ||
return { ...exitInfo, exitCode }; | ||
})); | ||
@@ -38,2 +38,1 @@ return new Proxy(command, { | ||
exports.KillOnSignal = KillOnSignal; | ||
; |
@@ -11,3 +11,3 @@ import { Command } from '../command'; | ||
private readonly conditions; | ||
constructor({ logger, conditions }: { | ||
constructor({ logger, conditions, }: { | ||
logger: Logger; | ||
@@ -14,0 +14,0 @@ conditions: ProcessCloseCondition | ProcessCloseCondition[]; |
@@ -13,3 +13,3 @@ "use strict"; | ||
class KillOthers { | ||
constructor({ logger, conditions }) { | ||
constructor({ logger, conditions, }) { | ||
this.logger = logger; | ||
@@ -19,4 +19,3 @@ this.conditions = lodash_1.default.castArray(conditions); | ||
handle(commands) { | ||
const conditions = this.conditions.filter(condition => (condition === 'failure' || | ||
condition === 'success')); | ||
const conditions = this.conditions.filter(condition => condition === 'failure' || condition === 'success'); | ||
if (!conditions.length) { | ||
@@ -37,2 +36,1 @@ return { commands }; | ||
exports.KillOthers = KillOthers; | ||
; |
@@ -14,3 +14,3 @@ "use strict"; | ||
this.logger.logCommandEvent(`Error occurred when executing command: ${command.command}`, command); | ||
const errorText = String(event instanceof Error ? (event.stack || event) : event); | ||
const errorText = String(event instanceof Error ? event.stack || event : event); | ||
this.logger.logCommandEvent(errorText, command); | ||
@@ -22,2 +22,1 @@ })); | ||
exports.LogError = LogError; | ||
; |
@@ -19,2 +19,1 @@ "use strict"; | ||
exports.LogExit = LogExit; | ||
; |
@@ -20,2 +20,1 @@ "use strict"; | ||
exports.LogOutput = LogOutput; | ||
; |
@@ -15,10 +15,10 @@ import { CloseEvent, Command } from '../command'; | ||
export declare class LogTimings implements FlowController { | ||
static mapCloseEventToTimingInfo({ command, timings, killed, exitCode }: CloseEvent): TimingInfo; | ||
static mapCloseEventToTimingInfo({ command, timings, killed, exitCode, }: CloseEvent): TimingInfo; | ||
private readonly logger?; | ||
private readonly timestampFormat; | ||
constructor({ logger, timestampFormat }: { | ||
constructor({ logger, timestampFormat, }: { | ||
logger?: Logger; | ||
timestampFormat?: string; | ||
}); | ||
printExitInfoTimingTable(exitInfos: CloseEvent[]): CloseEvent[]; | ||
private printExitInfoTimingTable; | ||
handle(commands: Command[]): { | ||
@@ -25,0 +25,0 @@ commands: Command[]; |
@@ -39,7 +39,7 @@ "use strict"; | ||
class LogTimings { | ||
constructor({ logger, timestampFormat = defaults.timestampFormat }) { | ||
constructor({ logger, timestampFormat = defaults.timestampFormat, }) { | ||
this.logger = logger; | ||
this.timestampFormat = timestampFormat; | ||
} | ||
static mapCloseEventToTimingInfo({ command, timings, killed, exitCode }) { | ||
static mapCloseEventToTimingInfo({ command, timings, killed, exitCode, }) { | ||
const readableDurationMs = (timings.endDate.getTime() - timings.startDate.getTime()).toLocaleString(); | ||
@@ -55,3 +55,2 @@ return { | ||
printExitInfoTimingTable(exitInfos) { | ||
var _a, _b; | ||
const exitInfoTable = (0, lodash_1.default)(exitInfos) | ||
@@ -62,7 +61,6 @@ .sortBy(({ timings }) => timings.durationSeconds) | ||
.value(); | ||
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.logGlobalEvent('Timings:'); | ||
(_b = this.logger) === null || _b === void 0 ? void 0 : _b.logTable(exitInfoTable); | ||
this.logger.logGlobalEvent('Timings:'); | ||
this.logger.logTable(exitInfoTable); | ||
return exitInfos; | ||
} | ||
; | ||
handle(commands) { | ||
@@ -75,6 +73,5 @@ if (!this.logger) { | ||
command.timer.subscribe(({ startDate, endDate }) => { | ||
var _a, _b; | ||
if (!endDate) { | ||
const formattedStartDate = (0, format_1.default)(startDate, this.timestampFormat); | ||
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.logCommandEvent(`${command.command} started at ${formattedStartDate}`, command); | ||
this.logger.logCommandEvent(`${command.command} started at ${formattedStartDate}`, command); | ||
} | ||
@@ -84,3 +81,3 @@ else { | ||
const formattedEndDate = (0, format_1.default)(endDate, this.timestampFormat); | ||
(_b = this.logger) === null || _b === void 0 ? void 0 : _b.logCommandEvent(`${command.command} stopped at ${formattedEndDate} after ${durationMs.toLocaleString()}ms`, command); | ||
this.logger.logCommandEvent(`${command.command} stopped at ${formattedEndDate} after ${durationMs.toLocaleString()}ms`, command); | ||
} | ||
@@ -92,3 +89,3 @@ }); | ||
const allProcessesClosed = Rx.merge(...closeStreams).pipe((0, operators_1.bufferCount)(closeStreams.length), (0, operators_1.take)(1)); | ||
allProcessesClosed.subscribe((exitInfos) => this.printExitInfoTimingTable(exitInfos)); | ||
allProcessesClosed.subscribe(exitInfos => this.printExitInfoTimingTable(exitInfos)); | ||
return { commands }; | ||
@@ -98,2 +95,1 @@ } | ||
exports.LogTimings = LogTimings; | ||
; |
@@ -13,3 +13,3 @@ import * as Rx from 'rxjs'; | ||
readonly tries: number; | ||
constructor({ delay, tries, logger, scheduler }: { | ||
constructor({ delay, tries, logger, scheduler, }: { | ||
delay?: number; | ||
@@ -16,0 +16,0 @@ tries?: number; |
@@ -34,3 +34,3 @@ "use strict"; | ||
class RestartProcess { | ||
constructor({ delay, tries, logger, scheduler }) { | ||
constructor({ delay, tries, logger, scheduler, }) { | ||
this.logger = logger; | ||
@@ -46,3 +46,5 @@ this.delay = delay != null ? +delay : defaults.restartDelay; | ||
} | ||
commands.map(command => command.close.pipe((0, operators_1.take)(this.tries), (0, operators_1.takeWhile)(({ exitCode }) => exitCode !== 0))).map((failure, index) => Rx.merge( | ||
commands | ||
.map(command => command.close.pipe((0, operators_1.take)(this.tries), (0, operators_1.takeWhile)(({ exitCode }) => exitCode !== 0))) | ||
.map((failure, index) => Rx.merge( | ||
// Delay the emission (so that the restarts happen on time), | ||
@@ -77,2 +79,1 @@ // explicitly telling the subscriber that a restart is needed | ||
exports.RestartProcess = RestartProcess; | ||
; |
/// <reference types="node" /> | ||
/// <reference types="node" /> | ||
/// <reference types="node" /> | ||
/// <reference types="node" /> | ||
import { SpawnOptions } from 'child_process'; | ||
@@ -29,3 +32,3 @@ import supportsColor from 'supports-color'; | ||
*/ | ||
env?: Record<string, any>; | ||
env?: Record<string, unknown>; | ||
}) => SpawnOptions; |
@@ -8,5 +8,12 @@ "use strict"; | ||
const supports_color_1 = __importDefault(require("supports-color")); | ||
const getSpawnOpts = ({ colorSupport = supports_color_1.default.stdout, cwd, process = global.process, raw = false, env = {}, }) => Object.assign({ | ||
const getSpawnOpts = ({ colorSupport = supports_color_1.default.stdout, cwd, process = global.process, raw = false, env = {}, }) => ({ | ||
cwd: cwd || process.cwd(), | ||
}, raw && { stdio: 'inherit' }, /^win/.test(process.platform) && { detached: false }, { env: Object.assign(colorSupport ? { FORCE_COLOR: colorSupport.level } : {}, process.env, env) }); | ||
...(raw && { stdio: 'inherit' }), | ||
...(/^win/.test(process.platform) && { detached: false }), | ||
env: { | ||
...(colorSupport ? { FORCE_COLOR: colorSupport.level.toString() } : {}), | ||
...process.env, | ||
...env, | ||
}, | ||
}); | ||
exports.getSpawnOpts = getSpawnOpts; |
@@ -22,3 +22,3 @@ import * as Rx from 'rxjs'; | ||
}>; | ||
constructor({ hide, prefixFormat, prefixLength, raw, timestampFormat }: { | ||
constructor({ hide, prefixFormat, prefixLength, raw, timestampFormat, }: { | ||
/** | ||
@@ -70,5 +70,5 @@ * Which command(s) should have their output hidden. | ||
*/ | ||
logTable(tableContents: any[]): void; | ||
logTable(tableContents: unknown[]): void; | ||
log(prefix: string, text: string, command?: Command): void; | ||
emit(command: Command | undefined, text: string): void; | ||
} |
@@ -36,3 +36,3 @@ "use strict"; | ||
class Logger { | ||
constructor({ hide, prefixFormat, prefixLength, raw = false, timestampFormat }) { | ||
constructor({ hide, prefixFormat, prefixLength, raw = false, timestampFormat, }) { | ||
/** | ||
@@ -46,3 +46,5 @@ * Observable that emits when there's been output logged. | ||
// This might happen through the CLI when no `--hide` argument is specified, for example. | ||
this.hide = lodash_1.default.castArray(hide).filter(name => name || name === 0).map(String); | ||
this.hide = lodash_1.default.castArray(hide) | ||
.filter(name => name || name === 0) | ||
.map(String); | ||
this.raw = raw; | ||
@@ -61,4 +63,4 @@ this.prefixFormat = prefixFormat; | ||
const beginningLength = prefixLength - endLength; | ||
const beginnning = text.substring(0, beginningLength); | ||
const end = text.substring(text.length - endLength, text.length); | ||
const beginnning = text.slice(0, beginningLength); | ||
const end = text.slice(text.length - endLength, text.length); | ||
return beginnning + ellipsis + end; | ||
@@ -143,3 +145,3 @@ } | ||
const rowContents = []; | ||
Object.keys(row).forEach((col) => { | ||
Object.keys(row).forEach(col => { | ||
if (!headers[col]) { | ||
@@ -160,5 +162,3 @@ headers[col] = { | ||
}); | ||
const headersFormatted = Object | ||
.keys(headers) | ||
.map(header => header.padEnd(headers[header].length, ' ')); | ||
const headersFormatted = Object.keys(headers).map(header => header.padEnd(headers[header].length, ' ')); | ||
if (!headersFormatted.length) { | ||
@@ -208,2 +208,1 @@ // No columns exist. | ||
exports.Logger = Logger; | ||
; |
@@ -12,3 +12,3 @@ /// <reference types="node" /> | ||
activeCommandIndex: number; | ||
constructor({ outputStream, group, commands }: { | ||
constructor({ outputStream, group, commands, }: { | ||
outputStream: Writable; | ||
@@ -15,0 +15,0 @@ group: boolean; |
@@ -32,3 +32,3 @@ "use strict"; | ||
class OutputWriter { | ||
constructor({ outputStream, group, commands }) { | ||
constructor({ outputStream, group, commands, }) { | ||
this.activeCommandIndex = 0; | ||
@@ -39,4 +39,3 @@ this.outputStream = outputStream; | ||
if (this.group) { | ||
Rx.merge(...commands.map(c => c.close)) | ||
.subscribe(command => { | ||
Rx.merge(...commands.map(c => c.close)).subscribe(command => { | ||
if (command.index !== this.activeCommandIndex) { | ||
@@ -75,2 +74,1 @@ return; | ||
exports.OutputWriter = OutputWriter; | ||
; |
@@ -5,4 +5,5 @@ // | ||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
const concurrently = require('./dist/src/index.js'); | ||
module.exports = exports = concurrently.default; | ||
Object.assign(exports, concurrently); |
{ | ||
"name": "concurrently", | ||
"version": "7.2.2", | ||
"version": "7.3.0", | ||
"description": "Run commands concurrently", | ||
@@ -15,6 +15,9 @@ "main": "index.js", | ||
"exports": { | ||
"import": "./index.mjs", | ||
"require": "./index.js", | ||
"default": "./index.js", | ||
"types": "./dist/src/index.d.ts" | ||
".": { | ||
"import": "./index.mjs", | ||
"require": "./index.js", | ||
"default": "./index.js", | ||
"types": "./dist/src/index.d.ts" | ||
}, | ||
"./package.json": "./package.json" | ||
}, | ||
@@ -25,3 +28,6 @@ "scripts": { | ||
"clean": "tsc --build --clean", | ||
"format": "prettier --ignore-path .gitignore --check '**/{!(package-lock).json,*.y?(a)ml,*.md}'", | ||
"format:fix": "npm run format -- --write", | ||
"lint": "eslint . --ext js,ts --ignore-path .gitignore", | ||
"lint:fix": "npm run lint -- --fix", | ||
"prepublishOnly": "npm run build", | ||
@@ -57,2 +63,5 @@ "report-coverage": "cat coverage/lcov.info | coveralls", | ||
"devDependencies": { | ||
"@swc-node/register": "^1.5.1", | ||
"@swc/core": "^1.2.204", | ||
"@swc/jest": "^0.2.21", | ||
"@types/jest": "^27.0.3", | ||
@@ -68,6 +77,9 @@ "@types/lodash": "^4.14.178", | ||
"eslint": "^8.15.0", | ||
"eslint-config-prettier": "^8.5.0", | ||
"eslint-plugin-prettier": "^4.0.0", | ||
"jest": "^27.5.1", | ||
"jest-create-mock-instance": "^2.0.0", | ||
"ts-jest": "^27.1.4", | ||
"ts-node": "^10.4.0", | ||
"lint-staged": "^12.4.1", | ||
"prettier": "^2.6.2", | ||
"simple-git-hooks": "^2.7.0", | ||
"typescript": "^4.5.4" | ||
@@ -83,19 +95,9 @@ }, | ||
], | ||
"jest": { | ||
"preset": "ts-jest", | ||
"collectCoverage": true, | ||
"collectCoverageFrom": [ | ||
"src/**/*.ts", | ||
"!src/index.ts" | ||
], | ||
"coveragePathIgnorePatterns": [ | ||
"/fixtures/", | ||
"/node_modules/" | ||
], | ||
"testEnvironment": "node", | ||
"testPathIgnorePatterns": [ | ||
"/node_modules/", | ||
"/dist" | ||
] | ||
"simple-git-hooks": { | ||
"pre-commit": "npx lint-staged" | ||
}, | ||
"lint-staged": { | ||
"*.{js,ts}": "eslint --fix", | ||
"{!(package-lock).json,*.y?(a)ml,*.md}": "prettier --write" | ||
} | ||
} |
149
README.md
@@ -1,15 +0,17 @@ | ||
# Concurrently | ||
# concurrently | ||
[![Build Status](https://github.com/open-cli-tools/concurrently/workflows/Tests/badge.svg)](https://github.com/open-cli-tools/concurrently/actions?workflow=Tests) | ||
[![Coverage Status](https://coveralls.io/repos/github/open-cli-tools/concurrently/badge.svg?branch=master)](https://coveralls.io/github/open-cli-tools/concurrently?branch=master) | ||
[![Latest Release](https://img.shields.io/github/v/release/open-cli-tools/concurrently?label=Release)](https://github.com/open-cli-tools/concurrently/releases) | ||
[![License](https://img.shields.io/github/license/open-cli-tools/concurrently?label=License)](https://github.com/open-cli-tools/concurrently/blob/main/LICENSE) | ||
[![Weekly Downloads on NPM](https://img.shields.io/npm/dw/concurrently?label=Downloads&logo=npm)](https://www.npmjs.com/package/concurrently) | ||
[![CI Status](https://img.shields.io/github/workflow/status/open-cli-tools/concurrently/CI?label=CI&logo=github)](https://github.com/open-cli-tools/concurrently/actions/workflows/ci.yml) | ||
[![Coverage Status](https://img.shields.io/coveralls/github/open-cli-tools/concurrently/main?label=Coverage&logo=coveralls)](https://coveralls.io/github/open-cli-tools/concurrently?branch=main) | ||
[![NPM Badge](https://nodei.co/npm/concurrently.png?downloads=true)](https://www.npmjs.com/package/concurrently) | ||
Run multiple commands concurrently. | ||
Like `npm run watch-js & npm run watch-less` but better. | ||
![](docs/demo.gif) | ||
![Demo](docs/demo.gif) | ||
**Table of contents** | ||
- [Concurrently](#concurrently) | ||
**Table of Contents** | ||
- [concurrently](#concurrently) | ||
- [Why](#why) | ||
@@ -37,6 +39,6 @@ - [Install](#install) | ||
* Cross platform (including Windows) | ||
* Output is easy to follow with prefixes | ||
* With `--kill-others` switch, all commands are killed if one dies | ||
* Spawns commands with [spawn-command](https://github.com/mmalecki/spawn-command) | ||
- Cross platform (including Windows) | ||
- Output is easy to follow with prefixes | ||
- With `--kill-others` switch, all commands are killed if one dies | ||
- Spawns commands with [spawn-command](https://github.com/mmalecki/spawn-command) | ||
@@ -60,2 +62,3 @@ ## Install | ||
Remember to surround separate commands with quotes: | ||
```bash | ||
@@ -86,13 +89,13 @@ concurrently "command1 arg" "command2 arg" | ||
```javascript | ||
```jsonc | ||
{ | ||
//... | ||
"scripts": { | ||
// ... | ||
"watch-js": "...", | ||
"watch-css": "...", | ||
"watch-node": "...", | ||
// ... | ||
}, | ||
//... | ||
"scripts": { | ||
// ... | ||
"watch-js": "...", | ||
"watch-css": "...", | ||
"watch-node": "..." | ||
// ... | ||
} | ||
// ... | ||
} | ||
@@ -116,15 +119,17 @@ ``` | ||
Exclusion is also supported. Given the following scripts in package.json: | ||
```javascript | ||
```jsonc | ||
{ | ||
// ... | ||
"scripts": { | ||
"lint:js": "...", | ||
"lint:ts": "...", | ||
"lint:fix:js": "...", | ||
"lint:fix:ts": "..." | ||
// ... | ||
"scripts": { | ||
"lint:js": "...", | ||
"lint:ts": "...", | ||
"lint:fix:js": "...", | ||
"lint:fix:ts": "...", | ||
// ... | ||
} | ||
// ... | ||
} | ||
// ... | ||
} | ||
``` | ||
```bash | ||
@@ -298,4 +303,5 @@ # Running only lint:js and lint:ts | ||
## API | ||
concurrently can be used programmatically by using the API documented below: | ||
**concurrently** can be used programmatically by using the API documented below: | ||
### `concurrently(commands[, options])` | ||
@@ -307,34 +313,35 @@ | ||
- `options` (optional): an object containing any of the below: | ||
- `cwd`: the working directory to be used by all commands. Can be overriden per command. | ||
- `cwd`: the working directory to be used by all commands. Can be overriden per command. | ||
Default: `process.cwd()`. | ||
- `defaultInputTarget`: the default input target when reading from `inputStream`. | ||
- `defaultInputTarget`: the default input target when reading from `inputStream`. | ||
Default: `0`. | ||
- `handleInput`: when `true`, reads input from `process.stdin`. | ||
- `inputStream`: a [`Readable` stream](https://nodejs.org/dist/latest-v10.x/docs/api/stream.html#stream_readable_streams) | ||
- `handleInput`: when `true`, reads input from `process.stdin`. | ||
- `inputStream`: a [`Readable` stream](https://nodejs.org/dist/latest-v10.x/docs/api/stream.html#stream_readable_streams) | ||
to read the input from. Should only be used in the rare instance you would like to stream anything other than `process.stdin`. Overrides `handleInput`. | ||
- `pauseInputStreamOnFinish`: by default, pauses the input stream (`process.stdin` when `handleInput` is enabled, or `inputStream` if provided) when all of the processes have finished. If you need to read from the input stream after `concurrently` has finished, set this to `false`. ([#252](https://github.com/kimmobrunfeldt/concurrently/issues/252)). | ||
- `killOthers`: an array of exitting conditions that will cause a process to kill others. | ||
- `pauseInputStreamOnFinish`: by default, pauses the input stream (`process.stdin` when `handleInput` is enabled, or `inputStream` if provided) when all of the processes have finished. If you need to read from the input stream after `concurrently` has finished, set this to `false`. ([#252](https://github.com/kimmobrunfeldt/concurrently/issues/252)). | ||
- `killOthers`: an array of exitting conditions that will cause a process to kill others. | ||
Can contain any of `success` or `failure`. | ||
- `maxProcesses`: how many processes should run at once. | ||
- `outputStream`: a [`Writable` stream](https://nodejs.org/dist/latest-v10.x/docs/api/stream.html#stream_writable_streams) | ||
- `maxProcesses`: how many processes should run at once. | ||
- `outputStream`: a [`Writable` stream](https://nodejs.org/dist/latest-v10.x/docs/api/stream.html#stream_writable_streams) | ||
to write logs to. Default: `process.stdout`. | ||
- `prefix`: the prefix type to use when logging processes output. | ||
Possible values: `index`, `pid`, `time`, `command`, `name`, `none`, or a template (eg `[{time} process: {pid}]`). | ||
Default: the name of the process, or its index if no name is set. | ||
- `prefixColors`: a list of colors as supported by [chalk](https://www.npmjs.com/package/chalk). | ||
If concurrently would run more commands than there are colors, the last color is repeated. | ||
Prefix colors specified per-command take precedence over this list. | ||
- `prefixLength`: how many characters to show when prefixing with `command`. Default: `10` | ||
- `raw`: whether raw mode should be used, meaning strictly process output will | ||
- `prefix`: the prefix type to use when logging processes output. | ||
Possible values: `index`, `pid`, `time`, `command`, `name`, `none`, or a template (eg `[{time} process: {pid}]`). | ||
Default: the name of the process, or its index if no name is set. | ||
- `prefixColors`: a list of colors as supported by [chalk](https://www.npmjs.com/package/chalk). | ||
If concurrently would run more commands than there are colors, the last color is repeated. | ||
Prefix colors specified per-command take precedence over this list. | ||
- `prefixLength`: how many characters to show when prefixing with `command`. Default: `10` | ||
- `raw`: whether raw mode should be used, meaning strictly process output will | ||
be logged, without any prefixes, colouring or extra stuff. | ||
- `successCondition`: the condition to consider the run was successful. | ||
- `successCondition`: the condition to consider the run was successful. | ||
If `first`, only the first process to exit will make up the success of the run; if `last`, the last process that exits will determine whether the run succeeds. | ||
Anything else means all processes should exit successfully. | ||
- `restartTries`: how many attempts to restart a process that dies will be made. Default: `0`. | ||
- `restartDelay`: how many milliseconds to wait between process restarts. Default: `0`. | ||
- `timestampFormat`: a [date-fns format](https://date-fns.org/v2.0.1/docs/format) | ||
- `restartTries`: how many attempts to restart a process that dies will be made. Default: `0`. | ||
- `restartDelay`: how many milliseconds to wait between process restarts. Default: `0`. | ||
- `timestampFormat`: a [date-fns format](https://date-fns.org/v2.0.1/docs/format) | ||
to use when prefixing with `time`. Default: `yyyy-MM-dd HH:mm:ss.ZZZ` | ||
- `additionalArguments`: list of additional arguments passed that will get replaced in each command. If not defined, no argument replacing will happen. | ||
- `additionalArguments`: list of additional arguments passed that will get replaced in each command. If not defined, no argument replacing will happen. | ||
> **Returns:** an object in the shape `{ result, commands }`. | ||
> | ||
> - `result`: a `Promise` that resolves if the run was successful (according to `successCondition` option), | ||
@@ -348,8 +355,14 @@ > or rejects, containing an array of [`CloseEvent`](#CloseEvent), in the order that the commands terminated. | ||
const concurrently = require('concurrently'); | ||
const { result } = concurrently([ | ||
const { result } = concurrently( | ||
[ | ||
'npm:watch-*', | ||
{ command: 'nodemon', name: 'server' }, | ||
{ command: 'deploy', name: 'deploy', env: { PUBLIC_KEY: '...' } }, | ||
{ command: 'watch', name: 'watch', cwd: path.resolve(__dirname, 'scripts/watchers')} | ||
], { | ||
{ | ||
command: 'watch', | ||
name: 'watch', | ||
cwd: path.resolve(__dirname, 'scripts/watchers'), | ||
}, | ||
], | ||
{ | ||
prefix: 'name', | ||
@@ -359,3 +372,4 @@ killOthers: ['failure', 'success'], | ||
cwd: path.resolve(__dirname, 'scripts'), | ||
}); | ||
} | ||
); | ||
result.then(success, failure); | ||
@@ -365,2 +379,3 @@ ``` | ||
### `Command` | ||
An object that contains all information about a spawned command, and ways to interact with it.<br> | ||
@@ -388,2 +403,3 @@ It has the following properties: | ||
### `CloseEvent` | ||
An object with information about a command's closing event.<br> | ||
@@ -400,17 +416,16 @@ It contains the following properties: | ||
* Process exited with code *null*? | ||
- Process exited with code _null_? | ||
From [Node child_process documentation](http://nodejs.org/api/child_process.html#child_process_event_exit), `exit` event: | ||
From [Node child_process documentation](http://nodejs.org/api/child_process.html#child_process_event_exit), `exit` event: | ||
> This event is emitted after the child process ends. If the process | ||
> terminated normally, code is the final exit code of the process, | ||
> otherwise null. If the process terminated due to receipt of a signal, | ||
> signal is the string name of the signal, otherwise null. | ||
> This event is emitted after the child process ends. If the process | ||
> terminated normally, code is the final exit code of the process, | ||
> otherwise null. If the process terminated due to receipt of a signal, | ||
> signal is the string name of the signal, otherwise null. | ||
So _null_ means the process didn't terminate normally. This will make **concurrently** | ||
to return non-zero exit code too. | ||
So *null* means the process didn't terminate normally. This will make **concurrent** | ||
to return non-zero exit code too. | ||
- Does this work with the npm-replacements [yarn](https://github.com/yarnpkg/yarn) or [pnpm](https://pnpm.js.org/)? | ||
* Does this work with the npm-replacements [yarn](https://github.com/yarnpkg/yarn) or [pnpm](https://pnpm.js.org/)? | ||
Yes! In all examples above, you may replace "`npm`" with "`yarn`" or "`pnpm`". | ||
Yes! In all examples above, you may replace "`npm`" with "`yarn`" or "`pnpm`". |
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
421
110862
21
2307