This commit is contained in:
2025-03-18 16:37:12 +02:00
commit 91c2721fe6
4862 changed files with 405393 additions and 0 deletions

2
node_modules/concurrently/dist/bin/concurrently.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
#!/usr/bin/env node
export {};

251
node_modules/concurrently/dist/bin/concurrently.js generated vendored Normal file
View File

@@ -0,0 +1,251 @@
#!/usr/bin/env node
"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 });
const lodash_1 = __importDefault(require("lodash"));
const yargs_1 = __importDefault(require("yargs"));
const helpers_1 = require("yargs/helpers");
const defaults = __importStar(require("../src/defaults"));
const index_1 = require("../src/index");
const read_package_1 = require("./read-package");
const version = String((0, read_package_1.readPackage)().version);
const epilogue = `For documentation and more examples, visit:\nhttps://github.com/open-cli-tools/concurrently/tree/v${version}/docs`;
// Clean-up arguments (yargs expects only the arguments after the program name)
const program = (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
.parserConfiguration({
// Avoids options that can be specified multiple times from requiring a `--` to pass commands
'greedy-arrays': false,
// Makes sure that --passthrough-arguments works correctly
'populate--': true,
})
.usage('$0 [options] <command ...>')
.help('h')
.alias('h', 'help')
.version(version)
.alias('version', 'v')
.alias('version', 'V')
// TODO: Add some tests for this.
.env('CONCURRENTLY')
.options({
// General
'max-processes': {
alias: 'm',
describe: 'How many processes should run at once.\n' +
'New processes only spawn after all restart tries of a process.\n' +
'Exact number or a percent of CPUs available (for example "50%")',
type: 'string',
},
names: {
alias: 'n',
describe: 'List of custom names to be used in prefix template.\n' +
'Example names: "main,browser,server"',
type: 'string',
},
'name-separator': {
describe: 'The character to split <names> on. Example usage:\n' +
'-n "styles|scripts|server" --name-separator "|"',
default: defaults.nameSeparator,
},
success: {
alias: 's',
describe: 'Which command(s) must exit with code 0 in order for concurrently exit with ' +
'code 0 too. Options are:\n' +
'- "first" for the first command to exit;\n' +
'- "last" for the last command to exit;\n' +
'- "all" for all commands;\n' +
// Note: not a typo. Multiple commands can have the same name.
'- "command-{name}"/"command-{index}" for the commands with that name or index;\n' +
'- "!command-{name}"/"!command-{index}" for all commands but the ones with that ' +
'name or index.\n',
default: defaults.success,
},
raw: {
alias: 'r',
describe: 'Output only raw output of processes, disables prettifying ' +
'and concurrently coloring.',
type: 'boolean',
},
// This one is provided for free. Chalk reads this itself and removes colors.
// https://www.npmjs.com/package/chalk#chalksupportscolor
'no-color': {
describe: 'Disables colors from logging',
type: 'boolean',
},
hide: {
describe: 'Comma-separated list of processes to hide the output.\n' +
'The processes can be identified by their name or index.',
default: defaults.hide,
type: 'string',
},
group: {
alias: 'g',
describe: 'Order the output as if the commands were run sequentially.',
type: 'boolean',
},
timings: {
describe: 'Show timing information for all processes.',
type: 'boolean',
default: defaults.timings,
},
'passthrough-arguments': {
alias: 'P',
describe: 'Passthrough additional arguments to commands (accessible via placeholders) ' +
'instead of treating them as commands.',
type: 'boolean',
default: defaults.passthroughArguments,
},
teardown: {
describe: 'Clean up command(s) to execute before exiting concurrently. Might be specified multiple times.\n' +
"These aren't prefixed and they don't affect concurrently's exit code.",
type: 'string',
array: true,
},
// Kill others
'kill-others': {
alias: 'k',
describe: 'Kill other processes if one exits or dies.',
type: 'boolean',
},
'kill-others-on-fail': {
describe: 'Kill other processes if one exits with non zero status code.',
type: 'boolean',
},
'kill-signal': {
alias: 'ks',
describe: 'Signal to send to other processes if one exits or dies. (SIGTERM/SIGKILL, defaults to SIGTERM)',
type: 'string',
default: defaults.killSignal,
},
// Prefix
prefix: {
alias: 'p',
describe: 'Prefix used in logging for each process.\n' +
'Possible values: index, pid, time, command, name, none, or a template. ' +
'Example template: "{time}-{pid}"',
defaultDescription: 'index or name (when --names is set)',
type: 'string',
},
'prefix-colors': {
alias: 'c',
describe: 'Comma-separated list of chalk colors to use on prefixes. ' +
'If there are more commands than colors, the last color will be repeated.\n' +
'- Available modifiers: reset, bold, dim, italic, underline, inverse, hidden, strikethrough\n' +
'- Available colors: black, red, green, yellow, blue, magenta, cyan, white, gray, \n' +
'any hex values for colors (e.g. #23de43) or auto for an automatically picked color\n' +
'- Available background colors: bgBlack, bgRed, bgGreen, bgYellow, bgBlue, bgMagenta, bgCyan, bgWhite\n' +
'See https://www.npmjs.com/package/chalk for more information.',
default: defaults.prefixColors,
type: 'string',
},
'prefix-length': {
alias: 'l',
describe: 'Limit how many characters of the command is displayed in prefix. ' +
'The option can be used to shorten the prefix when it is set to "command"',
default: defaults.prefixLength,
type: 'number',
},
'pad-prefix': {
describe: 'Pads short prefixes with spaces so that the length of all prefixes match',
type: 'boolean',
},
'timestamp-format': {
alias: 't',
describe: 'Specify the timestamp in Unicode format:\n' +
'https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table',
default: defaults.timestampFormat,
type: 'string',
},
// Restarting
'restart-tries': {
describe: 'How many times a process that died should restart.\n' +
'Negative numbers will make the process restart forever.',
default: defaults.restartTries,
type: 'number',
},
'restart-after': {
describe: 'Delay before restarting the process, in milliseconds, or "exponential".',
default: defaults.restartDelay,
type: 'string',
},
// Input
'handle-input': {
alias: 'i',
describe: 'Whether input should be forwarded to the child processes. ' +
'See examples for more information.',
type: 'boolean',
},
'default-input-target': {
default: defaults.defaultInputTarget,
describe: 'Identifier for child process to which input on stdin ' +
'should be sent if not specified at start of input.\n' +
'Can be either the index or the name of the process.',
},
})
.group(['m', 'n', 'name-separator', 's', 'r', 'no-color', 'hide', 'g', 'timings', 'P', 'teardown'], 'General')
.group(['p', 'c', 'l', 't', 'pad-prefix'], 'Prefix styling')
.group(['i', 'default-input-target'], 'Input handling')
.group(['k', 'kill-others-on-fail', 'kill-signal'], 'Killing other processes')
.group(['restart-tries', 'restart-after'], 'Restarting')
.epilogue(epilogue);
const args = program.parseSync();
// Get names of commands by the specified separator
const names = (args.names || '').split(args.nameSeparator);
const additionalArguments = lodash_1.default.castArray(args['--'] ?? []).map(String);
const commands = args.passthroughArguments ? args._ : args._.concat(additionalArguments);
if (!commands.length) {
program.showHelp();
process.exit();
}
(0, index_1.concurrently)(commands.map((command, index) => ({
command: String(command),
name: names[index],
})), {
handleInput: args.handleInput,
defaultInputTarget: args.defaultInputTarget,
killOthers: args.killOthers
? ['success', 'failure']
: args.killOthersOnFail
? ['failure']
: [],
killSignal: args.killSignal,
maxProcesses: args.maxProcesses,
raw: args.raw,
hide: args.hide.split(','),
group: args.group,
prefix: args.prefix,
prefixColors: args.prefixColors.split(','),
prefixLength: args.prefixLength,
padPrefix: args.padPrefix,
restartDelay: args.restartAfter === 'exponential' ? 'exponential' : Number(args.restartAfter),
restartTries: args.restartTries,
successCondition: args.success,
timestampFormat: args.timestampFormat,
timings: args.timings,
teardown: args.teardown,
additionalArguments: args.passthroughArguments ? additionalArguments : undefined,
}).result.then(() => process.exit(0), () => process.exit(1));

6
node_modules/concurrently/dist/bin/read-package.d.ts generated vendored Normal file
View File

@@ -0,0 +1,6 @@
/**
* Traverses the directory tree until a package.json file is found.
*
* @throws if the root directory is reached, and no package.json is found.
*/
export declare function readPackage(): Record<string, unknown>;

47
node_modules/concurrently/dist/bin/read-package.js generated vendored Normal file
View File

@@ -0,0 +1,47 @@
"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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.readPackage = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
/**
* Traverses the directory tree until a package.json file is found.
*
* @throws if the root directory is reached, and no package.json is found.
*/
function readPackage() {
let dir = require.main?.path ?? process.cwd();
let oldDir = dir;
do {
const pkgPath = path.join(dir, 'package.json');
if (fs.existsSync(pkgPath)) {
return JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
}
oldDir = dir;
dir = path.dirname(dir);
} while (oldDir !== dir);
throw new Error('package.json not found');
}
exports.readPackage = readPackage;

View File

@@ -0,0 +1,19 @@
import { CommandInfo } from '../command';
/**
* A command parser encapsulates a specific logic for mapping `CommandInfo` objects
* into another `CommandInfo`.
*
* A prime example is turning an abstract `npm:foo` into `npm run foo`, but it could also turn
* the prefix color of a command brighter, or maybe even prefixing each command with `time(1)`.
*/
export interface CommandParser {
/**
* Parses `commandInfo` and returns one or more `CommandInfo`s.
*
* Returning multiple `CommandInfo` is used when there are multiple possibilities of commands to
* run given the original input.
* An example of this is when the command contains a wildcard and it must be expanded into all
* viable options so that the consumer can decide which ones to run.
*/
parse(commandInfo: CommandInfo): CommandInfo | CommandInfo[];
}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,18 @@
import { CommandInfo } from '../command';
import { CommandParser } from './command-parser';
/**
* Replace placeholders with additional arguments.
*/
export declare class ExpandArguments implements CommandParser {
private readonly additionalArguments;
constructor(additionalArguments: string[]);
parse(commandInfo: CommandInfo): {
command: string;
name: string;
env?: Record<string, unknown> | undefined;
cwd?: string | undefined;
prefixColor?: string | undefined;
ipc?: number | undefined;
raw?: boolean | undefined;
};
}

View File

@@ -0,0 +1,39 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExpandArguments = void 0;
const shell_quote_1 = require("shell-quote");
/**
* Replace placeholders with additional arguments.
*/
class ExpandArguments {
additionalArguments;
constructor(additionalArguments) {
this.additionalArguments = additionalArguments;
}
parse(commandInfo) {
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.slice(1);
}
// Replace numeric placeholder if value exists in additional arguments.
if (!isNaN(placeholderTarget) &&
placeholderTarget <= this.additionalArguments.length) {
return (0, shell_quote_1.quote)([this.additionalArguments[placeholderTarget - 1]]);
}
// Replace all arguments placeholder.
if (placeholderTarget === '@') {
return (0, shell_quote_1.quote)(this.additionalArguments);
}
// Replace combined arguments placeholder.
if (placeholderTarget === '*') {
return (0, shell_quote_1.quote)([this.additionalArguments.join(' ')]);
}
// Replace placeholder with empty string
// if value doesn't exist in additional arguments.
return '';
});
return { ...commandInfo, command };
}
}
exports.ExpandArguments = ExpandArguments;

View File

@@ -0,0 +1,17 @@
import { CommandInfo } from '../command';
import { CommandParser } from './command-parser';
/**
* Expands shortcuts according to the following table:
*
* | Syntax | Expands to |
* | --------------- | --------------------- |
* | `npm:<script>` | `npm run <script>` |
* | `pnpm:<script>` | `pnpm run <script>` |
* | `yarn:<script>` | `yarn run <script>` |
* | `bun:<script>` | `bun run <script>` |
* | `node:<script>` | `node --run <script>` |
* | `deno:<script>` | `deno task <script>` |
*/
export declare class ExpandShortcut implements CommandParser {
parse(commandInfo: CommandInfo): CommandInfo;
}

View File

@@ -0,0 +1,39 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExpandShortcut = void 0;
/**
* Expands shortcuts according to the following table:
*
* | Syntax | Expands to |
* | --------------- | --------------------- |
* | `npm:<script>` | `npm run <script>` |
* | `pnpm:<script>` | `pnpm run <script>` |
* | `yarn:<script>` | `yarn run <script>` |
* | `bun:<script>` | `bun run <script>` |
* | `node:<script>` | `node --run <script>` |
* | `deno:<script>` | `deno task <script>` |
*/
class ExpandShortcut {
parse(commandInfo) {
const [, prefix, script, args] = /^(npm|yarn|pnpm|bun|node|deno):(\S+)(.*)/.exec(commandInfo.command) || [];
if (!script) {
return commandInfo;
}
let command;
if (prefix === 'node') {
command = 'node --run';
}
else if (prefix === 'deno') {
command = 'deno task';
}
else {
command = `${prefix} run`;
}
return {
...commandInfo,
name: commandInfo.name || script,
command: `${command} ${script}${args}`,
};
}
}
exports.ExpandShortcut = ExpandShortcut;

