UNPKG

@gobstones/gobstones-scripts

Version:

Scripts to abstract away build configuration of Gobstones Project's libraries and modules.

132 lines (117 loc) 4.03 kB
/* * ***************************************************************************** * 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(' ')}`; };