diff --git a/packages/scripts/src/run.js b/packages/scripts/src/run.js index 236acf7..0d7c7f7 100755 --- a/packages/scripts/src/run.js +++ b/packages/scripts/src/run.js @@ -7,19 +7,21 @@ import { } from 'argue-cli' import { detectPackageManager, + readPackageJsonUpward, readScripts, runParallel, runSerial } from './utils/index.js' const pm = detectPackageManager() +const pkg = await readPackageJsonUpward() const { parallel } = readOptions( option(alias('parallel', 'p'), Boolean), ) const scripts = readScripts() if (parallel) { - process.exit(await runParallel(pm, scripts)) + process.exit(await runParallel(pm, scripts, pkg)) } else { - process.exit(await runSerial(pm, scripts)) + process.exit(await runSerial(pm, scripts, pkg)) } diff --git a/packages/scripts/src/utils/args.js b/packages/scripts/src/utils/args.js index 56c3469..fb0abbf 100644 --- a/packages/scripts/src/utils/args.js +++ b/packages/scripts/src/utils/args.js @@ -33,6 +33,23 @@ export function getRunArgs(pm, args) { ] } +/** + * Get args to run command. + * @param {string} pm - Package manager name. + * @param {string[]} args - Command args. + * @param {{ scripts?: Record }} pkg - package.json + * @returns {[string, string[]]} - Bin and commands. + */ +export function getArgs(pm, args, pkg) { + if (pkg.scripts && (args[0] in pkg.scripts)) { + return [pm, getRunArgs(pm, args)] + } + + const [bin, ...restArgs] = args + + return [bin, restArgs] +} + /** * Read scripts from argv to run with package manager. * @returns Package manager scripts to run. diff --git a/packages/scripts/src/utils/files.js b/packages/scripts/src/utils/files.js new file mode 100644 index 0000000..16ef7a1 --- /dev/null +++ b/packages/scripts/src/utils/files.js @@ -0,0 +1,41 @@ +import { resolve, dirname } from 'path' +import { constants, promises } from 'fs' + +const { access, readFile } = promises + +/** + * Find file starts from cwd ups to root. + * @param {string} filename + * @param {string} [dir] + * @returns {Promise} Path to file. + */ +export async function findFileUpward(filename, dir = process.cwd()) { + const file = resolve(dir, filename) + + try { + await access(file, constants.R_OK) + + return file + } catch (err) { + if (dir === '.') { + throw err + } + + return findFileUpward(filename, dirname(dir)) + } +} + +/** + * Find and read package.json file. + * @returns {Promise} package.json + */ +export async function readPackageJsonUpward() { + try { + const path = await findFileUpward('package.json') + const pkg = JSON.parse(await readFile(path, 'utf8')) + + return pkg + } catch (err) { + throw new Error(`Can't find package.json`) + } +} diff --git a/packages/scripts/src/utils/index.js b/packages/scripts/src/utils/index.js index 64a5e04..69ca2ef 100644 --- a/packages/scripts/src/utils/index.js +++ b/packages/scripts/src/utils/index.js @@ -1,3 +1,4 @@ export * from './args.js' +export * from './files.js' export * from './spawn.js' export * from './run.js' diff --git a/packages/scripts/src/utils/run.js b/packages/scripts/src/utils/run.js index 9f7b0b0..0599a5e 100644 --- a/packages/scripts/src/utils/run.js +++ b/packages/scripts/src/utils/run.js @@ -1,20 +1,21 @@ import { cpus } from 'os' import pLimit from 'p-limit' import { spawn } from './spawn.js' -import { getRunArgs } from './args.js' +import { getArgs } from './args.js' /** * Run package manager scripts serial. * @param {string} pm * @param {string[][]} scripts + * @param {{ scripts?: Record }} pkg - package.json * @returns Exit code */ -export async function runSerial(pm, scripts) { - const pmScripts = scripts.map(script => getRunArgs(pm, script)) +export async function runSerial(pm, scripts, pkg) { + const cmds = scripts.map(script => getArgs(pm, script, pkg)) let exitCode = 0 - for (const pmScript of pmScripts) { - exitCode = exitCode || (await spawn(pm, pmScript)).exitCode + for (const [bin, args] of cmds) { + exitCode = exitCode || (await spawn(bin, args)).exitCode } return exitCode @@ -24,12 +25,13 @@ export async function runSerial(pm, scripts) { * Run package manager scripts parallel. * @param {string} pm * @param {string[][]} scripts + * @param {{ scripts?: Record }} pkg - package.json * @returns Exit code. */ -export async function runParallel(pm, scripts) { +export async function runParallel(pm, scripts, pkg) { const limit = pLimit(cpus().length) - const pmScripts = scripts.map(script => getRunArgs(pm, script)) - const tasks = pmScripts.map(pmScript => limit(() => spawn(pm, pmScript, false))) + const cmds = scripts.map(script => getArgs(pm, script, pkg)) + const tasks = cmds.map(([bin, args]) => limit(() => spawn(bin, args, false))) let exitCode = 0 /** @type {{ exitCode: number, output?: string | Error }} */ let result