View File

@@ -0,0 +1,18 @@
import { CommandInfo } from '../command';
import { CommandParser } from './command-parser';
/**
* Finds wildcards in 'npm/yarn/pnpm/bun run', 'node --run' and 'deno task'
* commands and replaces them with all matching scripts in the NodeJS and Deno
* configuration files of the current directory.
*/
export declare class ExpandWildcard implements CommandParser {
private readonly readDeno;
private readonly readPackage;
static readDeno(): any;
static readPackage(): any;
private packageScripts?;
private denoTasks?;
constructor(readDeno?: typeof ExpandWildcard.readDeno, readPackage?: typeof ExpandWildcard.readPackage);
private relevantScripts;
parse(commandInfo: CommandInfo): CommandInfo | CommandInfo[];
}

View File

@@ -0,0 +1,107 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExpandWildcard = void 0;
const fs_1 = __importDefault(require("fs"));
const lodash_1 = __importDefault(require("lodash"));
const jsonc_1 = __importDefault(require("../jsonc"));
// Matches a negative filter surrounded by '(!' and ')'.
const OMISSION = /\(!([^)]+)\)/;
/**
* Finds wildcards in 'npm/yarn/pnpm/bun run', 'node --run' and 'deno task'
* commands and replaces them with all matching scripts in the NodeJS and Deno
* configuration files of the current directory.
*/
class ExpandWildcard {
readDeno;
readPackage;
static readDeno() {
try {
let json = '{}';
if (fs_1.default.existsSync('deno.json')) {
json = fs_1.default.readFileSync('deno.json', { encoding: 'utf-8' });
}
else if (fs_1.default.existsSync('deno.jsonc')) {
json = fs_1.default.readFileSync('deno.jsonc', { encoding: 'utf-8' });
}
return jsonc_1.default.parse(json);
}
catch (e) {
return {};
}
}
static readPackage() {
try {
const json = fs_1.default.readFileSync('package.json', { encoding: 'utf-8' });
return JSON.parse(json);
}
catch (e) {
return {};
}
}
packageScripts;
denoTasks;
constructor(readDeno = ExpandWildcard.readDeno, readPackage = ExpandWildcard.readPackage) {
this.readDeno = readDeno;
this.readPackage = readPackage;
}
relevantScripts(command) {
if (!this.packageScripts) {
this.packageScripts = Object.keys(this.readPackage().scripts || {});
}
if (command === 'deno task') {
if (!this.denoTasks) {
// If Deno tries to run a task that doesn't exist,
// it can fall back to running a script with the same name.
// Therefore, the actual list of tasks is the union of the tasks and scripts.
this.denoTasks = [
...Object.keys(this.readDeno().tasks || {}),
...this.packageScripts,
];
}
return this.denoTasks;
}
return this.packageScripts;
}
parse(commandInfo) {
// We expect one of the following patterns:
// - <npm|yarn|pnpm|bun> run <script> [args]
// - node --run <script> [args]
// - deno task <script> [args]
const [, command, scriptGlob, args] = /((?:npm|yarn|pnpm|bun) (?:run)|node --run|deno task) (\S+)([^&]*)/.exec(commandInfo.command) || [];
const wildcardPosition = (scriptGlob || '').indexOf('*');
// If the regex didn't match an npm script, or it has no wildcard,
// then we have nothing to do here
if (wildcardPosition === -1) {
return commandInfo;
}
const [, omission] = OMISSION.exec(scriptGlob) || [];
const scriptGlobSansOmission = scriptGlob.replace(OMISSION, '');
const preWildcard = lodash_1.default.escapeRegExp(scriptGlobSansOmission.slice(0, wildcardPosition));
const postWildcard = lodash_1.default.escapeRegExp(scriptGlobSansOmission.slice(wildcardPosition + 1));
const wildcardRegex = new RegExp(`^${preWildcard}(.*?)${postWildcard}$`);
// If 'commandInfo.name' doesn't match 'scriptGlob', this means a custom name
// has been specified and thus becomes the prefix (as described in the README).
const prefix = commandInfo.name !== scriptGlob ? commandInfo.name : '';
return this.relevantScripts(command)
.map((script) => {
if (omission && RegExp(omission).test(script)) {
return;
}
const [, match] = wildcardRegex.exec(script) || [];
if (match !== undefined) {
return {
...commandInfo,
command: `${command} ${script}${args}`,
// Will use an empty command name if no prefix has been specified and
// the wildcard match is empty, e.g. if `npm:watch-*` matches `npm run watch-`.
name: prefix + match,
};
}
})
.filter((commandInfo) => !!commandInfo);
}
}
exports.ExpandWildcard = ExpandWildcard;

View File

@@ -0,0 +1,16 @@
import { CommandInfo } from '../command';
import { CommandParser } from './command-parser';
/**
* Strips quotes around commands so that they can run on the current shell.
*/
export declare class StripQuotes implements CommandParser {
parse(commandInfo: CommandInfo): {
command: string;
name: string;
env?: Record<string, unknown> | undefined;
cwd?: string | undefined;
prefixColor?: string | undefined;
ipc?: number | undefined;
raw?: boolean | undefined;
};
}

View File

@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.StripQuotes = void 0;
/**
* Strips quotes around commands so that they can run on the current shell.
*/
class StripQuotes {
parse(commandInfo) {
let { command } = commandInfo;
// Removes the quotes surrounding a command.
if (/^"(.+?)"$/.test(command) || /^'(.+?)'$/.test(command)) {
command = command.slice(1, command.length - 1);
}
return { ...commandInfo, command };
}
}
exports.StripQuotes = StripQuotes;

162
node_modules/concurrently/dist/src/command.d.ts generated vendored Normal file
View File

@@ -0,0 +1,162 @@
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
import { ChildProcess as BaseChildProcess, MessageOptions, SendHandle, SpawnOptions } from 'child_process';
import * as Rx from 'rxjs';
import { EventEmitter, Writable } from 'stream';
/**
* Identifier for a command; if string, it's the command's name, if number, it's the index.
*/
export type CommandIdentifier = string | number;
export interface CommandInfo {
/**
* Command's name.
*/
name: string;
/**
* Which command line the command has.
*/
command: string;
/**
* Which environment variables should the spawned process have.
*/
env?: Record<string, unknown>;
/**
* The current working directory of the process when spawned.
*/
cwd?: string;
/**
* Color to use on prefix of the command.
*/
prefixColor?: string;
/**
* Whether sending of messages to/from this command (also known as "inter-process communication")
* should be enabled, and using which file descriptor number.
*
* If set, must be > 2.
*/
ipc?: number;
/**
* Output command in raw format.
*/
raw?: boolean;
}
export interface CloseEvent {
command: CommandInfo;
/**
* The command's index among all commands ran.
*/
index: number;
/**
* Whether the command exited because it was killed.
*/
killed: boolean;
/**
* The exit code or signal for the command.
*/
exitCode: string | number;
timings: {
startDate: Date;
endDate: Date;
durationSeconds: number;
};
}
export interface TimerEvent {
startDate: Date;
endDate?: Date;
}
export interface MessageEvent {
message: object;
handle?: SendHandle;
}
interface OutgoingMessageEvent extends MessageEvent {
options?: MessageOptions;
onSent(error?: unknown): void;
}
/**
* Subtype of NodeJS's child_process including only what's actually needed for a command to work.
*/
export type ChildProcess = EventEmitter & Pick<BaseChildProcess, 'pid' | 'stdin' | 'stdout' | 'stderr' | 'send'>;
/**
* Interface for a function that must kill the process with `pid`, optionally sending `signal` to it.
*/
export type KillProcess = (pid: number, signal?: string) => void;
/**
* Interface for a function that spawns a command and returns its child process instance.
*/
export type SpawnCommand = (command: string, options: SpawnOptions) => ChildProcess;
/**
* The state of a command.
*
* - `stopped`: command was never started
* - `started`: command is currently running
* - `errored`: command failed spawning
* - `exited`: command is not running anymore, e.g. it received a close event
*/
type CommandState = 'stopped' | 'started' | 'errored' | 'exited';
export declare class Command implements CommandInfo {
private readonly killProcess;
private readonly spawn;
private readonly spawnOpts;
readonly index: number;
/** @inheritdoc */
readonly name: string;
/** @inheritdoc */
readonly command: string;
/** @inheritdoc */
readonly prefixColor?: string;
/** @inheritdoc */
readonly env: Record<string, unknown>;
/** @inheritdoc */
readonly cwd?: string;
/** @inheritdoc */
readonly ipc?: number;
readonly close: Rx.Subject<CloseEvent>;
readonly error: Rx.Subject<unknown>;
readonly stdout: Rx.Subject<Buffer>;
readonly stderr: Rx.Subject<Buffer>;
readonly timer: Rx.Subject<TimerEvent>;
readonly messages: {
incoming: Rx.Subject<MessageEvent>;
outgoing: Rx.ReplaySubject<OutgoingMessageEvent>;
};
process?: ChildProcess;
private subscriptions;
stdin?: Writable;
pid?: number;
killed: boolean;
exited: boolean;
state: CommandState;
constructor({ index, name, command, prefixColor, env, cwd, ipc }: CommandInfo & {
index: number;
}, spawnOpts: SpawnOptions, spawn: SpawnCommand, killProcess: KillProcess);
/**
* Starts this command, piping output, error and close events onto the corresponding observables.
*/
start(): void;
private maybeSetupIPC;
/**
* Sends a message to the underlying process once it starts.
*
* @throws If the command doesn't have an IPC channel enabled
* @returns Promise that resolves when the message is sent,
* or rejects if it fails to deliver the message.
*/
send(message: object, handle?: SendHandle, options?: MessageOptions): Promise<void>;
/**
* Kills this command, optionally specifying a signal to send to it.
*/
kill(code?: string): void;
private cleanUp;
/**
* Detects whether a command can be killed.
*
* Also works as a type guard on the input `command`.
*/
static canKill(command: Command): command is Command & {
pid: number;
process: ChildProcess;
};
}
export {};

192
node_modules/concurrently/dist/src/command.js generated vendored Normal file
View File

@@ -0,0 +1,192 @@
"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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Command = void 0;
const Rx = __importStar(require("rxjs"));
class Command {
killProcess;
spawn;
spawnOpts;
index;
/** @inheritdoc */
name;
/** @inheritdoc */
command;
/** @inheritdoc */
prefixColor;
/** @inheritdoc */
env;
/** @inheritdoc */
cwd;
/** @inheritdoc */
ipc;
close = new Rx.Subject();
error = new Rx.Subject();
stdout = new Rx.Subject();
stderr = new Rx.Subject();
timer = new Rx.Subject();
messages = {
incoming: new Rx.Subject(),
outgoing: new Rx.ReplaySubject(),
};
process;
// TODO: Should exit/error/stdio subscriptions be added here?
subscriptions = [];
stdin;
pid;
killed = false;
exited = false;
state = 'stopped';
constructor({ index, name, command, prefixColor, env, cwd, ipc }, spawnOpts, spawn, killProcess) {
this.index = index;
this.name = name;
this.command = command;
this.prefixColor = prefixColor;
this.env = env || {};
this.cwd = cwd;
this.ipc = ipc;
this.killProcess = killProcess;
this.spawn = spawn;
this.spawnOpts = spawnOpts;
}
/**
* Starts this command, piping output, error and close events onto the corresponding observables.
*/
start() {
const child = this.spawn(this.command, this.spawnOpts);
this.state = 'started';
this.process = child;
this.pid = child.pid;
const startDate = new Date(Date.now());
const highResStartTime = process.hrtime();
this.timer.next({ startDate });
this.subscriptions = [...this.maybeSetupIPC(child)];
Rx.fromEvent(child, 'error').subscribe((event) => {
this.cleanUp();
const endDate = new Date(Date.now());
this.timer.next({ startDate, endDate });
this.error.next(event);
this.state = 'errored';
});
Rx.fromEvent(child, 'close')
.pipe(Rx.map((event) => event))
.subscribe(([exitCode, signal]) => {
this.cleanUp();
// Don't override error event
if (this.state !== 'errored') {
this.state = 'exited';
}
const endDate = new Date(Date.now());
this.timer.next({ startDate, endDate });
const [durationSeconds, durationNanoSeconds] = process.hrtime(highResStartTime);
this.close.next({
command: this,
index: this.index,
exitCode: exitCode ?? String(signal),
killed: this.killed,
timings: {
startDate,
endDate,
durationSeconds: durationSeconds + durationNanoSeconds / 1e9,
},
});
});
child.stdout &&
pipeTo(Rx.fromEvent(child.stdout, 'data').pipe(Rx.map((event) => event)), this.stdout);
child.stderr &&
pipeTo(Rx.fromEvent(child.stderr, 'data').pipe(Rx.map((event) => event)), this.stderr);
this.stdin = child.stdin || undefined;
}
maybeSetupIPC(child) {
if (!this.ipc) {
return [];
}
return [
pipeTo(Rx.fromEvent(child, 'message').pipe(Rx.map((event) => {
const [message, handle] = event;
return { message, handle };
})), this.messages.incoming),
this.messages.outgoing.subscribe((message) => {
if (!child.send) {
return message.onSent(new Error('Command does not have an IPC channel'));
}
child.send(message.message, message.handle, message.options, (error) => {
message.onSent(error);
});
}),
];
}
/**
* Sends a message to the underlying process once it starts.
*
* @throws If the command doesn't have an IPC channel enabled
* @returns Promise that resolves when the message is sent,
* or rejects if it fails to deliver the message.
*/
send(message, handle, options) {
if (this.ipc == null) {
throw new Error('Command IPC is disabled');
}
return new Promise((resolve, reject) => {
this.messages.outgoing.next({
message,
handle,
options,
onSent(error) {
error ? reject(error) : resolve();
},
});
});
}
/**
* Kills this command, optionally specifying a signal to send to it.
*/
kill(code) {
if (Command.canKill(this)) {
this.killed = true;
this.killProcess(this.pid, code);
}
}
cleanUp() {
this.subscriptions?.forEach((sub) => sub.unsubscribe());
this.messages.outgoing = new Rx.ReplaySubject();
this.process = undefined;
}
/**
* Detects whether a command can be killed.
*
* Also works as a type guard on the input `command`.
*/
static canKill(command) {
return !!command.pid && !!command.process;
}
}
exports.Command = Command;
/**
* Pipes all events emitted by `stream` into `subject`.
*/
function pipeTo(stream, subject) {
return stream.subscribe((event) => subject.next(event));
}

