{"id":19926613,"url":"https://github.com/microlinkhq/tinyspawn","last_synced_at":"2025-04-06T14:12:22.413Z","repository":{"id":212096205,"uuid":"730676116","full_name":"microlinkhq/tinyspawn","owner":"microlinkhq","description":"A minimalistic wrapper around Node.js `child_process.spawn` API.","archived":false,"fork":false,"pushed_at":"2025-03-27T15:39:57.000Z","size":99,"stargazers_count":29,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-30T12:07:20.613Z","etag":null,"topics":["child-process","nodejs","spawn"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/microlinkhq.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-12-12T12:43:03.000Z","updated_at":"2025-03-27T15:40:01.000Z","dependencies_parsed_at":"2023-12-15T17:27:24.042Z","dependency_job_id":"28a2e95f-0a3c-45d1-8e94-342d6ee1ab94","html_url":"https://github.com/microlinkhq/tinyspawn","commit_stats":null,"previous_names":["kikobeats/tinyspawn","microlinkhq/tinyspawn"],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microlinkhq%2Ftinyspawn","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microlinkhq%2Ftinyspawn/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microlinkhq%2Ftinyspawn/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microlinkhq%2Ftinyspawn/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/microlinkhq","download_url":"https://codeload.github.com/microlinkhq/tinyspawn/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247492557,"owners_count":20947545,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["child-process","nodejs","spawn"],"created_at":"2024-11-12T22:29:56.869Z","updated_at":"2025-04-06T14:12:22.387Z","avatar_url":"https://github.com/microlinkhq.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/microlinkhq/cdn/raw/master/dist/logo/banner.png#gh-light-mode-only\" alt=\"microlink cdn\"\u003e\n  \u003cimg src=\"https://github.com/microlinkhq/cdn/raw/master/dist/logo/banner-dark.png#gh-dark-mode-only\" alt=\"microlink cdn\"\u003e\n  \u003cbr\u003e\n  \u003cbr\u003e\n\u003c/div\u003e\n\n![Last version](https://img.shields.io/github/tag/microlinkhq/tinyspawn.svg?style=flat-square)\n[![Coverage Status](https://img.shields.io/coveralls/microlinkhq/tinyspawn.svg?style=flat-square)](https://coveralls.io/github/microlinkhq/tinyspawn)\n[![NPM Status](https://img.shields.io/npm/dm/tinyspawn.svg?style=flat-square)](https://www.npmjs.org/package/tinyspawn)\n\n**tinyspawn** is a minimalistic [`child_process`](https://nodejs.org/api/child_process.html) wrapper with following features:\n\n- Small (~80 LOC, 835 bytes).\n- Focus on performance.\n- Zero dependencies.\n- Meaningful errors.\n- Easy to extend.\n- Fully typed.\n\n## Install\n\n```bash\n$ npm install tinyspawn --save\n```\n\n## Usage\n\n### Getting started\n\nThe [child_process](https://nodejs.org/api/child_process.html) in Node.js is great, but I always found the API confusing and hard to remember.\n\nThat's why I created **tinyspawn**. It's recommended to bind it to `$`:\n\n```js\nconst $ = require('tinyspawn')\n```\n\nThe first argument is the command (with arguments) to be executed:\n\n```js\nconst { stdout } = await $(`node -e 'console.log(\"hello world\")'`)\nconsole.log(stdout) // =\u003e 'hello world'\n```\n\nThe second argument is any of the [spawn#options](https://nodejs.org/api/child_process.html#child_processspawncommand-args-options):\n\n```js\nconst { stdout } = $(`node -e 'console.log(\"hello world\")'`, {\n  shell: true\n})\n```\n\nWhen you execute a command, it returns a [ChildProcess](https://nodejs.org/api/child_process.html#class-childprocess) instance:\n\n```js\nconst {\n  exitCode,\n  killed,\n  pid,\n  signalCode,\n  spawnargs,\n  spawnfile,\n  stderr,\n  stdin,\n  stdout,\n} = await $('date')\n```\n\n### Piping streams\n\nSince **tinyspawn** returns a [ChildProcess](https://nodejs.org/api/child_process.html#class-childprocess) instance, you can use it for interacting with other Node.js streams:\n\n```js\nconst subprocess = $('echo 1234567890')\nsubprocess.stdout.pipe(process.stdout) // =\u003e 1234567890\n\n/* You can also continue interacting with it as a promise */\n\nconst { stdout } = await subprocess\nconsole.log(stdout) // =\u003e 1234567890\n```\n\nor stdin:\n\n```js\nconst { Readable } = require('node:stream')\n\nconst subprocess = $('cat')\nReadable.from('hello world').pipe(subprocess.stdin)\nconst { stdout } = await subprocess\n\nconsole.log(stdout) // 'hello world'\n```\n\n### JSON parsing\n\nA CLI program commonly supports a way to return a JSON that makes it easy to connect with other programs.\n\n**tinyspawn** has been designed to be easy to work with CLI programs, making it possible to call `$.json` or pass `{ json: true }` as an option:\n\n```js\nconst { stdout } = await $.json(`curl https://geolocation.microlink.io`)\n```\n\n### Extending behavior\n\nAlthough you can pass [spawn#options](https://nodejs.org/api/child_process.html#child_processspawncommand-args-options) as a second argument, sometimes defining something as default behavior is convenient.\n\n**tinyspawn** exports the method `$.extend` to create a tinyspawn with [spawn#options](https://nodejs.org/api/child_process.html#child_processspawncommand-args-options) defaults set:\n\n```js\nconst $ = require('tinyspawn').extend({\n  timeout: 5000,\n  killSignal: 'SIGKILL'\n})\n```\n\n### Meaningful errors\n\nWhen working with CLI programs and something wrong happens, it's crucial to present the error as readable as possible.\n\n**tinyspawn** prints meaningful errors to help you understa dn what happened:\n\n```js\nconst subprocess = $('node', ['child.js'], {\n  timeout: 500,\n  killSignal: 'SIGKILL'\n})\n\nconsole.log(await subprocess.catch(error =\u003e error))\n// Error [ChildProcessError]: The command spawned as:\n\n//   `node child.js`\n\n// exited with:\n\n//   `{ signal: 'null', code: 1 }`\n\n// with the following trace:\n\n//     at createChildProcessError (/Users/kikobeats/Projects/microlink/tinyspawn/src/index.js:20:17)\n//     at ChildProcess.\u003canonymous\u003e (/Users/kikobeats/Projects/microlink/tinyspawn/src/index.js:63:18)\n//     at ChildProcess.emit (node:events:531:35)\n//     at ChildProcess._handle.onexit (node:internal/child_process:294:12) {\n//   command: 'node child.js',\n//   connected: false,\n//   signalCode: null,\n//   exitCode: 1,\n//   killed: false,\n//   spawnfile: 'node',\n//   spawnargs: [ 'node', 'child.js' ],\n//   pid: 63467,\n//   stdout: '',\n//   stderr: 'node:internal/modules/cjs/loader:1148\\n' +\n//     '  throw err;\\n' +\n//     '  ^\\n' +\n//     '\\n' +\n//     \"Error: Cannot find module '/Users/kikobeats/Projects/microlink/tinyspawn/child.js'\\n\" +\n//     '    at Module._resolveFilename (node:internal/modules/cjs/loader:1145:15)\\n' +\n//     '    at Module._load (node:internal/modules/cjs/loader:986:27)\\n' +\n//     '    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:174:12)\\n' +\n//     '    at node:internal/main/run_main_module:28:49 {\\n' +\n//     \"  code: 'MODULE_NOT_FOUND',\\n\" +\n//     '  requireStack: []\\n' +\n//     '}\\n' +\n//     '\\n' +\n//     'Node.js v20.15.1'\n// }\n```\n\nThe [ChildProcess](https://nodejs.org/api/child_process.html#class-childprocess) instance properties are also available as part of the error:\n\n```js\nconst { stdout: node } = await $('which node')\n\nconst error = await $(`${node} -e 'require(\"notfound\")'`).catch(error =\u003e error)\n\nconst {\n  signalCode,\n  exitCode,\n  killed,\n  spawnfile,\n  spawnargs,\n  pid,\n  stdin,\n  stdout,\n  stderr,\n} = error\n```\n\n## Related\n\n- [tinyrun](https://github.com/Kikobeats/tinyrun) – CLI for executing multiple commands in parallel with minimal footprint (~2KB).\n\n## License\n\n**tinyspawn** © [microlink.io](https://microlink.io), released under the [MIT](https://github.com/microlinkhq/tinyspawn/blob/master/LICENSE.md) License.\u003cbr\u003e\nAuthored and maintained by [Kiko Beats](https://kikobeats.com) with help from [contributors](https://github.com/microlinkhq/tinyspawn/contributors).\n\n\u003e [microlink.io](https://microlink.io) · GitHub [microlink.io](https://github.com/microlinkhq) · X [@microlinkhq](https://x.com/microlinkhq)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmicrolinkhq%2Ftinyspawn","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmicrolinkhq%2Ftinyspawn","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmicrolinkhq%2Ftinyspawn/lists"}