@plinthjs/process
v0.1.1
Published
Plinth OS process runner.
Downloads
253
Maintainers
Readme
@plinthjs/process
Plinth's OS process runner. A fluent PendingProcess builder
over node:child_process, a ProcessResult with output and exit-code helpers, long-running
InvokedProcess handles, concurrent pools, pipes, and a recording Process.fake() for tests that
never spawns a real process.
Install
npm install @plinthjs/processUsage
import { Process } from '@plinthjs/process'
// A string command runs through a shell; an argv array runs with no shell.
const result = await Process.run('ls -la')
const version = await Process.run(['node', '--version'])
result.successful() // exit code 0
result.failed()
result.exitCode() // number | null
result.output() // stdout
result.errorOutput() // stderr
result.seeInOutput('package.json')
// Throw a ProcessFailedError when the process failed.
const tests = await Process.run('npm test')
tests.throw() // returns the result when it succeededConfiguring a process
Every setter returns the builder, so calls chain:
const result = await Process.path('/var/www/app')
.env({ NODE_ENV: 'production' })
.timeout(120) // seconds; the default is 60
.idleTimeout(30) // killed if no output arrives for 30 seconds
.input('yes\n') // written to stdin, then closed
.run('npm run build', (type, chunk) => {
process.stdout.write(`[${type}] ${chunk}`) // live output, type is 'stdout' or 'stderr'
})Use forever() to disable the timeout, quietly() to ignore the output callback, and
options(spawnOptions) to merge raw Node SpawnOptions. Process.command(cmd) returns a bare
PendingProcess to configure and run() later.
Long-running processes
const server = Process.start('node server.js')
server.pid()
server.running() // true
server.latestOutput() // stdout accumulated so far
await server.stop() // SIGTERM by default; resolves the ProcessResult
const done = await Process.start('node build.js').wait()Pools and pipes
const results = await Process.pool((pool) => {
pool.command('npm run lint')
pool.command('npm run typecheck')
pool.add().path('packages/api').command('npm test')
})
results.successful() // every process exited 0
results.get(0)?.output()
for (const result of results) console.log(result.command(), result.exitCode())
// Each step's stdout feeds the next step's stdin; stops at the first failure.
const count = await Process.pipe(['cat access.log', 'grep 500', 'wc -l'])Process.concurrently(callback) is an alias of Process.pool.
Testing
import { clearFake, Process } from '@plinthjs/process'
const fake = Process.fake({
'git status': { output: 'nothing to commit' },
'deploy *': { errorOutput: 'permission denied', exitCode: 13 },
'npm *': (command) => Process.fakeResult({ output: `ran: ${command}` }),
}).preventStrayProcesses()
await deployApp()
fake.assertRan('deploy *')
fake.assertRanTimes((command) => command.startsWith('git'), 1)
fake.assertNotRan('rm -rf *')
clearFake() // restore real spawningPatterns match exactly unless they contain * wildcards. Without a matching stub a command gets an
empty success, unless preventStrayProcesses() makes it throw.