View File

@@ -0,0 +1,43 @@
/// <reference types="node" />
import * as Rx from 'rxjs';
import { CloseEvent, Command } from './command';
/**
* Defines which command(s) in a list must exit successfully (with an exit code of `0`):
*
* - `first`: only the first specified command;
* - `last`: only the last specified command;
* - `all`: all commands.
* - `command-{name|index}`: only the commands with the specified names or index.
* - `!command-{name|index}`: all commands but the ones with the specified names or index.
*/
export type SuccessCondition = 'first' | 'last' | 'all' | `command-${string | number}` | `!command-${string | number}`;
/**
* Provides logic to determine whether lists of commands ran successfully.
*/
export declare class CompletionListener {
private readonly successCondition;
private readonly scheduler?;
constructor({ successCondition, scheduler, }: {
/**
* How this instance will define that a list of commands ran successfully.
* Defaults to `all`.
*
* @see {SuccessCondition}
*/
successCondition?: SuccessCondition;
/**
* For testing only.
*/
scheduler?: Rx.SchedulerLike;
});
private isSuccess;
/**
* Given a list of commands, wait for all of them to exit and then evaluate their exit codes.
*
* @returns A Promise that resolves if the success condition is met, or rejects otherwise.
* In either case, the value is a list of close events for commands that spawned.
* Commands that didn't spawn are filtered out.
*/
listen(commands: Command[], abortSignal?: AbortSignal): Promise<CloseEvent[]>;
private emitWithScheduler;
}

View File

@@ -0,0 +1,101 @@
"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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CompletionListener = void 0;
const Rx = __importStar(require("rxjs"));
const operators_1 = require("rxjs/operators");
/**
* Provides logic to determine whether lists of commands ran successfully.
*/
class CompletionListener {
successCondition;
scheduler;
constructor({ successCondition = 'all', scheduler, }) {
this.successCondition = successCondition;
this.scheduler = scheduler;
}
isSuccess(events) {
if (!events.length) {
// When every command was aborted, consider a success.
return true;
}
if (this.successCondition === 'first') {
return events[0].exitCode === 0;
}
else if (this.successCondition === 'last') {
return events[events.length - 1].exitCode === 0;
}
const commandSyntaxMatch = this.successCondition.match(/^!?command-(.+)$/);
if (commandSyntaxMatch == null) {
// If not a `command-` syntax, then it's an 'all' condition or it's treated as such.
return events.every(({ exitCode }) => exitCode === 0);
}
// Check `command-` syntax condition.
// Note that a command's `name` is not necessarily unique,
// in which case all of them must meet the success condition.
const nameOrIndex = commandSyntaxMatch[1];
const targetCommandsEvents = events.filter(({ command, index }) => command.name === nameOrIndex || index === Number(nameOrIndex));
if (this.successCondition.startsWith('!')) {
// All commands except the specified ones must exit successfully
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));
}
/**
* Given a list of commands, wait for all of them to exit and then evaluate their exit codes.
*
* @returns A Promise that resolves if the success condition is met, or rejects otherwise.
* In either case, the value is a list of close events for commands that spawned.
* Commands that didn't spawn are filtered out.
*/
listen(commands, abortSignal) {
const abort = abortSignal &&
Rx.fromEvent(abortSignal, 'abort', { once: true }).pipe(
// The abort signal must happen before commands are killed, otherwise new commands
// might spawn. Because of this, it's not be possible to capture the close events
// without an immediate delay
(0, operators_1.delay)(0, this.scheduler), (0, operators_1.map)(() => undefined),
// #502 - node might warn of too many active listeners on this object if it isn't shared,
// as each command subscribes to abort event over and over
(0, operators_1.share)());
const closeStreams = commands.map((command) => abort
? // Commands that have been started must close.
Rx.race(command.close, abort.pipe((0, operators_1.filter)(() => command.state === 'stopped')))
: command.close);
return Rx.lastValueFrom(Rx.combineLatest(closeStreams).pipe((0, operators_1.filter)(() => commands.every((command) => command.state !== 'started')), (0, operators_1.map)((events) => events
// Filter out aborts, since they cannot be sorted and are considered success condition anyways
.filter((event) => event != null)
// Sort according to exit time
.sort((first, second) => first.timings.endDate.getTime() - second.timings.endDate.getTime())), (0, operators_1.switchMap)((events) => this.isSuccess(events)
? this.emitWithScheduler(Rx.of(events))
: this.emitWithScheduler(Rx.throwError(() => events))), (0, operators_1.take)(1)));
}
emitWithScheduler(input) {
return this.scheduler ? input.pipe(Rx.observeOn(this.scheduler)) : input;
}
}
exports.CompletionListener = CompletionListener;

122
node_modules/concurrently/dist/src/concurrently.d.ts generated vendored Normal file
View File

@@ -0,0 +1,122 @@
/// <reference types="node" />
/// <reference types="node" />
import { Writable } from 'stream';
import { CloseEvent, Command, CommandIdentifier, CommandInfo, KillProcess, SpawnCommand } from './command';
import { SuccessCondition } from './completion-listener';
import { FlowController } from './flow-control/flow-controller';
import { Logger } from './logger';
/**
* A command that is to be passed into `concurrently()`.
* If value is a string, then that's the command's command line.
* Fine grained options can be defined by using the object format.
*/
export type ConcurrentlyCommandInput = string | ({
command: string;
} & Partial<CommandInfo>);
export type ConcurrentlyResult = {
/**
* All commands created and ran by concurrently.
*/
commands: Command[];
/**
* A promise that resolves when concurrently ran successfully according to the specified
* success condition, or reject otherwise.
*
* Both the resolved and rejected value is a list of all the close events for commands that
* spawned; commands that didn't spawn are filtered out.
*/
result: Promise<CloseEvent[]>;
};
export type ConcurrentlyOptions = {
logger?: Logger;
/**
* Which stream should the commands output be written to.
*/
outputStream?: Writable;
/**
* Whether the output should be ordered as if the commands were run sequentially.
*/
group?: boolean;
/**
* A comma-separated list of chalk colors or a string for available styles listed below to use on prefixes.
* If there are more commands than colors, the last color will be repeated.
*
* Available modifiers:
* - `reset`, `bold`, `dim`, `italic`, `underline`, `inverse`, `hidden`, `strikethrough`
*
* Available colors:
* - `black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `white`, `gray`,
* any hex values for colors (e.g. `#23de43`) or `auto` for an automatically picked color
*
* Available background colors:
* - `bgBlack`, `bgRed`, `bgGreen`, `bgYellow`, `bgBlue`, `bgMagenta`, `bgCyan`, `bgWhite`
*
* Set to `false` to disable colors.
*
* @see {@link https://www.npmjs.com/package/chalk} for more information.
*/
prefixColors?: string | string[] | false;
/**
* Maximum number of commands to run at once.
* Exact number or a percent of CPUs available (for example "50%").
*
* If undefined, then all processes will start in parallel.
* Setting this value to 1 will achieve sequential running.
*/
maxProcesses?: number | string;
/**
* Whether commands should be spawned in raw mode.
* Defaults to false.
*/
raw?: boolean;
/**
* Which commands should have their output hidden.
*/
hide?: CommandIdentifier[];
/**
* The current working directory of commands which didn't specify one.
* Defaults to `process.cwd()`.
*/
cwd?: string;
/**
* @see CompletionListener
*/
successCondition?: SuccessCondition;
/**
* A signal to stop spawning further processes.
*/
abortSignal?: AbortSignal;
/**
* Which flow controllers should be applied on commands spawned by concurrently.
* Defaults to an empty array.
*/
controllers: FlowController[];
/**
* A function that will spawn commands.
* Defaults to a function that spawns using either `cmd.exe` or `/bin/sh`.
*/
spawn: SpawnCommand;
/**
* A function that will kill processes.
* Defaults to the `tree-kill` module.
*/
kill: KillProcess;
/**
* Signal to send to killed processes.
*/
killSignal?: string;
/**
* List of additional arguments passed that will get replaced in each command.
* If not defined, no argument replacing will happen.
*
* @see ExpandArguments
*/
additionalArguments?: string[];
};
/**
* Core concurrently functionality -- spawns the given commands concurrently and
* returns the commands themselves + the result according to the specified success condition.
*
* @see CompletionListener
*/
export declare function concurrently(baseCommands: ConcurrentlyCommandInput[], baseOptions?: Partial<ConcurrentlyOptions>): ConcurrentlyResult;

131
node_modules/concurrently/dist/src/concurrently.js generated vendored Normal file
View File

@@ -0,0 +1,131 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.concurrently = void 0;
const assert_1 = __importDefault(require("assert"));
const lodash_1 = __importDefault(require("lodash"));
const os_1 = require("os");
const tree_kill_1 = __importDefault(require("tree-kill"));
const command_1 = require("./command");
const expand_arguments_1 = require("./command-parser/expand-arguments");
const expand_shortcut_1 = require("./command-parser/expand-shortcut");
const expand_wildcard_1 = require("./command-parser/expand-wildcard");
const strip_quotes_1 = require("./command-parser/strip-quotes");
const completion_listener_1 = require("./completion-listener");
const output_writer_1 = require("./output-writer");
const prefix_color_selector_1 = require("./prefix-color-selector");
const spawn_1 = require("./spawn");
const defaults = {
spawn: spawn_1.spawn,
kill: tree_kill_1.default,
raw: false,
controllers: [],
cwd: undefined,
};
/**
* Core concurrently functionality -- spawns the given commands concurrently and
* returns the commands themselves + the result according to the specified success condition.
*
* @see CompletionListener
*/
function concurrently(baseCommands, baseOptions) {
assert_1.default.ok(Array.isArray(baseCommands), '[concurrently] commands should be an array');
assert_1.default.notStrictEqual(baseCommands.length, 0, '[concurrently] no commands provided');
const options = lodash_1.default.defaults(baseOptions, defaults);
const prefixColorSelector = new prefix_color_selector_1.PrefixColorSelector(options.prefixColors || []);
const commandParsers = [
new strip_quotes_1.StripQuotes(),
new expand_shortcut_1.ExpandShortcut(),
new expand_wildcard_1.ExpandWildcard(),
];
if (options.additionalArguments) {
commandParsers.push(new expand_arguments_1.ExpandArguments(options.additionalArguments));
}
const hide = (options.hide || []).map(String);
let commands = (0, lodash_1.default)(baseCommands)
.map(mapToCommandInfo)
.flatMap((command) => parseCommand(command, commandParsers))
.map((command, index) => {
const hidden = hide.includes(command.name) || hide.includes(String(index));
return new command_1.Command({
index,
prefixColor: prefixColorSelector.getNextColor(),
...command,
}, (0, spawn_1.getSpawnOpts)({
ipc: command.ipc,
stdio: hidden ? 'hidden' : command.raw ?? options.raw ? 'raw' : 'normal',
env: command.env,
cwd: command.cwd || options.cwd,
}), options.spawn, options.kill);
})
.value();
const handleResult = options.controllers.reduce(({ commands: prevCommands, onFinishCallbacks }, controller) => {
const { commands, onFinish } = controller.handle(prevCommands);
return {
commands,
onFinishCallbacks: lodash_1.default.concat(onFinishCallbacks, onFinish ? [onFinish] : []),
};
}, { commands, onFinishCallbacks: [] });
commands = handleResult.commands;
if (options.logger && options.outputStream) {
const outputWriter = new output_writer_1.OutputWriter({
outputStream: options.outputStream,
group: !!options.group,
commands,
});
options.logger.output.subscribe(({ command, text }) => outputWriter.write(command, text));
}
const commandsLeft = commands.slice();
const maxProcesses = Math.max(1, (typeof options.maxProcesses === 'string' && options.maxProcesses.endsWith('%')
? Math.round(((0, os_1.cpus)().length * Number(options.maxProcesses.slice(0, -1))) / 100)
: Number(options.maxProcesses)) || commandsLeft.length);
for (let i = 0; i < maxProcesses; i++) {
maybeRunMore(commandsLeft, options.abortSignal);
}
const result = new completion_listener_1.CompletionListener({ successCondition: options.successCondition })
.listen(commands, options.abortSignal)
.finally(() => Promise.all(handleResult.onFinishCallbacks.map((onFinish) => onFinish())));
return {
result,
commands,
};
}
exports.concurrently = concurrently;
function mapToCommandInfo(command) {
if (typeof command === 'string') {
return mapToCommandInfo({ command });
}
assert_1.default.ok(command.command, '[concurrently] command cannot be empty');
return {
command: command.command,
name: command.name || '',
env: command.env || {},
cwd: command.cwd || '',
ipc: command.ipc,
...(command.prefixColor
? {
prefixColor: command.prefixColor,
}
: {}),
...(command.raw !== undefined
? {
raw: command.raw,
}
: {}),
};
}
function parseCommand(command, parsers) {
return parsers.reduce((commands, parser) => lodash_1.default.flatMap(commands, (command) => parser.parse(command)), lodash_1.default.castArray(command));
}
function maybeRunMore(commandsLeft, abortSignal) {
const command = commandsLeft.shift();
if (!command || abortSignal?.aborted) {
return;
}
command.start();
command.close.subscribe(() => {
maybeRunMore(commandsLeft, abortSignal);
});
}

