@gobstones/gobstones-scripts
Version:
Scripts to abstract away build configuration of Gobstones Project's libraries and modules.
132 lines (117 loc) • 4.03 kB
text/typescript
/*
* *****************************************************************************
* Copyright (C) National University of Quilmes 2018-2024
* Gobstones (TM) is a trademark of the National University of Quilmes.
*
* This program is free software distributed under the terms of the
* GNU Affero General Public License version 3.
* Additional terms added in compliance to section 7 of such license apply.
*
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
/**
* ----------------------------------------------------
* @module Tasks
* @author Alan Rodas Bonjour <alanrodas@gmail.com>
* ----------------------------------------------------
*/
import { runBin } from './runBin';
import { shellEscape } from './shellEscape';
import { TaskConfigurationError } from '../Helpers/TaskError';
/**
* The definition for a concurrently run script.
*/
export interface ConcurrentScriptDefinition {
/**
* The actual bash script command to run.
*/
script: string;
/**
* The color to use when prefixing this script.
*/
color?: string;
}
/**
* Represent a concurrent script to run.
*/
export type ConcurrentScript = ConcurrentScriptDefinition | string;
/**
* Generates a bash command that uses `concurrently` to run
* scripts concurrently. Adds a few flags to make it
* behave as you probably want (like --kill-others-on-fail).
* In addition, it adds color and labels where the color
* can be specified or is defaulted and the label is based
* on the key for the script.
*
* @param scripts - The scripts to run.
*
* @example
* // returns a bit of a long script that can vary slightly
* // based on your environment...
* concurrent({
* lint: {
* script: 'eslint .',
* color: 'bgGreen.white.dim',
* },
* test: 'jest',
* build: {
* script: 'webpack'
* }
* })
*
* @return The bash command string.
*/
export const concurrently = (scripts: Record<string, ConcurrentScript>): string => {
if (typeof scripts !== 'object') {
throw new TaskConfigurationError(`concurrently expects an object with names as keys, and commands as values.`);
}
interface ReducedScriptDefinition {
colors: string[];
scripts: string[];
names: string[];
}
const reduceScripts = (
accumulator: ReducedScriptDefinition,
scriptName: string,
index: number
): ReducedScriptDefinition => {
if (!scripts[scriptName] || (typeof scripts[scriptName] === 'object' && !scripts[scriptName].script)) {
return accumulator;
}
const defaultColors = [
'bgBlue.bold',
'bgMagenta.bold',
'bgGreen.bold',
'bgBlack.bold',
'bgCyan.bold',
'bgRed.bold',
'bgWhite.bold',
'bgYellow.bold'
];
const scriptObj: ConcurrentScriptDefinition =
typeof scripts[scriptName] === 'object' ? scripts[scriptName] : { script: scripts[scriptName] };
scriptObj.color = scriptObj.color ?? defaultColors[index % defaultColors.length];
accumulator.names.push(scriptName);
accumulator.colors.push(scriptObj.color);
accumulator.scripts.push(scriptObj.script);
return accumulator;
};
const Object$keys$reduce = Object.keys(scripts).reduce(reduceScripts, {
colors: [],
scripts: [],
names: []
});
const colors = Object$keys$reduce.colors;
const quotedScripts = Object$keys$reduce.scripts;
const names = Object$keys$reduce.names;
const flags = [
'--kill-others-on-fail',
`--prefix-colors "${colors.join(',')}"`,
'--prefix "[{name}]"',
`--names "${names.join(',')}"`,
shellEscape(quotedScripts)
];
const concurrentlyBin = runBin('concurrently', 'concurrently');
return `${concurrentlyBin} ${flags.join(' ')}`;
};