@plugjs/plug
Version:
PlugJS Build System ===================
110 lines (96 loc) • 3.46 kB
text/typescript
import { install } from '../pipe'
import { execChild } from '../utils/exec'
import { parseOptions } from '../utils/options'
import type { Files } from '../files'
import type { Context, PipeParameters, Plug } from '../pipe'
import type { ExecChildOptions } from '../utils/exec'
/** Options for executing scripts */
export interface ExecOptions extends ExecChildOptions {
/**
* The current working directory of the process to execute.
*
* Defaults to the current {@link Files.directory | Files' directory}.
*/
cwd?: string
/**
* Whether the {@link Files} will be appended to the current arguments as
* _relative_ files (default or `true`) or _absolute_ (if `false`).
*/
relativePaths?: boolean
}
declare module '../index' {
export interface Pipe {
/**
* Execute a shell command, adding to its _arguments_ the list of files
* from the current pipe (much like `xargs` does on Unix systems).
*
* For example:
*
* ```
* import { build } from '@plugjs/plugjs'
*
* export default build({
* runme() {
* this.find('*.ts', { directory: 'src' })
* .exec('chmod', '755' })
* .exec('chown root:root', { shell: true })
* },
* })
* ```
*
* @param cmd The command to execute
* @param args Any additional argument for the command to execute
*/
exec(cmd: string, ...args: string[]): Pipe
/**
* Execute a shell command, adding to its _arguments_ the list of files
* from the current pipe (much like `xargs` does on Unix systems).
*
* For example:
*
* ```
* import { build } from '@plugjs/plugjs'
*
* export default build({
* runme() {
* this.find('*.ts', { directory: 'src' })
* .exec('chmod', '755' })
* .exec('chown root:root', { shell: true })
* },
* })
* ```
*
* @param cmd The command to execute
* @param args Any additional argument for the command to execute
* @param options Extra {@link ExecOptions | options} for process execution
*/
exec(cmd: string, ...extra: [ ...args: string[], options: ExecOptions ]): Pipe
}
}
/* ========================================================================== *
* INSTALLATION / IMPLEMENTATION *
* ========================================================================== */
install('exec', class Exec implements Plug<Files> {
private readonly _cmd: string
private readonly _args: readonly string[]
private readonly _options: ExecOptions
constructor(...args: PipeParameters<'exec'>) {
const { params, options } = parseOptions(args, {})
const [ _cmd, ..._args ] = params
this._cmd = _cmd
this._args = _args
this._options = options
}
async pipe(files: Files, context: Context): Promise<Files> {
const { relativePaths = true, ...options } = this._options
if (! options.cwd) options.cwd = files.directory
// What to use as extra arguments? Relative or absolute paths?
const params = [ ...(relativePaths ? files : files.absolutePaths() ) ]
// In case of shell usage, each extra parameter (file) gets quoted!
if (options.shell) params.forEach((s, i, a) => a[i] = JSON.stringify(s))
// Run our child
await execChild(this._cmd, [ ...this._args, ...params ], options, context)
// Return our files
return files
}
})