19
node_modules/concurrently/dist/src/date-format.d.ts generated vendored Normal file
View File

@@ -0,0 +1,19 @@
export type FormatterOptions = {
locale?: string;
calendar?: string;
};
/**
* Unicode-compliant date/time formatter.
*
* @see https://unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns
*/
export declare class DateFormatter {
private readonly options;
private static tokenRegex;
private readonly parts;
constructor(pattern: string, options?: FormatterOptions);
private compileLiteral;
private compileOther;
private compileToken;
format(date: Date): string;
}

318
node_modules/concurrently/dist/src/date-format.js generated vendored Normal file
View File

@@ -0,0 +1,318 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DateFormatter = void 0;
/**
* Unicode-compliant date/time formatter.
*
* @see https://unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns
*/
class DateFormatter {
options;
static tokenRegex = /[A-Z]/i;
parts = [];
constructor(pattern, options = {}) {
this.options = options;
let i = 0;
while (i < pattern.length) {
const char = pattern[i];
const { fn, length } = char === "'"
? this.compileLiteral(pattern, i)
: DateFormatter.tokenRegex.test(char)
? this.compileToken(pattern, i)
: this.compileOther(pattern, i);
this.parts.push(fn);
i += length;
}
}
compileLiteral(pattern, offset) {
let length = 1;
let value = '';
for (; length < pattern.length; length++) {
const i = offset + length;
const char = pattern[i];
if (char === "'") {
const nextChar = pattern[i + 1];
length++;
// if the next character is another single quote, it's been escaped.
// if not, then the literal has been closed
if (nextChar !== "'") {
break;
}
}
value += char;
}
return { fn: () => value || "'", length };
}
compileOther(pattern, offset) {
let value = '';
while (!DateFormatter.tokenRegex.test(pattern[offset]) && pattern[offset] !== "'") {
value += pattern[offset++];
}
return { fn: () => value, length: value.length };
}
compileToken(pattern, offset) {
const type = pattern[offset];
const token = tokens.get(type);
if (!token) {
throw new SyntaxError(`Formatting token "${type}" is invalid`);
}
let length = 0;
while (pattern[offset + length] === type) {
length++;
}
const tokenFn = token[length - 1];
if (!tokenFn) {
throw new RangeError(`Formatting token "${type.repeat(length)}" is unsupported`);
}
return { fn: tokenFn, length };
}
format(date) {
return this.parts.reduce((output, part) => output + String(part(date, this.options)), '');
}
}
exports.DateFormatter = DateFormatter;
/**
* A map of token to its implementations by length.
* If an index is undefined, then that token length is unsupported.
*/
const tokens = new Map()
// era
.set('G', [
makeTokenFn({ era: 'short' }, 'era'),
makeTokenFn({ era: 'short' }, 'era'),
makeTokenFn({ era: 'short' }, 'era'),
makeTokenFn({ era: 'long' }, 'era'),
makeTokenFn({ era: 'narrow' }, 'era'),
])
// year
.set('y', [
// TODO: does not support BC years.
// https://stackoverflow.com/a/41345095/2083599
(date) => date.getFullYear(),
(date) => pad(2, date.getFullYear()).slice(-2),
(date) => pad(3, date.getFullYear()),
(date) => pad(4, date.getFullYear()),
(date) => pad(5, date.getFullYear()),
])
.set('Y', [
getWeekYear,
(date, options) => pad(2, getWeekYear(date, options)).slice(-2),
(date, options) => pad(3, getWeekYear(date, options)),
(date, options) => pad(4, getWeekYear(date, options)),
(date, options) => pad(5, getWeekYear(date, options)),
])
.set('u', [])
.set('U', [
// Fallback implemented as yearName is not available in gregorian calendars, for instance.
makeTokenFn({ dateStyle: 'full' }, 'yearName', (date) => String(date.getFullYear())),
])
.set('r', [
// Fallback implemented as relatedYear is not available in gregorian calendars, for instance.
makeTokenFn({ dateStyle: 'full' }, 'relatedYear', (date) => String(date.getFullYear())),
])
// quarter
.set('Q', [
(date) => Math.floor(date.getMonth() / 3) + 1,
(date) => pad(2, Math.floor(date.getMonth() / 3) + 1),
// these aren't localized in Intl.DateTimeFormat.
undefined,
undefined,
(date) => Math.floor(date.getMonth() / 3) + 1,
])
.set('q', [
(date) => Math.floor(date.getMonth() / 3) + 1,
(date) => pad(2, Math.floor(date.getMonth() / 3) + 1),
// these aren't localized in Intl.DateTimeFormat.
undefined,
undefined,
(date) => Math.floor(date.getMonth() / 3) + 1,
])
// month
.set('M', [
(date) => date.getMonth() + 1,
(date) => pad(2, date.getMonth() + 1),
// these include the day so that it forces non-stand-alone month part
makeTokenFn({ day: 'numeric', month: 'short' }, 'month'),
makeTokenFn({ day: 'numeric', month: 'long' }, 'month'),
makeTokenFn({ day: 'numeric', month: 'narrow' }, 'month'),
])
.set('L', [
(date) => date.getMonth() + 1,
(date) => pad(2, date.getMonth() + 1),
makeTokenFn({ month: 'short' }, 'month'),
makeTokenFn({ month: 'long' }, 'month'),
makeTokenFn({ month: 'narrow' }, 'month'),
])
.set('l', [() => ''])
// week
.set('w', [getWeek, (date, options) => pad(2, getWeek(date, options))])
.set('W', [getWeekOfMonth])
// day
.set('d', [(date) => date.getDate(), (date) => pad(2, date.getDate())])
.set('D', [
getDayOfYear,
(date) => pad(2, getDayOfYear(date)),
(date) => pad(3, getDayOfYear(date)),
])
.set('F', [(date) => Math.ceil(date.getDate() / 7)])
.set('g', [])
// week day
.set('E', [
makeTokenFn({ weekday: 'short' }, 'weekday'),
makeTokenFn({ weekday: 'short' }, 'weekday'),
makeTokenFn({ weekday: 'short' }, 'weekday'),
makeTokenFn({ weekday: 'long' }, 'weekday'),
])
.set('e', [
undefined,
undefined,
makeTokenFn({ weekday: 'short' }, 'weekday'),
makeTokenFn({ weekday: 'long' }, 'weekday'),
])
.set('c', [])
// period
.set('a', [
makeTokenFn({ hour12: true, timeStyle: 'full' }, 'dayPeriod'),
makeTokenFn({ hour12: true, timeStyle: 'full' }, 'dayPeriod'),
makeTokenFn({ hour12: true, timeStyle: 'full' }, 'dayPeriod'),
])
.set('b', [])
.set('B', [
makeTokenFn({ dayPeriod: 'short' }, 'dayPeriod'),
makeTokenFn({ dayPeriod: 'short' }, 'dayPeriod'),
makeTokenFn({ dayPeriod: 'short' }, 'dayPeriod'),
makeTokenFn({ dayPeriod: 'long' }, 'dayPeriod'),
])
// hour
.set('h', [(date) => date.getHours() % 12 || 12, (date) => pad(2, date.getHours() % 12 || 12)])
.set('H', [(date) => date.getHours(), (date) => pad(2, date.getHours())])
.set('K', [(date) => date.getHours() % 12, (date) => pad(2, date.getHours() % 12)])
.set('k', [(date) => date.getHours() % 24 || 24, (date) => pad(2, date.getHours() % 24 || 24)])
.set('j', [])
.set('J', [])
.set('C', [])
// minute
.set('m', [(date) => date.getMinutes(), (date) => pad(2, date.getMinutes())])
// second
.set('s', [(date) => date.getSeconds(), (date) => pad(2, date.getSeconds())])
.set('S', [
(date) => Math.trunc(date.getMilliseconds() / 100),
(date) => pad(2, Math.trunc(date.getMilliseconds() / 10)),
(date) => pad(3, Math.trunc(date.getMilliseconds())),
])
.set('A', [])
// zone
// none of these have tests
.set('z', [
makeTokenFn({ timeZoneName: 'short' }, 'timeZoneName'),
makeTokenFn({ timeZoneName: 'short' }, 'timeZoneName'),
makeTokenFn({ timeZoneName: 'short' }, 'timeZoneName'),
makeTokenFn({ timeZoneName: 'long' }, 'timeZoneName'),
])
.set('Z', [
undefined,
undefined,
undefined,
// equivalent to `OOOO`.
makeTokenFn({ timeZoneName: 'longOffset' }, 'timeZoneName'),
])
.set('O', [
makeTokenFn({ timeZoneName: 'shortOffset' }, 'timeZoneName'),
undefined,
undefined,
// equivalent to `ZZZZ`.
makeTokenFn({ timeZoneName: 'longOffset' }, 'timeZoneName'),
])
.set('v', [
makeTokenFn({ timeZoneName: 'shortGeneric' }, 'timeZoneName'),
undefined,
undefined,
makeTokenFn({ timeZoneName: 'longGeneric' }, 'timeZoneName'),
])
.set('V', [])
.set('X', [])
.set('x', []);
let locale;
function getLocale(options) {
if (!locale || locale.baseName !== options.locale) {
locale = new Intl.Locale(options.locale || new Intl.DateTimeFormat().resolvedOptions().locale);
}
return locale;
}
/**
* Creates a token formatting function that returns the value of the chosen part type,
* using the current locale's settings.
*
* If the date/formatter settings doesn't include the requested part type,
* the `fallback` function is invoked, if specified. If none has been specified, returns an
* empty string.
*/
function makeTokenFn(options, type, fallback) {
let formatter;
return (date, formatterOptions) => {
// Allow tests to set a different locale and have that cause the formatter to be recreated
if (!formatter ||
formatter.resolvedOptions().locale !== formatterOptions.locale ||
formatter.resolvedOptions().calendar !== formatterOptions.calendar) {
formatter = new Intl.DateTimeFormat(formatterOptions.locale, {
...options,
calendar: options.calendar ?? formatterOptions.calendar,
});
}
const parts = formatter.formatToParts(date);
const part = parts.find((p) => p.type === type);
return part?.value ?? (fallback ? fallback(date, formatterOptions) : '');
};
}
function startOfWeek(date, options) {
const locale = getLocale(options);
const firstDay = locale.weekInfo.firstDay === 7 ? 0 : locale.weekInfo.firstDay;
const day = date.getDay();
const diff = (day < firstDay ? 7 : 0) + day - firstDay;
date.setDate(date.getDate() - diff);
date.setHours(0, 0, 0, 0);
return date;
}
function getWeekYear(date, options) {
const locale = getLocale(options);
const minimalDays = locale.weekInfo.minimalDays;
const year = date.getFullYear();
const thisYear = startOfWeek(new Date(year, 0, minimalDays), options);
const nextYear = startOfWeek(new Date(year + 1, 0, minimalDays), options);
if (date.getTime() >= nextYear.getTime()) {
return year + 1;
}
else if (date.getTime() >= thisYear.getTime()) {
return year;
}
else {
return year - 1;
}
}
function getWeek(date, options) {
const locale = getLocale(options);
const weekMs = 7 * 24 * 3600 * 1000;
const temp = startOfWeek(new Date(date), options);
const thisYear = new Date(getWeekYear(date, options), 0, locale.weekInfo.minimalDays);
startOfWeek(thisYear, options);
const diff = temp.getTime() - thisYear.getTime();
return Math.round(diff / weekMs) + 1;
}
function getWeekOfMonth(date, options) {
const current = new Date(date);
current.setHours(0, 0, 0, 0);
const monthWeekStart = startOfWeek(new Date(date.getFullYear(), date.getMonth(), 1), options);
const weekMs = 7 * 24 * 3600 * 1000;
return Math.floor((date.getTime() - monthWeekStart.getTime()) / weekMs) + 1;
}
function getDayOfYear(date) {
let days = 0;
for (let i = 0; i <= date.getMonth() - 1; i++) {
const temp = new Date(date.getFullYear(), i + 1, 0, 0, 0, 0);
days += temp.getDate();
}
return days + date.getDate();
}
function pad(length, val) {
return String(val).padStart(length, '0');
}

