Run a child as if it's the foreground process. Give it stdio. Exit when it exits.
Installations
npm install foreground-child
Developer Guide
Typescript
Yes
Module System
ESM
Min. Node Version
>=14
Node Version
20.13.1
NPM Version
10.7.0
Score
94.7
Supply Chain
99.5
Quality
81.9
Maintenance
100
Vulnerability
100
License
Releases
Unable to fetch releases
Contributors
Languages
TypeScript (83.37%)
JavaScript (15.81%)
Shell (0.82%)
Developer
Download Statistics
Total Downloads
2,574,699,777
Last Day
4,295,185
Last Week
32,372,409
Last Month
147,635,168
Last Year
1,460,896,173
GitHub Statistics
40 Stars
101 Commits
20 Forks
4 Watching
4 Branches
9 Contributors
Bundle Size
9.44 kB
Minified
3.69 kB
Minified + Gzipped
Sponsor this package
Package Meta Information
Latest Version
3.3.0
Package Id
foreground-child@3.3.0
Unpacked Size
67.36 kB
Size
12.30 kB
File Count
37
NPM Version
10.7.0
Node Version
20.13.1
Publised On
07 Aug 2024
Total Downloads
Cumulative downloads
Total Downloads
2,574,699,777
Last day
-34.2%
4,295,185
Compared to previous day
Last week
-10.9%
32,372,409
Compared to previous week
Last month
-0.9%
147,635,168
Compared to previous month
Last year
133%
1,460,896,173
Compared to previous year
Daily Downloads
Weekly Downloads
Monthly Downloads
Yearly Downloads
Dependencies
2
foreground-child
Run a child as if it's the foreground process. Give it stdio. Exit when it exits.
Mostly this module is here to support some use cases around
wrapping child processes for test coverage and such. But it's
also generally useful any time you want one program to execute
another as if it's the "main" process, for example, if a program
takes a --cmd
argument to execute in some way.
USAGE
1import { foregroundChild } from 'foreground-child' 2// hybrid module, this also works: 3// const { foregroundChild } = require('foreground-child') 4 5// cats out this file 6const child = foregroundChild('cat', [__filename]) 7 8// At this point, it's best to just do nothing else. 9// return or whatever. 10// If the child gets a signal, or just exits, then this 11// parent process will exit in the same way.
You can provide custom spawn options by passing an object after the program and arguments:
1const child = foregroundChild(`cat ${__filename}`, { shell: true })
A callback can optionally be provided, if you want to perform an action before your foreground-child exits:
1const child = foregroundChild('cat', [__filename], spawnOptions, () => {
2 doSomeActions()
3})
The callback can return a Promise in order to perform asynchronous actions. If the callback does not return a promise, then it must complete its actions within a single JavaScript tick.
1const child = foregroundChild('cat', [__filename], async () => {
2 await doSomeAsyncActions()
3})
If the callback throws or rejects, then it will be unhandled, and node will exit in error.
If the callback returns a string value, then that will be used as
the signal to exit the parent process. If it returns a number,
then that number will be used as the parent exit status code. If
it returns boolean false
, then the parent process will not be
terminated. If it returns undefined
, then it will exit with the
same signal/code as the child process.
Caveats
The "normal" standard IO file descriptors (0, 1, and 2 for stdin, stdout, and stderr respectively) are shared with the child process. Additionally, if there is an IPC channel set up in the parent, then messages are proxied to the child on file descriptor 3.
In Node, it's possible to also map arbitrary file descriptors into a child process. In these cases, foreground-child will not map the file descriptors into the child. If file descriptors 0, 1, or 2 are used for the IPC channel, then strange behavior may happen (like printing IPC messages to stderr, for example).
Note that a SIGKILL will always kill the parent process, but will not proxy the signal to the child process, because SIGKILL cannot be caught. In order to address this, a special "watchdog" child process is spawned which will send a SIGKILL to the child process if it does not terminate within half a second after the watchdog receives a SIGHUP due to its parent terminating.
On Windows, issuing a process.kill(process.pid, signal)
with a
fatal termination signal may cause the process to exit with a 1
status code rather than reporting the signal properly. This
module tries to do the right thing, but on Windows systems, you
may see that incorrect result. There is as far as I'm aware no
workaround for this.
util: foreground-child/proxy-signals
If you just want to proxy the signals to a child process that the
main process receives, you can use the proxy-signals
export
from this package.
1import { proxySignals } from 'foreground-child/proxy-signals' 2 3const childProcess = spawn('command', ['some', 'args']) 4proxySignals(childProcess)
Now, any fatal signal received by the current process will be proxied to the child process.
It doesn't go in the other direction; ie, signals sent to the
child process will not affect the parent. For that, listen to the
child exit
or close
events, and handle them appropriately.
util: foreground-child/watchdog
If you are spawning a child process, and want to ensure that it isn't left dangling if the parent process exits, you can use the watchdog utility exported by this module.
1import { watchdog } from 'foreground-child/watchdog' 2 3const childProcess = spawn('command', ['some', 'args']) 4const watchdogProcess = watchdog(childProcess) 5 6// watchdogProcess is a reference to the process monitoring the 7// parent and child. There's usually no reason to do anything 8// with it, as it's silent and will terminate 9// automatically when it's no longer needed.
No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
license file detected
Details
- Info: project has a license file: LICENSE:0
- Info: FSF or OSI recognized license: ISC License: LICENSE:0
Reason
3 existing vulnerabilities detected
Details
- Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg
- Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275
- Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q
Reason
Found 5/27 approved changesets -- score normalized to 1
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
detected GitHub workflow tokens with excessive permissions
Details
- Warn: no topLevel permission defined: .github/workflows/ci.yml:1
- Warn: no topLevel permission defined: .github/workflows/isaacs-makework.yml:1
- Info: topLevel 'contents' permission set to 'read': .github/workflows/typedoc.yml:14
- Info: no jobLevel write permissions found
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/tapjs/foreground-child/ci.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/tapjs/foreground-child/ci.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/isaacs-makework.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/tapjs/foreground-child/isaacs-makework.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/isaacs-makework.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/tapjs/foreground-child/isaacs-makework.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/typedoc.yml:32: update your workflow using https://app.stepsecurity.io/secureworkflow/tapjs/foreground-child/typedoc.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/typedoc.yml:34: update your workflow using https://app.stepsecurity.io/secureworkflow/tapjs/foreground-child/typedoc.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/typedoc.yml:42: update your workflow using https://app.stepsecurity.io/secureworkflow/tapjs/foreground-child/typedoc.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/typedoc.yml:44: update your workflow using https://app.stepsecurity.io/secureworkflow/tapjs/foreground-child/typedoc.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/typedoc.yml:49: update your workflow using https://app.stepsecurity.io/secureworkflow/tapjs/foreground-child/typedoc.yml/main?enable=pin
- Warn: npmCommand not pinned by hash: .github/workflows/typedoc.yml:39
- Info: 0 out of 9 GitHub-owned GitHubAction dependencies pinned
- Info: 0 out of 1 npmCommand dependencies pinned
Reason
project is not fuzzed
Details
- Warn: no fuzzer integrations found
Reason
branch protection not enabled on development/release branches
Details
- Warn: branch protection not enabled for branch 'main'
Reason
security policy file not detected
Details
- Warn: no security policy file detected
- Warn: no security file to analyze
- Warn: no security file to analyze
- Warn: no security file to analyze
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
- Warn: 0 commits out of 9 are checked with a SAST tool
Score
3.2
/10
Last Scanned on 2024-12-16
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More