68
node_modules/concurrently/dist/src/defaults.d.ts generated vendored Normal file
View File

@@ -0,0 +1,68 @@
import { SuccessCondition } from './completion-listener';
export declare const defaultInputTarget = 0;
/**
* Whether process.stdin should be forwarded to child processes.
*/
export declare const handleInput = false;
/**
* How many processes to run at once.
*/
export declare const maxProcesses = 0;
/**
* Indices and names of commands whose output are not to be logged.
*/
export declare const hide = "";
/**
* The character to split <names> on.
*/
export declare const nameSeparator = ",";
/**
* Which prefix style to use when logging processes output.
*/
export declare const prefix = "";
/**
* Default prefix color.
* @see https://www.npmjs.com/package/chalk
*/
export declare const prefixColors = "reset";
/**
* How many bytes we'll show on the command prefix.
*/
export declare const prefixLength = 10;
export declare const raw = false;
/**
* Number of attempts of restarting a process, if it exits with non-0 code.
*/
export declare const restartTries = 0;
/**
* How many milliseconds concurrently should wait before restarting a process.
*/
export declare const restartDelay = 0;
/**
* Condition of success for concurrently itself.
*/
export declare const success: SuccessCondition;
/**
* Date format used when logging date/time.
* @see https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
*/
export declare const timestampFormat = "yyyy-MM-dd HH:mm:ss.SSS";
/**
* Current working dir passed as option to spawn command.
* Defaults to process.cwd()
*/
export declare const cwd: string | undefined;
/**
* Whether to show timing information for processes in console output.
*/
export declare const timings = false;
/**
* Passthrough additional arguments to commands (accessible via placeholders) instead of treating them as commands.
*/
export declare const passthroughArguments = false;
/**
* Signal to send to other processes if one exits or dies.
*
* Defaults to OS specific signal. (SIGTERM on Linux/MacOS)
*/
export declare const killSignal: string | undefined;

73
node_modules/concurrently/dist/src/defaults.js generated vendored Normal file
View File

@@ -0,0 +1,73 @@
"use strict";
// This file is meant to be a shared place for default configs.
// It's read by the flow controllers, the executable, etc.
// Refer to tests for the meaning of the different possible values.
Object.defineProperty(exports, "__esModule", { value: true });
exports.killSignal = exports.passthroughArguments = exports.timings = exports.cwd = exports.timestampFormat = exports.success = exports.restartDelay = exports.restartTries = exports.raw = exports.prefixLength = exports.prefixColors = exports.prefix = exports.nameSeparator = exports.hide = exports.maxProcesses = exports.handleInput = exports.defaultInputTarget = void 0;
exports.defaultInputTarget = 0;
/**
* Whether process.stdin should be forwarded to child processes.
*/
exports.handleInput = false;
/**
* How many processes to run at once.
*/
exports.maxProcesses = 0;
/**
* Indices and names of commands whose output are not to be logged.
*/
exports.hide = '';
/**
* The character to split <names> on.
*/
exports.nameSeparator = ',';
/**
* Which prefix style to use when logging processes output.
*/
exports.prefix = '';
/**
* Default prefix color.
* @see https://www.npmjs.com/package/chalk
*/
exports.prefixColors = 'reset';
/**
* How many bytes we'll show on the command prefix.
*/
exports.prefixLength = 10;
exports.raw = false;
/**
* Number of attempts of restarting a process, if it exits with non-0 code.
*/
exports.restartTries = 0;
/**
* How many milliseconds concurrently should wait before restarting a process.
*/
exports.restartDelay = 0;
/**
* Condition of success for concurrently itself.
*/
exports.success = 'all';
/**
* Date format used when logging date/time.
* @see https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
*/
exports.timestampFormat = 'yyyy-MM-dd HH:mm:ss.SSS';
/**
* Current working dir passed as option to spawn command.
* Defaults to process.cwd()
*/
exports.cwd = undefined;
/**
* Whether to show timing information for processes in console output.
*/
exports.timings = false;
/**
* Passthrough additional arguments to commands (accessible via placeholders) instead of treating them as commands.
*/
exports.passthroughArguments = false;
/**
* Signal to send to other processes if one exits or dies.
*
* Defaults to OS specific signal. (SIGTERM on Linux/MacOS)
*/
exports.killSignal = undefined;

View File

@@ -0,0 +1,13 @@
import { Command } from '../command';
/**
* Interface for a class that controls and/or watches the behavior of commands.
*
* This may include logging their output, creating interactions between them, or changing when they
* actually finish.
*/
export interface FlowController {
handle(commands: Command[]): {
commands: Command[];
onFinish?: () => void | Promise<void>;
};
}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,30 @@
/// <reference types="node" />
import { Readable } from 'stream';
import { Command, CommandIdentifier } from '../command';
import { Logger } from '../logger';
import { FlowController } from './flow-controller';
/**
* Sends input from concurrently through to commands.
*
* Input can start with a command identifier, in which case it will be sent to that specific command.
* For instance, `0:bla` will send `bla` to command at index `0`, and `server:stop` will send `stop`
* to command with name `server`.
*
* If the input doesn't start with a command identifier, it is then always sent to the default target.
*/
export declare class InputHandler implements FlowController {
private readonly logger;
private readonly defaultInputTarget;
private readonly inputStream?;
private readonly pauseInputStreamOnFinish;
constructor({ defaultInputTarget, inputStream, pauseInputStreamOnFinish, logger, }: {
inputStream?: Readable;
logger: Logger;
defaultInputTarget?: CommandIdentifier;
pauseInputStreamOnFinish?: boolean;
});
handle(commands: Command[]): {
commands: Command[];
onFinish?: () => void | undefined;
};
}

View File

@@ -0,0 +1,94 @@
"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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.InputHandler = void 0;
const Rx = __importStar(require("rxjs"));
const operators_1 = require("rxjs/operators");
const defaults = __importStar(require("../defaults"));
/**
* Sends input from concurrently through to commands.
*
* Input can start with a command identifier, in which case it will be sent to that specific command.
* For instance, `0:bla` will send `bla` to command at index `0`, and `server:stop` will send `stop`
* to command with name `server`.
*
* If the input doesn't start with a command identifier, it is then always sent to the default target.
*/
class InputHandler {
logger;
defaultInputTarget;
inputStream;
pauseInputStreamOnFinish;
constructor({ defaultInputTarget, inputStream, pauseInputStreamOnFinish, logger, }) {
this.logger = logger;
this.defaultInputTarget = defaultInputTarget || defaults.defaultInputTarget;
this.inputStream = inputStream;
this.pauseInputStreamOnFinish = pauseInputStreamOnFinish !== false;
}
handle(commands) {
const { inputStream } = this;
if (!inputStream) {
return { commands };
}
const commandsMap = new Map();
for (const command of commands) {
commandsMap.set(command.index.toString(), command);
commandsMap.set(command.name, command);
}
Rx.fromEvent(inputStream, 'data')
.pipe((0, operators_1.map)((data) => String(data)))
.subscribe((data) => {
let command, input;
const dataParts = data.split(/:(.+)/s);
let target = dataParts[0];
if (dataParts.length > 1 && (command = commandsMap.get(target))) {
input = dataParts[1];
}
else {
// If `target` does not match a registered command,
// fallback to `defaultInputTarget` and forward the whole input data
target = this.defaultInputTarget.toString();
command = commandsMap.get(target);
input = data;
}
if (command && command.stdin) {
command.stdin.write(input);
}
else {
this.logger.logGlobalEvent(`Unable to find command "${target}", or it has no stdin open\n`);
}
});
return {
commands,
onFinish: () => {
if (this.pauseInputStreamOnFinish) {
// https://github.com/kimmobrunfeldt/concurrently/issues/252
inputStream.pause();
}
},
};
}
}
exports.InputHandler = InputHandler;

View File

@@ -0,0 +1,21 @@
/// <reference types="node" />
/// <reference types="node" />
import EventEmitter from 'events';
import { Command } from '../command';
import { FlowController } from './flow-controller';
/**
* Watches the main concurrently process for signals and sends the same signal down to each spawned
* command.
*/
export declare class KillOnSignal implements FlowController {
private readonly process;
private readonly abortController?;
constructor({ process, abortController, }: {
process: EventEmitter;
abortController?: AbortController;
});
handle(commands: Command[]): {
commands: Command[];
onFinish: () => void;
};
}

View File

@@ -0,0 +1,47 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.KillOnSignal = void 0;
const operators_1 = require("rxjs/operators");
const SIGNALS = ['SIGINT', 'SIGTERM', 'SIGHUP'];
/**
* Watches the main concurrently process for signals and sends the same signal down to each spawned
* command.
*/
class KillOnSignal {
process;
abortController;
constructor({ process, abortController, }) {
this.process = process;
this.abortController = abortController;
}
handle(commands) {
let caughtSignal;
const signalListener = (signal) => {
caughtSignal = signal;
this.abortController?.abort();
commands.forEach((command) => command.kill(signal));
};
SIGNALS.forEach((signal) => this.process.on(signal, signalListener));
return {
commands: commands.map((command) => {
const closeStream = command.close.pipe((0, operators_1.map)((exitInfo) => {
const exitCode = caughtSignal === 'SIGINT' ? 0 : exitInfo.exitCode;
return { ...exitInfo, exitCode };
}));
// Return a proxy so that mutations happen on the original Command object.
// If either `Object.assign()` or `Object.create()` were used, it'd be hard to
// reflect the mutations on Command objects referenced by previous flow controllers.
return new Proxy(command, {
get(target, prop) {
return prop === 'close' ? closeStream : target[prop];
},
});
}),
onFinish: () => {
// Avoids MaxListenersExceededWarning when running programmatically
SIGNALS.forEach((signal) => this.process.off(signal, signalListener));
},
};
}
}
exports.KillOnSignal = KillOnSignal;

View File

@@ -0,0 +1,23 @@
/// <reference types="node" />
import { Command } from '../command';
import { Logger } from '../logger';
import { FlowController } from './flow-controller';
export type ProcessCloseCondition = 'failure' | 'success';
/**
* Sends a SIGTERM signal to all commands when one of the commands exits with a matching condition.
*/
export declare class KillOthers implements FlowController {
private readonly logger;
private readonly abortController?;
private readonly conditions;
private readonly killSignal;
constructor({ logger, abortController, conditions, killSignal, }: {
logger: Logger;
abortController?: AbortController;
conditions: ProcessCloseCondition | ProcessCloseCondition[];
killSignal: string | undefined;
});
handle(commands: Command[]): {
commands: Command[];
};
}

View File

@@ -0,0 +1,41 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.KillOthers = void 0;
const lodash_1 = __importDefault(require("lodash"));
const operators_1 = require("rxjs/operators");
const command_1 = require("../command");
/**
* Sends a SIGTERM signal to all commands when one of the commands exits with a matching condition.
*/
class KillOthers {
logger;
abortController;
conditions;
killSignal;
constructor({ logger, abortController, conditions, killSignal, }) {
this.logger = logger;
this.abortController = abortController;
this.conditions = lodash_1.default.castArray(conditions);
this.killSignal = killSignal;
}
handle(commands) {
const conditions = this.conditions.filter((condition) => condition === 'failure' || condition === 'success');
if (!conditions.length) {
return { commands };
}
const closeStates = commands.map((command) => command.close.pipe((0, operators_1.map)(({ exitCode }) => exitCode === 0 ? 'success' : 'failure'), (0, operators_1.filter)((state) => conditions.includes(state))));
closeStates.forEach((closeState) => closeState.subscribe(() => {
this.abortController?.abort();
const killableCommands = commands.filter((command) => command_1.Command.canKill(command));
if (killableCommands.length) {
this.logger.logGlobalEvent(`Sending ${this.killSignal || 'SIGTERM'} to other processes..`);
killableCommands.forEach((command) => command.kill(this.killSignal));
}
}));
return { commands };
}
}
exports.KillOthers = KillOthers;

View File

@@ -0,0 +1,15 @@
import { Command } from '../command';
import { Logger } from '../logger';
import { FlowController } from './flow-controller';
/**
* Logs when commands failed executing, e.g. due to the executable not existing in the system.
*/
export declare class LogError implements FlowController {
private readonly logger;
constructor({ logger }: {
logger: Logger;
});
handle(commands: Command[]): {
commands: Command[];
};
}

View File

@@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LogError = void 0;
/**
* Logs when commands failed executing, e.g. due to the executable not existing in the system.
*/
class LogError {
logger;
constructor({ logger }) {
this.logger = logger;
}
handle(commands) {
commands.forEach((command) => command.error.subscribe((event) => {
this.logger.logCommandEvent(`Error occurred when executing command: ${command.command}`, command);
const errorText = String(event instanceof Error ? event.stack || event : event);
this.logger.logCommandEvent(errorText, command);
}));
return { commands };
}
}
exports.LogError = LogError;

View File

@@ -0,0 +1,15 @@
import { Command } from '../command';
import { Logger } from '../logger';
import { FlowController } from './flow-controller';
/**
* Logs the exit code/signal of commands.
*/
export declare class LogExit implements FlowController {
private readonly logger;
constructor({ logger }: {
logger: Logger;
});
handle(commands: Command[]): {
commands: Command[];
};
}

View File

@@ -0,0 +1,19 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LogExit = void 0;
/**
* Logs the exit code/signal of commands.
*/
class LogExit {
logger;
constructor({ logger }) {
this.logger = logger;
}
handle(commands) {
commands.forEach((command) => command.close.subscribe(({ exitCode }) => {
this.logger.logCommandEvent(`${command.command} exited with code ${exitCode}`, command);
}));
return { commands };
}
}
exports.LogExit = LogExit;

View File

@@ -0,0 +1,15 @@
import { Command } from '../command';
import { Logger } from '../logger';
import { FlowController } from './flow-controller';
/**
* Logs the stdout and stderr output of commands.
*/
export declare class LogOutput implements FlowController {
private readonly logger;
constructor({ logger }: {
logger: Logger;
});
handle(commands: Command[]): {
commands: Command[];
};
}

View File

@@ -0,0 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LogOutput = void 0;
/**
* Logs the stdout and stderr output of commands.
*/
class LogOutput {
logger;
constructor({ logger }) {
this.logger = logger;
}
handle(commands) {
commands.forEach((command) => {
command.stdout.subscribe((text) => this.logger.logCommandText(text.toString(), command));
command.stderr.subscribe((text) => this.logger.logCommandText(text.toString(), command));
});
return { commands };
}
}
exports.LogOutput = LogOutput;

View File

@@ -0,0 +1,31 @@
import { CloseEvent, Command } from '../command';
import { Logger } from '../logger';
import { FlowController } from './flow-controller';
type TimingInfo = {
name: string;
duration: string;
'exit code': string | number;
killed: boolean;
command: string;
};
/**
* Logs timing information about commands as they start/stop and then a summary when all commands finish.
*/
export declare class LogTimings implements FlowController {
static mapCloseEventToTimingInfo({ command, timings, killed, exitCode, }: CloseEvent): TimingInfo;
private readonly logger?;
private readonly dateFormatter;
constructor({ logger, timestampFormat, }: {
logger?: Logger;
timestampFormat?: string;
});
private printExitInfoTimingTable;
handle(commands: Command[]): {
commands: Command[];
onFinish?: undefined;
} | {
commands: Command[];
onFinish: () => void;
};
}
export {};

View File

@@ -0,0 +1,94 @@
"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.LogTimings = void 0;
const assert = __importStar(require("assert"));
const lodash_1 = __importDefault(require("lodash"));
const Rx = __importStar(require("rxjs"));
const operators_1 = require("rxjs/operators");
const date_format_1 = require("../date-format");
const defaults = __importStar(require("../defaults"));
/**
* Logs timing information about commands as they start/stop and then a summary when all commands finish.
*/
class LogTimings {
static mapCloseEventToTimingInfo({ command, timings, killed, exitCode, }) {
const readableDurationMs = (timings.endDate.getTime() - timings.startDate.getTime()).toLocaleString();
return {
name: command.name,
duration: readableDurationMs,
'exit code': exitCode,
killed,
command: command.command,
};
}
logger;
dateFormatter;
constructor({ logger, timestampFormat = defaults.timestampFormat, }) {
this.logger = logger;
this.dateFormatter = new date_format_1.DateFormatter(timestampFormat);
}
printExitInfoTimingTable(exitInfos) {
assert.ok(this.logger);
const exitInfoTable = (0, lodash_1.default)(exitInfos)
.sortBy(({ timings }) => timings.durationSeconds)
.reverse()
.map(LogTimings.mapCloseEventToTimingInfo)
.value();
this.logger.logGlobalEvent('Timings:');
this.logger.logTable(exitInfoTable);
return exitInfos;
}
handle(commands) {
const { logger } = this;
if (!logger) {
return { commands };
}
// individual process timings
commands.forEach((command) => {
command.timer.subscribe(({ startDate, endDate }) => {
if (!endDate) {
const formattedStartDate = this.dateFormatter.format(startDate);
logger.logCommandEvent(`${command.command} started at ${formattedStartDate}`, command);
}
else {
const durationMs = endDate.getTime() - startDate.getTime();
const formattedEndDate = this.dateFormatter.format(endDate);
logger.logCommandEvent(`${command.command} stopped at ${formattedEndDate} after ${durationMs.toLocaleString()}ms`, command);
}
});
});
// overall summary timings
const closeStreams = commands.map((command) => command.close);
const finished = new Rx.Subject();
const allProcessesClosed = Rx.merge(...closeStreams).pipe((0, operators_1.bufferCount)(closeStreams.length), (0, operators_1.take)(1), (0, operators_1.combineLatestWith)(finished));
allProcessesClosed.subscribe(([exitInfos]) => this.printExitInfoTimingTable(exitInfos));
return { commands, onFinish: () => finished.next() };
}
}
exports.LogTimings = LogTimings;

View File

@@ -0,0 +1,13 @@
import { Command } from '../command';
import { Logger } from '../logger';
import { FlowController } from './flow-controller';
export declare class LoggerPadding implements FlowController {
private readonly logger;
constructor({ logger }: {
logger: Logger;
});
handle(commands: Command[]): {
commands: Command[];
onFinish: () => void;
};
}

View File

@@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LoggerPadding = void 0;
class LoggerPadding {
logger;
constructor({ logger }) {
this.logger = logger;
}
handle(commands) {
// Sometimes there's limited concurrency, so not all commands will spawn straight away.
// Compute the prefix length now, which works for all styles but those with a PID.
let length = commands.reduce((length, command) => {
const content = this.logger.getPrefixContent(command);
return Math.max(length, content?.value.length || 0);
}, 0);
this.logger.setPrefixLength(length);
// The length of prefixes is somewhat stable, except for PIDs, which might change when a
// process spawns (e.g. PIDs might look like 1, 10 or 100), therefore listen to command starts
// and update the prefix length when this happens.
const subs = commands.map((command) => command.timer.subscribe((event) => {
if (!event.endDate) {
const content = this.logger.getPrefixContent(command);
length = Math.max(length, content?.value.length || 0);
this.logger.setPrefixLength(length);
}
}));
return {
commands,
onFinish() {
subs.forEach((sub) => sub.unsubscribe());
},
};
}
}
exports.LoggerPadding = LoggerPadding;

View File

@@ -0,0 +1,23 @@
import * as Rx from 'rxjs';
import { Command } from '../command';
import { Logger } from '../logger';
import { FlowController } from './flow-controller';
export type RestartDelay = number | 'exponential';
/**
* Restarts commands that fail up to a defined number of times.
*/
export declare class RestartProcess implements FlowController {
private readonly logger;
private readonly scheduler?;
private readonly delay;
readonly tries: number;
constructor({ delay, tries, logger, scheduler, }: {
delay?: RestartDelay;
tries?: number;
logger: Logger;
scheduler?: Rx.SchedulerLike;
});
handle(commands: Command[]): {
commands: Command[];
};
}

View File

@@ -0,0 +1,88 @@
"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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RestartProcess = void 0;
const Rx = __importStar(require("rxjs"));
const operators_1 = require("rxjs/operators");
const defaults = __importStar(require("../defaults"));
/**
* Restarts commands that fail up to a defined number of times.
*/
class RestartProcess {
logger;
scheduler;
delay;
tries;
constructor({ delay, tries, logger, scheduler, }) {
this.logger = logger;
this.delay = delay ?? 0;
this.tries = tries != null ? +tries : defaults.restartTries;
this.tries = this.tries < 0 ? Infinity : this.tries;
this.scheduler = scheduler;
}
handle(commands) {
if (this.tries === 0) {
return { commands };
}
const delayOperator = (0, operators_1.delayWhen)((_, index) => {
const { delay } = this;
const value = delay === 'exponential' ? Math.pow(2, index) * 1000 : delay;
return Rx.timer(value, this.scheduler);
});
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),
// explicitly telling the subscriber that a restart is needed
failure.pipe(delayOperator, (0, operators_1.map)(() => true)),
// Skip the first N emissions (as these would be duplicates of the above),
// meaning it will be empty because of success, or failed all N times,
// and no more restarts should be attempted.
failure.pipe((0, operators_1.skip)(this.tries), (0, operators_1.map)(() => false), (0, operators_1.defaultIfEmpty)(false))).subscribe((restart) => {
const command = commands[index];
if (restart) {
this.logger.logCommandEvent(`${command.command} restarted`, command);
command.start();
}
}));
return {
commands: commands.map((command) => {
const closeStream = command.close.pipe((0, operators_1.filter)(({ exitCode }, emission) => {
// We let all success codes pass, and failures only after restarting won't happen again
return exitCode === 0 || emission >= this.tries;
}));
// Return a proxy so that mutations happen on the original Command object.
// If either `Object.assign()` or `Object.create()` were used, it'd be hard to
// reflect the mutations on Command objects referenced by previous flow controllers.
return new Proxy(command, {
get(target, prop) {
return prop === 'close' ? closeStream : target[prop];
},
});
}),
};
}
}
exports.RestartProcess = RestartProcess;

View File

@@ -0,0 +1,21 @@
import { Command, SpawnCommand } from '../command';
import { Logger } from '../logger';
import { FlowController } from './flow-controller';
export declare class Teardown implements FlowController {
private readonly logger;
private readonly spawn;
private readonly teardown;
constructor({ logger, spawn, commands, }: {
logger: Logger;
/**
* Which function to use to spawn commands.
* Defaults to the same used by the rest of concurrently.
*/
spawn?: SpawnCommand;
commands: readonly string[];
});
handle(commands: Command[]): {
commands: Command[];
onFinish: () => Promise<void>;
};
}

View File

@@ -0,0 +1,72 @@
"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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Teardown = void 0;
const Rx = __importStar(require("rxjs"));
const spawn_1 = require("../spawn");
class Teardown {
logger;
spawn;
teardown;
constructor({ logger, spawn, commands, }) {
this.logger = logger;
this.spawn = spawn || spawn_1.spawn;
this.teardown = commands;
}
handle(commands) {
const { logger, teardown, spawn } = this;
const onFinish = async () => {
if (!teardown.length) {
return;
}
for (const command of teardown) {
logger.logGlobalEvent(`Running teardown command "${command}"`);
const child = spawn(command, (0, spawn_1.getSpawnOpts)({ stdio: 'raw' }));
const error = Rx.fromEvent(child, 'error');
const close = Rx.fromEvent(child, 'close');
try {
const [exitCode, signal] = await Promise.race([
Rx.firstValueFrom(error).then((event) => {
throw event;
}),
Rx.firstValueFrom(close).then((event) => event),
]);
logger.logGlobalEvent(`Teardown command "${command}" exited with code ${exitCode ?? signal}`);
if (signal === 'SIGINT') {
break;
}
}
catch (error) {
const errorText = String(error instanceof Error ? error.stack || error : error);
logger.logGlobalEvent(`Teardown command "${command}" errored:`);
logger.logGlobalEvent(errorText);
return Promise.reject();
}
}
};
return { commands, onFinish };
}
}
exports.Teardown = Teardown;

84
node_modules/concurrently/dist/src/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,84 @@
/// <reference types="node" />
import { Readable } from 'stream';
import { CloseEvent, Command, CommandIdentifier, TimerEvent } from './command';
import { concurrently as createConcurrently, ConcurrentlyCommandInput, ConcurrentlyOptions as BaseConcurrentlyOptions, ConcurrentlyResult } from './concurrently';
import { FlowController } from './flow-control/flow-controller';
import { InputHandler } from './flow-control/input-handler';
import { KillOnSignal } from './flow-control/kill-on-signal';
import { KillOthers, ProcessCloseCondition } from './flow-control/kill-others';
import { LogError } from './flow-control/log-error';
import { LogExit } from './flow-control/log-exit';
import { LogOutput } from './flow-control/log-output';
import { LogTimings } from './flow-control/log-timings';
import { RestartDelay, RestartProcess } from './flow-control/restart-process';
import { Logger } from './logger';
export type ConcurrentlyOptions = Omit<BaseConcurrentlyOptions, 'abortSignal' | 'hide'> & {
/**
* Which command(s) should have their output hidden.
*/
hide?: CommandIdentifier | CommandIdentifier[];
/**
* The prefix format to use when logging a command's output.
* Defaults to the command's index.
*/
prefix?: string;
/**
* How many characters should a prefix have at most, used when the prefix format is `command`.
*/
prefixLength?: number;
/**
* Pads short prefixes with spaces so that all prefixes have the same length.
*/
padPrefix?: boolean;
/**
* Whether output should be formatted to include prefixes and whether "event" logs will be logged.
*/
raw?: boolean;
/**
* Date format used when logging date/time.
* @see https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
*/
timestampFormat?: string;
defaultInputTarget?: CommandIdentifier;
inputStream?: Readable;
handleInput?: boolean;
pauseInputStreamOnFinish?: boolean;
/**
* How much time in milliseconds to wait before restarting a command.
*
* @see RestartProcess
*/
restartDelay?: RestartDelay;
/**
* How many times commands should be restarted when they exit with a failure.
*
* @see RestartProcess
*/
restartTries?: number;
/**
* Under which condition(s) should other commands be killed when the first one exits.
*
* @see KillOthers
*/
killOthers?: ProcessCloseCondition | ProcessCloseCondition[];
/**
* Whether to output timing information for processes.
*
* @see LogTimings
*/
timings?: boolean;
/**
* Clean up command(s) to execute before exiting concurrently.
* These won't be prefixed and don't affect concurrently's exit code.
*/
teardown?: readonly string[];
/**
* List of additional arguments passed that will get replaced in each command.
* If not defined, no argument replacing will happen.
*/
additionalArguments?: string[];
};
export declare function concurrently(commands: ConcurrentlyCommandInput[], options?: Partial<ConcurrentlyOptions>): ConcurrentlyResult;
export { ConcurrentlyCommandInput, ConcurrentlyResult, createConcurrently, Logger };
export { CloseEvent, Command, CommandIdentifier, TimerEvent };
export { FlowController, InputHandler, KillOnSignal, KillOthers, LogError, LogExit, LogOutput, LogTimings, RestartProcess, };

93
node_modules/concurrently/dist/src/index.js generated vendored Normal file
View File

@@ -0,0 +1,93 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RestartProcess = exports.LogTimings = exports.LogOutput = exports.LogExit = exports.LogError = exports.KillOthers = exports.KillOnSignal = exports.InputHandler = exports.Command = exports.Logger = exports.createConcurrently = exports.concurrently = void 0;
const lodash_1 = __importDefault(require("lodash"));
const command_1 = require("./command");
Object.defineProperty(exports, "Command", { enumerable: true, get: function () { return command_1.Command; } });
const concurrently_1 = require("./concurrently");
Object.defineProperty(exports, "createConcurrently", { enumerable: true, get: function () { return concurrently_1.concurrently; } });
const input_handler_1 = require("./flow-control/input-handler");
Object.defineProperty(exports, "InputHandler", { enumerable: true, get: function () { return input_handler_1.InputHandler; } });
const kill_on_signal_1 = require("./flow-control/kill-on-signal");
Object.defineProperty(exports, "KillOnSignal", { enumerable: true, get: function () { return kill_on_signal_1.KillOnSignal; } });
const kill_others_1 = require("./flow-control/kill-others");
Object.defineProperty(exports, "KillOthers", { enumerable: true, get: function () { return kill_others_1.KillOthers; } });
const log_error_1 = require("./flow-control/log-error");
Object.defineProperty(exports, "LogError", { enumerable: true, get: function () { return log_error_1.LogError; } });
const log_exit_1 = require("./flow-control/log-exit");
Object.defineProperty(exports, "LogExit", { enumerable: true, get: function () { return log_exit_1.LogExit; } });
const log_output_1 = require("./flow-control/log-output");
Object.defineProperty(exports, "LogOutput", { enumerable: true, get: function () { return log_output_1.LogOutput; } });
const log_timings_1 = require("./flow-control/log-timings");
Object.defineProperty(exports, "LogTimings", { enumerable: true, get: function () { return log_timings_1.LogTimings; } });
const logger_padding_1 = require("./flow-control/logger-padding");
const restart_process_1 = require("./flow-control/restart-process");
Object.defineProperty(exports, "RestartProcess", { enumerable: true, get: function () { return restart_process_1.RestartProcess; } });
const teardown_1 = require("./flow-control/teardown");
const logger_1 = require("./logger");
Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return logger_1.Logger; } });
function concurrently(commands, options = {}) {
// To avoid empty strings from hiding the output of commands that don't have a name,
// keep in the list of commands to hide only strings with some length.
// This might happen through the CLI when no `--hide` argument is specified, for example.
const hide = lodash_1.default.castArray(options.hide).filter((id) => id || id === 0);
const logger = options.logger ||
new logger_1.Logger({
hide,
prefixFormat: options.prefix,
commandLength: options.prefixLength,
raw: options.raw,
timestampFormat: options.timestampFormat,
});
if (options.prefixColors === false) {
logger.toggleColors(false);
}
const abortController = new AbortController();
return (0, concurrently_1.concurrently)(commands, {
maxProcesses: options.maxProcesses,
raw: options.raw,
successCondition: options.successCondition,
cwd: options.cwd,
hide,
logger,
outputStream: options.outputStream || process.stdout,
group: options.group,
abortSignal: abortController.signal,
controllers: [
// LoggerPadding needs to run before any other controllers that might output something
...(options.padPrefix ? [new logger_padding_1.LoggerPadding({ logger })] : []),
new log_error_1.LogError({ logger }),
new log_output_1.LogOutput({ logger }),
new log_exit_1.LogExit({ logger }),
new input_handler_1.InputHandler({
logger,
defaultInputTarget: options.defaultInputTarget,
inputStream: options.inputStream || (options.handleInput ? process.stdin : undefined),
pauseInputStreamOnFinish: options.pauseInputStreamOnFinish,
}),
new kill_on_signal_1.KillOnSignal({ process, abortController }),
new restart_process_1.RestartProcess({
logger,
delay: options.restartDelay,
tries: options.restartTries,
}),
new kill_others_1.KillOthers({
logger,
conditions: options.killOthers || [],
killSignal: options.killSignal,
abortController,
}),
new log_timings_1.LogTimings({
logger: options.timings ? logger : undefined,
timestampFormat: options.timestampFormat,
}),
new teardown_1.Teardown({ logger, spawn: options.spawn, commands: options.teardown || [] }),
],
prefixColors: options.prefixColors || [],
additionalArguments: options.additionalArguments,
});
}
exports.concurrently = concurrently;

8
node_modules/concurrently/dist/src/jsonc.d.ts generated vendored Normal file
View File

@@ -0,0 +1,8 @@
declare const JSONC: {
parse: (text: string) => any;
stringify: {
(value: any, replacer?: ((this: any, key: string, value: any) => any) | undefined, space?: string | number | undefined): string;
(value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string;
};
};
export default JSONC;

29
node_modules/concurrently/dist/src/jsonc.js generated vendored Normal file
View File

@@ -0,0 +1,29 @@
"use strict";
/*
ORIGINAL https://www.npmjs.com/package/tiny-jsonc
BY Fabio Spampinato
MIT license
Copied due to the dependency not being compatible with CommonJS
*/
Object.defineProperty(exports, "__esModule", { value: true });
/* HELPERS */
const stringOrCommentRe = /("(?:\\?[^])*?")|(\/\/.*)|(\/\*[^]*?\*\/)/g;
const stringOrTrailingCommaRe = /("(?:\\?[^])*?")|(,\s*)(?=]|})/g;
/* MAIN */
const JSONC = {
parse: (text) => {
text = String(text); // To be extra safe
try {
// Fast path for valid JSON
return JSON.parse(text);
}
catch {
// Slow path for JSONC and invalid inputs
return JSON.parse(text.replace(stringOrCommentRe, '$1').replace(stringOrTrailingCommaRe, '$1'));
}
},
stringify: JSON.stringify,
};
/* EXPORT */
exports.default = JSONC;

87
node_modules/concurrently/dist/src/logger.d.ts generated vendored Normal file
View File

@@ -0,0 +1,87 @@
import * as Rx from 'rxjs';
import { Command, CommandIdentifier } from './command';
export declare class Logger {
private readonly hide;
private readonly raw;
private readonly prefixFormat?;
private readonly commandLength;
private readonly dateFormatter;
private chalk;
/**
* How many characters should a prefix have.
* Prefixes shorter than this will be padded with spaces to the right.
*/
private prefixLength;
/**
* Last character emitted, and from which command.
* If `undefined`, then nothing has been logged yet.
*/
private lastWrite?;
/**
* Observable that emits when there's been output logged.
* If `command` is is `undefined`, then the log is for a global event.
*/
readonly output: Rx.Subject<{
command: Command | undefined;
text: string;
}>;
constructor({ hide, prefixFormat, commandLength, raw, timestampFormat, }: {
/**
* Which commands should have their output hidden.
*/
hide?: CommandIdentifier[];
/**
* Whether output should be formatted to include prefixes and whether "event" logs will be
* logged.
*/
raw?: boolean;
/**
* The prefix format to use when logging a command's output.
* Defaults to the command's index.
*/
prefixFormat?: string;
/**
* How many characters should a prefix have at most when the format is `command`.
*/
commandLength?: number;
/**
* Date format used when logging date/time.
* @see https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
*/
timestampFormat?: string;
});
/**
* Toggles colors on/off globally.
*/
toggleColors(on: boolean): void;
private shortenText;
private getPrefixesFor;
getPrefixContent(command: Command): {
type: 'default' | 'template';
value: string;
} | undefined;
getPrefix(command: Command): string;
setPrefixLength(length: number): void;
colorText(command: Command, text: string): string;
/**
* Logs an event for a command (e.g. start, stop).
*
* If raw mode is on, then nothing is logged.
*/
logCommandEvent(text: string, command: Command): void;
logCommandText(text: string, command: Command): void;
/**
* Logs a global event (e.g. sending signals to processes).
*
* If raw mode is on, then nothing is logged.
*/
logGlobalEvent(text: string): void;
/**
* Logs a table from an input object array, like `console.table`.
*
* Each row is a single input item, and they are presented in the input order.
*/
logTable(tableContents: Record<string, unknown>[]): void;
log(prefix: string, text: string, command?: Command): void;
emit(command: Command | undefined, text: string): void;
}

241
node_modules/concurrently/dist/src/logger.js generated vendored Normal file
View File

@@ -0,0 +1,241 @@
"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.Logger = void 0;
const chalk_1 = __importDefault(require("chalk"));
const lodash_1 = __importDefault(require("lodash"));
const Rx = __importStar(require("rxjs"));
const date_format_1 = require("./date-format");
const defaults = __importStar(require("./defaults"));
const defaultChalk = chalk_1.default;
const noColorChalk = new chalk_1.default.Instance({ level: 0 });
class Logger {
hide;
raw;
prefixFormat;
commandLength;
dateFormatter;
chalk = defaultChalk;
/**
* How many characters should a prefix have.
* Prefixes shorter than this will be padded with spaces to the right.
*/
prefixLength = 0;
/**
* Last character emitted, and from which command.
* If `undefined`, then nothing has been logged yet.
*/
lastWrite;
/**
* Observable that emits when there's been output logged.
* If `command` is is `undefined`, then the log is for a global event.
*/
output = new Rx.Subject();
constructor({ hide, prefixFormat, commandLength, raw = false, timestampFormat, }) {
this.hide = (hide || []).map(String);
this.raw = raw;
this.prefixFormat = prefixFormat;
this.commandLength = commandLength || defaults.prefixLength;
this.dateFormatter = new date_format_1.DateFormatter(timestampFormat || defaults.timestampFormat);
}
/**
* Toggles colors on/off globally.
*/
toggleColors(on) {
this.chalk = on ? defaultChalk : noColorChalk;
}
shortenText(text) {
if (!text || text.length <= this.commandLength) {
return text;
}
const ellipsis = '..';
const prefixLength = this.commandLength - ellipsis.length;
const endLength = Math.floor(prefixLength / 2);
const beginningLength = prefixLength - endLength;
const beginnning = text.slice(0, beginningLength);
const end = text.slice(text.length - endLength, text.length);
return beginnning + ellipsis + end;
}
getPrefixesFor(command) {
return {
// When there's limited concurrency, the PID might not be immediately available,
// so avoid the string 'undefined' from becoming a prefix
pid: command.pid != null ? String(command.pid) : '',
index: String(command.index),
name: command.name,
command: this.shortenText(command.command),
time: this.dateFormatter.format(new Date()),
};
}
getPrefixContent(command) {
const prefix = this.prefixFormat || (command.name ? 'name' : 'index');
if (prefix === 'none') {
return;
}
const prefixes = this.getPrefixesFor(command);
if (Object.keys(prefixes).includes(prefix)) {
return { type: 'default', value: prefixes[prefix] };
}
const value = lodash_1.default.reduce(prefixes, (prev, val, key) => {
const keyRegex = new RegExp(lodash_1.default.escapeRegExp(`{${key}}`), 'g');
return prev.replace(keyRegex, String(val));
}, prefix);
return { type: 'template', value };
}
getPrefix(command) {
const content = this.getPrefixContent(command);
if (!content) {
return '';
}
return content.type === 'template'
? content.value.padEnd(this.prefixLength, ' ')
: `[${content.value.padEnd(this.prefixLength, ' ')}]`;
}
setPrefixLength(length) {
this.prefixLength = length;
}
colorText(command, text) {
let color;
if (command.prefixColor && command.prefixColor.startsWith('#')) {
color = this.chalk.hex(command.prefixColor);
}
else {
const defaultColor = lodash_1.default.get(this.chalk, defaults.prefixColors, this.chalk.reset);
color = lodash_1.default.get(this.chalk, command.prefixColor ?? '', defaultColor);
}
return color(text);
}
/**
* Logs an event for a command (e.g. start, stop).
*
* If raw mode is on, then nothing is logged.
*/
logCommandEvent(text, command) {
if (this.raw) {
return;
}
// Last write was from this command, but it didn't end with a line feed.
// Prepend one, otherwise the event's text will be concatenated to that write.
// A line feed is otherwise inserted anyway.
let prefix = '';
if (this.lastWrite?.command === command && this.lastWrite.char !== '\n') {
prefix = '\n';
}
this.logCommandText(prefix + this.chalk.reset(text) + '\n', command);
}
logCommandText(text, command) {
if (this.hide.includes(String(command.index)) || this.hide.includes(command.name)) {
return;
}
const prefix = this.colorText(command, this.getPrefix(command));
return this.log(prefix + (prefix ? ' ' : ''), text, command);
}
/**
* Logs a global event (e.g. sending signals to processes).
*
* If raw mode is on, then nothing is logged.
*/
logGlobalEvent(text) {
if (this.raw) {
return;
}
this.log(this.chalk.reset('-->') + ' ', this.chalk.reset(text) + '\n');
}
/**
* Logs a table from an input object array, like `console.table`.
*
* Each row is a single input item, and they are presented in the input order.
*/
logTable(tableContents) {
// For now, can only print array tables with some content.
if (this.raw || !Array.isArray(tableContents) || !tableContents.length) {
return;
}
let nextColIndex = 0;
const headers = {};
const contentRows = tableContents.map((row) => {
const rowContents = [];
Object.keys(row).forEach((col) => {
if (!headers[col]) {
headers[col] = {
index: nextColIndex++,
length: col.length,
};
}
const colIndex = headers[col].index;
const formattedValue = String(row[col] == null ? '' : row[col]);
// Update the column length in case this rows value is longer than the previous length for the column.
headers[col].length = Math.max(formattedValue.length, headers[col].length);
rowContents[colIndex] = formattedValue;
return rowContents;
});
return rowContents;
});
const headersFormatted = Object.keys(headers).map((header) => header.padEnd(headers[header].length, ' '));
if (!headersFormatted.length) {
// No columns exist.
return;
}
const borderRowFormatted = headersFormatted.map((header) => '─'.padEnd(header.length, '─'));
this.logGlobalEvent(`┌─${borderRowFormatted.join('─┬─')}─┐`);
this.logGlobalEvent(`${headersFormatted.join(' │ ')}`);
this.logGlobalEvent(`├─${borderRowFormatted.join('─┼─')}─┤`);
contentRows.forEach((contentRow) => {
const contentRowFormatted = headersFormatted.map((header, colIndex) => {
// If the table was expanded after this row was processed, it won't have this column.
// Use an empty string in this case.
const col = contentRow[colIndex] || '';
return col.padEnd(header.length, ' ');
});
this.logGlobalEvent(`${contentRowFormatted.join(' │ ')}`);
});
this.logGlobalEvent(`└─${borderRowFormatted.join('─┴─')}─┘`);
}
log(prefix, text, command) {
if (this.raw) {
return this.emit(command, text);
}
// #70 - replace some ANSI code that would impact clearing lines
text = text.replace(/\u2026/g, '...');
// This write's interrupting another command, emit a line feed to start clean.
if (this.lastWrite && this.lastWrite.command !== command && this.lastWrite.char !== '\n') {
this.emit(this.lastWrite.command, '\n');
}
// Clean lines should emit a prefix
if (!this.lastWrite || this.lastWrite.char === '\n') {
this.emit(command, prefix);
}
const textToWrite = text.replaceAll('\n', (lf, i) => lf + (text[i + 1] ? prefix : ''));
this.emit(command, textToWrite);
}
emit(command, text) {
this.lastWrite = { command, char: text[text.length - 1] };
this.output.next({ command, text });
}
}
exports.Logger = Logger;

19
node_modules/concurrently/dist/src/output-writer.d.ts generated vendored Normal file
View File

@@ -0,0 +1,19 @@
/// <reference types="node" />
import { Writable } from 'stream';
import { Command } from './command';
/**
* Class responsible for actually writing output onto a writable stream.
*/
export declare class OutputWriter {
private readonly outputStream;
private readonly group;
readonly buffers: string[][];
activeCommandIndex: number;
constructor({ outputStream, group, commands, }: {
outputStream: Writable;
group: boolean;
commands: Command[];
});
write(command: Command | undefined, text: string): void;
private flushBuffer;
}

75
node_modules/concurrently/dist/src/output-writer.js generated vendored Normal file
View File

@@ -0,0 +1,75 @@
"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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OutputWriter = void 0;
const Rx = __importStar(require("rxjs"));
/**
* Class responsible for actually writing output onto a writable stream.
*/
class OutputWriter {
outputStream;
group;
buffers;
activeCommandIndex = 0;
constructor({ outputStream, group, commands, }) {
this.outputStream = outputStream;
this.group = group;
this.buffers = commands.map(() => []);
if (this.group) {
Rx.merge(...commands.map((c) => c.close)).subscribe((command) => {
if (command.index !== this.activeCommandIndex) {
return;
}
for (let i = command.index + 1; i < commands.length; i++) {
this.activeCommandIndex = i;
this.flushBuffer(i);
// TODO: Should errored commands also flush buffer?
if (commands[i].state !== 'exited') {
break;
}
}
});
}
}
write(command, text) {
if (this.group && command) {
if (command.index <= this.activeCommandIndex) {
this.outputStream.write(text);
}
else {
this.buffers[command.index].push(text);
}
}
else {
// "global" logs (command=null) are output out of order
this.outputStream.write(text);
}
}
flushBuffer(index) {
this.buffers[index].forEach((t) => this.outputStream.write(t));
this.buffers[index] = [];
}
}
exports.OutputWriter = OutputWriter;

View File

@@ -0,0 +1,11 @@
import chalk from 'chalk';
export declare class PrefixColorSelector {
private colorGenerator;
constructor(customColors?: string | string[]);
/** A list of colors that are readable in a terminal. */
static get ACCEPTABLE_CONSOLE_COLORS(): ("stderr" | keyof chalk.Chalk | "supportsColor" | "Level" | "Color" | "ForegroundColor" | "BackgroundColor" | "Modifiers")[];
/**
* @returns The given custom colors then a set of acceptable console colors indefinitely.
*/
getNextColor(): string;
}

View File

@@ -0,0 +1,94 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PrefixColorSelector = void 0;
function getConsoleColorsWithoutCustomColors(customColors) {
return PrefixColorSelector.ACCEPTABLE_CONSOLE_COLORS.filter(
// Consider the "Bright" variants of colors to be the same as the plain color to avoid similar colors
(color) => !customColors.includes(color.replace(/Bright$/, '')));
}
/**
* Creates a generator that yields an infinite stream of colors.
*/
function* createColorGenerator(customColors) {
// Custom colors should be used as is, except for "auto"
const nextAutoColors = getConsoleColorsWithoutCustomColors(customColors);
let lastColor;
for (const customColor of customColors) {
let currentColor = customColor;
if (currentColor !== 'auto') {
yield currentColor; // Manual color
}
else {
// Find the first auto color that is not the same as the last color
while (currentColor === 'auto' || lastColor === currentColor) {
if (!nextAutoColors.length) {
// There could be more "auto" values than auto colors so this needs to be able to refill
nextAutoColors.push(...PrefixColorSelector.ACCEPTABLE_CONSOLE_COLORS);
}
currentColor = String(nextAutoColors.shift());
}
yield currentColor; // Auto color
}
lastColor = currentColor;
}
const lastCustomColor = customColors[customColors.length - 1] || '';
if (lastCustomColor !== 'auto') {
while (true) {
yield lastCustomColor; // If last custom color was not "auto" then return same color forever, to maintain existing behaviour
}
}
// Finish the initial set(s) of auto colors to avoid repetition
for (const color of nextAutoColors) {
yield color;
}
// Yield an infinite stream of acceptable console colors
//
// If the given custom colors use every ACCEPTABLE_CONSOLE_COLORS except one then there is a chance a color will be repeated,
// however its highly unlikely and low consequence so not worth the extra complexity to account for it
while (true) {
for (const color of PrefixColorSelector.ACCEPTABLE_CONSOLE_COLORS) {
yield color; // Repeat colors forever
}
}
}
class PrefixColorSelector {
colorGenerator;
constructor(customColors = []) {
const normalizedColors = typeof customColors === 'string' ? [customColors] : customColors;
this.colorGenerator = createColorGenerator(normalizedColors);
}
/** A list of colors that are readable in a terminal. */
static get ACCEPTABLE_CONSOLE_COLORS() {
// Colors picked randomly, can be amended if required
return [
// Prevent duplicates, in case the list becomes significantly large
...new Set([
// Text colors
'cyan',
'yellow',
'greenBright',
'blueBright',
'magentaBright',
'white',
'grey',
'red',
// Background colors
'bgCyan',
'bgYellow',
'bgGreenBright',
'bgBlueBright',
'bgMagenta',
'bgWhiteBright',
'bgGrey',
'bgRed',
]),
];
}
/**
* @returns The given custom colors then a set of acceptable console colors indefinitely.
*/
getNextColor() {
return this.colorGenerator.next().value;
}
}
exports.PrefixColorSelector = PrefixColorSelector;

49
node_modules/concurrently/dist/src/spawn.d.ts generated vendored Normal file
View File

@@ -0,0 +1,49 @@
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
import { ChildProcess, SpawnOptions } from 'child_process';
import supportsColor from 'supports-color';
/**
* Spawns a command using `cmd.exe` on Windows, or `/bin/sh` elsewhere.
*/
export declare function spawn(command: string, options: SpawnOptions, spawn?: (command: string, args: string[], options: SpawnOptions) => ChildProcess, process?: Pick<NodeJS.Process, 'platform'>): ChildProcess;
export declare const getSpawnOpts: ({ colorSupport, cwd, process, ipc, stdio, env, }: {
/**
* What the color support of the spawned processes should be.
* If set to `false`, then no colors should be output.
*
* Defaults to whatever the terminal's stdout support is.
*/
colorSupport?: false | Pick<supportsColor.supportsColor.Level, "level"> | undefined;
/**
* The NodeJS process.
*/
process?: Pick<NodeJS.Process, "platform" | "cwd" | "env"> | undefined;
/**
* A custom working directory to spawn processes in.
* Defaults to `process.cwd()`.
*/
cwd?: string | undefined;
/**
* The file descriptor number at which the channel for inter-process communication
* should be set up.
*/
ipc?: number | undefined;
/**
* Which stdio mode to use. Raw implies inheriting the parent process' stdio.
*
* - `normal`: all of stdout, stderr and stdin are piped
* - `hidden`: stdin is piped, stdout/stderr outputs are ignored
* - `raw`: all of stdout, stderr and stdin are inherited from the main process
*
* Defaults to `normal`.
*/
stdio?: "raw" | "hidden" | "normal" | undefined;
/**
* Map of custom environment variables to include in the spawn options.
*/
env?: Record<string, unknown> | undefined;
}) => SpawnOptions;

49
node_modules/concurrently/dist/src/spawn.js generated vendored Normal file
View File

@@ -0,0 +1,49 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSpawnOpts = exports.spawn = void 0;
const assert_1 = __importDefault(require("assert"));
const child_process_1 = require("child_process");
const supports_color_1 = __importDefault(require("supports-color"));
/**
* Spawns a command using `cmd.exe` on Windows, or `/bin/sh` elsewhere.
*/
// Implementation based off of https://github.com/mmalecki/spawn-command/blob/v0.0.2-1/lib/spawn-command.js
function spawn(command, options,
// For testing
spawn = child_process_1.spawn, process = global.process) {
let file = '/bin/sh';
let args = ['-c', command];
if (process.platform === 'win32') {
file = 'cmd.exe';
args = ['/s', '/c', `"${command}"`];
options.windowsVerbatimArguments = true;
}
return spawn(file, args, options);
}
exports.spawn = spawn;
const getSpawnOpts = ({ colorSupport = supports_color_1.default.stdout, cwd, process = global.process, ipc, stdio = 'normal', env = {}, }) => {
const stdioValues = stdio === 'normal'
? ['pipe', 'pipe', 'pipe']
: stdio === 'raw'
? ['inherit', 'inherit', 'inherit']
: ['pipe', 'ignore', 'ignore'];
if (ipc != null) {
// Avoid overriding the stdout/stderr/stdin
assert_1.default.ok(ipc > 2, '[concurrently] the IPC channel number should be > 2');
stdioValues[ipc] = 'ipc';
}
return {
cwd: cwd || process.cwd(),
stdio: stdioValues,
...(/^win/.test(process.platform) && { detached: false }),
env: {
...(colorSupport ? { FORCE_COLOR: colorSupport.level.toString() } : {}),
...process.env,
...env,
},
};
};
exports.getSpawnOpts = getSpawnOpts;