Comparing version 7.0.1 to 8.0.0-next.1573414430.53c4cd7b292d3b083ac24ef130e06e0c7a76ad1f
158
HISTORY.md
# History | ||
## v8.0.0 2019 November 11 | ||
- Updated dependencies, [base files](https://github.com/bevry/base), and [editions](https://editions.bevry.me) using [boundation](https://github.com/bevry/boundation) | ||
- Minimum required node version changed from `node: >=0.8` to `node: >=0.10` due to mandatory ecosystem changes | ||
## v7.0.1 2017 April 16 | ||
- Fixed `fatal: remote origin already exists` on `initGitRepo` when remote already existed, it will now overwrite the remote | ||
- Fixed `fatal: remote origin already exists` on `initGitRepo` when remote already existed, it will now overwrite the remote | ||
## v7.0.0 2017 April 16 | ||
- Removed `initOrPullGitRepo` and put its functionality into `initGitRepo` if the appropriate args are provided, also checkout the branch (if provided) before pulling it | ||
- Thanks to [Nathan Friedly](https://github.com/nfriedly) for his help on [issue #7](https://github.com/bevry/safeps/issues/7) and [pull request #8](https://github.com/bevry/safeps/pull/8) | ||
- Removed `initOrPullGitRepo` and put its functionality into `initGitRepo` if the appropriate args are provided, also checkout the branch (if provided) before pulling it | ||
- Thanks to [Nathan Friedly](https://github.com/nfriedly) for his help on [issue #7](https://github.com/bevry/safeps/issues/7) and [pull request #8](https://github.com/bevry/safeps/pull/8) | ||
## v6.4.0 2017 April 16 | ||
- Updated base files | ||
- Fix node <0.12 support | ||
- Updated base files | ||
- Fix node <0.12 support | ||
## v6.3.0 2016 June 4 | ||
- Updated dependencies | ||
- Updated dependencies | ||
## v6.2.0 2016 June 4 | ||
- Introduced `determineExecPathSync` which is now used of `opts.sync` is `true` in `determineExecPath` | ||
- Removes the need for `sync` option in TaskGroup, which has caused too much complexity over the years | ||
- Introduced `determineExecPathSync` which is now used of `opts.sync` is `true` in `determineExecPath` | ||
- Removes the need for `sync` option in TaskGroup, which has caused too much complexity over the years | ||
## v6.1.0 2016 May 28 | ||
- Updated internal conventions | ||
- Moved from [ESNextGuardian](https://github.com/bevry/esnextguardian) to [Editions](https://github.com/bevry/editions) | ||
- Updated internal conventions | ||
- Moved from [ESNextGuardian](https://github.com/bevry/esnextguardian) to [Editions](https://github.com/bevry/editions) | ||
## v6.0.2 2015 December 10 | ||
- Updated internal conventions | ||
- Updated internal conventions | ||
## v6.0.1 2015 September 24 | ||
- Updated base files | ||
- Updated dependencies | ||
- Updated base files | ||
- Updated dependencies | ||
## v6.0.0 2015 September 7 | ||
- Dropped support for node 0.10 and earlier, minimum supported version is now 0.12 | ||
- This is due to the compiled babel code not supporting `for of` loops | ||
- Moved from CoffeeScript to ES6+ | ||
- Fixed callback support on `execSync` | ||
- Fixed error handling on `initOrPullGitRepo` | ||
- Dropped support for node 0.10 and earlier, minimum supported version is now 0.12 - This is due to the compiled babel code not supporting `for of` loops | ||
- Moved from CoffeeScript to ES6+ | ||
- Fixed callback support on `execSync` | ||
- Fixed error handling on `initOrPullGitRepo` | ||
## v5.1.0 2015 April 7 | ||
- Added `spawnNodeModule` | ||
- Added `spawnNodeModule` | ||
## v5.0.0 2015 April 7 | ||
- Removed `requireFresh(path)` instead use the [requirefresh](https://npmjs.org/package/requirefresh) package | ||
- Deprecated `path` option on `initGitRepo`, `initOrPullGitRepo`, `initNodeModules` - use `cwd` option instead | ||
- Removed `requireFresh(path)` instead use the [requirefresh](https://npmjs.org/package/requirefresh) package | ||
- Deprecated `path` option on `initGitRepo`, `initOrPullGitRepo`, `initNodeModules` - use `cwd` option instead | ||
## v4.0.0 2015 March 17 | ||
- Removed `spawnCommand` and `spawnCommands` use `spawn` and `spawnMultiple` instead | ||
- Removed `spawnCommand` and `spawnCommands` use `spawn` and `spawnMultiple` instead | ||
## v3.0.2 2015 March 17 | ||
- Will no longer attempt to read `stdout` and `stderr` on spawn if `stdio` option is set (it's not possible) | ||
- Will no longer attempt to read `stdout` and `stderr` on spawn if `stdio` option is set (it's not possible) | ||
## v3.0.1 2015 March 17 | ||
- Fixed Buffer concatenation error inside spawn | ||
- Fixed Buffer concatenation error inside spawn | ||
## v3.0.0 2015 March 17 | ||
- Backwards Compatibility Breaks: | ||
- `spawn`'s `stdout` and `stderr` are now Buffers | ||
- If you're upgrading, all you have to do to get the previous functionality is to do `stdout.toString()` | ||
- `outputPrefix` value no longer affects `stdout` and `stderr` results (only their output to the terminal) | ||
- Added: | ||
- `hasSpawnSync` | ||
- `hasExecSync` | ||
- `isExecutable(path, opts?, next)` | ||
- `isExecutableSync(path, opts?, next?)` | ||
- `spawnSync(command, opts?, next?)` | ||
- `execSync(command, opts?, next?)` | ||
- Improvements: | ||
- `exec` now supports `outputPrefix` option | ||
- The checks to see if an executable path exists and works have been greatly improved and abstracted out from `determineExecPath` into `isExecutable` and `isExecutableSync` | ||
- `determineExecPath`, `getExecPath`, and `isExecutable` can now operate synchronously with a callback using the `sync: true` option | ||
- Retrieval and writing to a path cache can now be disabled using the `cache: false` option | ||
- Updated dependencies | ||
- Backwards Compatibility Breaks: - `spawn`'s `stdout` and `stderr` are now Buffers - If you're upgrading, all you have to do to get the previous functionality is to do `stdout.toString()` - `outputPrefix` value no longer affects `stdout` and `stderr` results (only their output to the terminal) | ||
- Added: - `hasSpawnSync` - `hasExecSync` - `isExecutable(path, opts?, next)` - `isExecutableSync(path, opts?, next?)` - `spawnSync(command, opts?, next?)` - `execSync(command, opts?, next?)` | ||
- Improvements: - `exec` now supports `outputPrefix` option - The checks to see if an executable path exists and works have been greatly improved and abstracted out from `determineExecPath` into `isExecutable` and `isExecutableSync` - `determineExecPath`, `getExecPath`, and `isExecutable` can now operate synchronously with a callback using the `sync: true` option - Retrieval and writing to a path cache can now be disabled using the `cache: false` option | ||
- Updated dependencies | ||
## v2.2.13 2015 February 7 | ||
- Updated dependencies | ||
- Updated dependencies | ||
## v2.2.12 2014 May 21 | ||
- Fix `execMultiple` | ||
- Updated dependencies | ||
- Fix `execMultiple` | ||
- Updated dependencies | ||
## v2.2.11 2014 January 10 | ||
- Added `outputPrefix` option for `safeps.spawn` | ||
- Added `outputPrefix` option for `safeps.spawn` | ||
## v2.2.10 2013 December 27 | ||
- Updated dependencies | ||
- Updated dependencies | ||
## v2.2.9 2013 November 6 | ||
- Repackaged | ||
- Updated dependencies | ||
- Repackaged | ||
- Updated dependencies | ||
## v2.2.8 2013 September 16 | ||
- Fixed `Error: A task's completion callback has fired when the task was already in a completed state, this is unexpected` when an error occurs before close within a spawned process | ||
- Fixed `Error: A task's completion callback has fired when the task was already in a completed state, this is unexpected` when an error occurs before close within a spawned process | ||
## v2.2.7 2013 August 29 | ||
- Updated dependencies | ||
- Updated dependencies | ||
## v2.2.6 2013 June 29 | ||
- Added support for `.cmd` aliases on windows to `getPossibleExecPaths` | ||
- Added support for `.cmd` aliases on windows to `getPossibleExecPaths` | ||
## v2.2.5 2013 June 29 | ||
- Split out possible exec path functionality from `getExecPath` to `getPossibleExecPaths(execName?)` | ||
- Added support for `.bat` aliases on windows to `getPossibleExecPaths` | ||
- More efficient possible exec paths ordering when on windows | ||
- Split out possible exec path functionality from `getExecPath` to `getPossibleExecPaths(execName?)` | ||
- Added support for `.bat` aliases on windows to `getPossibleExecPaths` | ||
- More efficient possible exec paths ordering when on windows | ||
## v2.2.4 2013 June 25 | ||
- Repackaged | ||
- Repackaged | ||
## v2.2.3 2013 June 25 | ||
- `spawn` now works when `stdio` is set to `inherit` | ||
- `spawn` now works when `stdio` is set to `inherit` | ||
## v2.2.2 2013 June 24 | ||
- `determineExecPath` now works for processes that do not implement `--version` | ||
- `spawn` now won't crash on `EACCESS` errors | ||
- `determineExecPath` now works for processes that do not implement `--version` | ||
- `spawn` now won't crash on `EACCESS` errors | ||
## v2.2.1 2013 June 24 | ||
- `determinePossibleExecPath` is now more effecient | ||
- `getGitPath`, `getNodePath`, `getNpmPath` won't added `undefined` paths | ||
- `spawn` | ||
- now inherits our `process.env` by default, can be changed with `opts.env` | ||
- now sends `signal` and `code` in the completion callback correctly | ||
- now works | ||
- `getExecPath` | ||
- now caches the result | ||
- won't currupt absolute paths | ||
- will work with relative paths | ||
- `determinePossibleExecPath` is now more effecient | ||
- `getGitPath`, `getNodePath`, `getNpmPath` won't added `undefined` paths | ||
- `spawn` - now inherits our `process.env` by default, can be changed with `opts.env` - now sends `signal` and `code` in the completion callback correctly - now works | ||
- `getExecPath` - now caches the result - won't currupt absolute paths - will work with relative paths | ||
## v2.2.0 2013 June 24 | ||
- Split from [bal-util](https://github.com/balupton/bal-util) with these additional changes: | ||
- `spawn` is now safe rather than just `spawnCommand` | ||
- `spawn` now waits for `close` instead of `exit` | ||
- Thanks to Johny Jose for [balupton/bal-util#9](https://github.com/balupton/bal-util/pull/9) | ||
- `getEnvironmentPaths` now uses `require('path').delimiter` for seperation | ||
- `getStandardExecPaths` now uses `require('path').join` for joining `execName` to a possible path | ||
- `initGitRepo`, `initOrPullGitRepo` and `initNodeModules` now use `opts.cwd` instead of `opts.path` | ||
- Split from [bal-util](https://github.com/balupton/bal-util) with these additional changes: - `spawn` is now safe rather than just `spawnCommand` - `spawn` now waits for `close` instead of `exit` - Thanks to Johny Jose for [balupton/bal-util#9](https://github.com/balupton/bal-util/pull/9) - `getEnvironmentPaths` now uses `require('path').delimiter` for seperation - `getStandardExecPaths` now uses `require('path').join` for joining `execName` to a possible path - `initGitRepo`, `initOrPullGitRepo` and `initNodeModules` now use `opts.cwd` instead of `opts.path` |
@@ -1,5 +0,4 @@ | ||
// 2016 December 29 | ||
// https://github.com/bevry/editions | ||
'use strict' | ||
/** @type {typeof import("./source/index.js") } */ | ||
module.exports = require('editions').requirePackage(__dirname, require) |
@@ -19,3 +19,3 @@ <!-- LICENSEFILE/ --> | ||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software. | ||
@@ -22,0 +22,0 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
157
package.json
{ | ||
"title": "Safe PS", | ||
"name": "safeps", | ||
"version": "7.0.1", | ||
"version": "8.0.0-next.1573414430.53c4cd7b292d3b083ac24ef130e06e0c7a76ad1f", | ||
"description": "Work with processes safely and easily with Node.js", | ||
@@ -26,22 +26,26 @@ "homepage": "https://github.com/bevry/safeps", | ||
"patreon", | ||
"flattr", | ||
"liberapay", | ||
"buymeacoffee", | ||
"opencollective", | ||
"gratipay", | ||
"flattr", | ||
"crypto", | ||
"paypal", | ||
"bitcoin", | ||
"wishlist", | ||
"---", | ||
"slackin" | ||
"wishlist" | ||
], | ||
"config": { | ||
"buymeacoffeeUsername": "balupton", | ||
"cryptoURL": "https://bevry.me/crypto", | ||
"flattrUsername": "balupton", | ||
"liberapayUsername": "bevry", | ||
"opencollectiveUsername": "bevry", | ||
"patreonUsername": "bevry", | ||
"opencollectiveUsername": "bevry", | ||
"gratipayUsername": "bevry", | ||
"flattrUsername": "balupton", | ||
"paypalURL": "https://bevry.me/paypal", | ||
"bitcoinURL": "https://bevry.me/bitcoin", | ||
"wishlistURL": "https://bevry.me/wishlist", | ||
"slackinURL": "https://slack.bevry.me" | ||
"travisTLD": "com" | ||
} | ||
}, | ||
"funding": { | ||
"type": "cooperative", | ||
"url": "https://bevry.me/fund" | ||
}, | ||
"author": "2013+ Bevry Pty Ltd <us@bevry.me> (http://bevry.me), 2011-2012 Benjamin Lupton <b@lupton.cc> (http://balupton.com)", | ||
@@ -65,29 +69,31 @@ "maintainers": [ | ||
"engines": { | ||
"node": ">=0.8" | ||
"node": ">=0.10" | ||
}, | ||
"editions": [ | ||
{ | ||
"description": "Source + ESNext + Require", | ||
"description": "esnext source code with require for modules", | ||
"directory": "source", | ||
"entry": "index.js", | ||
"directory": "source", | ||
"syntaxes": [ | ||
"tags": [ | ||
"javascript", | ||
"esnext", | ||
"require", | ||
"let", | ||
"const", | ||
"destructuring", | ||
"shorthand", | ||
"template strings" | ||
] | ||
"require" | ||
], | ||
"engines": { | ||
"node": "6 || 8 || 10 || 12 || 13", | ||
"browsers": false | ||
} | ||
}, | ||
{ | ||
"description": "Babel Compiled + ES2015 + Require", | ||
"description": "esnext compiled for node.js 0.10 with require for modules", | ||
"directory": "edition-node-0.10", | ||
"entry": "index.js", | ||
"directory": "es2015", | ||
"syntaxes": [ | ||
"tags": [ | ||
"javascript", | ||
"es2015", | ||
"require" | ||
] | ||
], | ||
"engines": { | ||
"node": "0.10 || 0.12 || 4 || 6 || 8 || 10 || 12 || 13", | ||
"browsers": false | ||
} | ||
} | ||
@@ -97,40 +103,81 @@ ], | ||
"dependencies": { | ||
"editions": "^1.3.3", | ||
"editions": "^2.2.0", | ||
"extract-opts": "^3.3.1", | ||
"safefs": "^4.1.0", | ||
"taskgroup": "^5.0.0", | ||
"typechecker": "^4.3.0" | ||
"taskgroup": "^5.3.0", | ||
"typechecker": "^4.8.0" | ||
}, | ||
"devDependencies": { | ||
"assert-helpers": "^4.5.0", | ||
"babel-cli": "^6.24.1", | ||
"babel-preset-es2015": "^6.24.1", | ||
"documentation": "^4.0.0-beta.19", | ||
"eslint": "^3.19.0", | ||
"joe": "^2.0.2", | ||
"joe-reporter-console": "^2.0.1", | ||
"projectz": "^1.4.0", | ||
"surge": "^0.19.0" | ||
"@babel/cli": "^7.7.0", | ||
"@babel/core": "^7.7.2", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.6.2", | ||
"@babel/preset-env": "^7.7.1", | ||
"assert-helpers": "4.10.0", | ||
"bevry-echo": "^1.0.1", | ||
"eslint": "^6.6.0", | ||
"eslint-config-bevry": "^1.2.1", | ||
"eslint-config-prettier": "^6.5.0", | ||
"eslint-plugin-prettier": "^3.1.1", | ||
"jsdoc": "^3.6.3", | ||
"kava": "^3.1.0", | ||
"minami": "^1.2.3", | ||
"prettier": "^1.19.1", | ||
"projectz": "^1.9.0", | ||
"surge": "^0.21.3", | ||
"valid-directory": "^1.0.0" | ||
}, | ||
"scripts": { | ||
"our:setup": "npm run our:setup:npm", | ||
"our:setup:npm": "npm install", | ||
"our:clean": "rm -Rf ./docs ./es2015 ./es5 ./out", | ||
"our:compile": "npm run our:compile:es2015", | ||
"our:compile:es2015": "babel ./source --out-dir ./es2015 --presets es2015", | ||
"our:clean": "rm -Rf ./docs ./edition* ./es2015 ./es5 ./out ./.next", | ||
"our:compile": "npm run our:compile:edition-node-0.10", | ||
"our:compile:edition-node-0.10": "env BABEL_ENV=edition-node-0.10 babel --out-dir ./edition-node-0.10 ./source", | ||
"our:deploy": "echo no need for this project", | ||
"our:meta": "npm run our:meta:docs && npm run our:meta:projectz", | ||
"our:meta:docs": "documentation build -f html -o ./docs -g --shallow ./source/**.js", | ||
"our:meta:docs": "npm run our:meta:docs:jsdoc", | ||
"our:meta:docs:jsdoc": "rm -Rf ./docs && jsdoc --recurse --pedantic --access all --destination ./docs --package ./package.json --readme ./README.md --template ./node_modules/minami ./source && mv ./docs/$npm_package_name/$npm_package_version/* ./docs/ && rm -Rf ./docs/$npm_package_name/$npm_package_version", | ||
"our:meta:projectz": "projectz compile", | ||
"our:verify": "npm run our:verify:eslint", | ||
"our:verify:eslint": "eslint --fix ./source", | ||
"our:test": "npm run our:verify && npm test", | ||
"our:release": "npm run our:release:prepare && npm run our:release:check && npm run our:release:tag && npm run our:release:push", | ||
"our:release": "npm run our:release:prepare && npm run our:release:check-changelog && npm run our:release:check-dirty && npm run our:release:tag && npm run our:release:push", | ||
"our:release:check-changelog": "cat ./HISTORY.md | grep v$npm_package_version || (echo add a changelog entry for v$npm_package_version && exit -1)", | ||
"our:release:check-dirty": "git diff --exit-code", | ||
"our:release:prepare": "npm run our:clean && npm run our:compile && npm run our:test && npm run our:meta", | ||
"our:release:check": "npm run our:release:check:changelog && npm run our:release:check:dirty", | ||
"our:release:check:changelog": "cat ./HISTORY.md | grep v$npm_package_version || (echo add a changelog entry for v$npm_package_version && exit -1)", | ||
"our:release:check:dirty": "git diff --exit-code", | ||
"our:release:push": "git push origin master && git push origin --tags", | ||
"our:release:tag": "export MESSAGE=$(cat ./HISTORY.md | sed -n \"/## v$npm_package_version/,/##/p\" | sed 's/## //' | awk 'NR>1{print buf}{buf = $0}') && test \"$MESSAGE\" || (echo 'proper changelog entry not found' && exit -1) && git tag v$npm_package_version -am \"$MESSAGE\"", | ||
"our:release:push": "git push origin master && git push origin --tags", | ||
"test": "node --harmony ./test.js --joe-reporter=console" | ||
"our:setup": "npm run our:setup:install", | ||
"our:setup:install": "npm install", | ||
"our:test": "npm run our:verify && npm test", | ||
"our:verify": "npm run our:verify:directory && npm run our:verify:eslint && npm run our:verify:prettier", | ||
"our:verify:directory": "npx valid-directory", | ||
"our:verify:eslint": "eslint --fix --ignore-pattern '**/*.d.ts' --ignore-pattern '**/vendor/' --ignore-pattern '**/node_modules/' --ext .mjs,.js,.jsx,.ts,.tsx ./source", | ||
"our:verify:prettier": "prettier --write ./source/**", | ||
"test": "node ./test.js" | ||
}, | ||
"eslintConfig": { | ||
"extends": [ | ||
"bevry" | ||
] | ||
}, | ||
"prettier": { | ||
"semi": false, | ||
"singleQuote": true | ||
}, | ||
"babel": { | ||
"env": { | ||
"edition-node-0.10": { | ||
"sourceType": "script", | ||
"presets": [ | ||
[ | ||
"@babel/preset-env", | ||
{ | ||
"targets": { | ||
"node": "0.10" | ||
}, | ||
"modules": "commonjs" | ||
} | ||
] | ||
], | ||
"plugins": [ | ||
"@babel/proposal-object-rest-spread" | ||
] | ||
} | ||
} | ||
} | ||
} |
@@ -10,3 +10,3 @@ <!-- TITLE/ --> | ||
<span class="badge-travisci"><a href="http://travis-ci.org/bevry/safeps" title="Check this project's build status on TravisCI"><img src="https://img.shields.io/travis/bevry/safeps/master.svg" alt="Travis CI Build Status" /></a></span> | ||
<span class="badge-travisci"><a href="http://travis-ci.com/bevry/safeps" title="Check this project's build status on TravisCI"><img src="https://img.shields.io/travis/com/bevry/safeps/master.svg" alt="Travis CI Build Status" /></a></span> | ||
<span class="badge-npmversion"><a href="https://npmjs.org/package/safeps" title="View this project on NPM"><img src="https://img.shields.io/npm/v/safeps.svg" alt="NPM version" /></a></span> | ||
@@ -18,10 +18,9 @@ <span class="badge-npmdownloads"><a href="https://npmjs.org/package/safeps" title="View this project on NPM"><img src="https://img.shields.io/npm/dm/safeps.svg" alt="NPM downloads" /></a></span> | ||
<span class="badge-patreon"><a href="https://patreon.com/bevry" title="Donate to this project using Patreon"><img src="https://img.shields.io/badge/patreon-donate-yellow.svg" alt="Patreon donate button" /></a></span> | ||
<span class="badge-flattr"><a href="https://flattr.com/profile/balupton" title="Donate to this project using Flattr"><img src="https://img.shields.io/badge/flattr-donate-yellow.svg" alt="Flattr donate button" /></a></span> | ||
<span class="badge-liberapay"><a href="https://liberapay.com/bevry" title="Donate to this project using Liberapay"><img src="https://img.shields.io/badge/liberapay-donate-yellow.svg" alt="Liberapay donate button" /></a></span> | ||
<span class="badge-buymeacoffee"><a href="https://buymeacoffee.com/balupton" title="Donate to this project using Buy Me A Coffee"><img src="https://img.shields.io/badge/buy%20me%20a%20coffee-donate-yellow.svg" alt="Buy Me A Coffee donate button" /></a></span> | ||
<span class="badge-opencollective"><a href="https://opencollective.com/bevry" title="Donate to this project using Open Collective"><img src="https://img.shields.io/badge/open%20collective-donate-yellow.svg" alt="Open Collective donate button" /></a></span> | ||
<span class="badge-gratipay"><a href="https://www.gratipay.com/bevry" title="Donate weekly to this project using Gratipay"><img src="https://img.shields.io/badge/gratipay-donate-yellow.svg" alt="Gratipay donate button" /></a></span> | ||
<span class="badge-flattr"><a href="https://flattr.com/profile/balupton" title="Donate to this project using Flattr"><img src="https://img.shields.io/badge/flattr-donate-yellow.svg" alt="Flattr donate button" /></a></span> | ||
<span class="badge-crypto"><a href="https://bevry.me/crypto" title="Donate to this project using Cryptocurrency"><img src="https://img.shields.io/badge/crypto-donate-yellow.svg" alt="crypto donate button" /></a></span> | ||
<span class="badge-paypal"><a href="https://bevry.me/paypal" title="Donate to this project using Paypal"><img src="https://img.shields.io/badge/paypal-donate-yellow.svg" alt="PayPal donate button" /></a></span> | ||
<span class="badge-bitcoin"><a href="https://bevry.me/bitcoin" title="Donate once-off to this project using Bitcoin"><img src="https://img.shields.io/badge/bitcoin-donate-yellow.svg" alt="Bitcoin donate button" /></a></span> | ||
<span class="badge-wishlist"><a href="https://bevry.me/wishlist" title="Buy an item on our wishlist for us"><img src="https://img.shields.io/badge/wishlist-donate-yellow.svg" alt="Wishlist browse button" /></a></span> | ||
<br class="badge-separator" /> | ||
<span class="badge-slackin"><a href="https://slack.bevry.me" title="Join this project's slack community"><img src="https://slack.bevry.me/badge.svg" alt="Slack community badge" /></a></span> | ||
@@ -42,16 +41,28 @@ <!-- /BADGES --> | ||
<a href="https://npmjs.com" title="npm is a package manager for javascript"><h3>NPM</h3></a><ul> | ||
<a href="https://npmjs.com" title="npm is a package manager for javascript"><h3>npm</h3></a> | ||
<ul> | ||
<li>Install: <code>npm install --save safeps</code></li> | ||
<li>Module: <code>require('safeps')</code></li></ul> | ||
<li>Require: <code>require('safeps')</code></li> | ||
</ul> | ||
<h3><a href="https://github.com/bevry/editions" title="Editions are the best way to produce and consume packages you care about.">Editions</a></h3> | ||
<h3><a href="https://editions.bevry.me" title="Editions are the best way to produce and consume packages you care about.">Editions</a></h3> | ||
<p>This package is published with the following editions:</p> | ||
<ul><li><code>safeps</code> aliases <code>safeps/index.js</code> which uses <a href="https://github.com/bevry/editions" title="Editions are the best way to produce and consume packages you care about.">Editions</a> to automatically select the correct edition for the consumers environment</li> | ||
<li><code>safeps/source/index.js</code> is Source + <a href="https://babeljs.io/docs/learn-es2015/" title="ECMAScript Next">ESNext</a> + <a href="https://nodejs.org/dist/latest-v5.x/docs/api/modules.html" title="Node/CJS Modules">Require</a></li> | ||
<li><code>safeps/es2015/index.js</code> is <a href="https://babeljs.io" title="The compiler for writing next generation JavaScript">Babel</a> Compiled + <a href="http://babeljs.io/docs/plugins/preset-es2015/" title="ECMAScript 2015">ES2015</a> + <a href="https://nodejs.org/dist/latest-v5.x/docs/api/modules.html" title="Node/CJS Modules">Require</a></li></ul> | ||
<ul><li><code>safeps</code> aliases <code>safeps/index.js</code> which uses <a href="https://editions.bevry.me" title="Editions are the best way to produce and consume packages you care about.">Editions</a> to automatically select the correct edition for the consumers environment</li> | ||
<li><code>safeps/source/index.js</code> is esnext source code with require for modules</li> | ||
<li><code>safeps/edition-node-0.10/index.js</code> is esnext compiled for node.js 0.10 with require for modules</li></ul> | ||
<p>Older environments may need <a href="https://babeljs.io/docs/usage/polyfill/" title="A polyfill that emulates missing ECMAScript environment features">Babel's Polyfill</a> or something similar.</p> | ||
<h3><a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a></h3> | ||
This project provides its type information via inline <a href="http://usejsdoc.org" title="JSDoc is an API documentation generator for JavaScript, similar to Javadoc or phpDocumentor">JSDoc Comments</a>. To make use of this in <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a>, set your <code>maxNodeModuleJsDepth</code> compiler option to `5` or thereabouts. You can accomlish this via your `tsconfig.json` file like so: | ||
``` json | ||
{ | ||
"compilerOptions": { | ||
"maxNodeModuleJsDepth": 5 | ||
} | ||
} | ||
``` | ||
<!-- /INSTALL --> | ||
@@ -98,7 +109,8 @@ | ||
<span class="badge-patreon"><a href="https://patreon.com/bevry" title="Donate to this project using Patreon"><img src="https://img.shields.io/badge/patreon-donate-yellow.svg" alt="Patreon donate button" /></a></span> | ||
<span class="badge-flattr"><a href="https://flattr.com/profile/balupton" title="Donate to this project using Flattr"><img src="https://img.shields.io/badge/flattr-donate-yellow.svg" alt="Flattr donate button" /></a></span> | ||
<span class="badge-liberapay"><a href="https://liberapay.com/bevry" title="Donate to this project using Liberapay"><img src="https://img.shields.io/badge/liberapay-donate-yellow.svg" alt="Liberapay donate button" /></a></span> | ||
<span class="badge-buymeacoffee"><a href="https://buymeacoffee.com/balupton" title="Donate to this project using Buy Me A Coffee"><img src="https://img.shields.io/badge/buy%20me%20a%20coffee-donate-yellow.svg" alt="Buy Me A Coffee donate button" /></a></span> | ||
<span class="badge-opencollective"><a href="https://opencollective.com/bevry" title="Donate to this project using Open Collective"><img src="https://img.shields.io/badge/open%20collective-donate-yellow.svg" alt="Open Collective donate button" /></a></span> | ||
<span class="badge-gratipay"><a href="https://www.gratipay.com/bevry" title="Donate weekly to this project using Gratipay"><img src="https://img.shields.io/badge/gratipay-donate-yellow.svg" alt="Gratipay donate button" /></a></span> | ||
<span class="badge-flattr"><a href="https://flattr.com/profile/balupton" title="Donate to this project using Flattr"><img src="https://img.shields.io/badge/flattr-donate-yellow.svg" alt="Flattr donate button" /></a></span> | ||
<span class="badge-crypto"><a href="https://bevry.me/crypto" title="Donate to this project using Cryptocurrency"><img src="https://img.shields.io/badge/crypto-donate-yellow.svg" alt="crypto donate button" /></a></span> | ||
<span class="badge-paypal"><a href="https://bevry.me/paypal" title="Donate to this project using Paypal"><img src="https://img.shields.io/badge/paypal-donate-yellow.svg" alt="PayPal donate button" /></a></span> | ||
<span class="badge-bitcoin"><a href="https://bevry.me/bitcoin" title="Donate once-off to this project using Bitcoin"><img src="https://img.shields.io/badge/bitcoin-donate-yellow.svg" alt="Bitcoin donate button" /></a></span> | ||
<span class="badge-wishlist"><a href="https://bevry.me/wishlist" title="Buy an item on our wishlist for us"><img src="https://img.shields.io/badge/wishlist-donate-yellow.svg" alt="Wishlist browse button" /></a></span> | ||
@@ -105,0 +117,0 @@ |
1511
source/index.js
@@ -5,3 +5,3 @@ /* eslint no-sync:0 */ | ||
// Import | ||
const {TaskGroup} = require('taskgroup') | ||
const { TaskGroup } = require('taskgroup') | ||
const typeChecker = require('typechecker') | ||
@@ -17,3 +17,2 @@ const safefs = require('safefs') | ||
// ===================================== | ||
@@ -23,3 +22,3 @@ // Define Globals | ||
// Prepare | ||
if ( global.safepsGlobal == null ) { | ||
if (global.safepsGlobal == null) { | ||
global.safepsGlobal = {} | ||
@@ -30,5 +29,8 @@ } | ||
// Create a pool with the concurrency of our max number of open processes | ||
if ( global.safepsGlobal.pool == null ) { | ||
if (global.safepsGlobal.pool == null) { | ||
global.safepsGlobal.pool = new TaskGroup({ | ||
concurrency: process.env.NODE_MAX_OPEN_PROCESSES == null ? DEFAULT_MAX_OPEN_PROCESSES : process.env.NODE_MAX_OPEN_PROCESSES, | ||
concurrency: | ||
process.env.NODE_MAX_OPEN_PROCESSES == null | ||
? DEFAULT_MAX_OPEN_PROCESSES | ||
: process.env.NODE_MAX_OPEN_PROCESSES, | ||
abortOnError: false, | ||
@@ -39,3 +41,2 @@ destroyOnceDone: false | ||
// ===================================== | ||
@@ -45,16 +46,15 @@ // Define Module | ||
/** | ||
* Contains methods to safely spawn and manage | ||
* various file system processes. It differs | ||
* from the standard node.js child_process | ||
* module in that it intercepts and handles | ||
* many common errors that might occur when | ||
* invoking child processes that could cause | ||
* an application to crash. Most commonly, errors | ||
* such as ENOENT and EACCESS. This enables | ||
* an application to be both cleaner and more robust. | ||
* @class safeps | ||
* @static | ||
*/ | ||
* Contains methods to safely spawn and manage | ||
* various file system processes. It differs | ||
* from the standard node.js child_process | ||
* module in that it intercepts and handles | ||
* many common errors that might occur when | ||
* invoking child processes that could cause | ||
* an application to crash. Most commonly, errors | ||
* such as ENOENT and EACCESS. This enables | ||
* an application to be both cleaner and more robust. | ||
* @class safeps | ||
* @static | ||
*/ | ||
const safeps = { | ||
// ===================================== | ||
@@ -64,9 +64,9 @@ // Open and Close Processes | ||
/** | ||
* Open a file. | ||
* Pass your callback to fire when it is safe to open the process | ||
* @param {Function} fn callback | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
openProcess (fn) { | ||
* Open a file. | ||
* Pass your callback to fire when it is safe to open the process | ||
* @param {Function} fn callback | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
openProcess(fn) { | ||
// Add the task to the pool and execute it right away | ||
@@ -79,3 +79,2 @@ global.safepsGlobal.pool.addTask(fn) | ||
// ================================= | ||
@@ -86,6 +85,6 @@ // Environments | ||
/** | ||
* Returns whether or not we are running on a windows machine | ||
* @return {Boolean} | ||
*/ | ||
isWindows () { | ||
* Returns whether or not we are running on a windows machine | ||
* @return {Boolean} | ||
*/ | ||
isWindows() { | ||
return isWindows | ||
@@ -95,10 +94,14 @@ }, | ||
/** | ||
* Get locale code - eg: en-AU, | ||
* fr-FR, zh-CN etc. | ||
* @param {String} lang | ||
* @return {String} | ||
*/ | ||
getLocaleCode (lang) { | ||
* Get locale code - eg: en-AU, | ||
* fr-FR, zh-CN etc. | ||
* @param {String} lang | ||
* @return {String} | ||
*/ | ||
getLocaleCode(lang) { | ||
lang = lang || process.env.LANG || '' | ||
const localeCode = lang.replace(/\..+/, '').replace('-', '_').toLowerCase() || null | ||
const localeCode = | ||
lang | ||
.replace(/\..+/, '') | ||
.replace('-', '_') | ||
.toLowerCase() || null | ||
return localeCode | ||
@@ -108,10 +111,11 @@ }, | ||
/** | ||
* Given the localeCode, return | ||
* the language code. | ||
* @param {String} localeCode | ||
* @return {String} | ||
*/ | ||
getLanguageCode (localeCode) { | ||
* Given the localeCode, return | ||
* the language code. | ||
* @param {String} localeCode | ||
* @return {String} | ||
*/ | ||
getLanguageCode(localeCode) { | ||
localeCode = safeps.getLocaleCode(localeCode) || '' | ||
const languageCode = localeCode.replace(/^([a-z]+)[_-]([a-z]+)$/i, '$1').toLowerCase() || null | ||
const languageCode = | ||
localeCode.replace(/^([a-z]+)[_-]([a-z]+)$/i, '$1').toLowerCase() || null | ||
return languageCode | ||
@@ -121,14 +125,14 @@ }, | ||
/** | ||
* Given the localeCode, return | ||
* the country code. | ||
* @param {String} localeCode | ||
* @return {String} | ||
*/ | ||
getCountryCode (localeCode) { | ||
* Given the localeCode, return | ||
* the country code. | ||
* @param {String} localeCode | ||
* @return {String} | ||
*/ | ||
getCountryCode(localeCode) { | ||
localeCode = safeps.getLocaleCode(localeCode) || '' | ||
const countryCode = localeCode.replace(/^([a-z]+)[_-]([a-z]+)$/i, '$2').toLowerCase() || null | ||
const countryCode = | ||
localeCode.replace(/^([a-z]+)[_-]([a-z]+)$/i, '$2').toLowerCase() || null | ||
return countryCode | ||
}, | ||
// ================================= | ||
@@ -138,8 +142,8 @@ // Executeable Helpers | ||
/** | ||
* Has spawn sync. Returns true | ||
* if the child_process spawnSync | ||
* method exists, otherwise false | ||
* @return {Boolean} | ||
*/ | ||
hasSpawnSync () { | ||
* Has spawn sync. Returns true | ||
* if the child_process spawnSync | ||
* method exists, otherwise false | ||
* @return {Boolean} | ||
*/ | ||
hasSpawnSync() { | ||
return require('child_process').spawnSync != null | ||
@@ -149,8 +153,8 @@ }, | ||
/** | ||
* Has exec sync. Returns true | ||
* if the child_process execSync | ||
* method exists, otherwise false | ||
* @return {Boolean} | ||
*/ | ||
hasExecSync () { | ||
* Has exec sync. Returns true | ||
* if the child_process execSync | ||
* method exists, otherwise false | ||
* @return {Boolean} | ||
*/ | ||
hasExecSync() { | ||
return require('child_process').execSync != null | ||
@@ -160,12 +164,12 @@ }, | ||
/** | ||
* Is the path to a file object an executable? | ||
* Synchronised version of isExecutable | ||
* @param {String} path path to test | ||
* @param {Object} opts | ||
* @param {Function} [next] | ||
* @param {Error} next.err | ||
* @param {Boolean} next.isExecutable | ||
* @return {Boolean} | ||
*/ | ||
isExecutableSync (path, opts, next) { | ||
* Is the path to a file object an executable? | ||
* Synchronised version of isExecutable | ||
* @param {String} path path to test | ||
* @param {Object} opts | ||
* @param {Function} [next] | ||
* @param {Error} next.err | ||
* @param {Boolean} next.isExecutable | ||
* @return {Boolean} | ||
*/ | ||
isExecutableSync(path, opts, next) { | ||
// Prepare | ||
@@ -175,8 +179,7 @@ let isExecutable | ||
// Access (Node 0.12+) | ||
if ( fsUtil.accessSync ) { | ||
if (fsUtil.accessSync) { | ||
try { | ||
fsUtil.accessSync(path, fsUtil.X_OK) | ||
isExecutable = true | ||
} | ||
catch ( err ) { | ||
} catch (err) { | ||
isExecutable = false | ||
@@ -191,8 +194,9 @@ } | ||
isExecutable = true | ||
} | ||
catch ( err ) { | ||
} catch (err) { | ||
// If there was an error | ||
// determine if it was an error with trying to run it (not executable) | ||
// or an error from running it (executable) | ||
isExecutable = err.code !== 127 && (/EACCESS|Permission denied/).test(err.message) === false | ||
isExecutable = | ||
err.code !== 127 && | ||
/EACCESS|Permission denied/.test(err.message) === false | ||
} | ||
@@ -202,7 +206,6 @@ } | ||
// Return | ||
if ( next ) { | ||
if (next) { | ||
next(null, isExecutable) | ||
return safeps | ||
} | ||
else { | ||
} else { | ||
return isExecutable | ||
@@ -213,19 +216,19 @@ } | ||
/** | ||
* Is the path to a file object an executable? | ||
* Boolean result returned as the isExecutable parameter | ||
* of the passed callback. | ||
* @param {String} path path to test | ||
* @param {Object} [opts] | ||
* @param {Boolean} [opts.sync] true to test sync rather than async | ||
* @param {Function} next callback | ||
* @param {Error} next.err | ||
* @param {Boolean} next.isExecutable | ||
* @return {Boolean} returned if opts.sync = true | ||
*/ | ||
isExecutable (path, opts, next) { | ||
* Is the path to a file object an executable? | ||
* Boolean result returned as the isExecutable parameter | ||
* of the passed callback. | ||
* @param {String} path path to test | ||
* @param {Object} [opts] | ||
* @param {Boolean} [opts.sync] true to test sync rather than async | ||
* @param {Function} next callback | ||
* @param {Error} next.err | ||
* @param {Boolean} next.isExecutable | ||
* @return {Boolean} returned if opts.sync = true | ||
*/ | ||
isExecutable(path, opts, next) { | ||
// Prepare | ||
[opts, next] = extractOptsAndCallback(opts, next) | ||
;[opts, next] = extractOptsAndCallback(opts, next) | ||
// Sync? | ||
if ( opts.sync ) { | ||
if (opts.sync) { | ||
return safeps.isExecutableSync(path, opts, next) | ||
@@ -235,4 +238,4 @@ } | ||
// Access (Node 0.12+) | ||
if ( fsUtil.access ) { | ||
fsUtil.access(path, fsUtil.X_OK, function (err) { | ||
if (fsUtil.access) { | ||
fsUtil.access(path, fsUtil.X_OK, function(err) { | ||
const isExecutable = !err | ||
@@ -245,9 +248,11 @@ return next(null, isExecutable) | ||
else { | ||
require('child_process').exec(path + ' --version', function (err) { | ||
require('child_process').exec(path + ' --version', function(err) { | ||
// If there was no error, then execution worked fine, so we are executable | ||
if ( !err ) return next(null, true) | ||
if (!err) return next(null, true) | ||
// If there was an error | ||
// determine if it was an error with trying to run it (not executable) | ||
// or an error from running it (executable) | ||
const isExecutable = err.code !== 127 && (/EACCESS|Permission denied/).test(err.message) === false | ||
const isExecutable = | ||
err.code !== 127 && | ||
/EACCESS|Permission denied/.test(err.message) === false | ||
return next(null, isExecutable) | ||
@@ -262,15 +267,15 @@ }) | ||
/** | ||
* Internal: Prepare options for an execution. | ||
* Makes sure all options are populated or exist and | ||
* gives the opportunity to prepopulate some of those | ||
* options. | ||
* @access private | ||
* @param {Object} [opts] | ||
* @param {Stream} [opts.stdin=null] in stream | ||
* @param {Array} [opts.stdio=null] Child's stdio configuration | ||
* @param {Boolean} [opts.safe=true] | ||
* @param {Object} [opts.env=process.env] | ||
* @return {Object} opts | ||
*/ | ||
prepareExecutableOptions (opts) { | ||
* Internal: Prepare options for an execution. | ||
* Makes sure all options are populated or exist and | ||
* gives the opportunity to prepopulate some of those | ||
* options. | ||
* @access private | ||
* @param {Object} [opts] | ||
* @param {Stream} [opts.stdin=null] in stream | ||
* @param {Array} [opts.stdio=null] Child's stdio configuration | ||
* @param {Boolean} [opts.safe=true] | ||
* @param {Object} [opts.env=process.env] | ||
* @return {Object} opts | ||
*/ | ||
prepareExecutableOptions(opts) { | ||
// Prepare | ||
@@ -280,10 +285,10 @@ opts = opts || {} | ||
// Ensure all options exist | ||
if ( typeof opts.stdin === 'undefined' ) opts.stdin = null | ||
if ( typeof opts.stdio === 'undefined' ) opts.stdio = null | ||
if (typeof opts.stdin === 'undefined') opts.stdin = null | ||
if (typeof opts.stdio === 'undefined') opts.stdio = null | ||
// By default make sure execution is valid | ||
if ( opts.safe == null ) opts.safe = true | ||
if (opts.safe == null) opts.safe = true | ||
// If a direct pipe then don't do output modifiers | ||
if ( opts.stdio ) { | ||
if (opts.stdio) { | ||
opts.read = opts.output = false | ||
@@ -295,13 +300,13 @@ opts.outputPrefix = null | ||
else { | ||
if ( opts.read == null ) opts.read = true | ||
if ( opts.output == null ) opts.output = Boolean(opts.outputPrefix) | ||
if ( opts.outputPrefix == null ) opts.outputPrefix = null | ||
if (opts.read == null) opts.read = true | ||
if (opts.output == null) opts.output = Boolean(opts.outputPrefix) | ||
if (opts.outputPrefix == null) opts.outputPrefix = null | ||
} | ||
// By default inherit environment variables | ||
if ( opts.env == null ) { | ||
if (opts.env == null) { | ||
opts.env = process.env | ||
} | ||
// If we don't want to inherit environment variables, then don't | ||
else if ( opts.env === false ) { | ||
else if (opts.env === false) { | ||
opts.env = null | ||
@@ -315,20 +320,20 @@ } | ||
/** | ||
* Internal: Prepare result of an execution | ||
* @access private | ||
* @param {Object} result | ||
* @param {Object} result.pid Number Pid of the child process | ||
* @param {Object} result.output output Array Array of results from stdio output | ||
* @param {Stream} result.stdout stdout The contents of output | ||
* @param {Stream} result.stderr stderr The contents of output | ||
* @param {Number} result.status status The exit code of the child process | ||
* @param {String} result.signal signal The signal used to kill the child process | ||
* @param {Error} result.error The error object if the child process failed or timed out | ||
* @param {Object} [opts] | ||
* @param {Object} [opts.output] | ||
* @param {Object} [opts.outputPrefix] | ||
* @return {Object} result | ||
*/ | ||
updateExecutableResult (result, opts) { | ||
* Internal: Prepare result of an execution | ||
* @access private | ||
* @param {Object} result | ||
* @param {Object} result.pid Number Pid of the child process | ||
* @param {Object} result.output output Array Array of results from stdio output | ||
* @param {Stream} result.stdout stdout The contents of output | ||
* @param {Stream} result.stderr stderr The contents of output | ||
* @param {Number} result.status status The exit code of the child process | ||
* @param {String} result.signal signal The signal used to kill the child process | ||
* @param {Error} result.error The error object if the child process failed or timed out | ||
* @param {Object} [opts] | ||
* @param {Object} [opts.output] | ||
* @param {Object} [opts.outputPrefix] | ||
* @return {Object} result | ||
*/ | ||
updateExecutableResult(result, opts) { | ||
// If we want to output, then output the correct streams with the correct prefixes | ||
if ( opts.output ) { | ||
if (opts.output) { | ||
safeps.outputData(result.stdout, 'stdout', opts.outputPrefix) | ||
@@ -339,3 +344,3 @@ safeps.outputData(result.stderr, 'stderr', opts.outputPrefix) | ||
// If we already have an error, then don't continue | ||
if ( result.error ) { | ||
if (result.error) { | ||
return result | ||
@@ -346,3 +351,3 @@ } | ||
// Check if the status code exists, and if it is not zero, zero is the success code | ||
if ( result.status != null && result.status !== 0 ) { | ||
if (result.status != null && result.status !== 0) { | ||
let message = 'Command exited with a non-zero status code.' | ||
@@ -352,5 +357,5 @@ | ||
// we should output the stdout if we have it | ||
if ( result.stdout ) { | ||
if (result.stdout) { | ||
const tmp = safeps.prefixData(result.stdout) | ||
if ( tmp ) { | ||
if (tmp) { | ||
message += "\nThe command's stdout output:\n" + tmp | ||
@@ -360,5 +365,5 @@ } | ||
// and output the stderr if we have it | ||
if ( result.stderr ) { | ||
if (result.stderr) { | ||
const tmp = safeps.prefixData(result.stderr) | ||
if ( tmp ) { | ||
if (tmp) { | ||
message += "\nThe command's stderr output:\n" + tmp | ||
@@ -377,13 +382,12 @@ } | ||
/** | ||
* Internal: prefix data | ||
* @access private | ||
* @param {Object} data | ||
* @param {String} [prefix = '>\t'] | ||
* @return {Object} data | ||
*/ | ||
prefixData (data, prefix = '>\t') { | ||
* Internal: prefix data | ||
* @access private | ||
* @param {Object} data | ||
* @param {String} [prefix = '>\t'] | ||
* @return {Object} data | ||
*/ | ||
prefixData(data, prefix = '>\t') { | ||
data = (data && data.toString && data.toString()) || '' | ||
if ( prefix && data ) { | ||
if (prefix && data) { | ||
data = prefix + data.trim().replace(/\n/g, '\n' + prefix) + '\n' | ||
@@ -395,13 +399,13 @@ } | ||
/** | ||
* Internal: Set output data | ||
* @access private | ||
* @param {Object} data | ||
* @param {Object} [channel = 'stdout'] | ||
* @param {Object} prefix | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
outputData (data, channel = 'stdout', prefix) { | ||
if ( data.toString().trim().length !== 0 ) { | ||
if ( prefix ) { | ||
* Internal: Set output data | ||
* @access private | ||
* @param {Object} data | ||
* @param {Object} [channel = 'stdout'] | ||
* @param {Object} prefix | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
outputData(data, channel = 'stdout', prefix) { | ||
if (data.toString().trim().length !== 0) { | ||
if (prefix) { | ||
data = safeps.prefixData(data, prefix) | ||
@@ -414,3 +418,2 @@ } | ||
// ================================= | ||
@@ -420,47 +423,47 @@ // Spawn | ||
/** | ||
* Syncronised version of safeps.spawn. Will not return until the | ||
* child process has fully closed. Results can be returned | ||
* from the method call or via a passed callback. Even if | ||
* a callback is passed to spawnSync, the method will still | ||
* be syncronised with the child process and the callback will | ||
* only return after the child process has closed. | ||
* | ||
* Simple usage example: | ||
* | ||
* var safeps = require('safeps'); | ||
* var command = ['npm', 'install', 'jade', '--save']; | ||
* | ||
* //a lot of the time you won't need the opts argument | ||
* var opts = { | ||
* cwd: __dirname //this is actually pointless in a real application | ||
* }; | ||
* | ||
* var result = safeps.spawnSync(command, opts); | ||
* | ||
* console.log(result.error); | ||
* console.log(result.status); | ||
* console.log(result.signal); | ||
* console.log("I've finished..."); | ||
* | ||
* @param {Array|String} command | ||
* @param {Object} [opts] | ||
* @param {Boolean} [opts.safe] Whether to check the executable path. | ||
* @param {String} [opts.cwd] Current working directory of the child process | ||
* @param {Array|String} [opts.stdio] Child's stdio configuration. | ||
* @param {Array} [opts.customFds] Deprecated File descriptors for the child to use for stdio. | ||
* @param {Object} [opts.env] Environment key-value pairs. | ||
* @param {Boolean} [opts.detached] The child will be a process group leader. | ||
* @param {Number} [opts.uid] Sets the user identity of the process. | ||
* @param {Number} [opts.gid] Sets the group identity of the process | ||
* @param {Function} [next] callback | ||
* @param {Error} next.error | ||
* @param {Stream} next.stdout out stream | ||
* @param {Stream} next.stderr error stream | ||
* @param {Number} next.status node.js exit code | ||
* @param {String} next.signal unix style signal such as SIGKILL or SIGHUP | ||
* @return {Object} {error, pid, output, stdout, stderr, status, signal} | ||
*/ | ||
spawnSync (command, opts, next) { | ||
* Syncronised version of safeps.spawn. Will not return until the | ||
* child process has fully closed. Results can be returned | ||
* from the method call or via a passed callback. Even if | ||
* a callback is passed to spawnSync, the method will still | ||
* be syncronised with the child process and the callback will | ||
* only return after the child process has closed. | ||
* | ||
* Simple usage example: | ||
* | ||
* var safeps = require('safeps'); | ||
* var command = ['npm', 'install', 'jade', '--save']; | ||
* | ||
* //a lot of the time you won't need the opts argument | ||
* var opts = { | ||
* cwd: __dirname //this is actually pointless in a real application | ||
* }; | ||
* | ||
* var result = safeps.spawnSync(command, opts); | ||
* | ||
* console.log(result.error); | ||
* console.log(result.status); | ||
* console.log(result.signal); | ||
* console.log("I've finished..."); | ||
* | ||
* @param {Array|String} command | ||
* @param {Object} [opts] | ||
* @param {Boolean} [opts.safe] Whether to check the executable path. | ||
* @param {String} [opts.cwd] Current working directory of the child process | ||
* @param {Array|String} [opts.stdio] Child's stdio configuration. | ||
* @param {Array} [opts.customFds] Deprecated File descriptors for the child to use for stdio. | ||
* @param {Object} [opts.env] Environment key-value pairs. | ||
* @param {Boolean} [opts.detached] The child will be a process group leader. | ||
* @param {Number} [opts.uid] Sets the user identity of the process. | ||
* @param {Number} [opts.gid] Sets the group identity of the process | ||
* @param {Function} [next] callback | ||
* @param {Error} next.error | ||
* @param {Stream} next.stdout out stream | ||
* @param {Stream} next.stderr error stream | ||
* @param {Number} next.status node.js exit code | ||
* @param {String} next.signal unix style signal such as SIGKILL or SIGHUP | ||
* @return {Object} {error, pid, output, stdout, stderr, status, signal} | ||
*/ | ||
spawnSync(command, opts, next) { | ||
// Prepare | ||
[opts, next] = extractOptsAndCallback(opts, next) | ||
;[opts, next] = extractOptsAndCallback(opts, next) | ||
opts = safeps.prepareExecutableOptions(opts) | ||
@@ -470,3 +473,3 @@ opts.sync = true | ||
// If the command is a string, then convert it into an array | ||
if ( typeChecker.isString(command) ) { | ||
if (typeChecker.isString(command)) { | ||
command = command.split(' ') | ||
@@ -478,11 +481,13 @@ } | ||
// Otherwise, don't worry about it and output a warning to stderr | ||
if ( opts.safe ) { | ||
if (opts.safe) { | ||
let wasSync = 0 | ||
safeps.getExecPath(command[0], opts, function (err, execPath) { | ||
if ( err ) return | ||
safeps.getExecPath(command[0], opts, function(err, execPath) { | ||
if (err) return | ||
command[0] = execPath | ||
wasSync = 1 | ||
}) | ||
if ( wasSync === 0 ) { | ||
process.stderr.write('safeps.spawnSync: was unable to get the executable path synchronously') | ||
if (wasSync === 0) { | ||
process.stderr.write( | ||
'safeps.spawnSync: was unable to get the executable path synchronously' | ||
) | ||
} | ||
@@ -492,10 +497,19 @@ } | ||
// Spawn Synchronously | ||
const result = require('child_process').spawnSync(command[0], command.slice(1), opts) | ||
const result = require('child_process').spawnSync( | ||
command[0], | ||
command.slice(1), | ||
opts | ||
) | ||
safeps.updateExecutableResult(result, opts) | ||
// Complete | ||
if ( next ) { | ||
next(result.error, result.stdout, result.stderr, result.status, result.signal) | ||
} | ||
else { | ||
if (next) { | ||
next( | ||
result.error, | ||
result.stdout, | ||
result.stderr, | ||
result.status, | ||
result.signal | ||
) | ||
} else { | ||
return result | ||
@@ -506,51 +520,51 @@ } | ||
/** | ||
* Wrapper around node's spawn command for a cleaner, more robust and powerful API. | ||
* Launches a new process with the given command. Command line arguments are | ||
* part of the command parameter (unlike the node.js spawn). Command can be | ||
* an array of command line arguments or a command line string. Opts allows | ||
* additional options to be sent to the spawning action. | ||
* | ||
* Simple usage example: | ||
* | ||
* var safeps = require('safeps'); | ||
* var command = ['npm', 'install','jade','--save']; | ||
* | ||
* //a lot of the time you won't need the opts argument | ||
* var opts = { | ||
* cwd: __dirname //this is actually pointless in a real application | ||
* } | ||
* function myCallback(error, stdout, stderr, status, signal){ | ||
* console.log(error); | ||
* console.log(status); | ||
* console.log(signal); | ||
* console.log("I've finished..."); | ||
* } | ||
* safeps.spawn(command, opts, myCallback); | ||
* | ||
* @param {Array|String} command | ||
* @param {Object} [opts] | ||
* @param {Boolean} [opts.safe] Whether to check the executable path. | ||
* @param {String} [opts.cwd] Current working directory of the child process | ||
* @param {Array|String} [opts.stdio] Child's stdio configuration. | ||
* @param {Array} [opts.customFds] Deprecated File descriptors for the child to use for stdio. | ||
* @param {Object} [opts.env] Environment key-value pairs. | ||
* @param {Boolean} [opts.detached] The child will be a process group leader. | ||
* @param {Number} [opts.uid] Sets the user identity of the process. | ||
* @param {Number} [opts.gid] Sets the group identity of the process. | ||
* @param {Function} next callback | ||
* @param {Error} next.error | ||
* @param {Stream} next.stdout out stream | ||
* @param {Stream} next.stderr error stream | ||
* @param {Number} next.status node.js exit code | ||
* @param {String} next.signal unix style signal such as SIGKILL or SIGHUP | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
spawn (command, opts, next) { | ||
* Wrapper around node's spawn command for a cleaner, more robust and powerful API. | ||
* Launches a new process with the given command. Command line arguments are | ||
* part of the command parameter (unlike the node.js spawn). Command can be | ||
* an array of command line arguments or a command line string. Opts allows | ||
* additional options to be sent to the spawning action. | ||
* | ||
* Simple usage example: | ||
* | ||
* var safeps = require('safeps'); | ||
* var command = ['npm', 'install','jade','--save']; | ||
* | ||
* //a lot of the time you won't need the opts argument | ||
* var opts = { | ||
* cwd: __dirname //this is actually pointless in a real application | ||
* } | ||
* function myCallback(error, stdout, stderr, status, signal){ | ||
* console.log(error); | ||
* console.log(status); | ||
* console.log(signal); | ||
* console.log("I've finished..."); | ||
* } | ||
* safeps.spawn(command, opts, myCallback); | ||
* | ||
* @param {Array|String} command | ||
* @param {Object} [opts] | ||
* @param {Boolean} [opts.safe] Whether to check the executable path. | ||
* @param {String} [opts.cwd] Current working directory of the child process | ||
* @param {Array|String} [opts.stdio] Child's stdio configuration. | ||
* @param {Array} [opts.customFds] Deprecated File descriptors for the child to use for stdio. | ||
* @param {Object} [opts.env] Environment key-value pairs. | ||
* @param {Boolean} [opts.detached] The child will be a process group leader. | ||
* @param {Number} [opts.uid] Sets the user identity of the process. | ||
* @param {Number} [opts.gid] Sets the group identity of the process. | ||
* @param {Function} next callback | ||
* @param {Error} next.error | ||
* @param {Stream} next.stdout out stream | ||
* @param {Stream} next.stderr error stream | ||
* @param {Number} next.status node.js exit code | ||
* @param {String} next.signal unix style signal such as SIGKILL or SIGHUP | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
spawn(command, opts, next) { | ||
// Prepare | ||
[opts, next] = extractOptsAndCallback(opts, next) | ||
;[opts, next] = extractOptsAndCallback(opts, next) | ||
opts = safeps.prepareExecutableOptions(opts) | ||
// Check if we want sync instead | ||
if ( opts.sync ) { | ||
if (opts.sync) { | ||
return safeps.spawnSync(command, opts, next) | ||
@@ -560,5 +574,5 @@ } | ||
// Patience | ||
safeps.openProcess(function (closeProcess) { | ||
safeps.openProcess(function(closeProcess) { | ||
// If the command is a string, then convert it into an array | ||
if ( typeChecker.isString(command) ) { | ||
if (typeChecker.isString(command)) { | ||
command = command.split(' ') | ||
@@ -580,13 +594,19 @@ } | ||
// Tasks | ||
const tasks = new TaskGroup().done(function (err) { | ||
const tasks = new TaskGroup().done(function(err) { | ||
exited = true | ||
closeProcess() | ||
next(err || result.error, result.stdout, result.stderr, result.status, result.signal) | ||
next( | ||
err || result.error, | ||
result.stdout, | ||
result.stderr, | ||
result.status, | ||
result.signal | ||
) | ||
}) | ||
// Get correct executable path | ||
if ( opts.safe ) { | ||
tasks.addTask(function (complete) { | ||
safeps.getExecPath(command[0], opts, function (err, execPath) { | ||
if ( err ) return complete(err) | ||
if (opts.safe) { | ||
tasks.addTask(function(complete) { | ||
safeps.getExecPath(command[0], opts, function(err, execPath) { | ||
if (err) return complete(err) | ||
command[0] = execPath | ||
@@ -599,9 +619,13 @@ complete() | ||
// Spawn | ||
tasks.addTask(function (complete) { | ||
tasks.addTask(function(complete) { | ||
// Spawn | ||
result.pid = require('child_process').spawn(command[0], command.slice(1), opts) | ||
result.pid = require('child_process').spawn( | ||
command[0], | ||
command.slice(1), | ||
opts | ||
) | ||
// Write if we want to | ||
// result.pid.stdin may be null of stdio is 'inherit' | ||
if ( opts.stdin && result.pid.stdin) { | ||
if (opts.stdin && result.pid.stdin) { | ||
result.pid.stdin.write(opts.stdin) | ||
@@ -612,13 +636,12 @@ result.pid.stdin.end() | ||
// Read if we want to by listening to the streams and updating our result variables | ||
if ( opts.read ) { | ||
if (opts.read) { | ||
// result.pid.stdout may be null of stdio is 'inherit' | ||
if ( result.pid.stdout ) { | ||
result.pid.stdout.on('data', function (data) { | ||
if ( opts.output ) { | ||
if (result.pid.stdout) { | ||
result.pid.stdout.on('data', function(data) { | ||
if (opts.output) { | ||
safeps.outputData(data, 'stdout', opts.outputPrefix) | ||
} | ||
if ( result.stdout ) { | ||
if (result.stdout) { | ||
result.stdout = Buffer.concat([result.stdout, data]) | ||
} | ||
else { | ||
} else { | ||
result.stdout = data | ||
@@ -630,11 +653,10 @@ } | ||
// result.pid.stderr may be null of stdio is 'inherit' | ||
if ( result.pid.stderr ) { | ||
result.pid.stderr.on('data', function (data) { | ||
if ( opts.output) { | ||
if (result.pid.stderr) { | ||
result.pid.stderr.on('data', function(data) { | ||
if (opts.output) { | ||
safeps.outputData(data, 'stderr', opts.outputPrefix) | ||
} | ||
if ( result.stderr ) { | ||
if (result.stderr) { | ||
result.stderr = Buffer.concat([result.stderr, data]) | ||
} | ||
else { | ||
} else { | ||
result.stderr = data | ||
@@ -647,3 +669,3 @@ } | ||
// Wait | ||
result.pid.on('close', function (status, signal) { | ||
result.pid.on('close', function(status, signal) { | ||
// Apply to local global | ||
@@ -658,3 +680,3 @@ result.status = status | ||
// if it happens the other way round, close, then error, we want to be alerted of that | ||
if ( exited === true ) return | ||
if (exited === true) return | ||
@@ -677,44 +699,46 @@ // Check result and complete | ||
/** | ||
* Spawn multiple processes in the one method call. | ||
* Launches new processes with the given array of commands. | ||
* Each item in the commands array represents a command parameter | ||
* sent to the safeps.spawn method, so each item can be a command line | ||
* string or an array of command line inputs. It is also possible | ||
* to pass a single command string and in this case calling | ||
* spawnMultiple will be effectively the same as calling safeps.spawn. | ||
* @param {Array|String} commands | ||
* @param {Object} [opts] | ||
* @param {Boolean} [opts.concurrency=1] Whether to spawn processes concurrently. | ||
* @param {String} opts.cwd Current working directory of the child process. | ||
* @param {Array|String} opts.stdio Child's stdio configuration. | ||
* @param {Array} opts.customFds Deprecated File descriptors for the child to use for stdio. | ||
* @param {Object} opts.env Environment key-value pairs. | ||
* @param {Boolean} opts.detached The child will be a process group leader. | ||
* @param {Number} opts.uid Sets the user identity of the process. | ||
* @param {Number} opts.gid Sets the group identity of the process. | ||
* @param {Function} next callback | ||
* @param {Error} next.error | ||
* @param {Array} next.results array of spawn results | ||
* @param {Stream} next.results[i].stdout out stream | ||
* @param {Stream} next.results[i].stderr error stream | ||
* @param {Number} next.results[i].status node.js exit code | ||
* @param {String} next.results[i].signal unix style signal such as SIGKILL or SIGHUP | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
spawnMultiple (commands, opts, next) { | ||
* Spawn multiple processes in the one method call. | ||
* Launches new processes with the given array of commands. | ||
* Each item in the commands array represents a command parameter | ||
* sent to the safeps.spawn method, so each item can be a command line | ||
* string or an array of command line inputs. It is also possible | ||
* to pass a single command string and in this case calling | ||
* spawnMultiple will be effectively the same as calling safeps.spawn. | ||
* @param {Array|String} commands | ||
* @param {Object} [opts] | ||
* @param {Boolean} [opts.concurrency=1] Whether to spawn processes concurrently. | ||
* @param {String} opts.cwd Current working directory of the child process. | ||
* @param {Array|String} opts.stdio Child's stdio configuration. | ||
* @param {Array} opts.customFds Deprecated File descriptors for the child to use for stdio. | ||
* @param {Object} opts.env Environment key-value pairs. | ||
* @param {Boolean} opts.detached The child will be a process group leader. | ||
* @param {Number} opts.uid Sets the user identity of the process. | ||
* @param {Number} opts.gid Sets the group identity of the process. | ||
* @param {Function} next callback | ||
* @param {Error} next.error | ||
* @param {Array} next.results array of spawn results | ||
* @param {Stream} next.results[i].stdout out stream | ||
* @param {Stream} next.results[i].stderr error stream | ||
* @param {Number} next.results[i].status node.js exit code | ||
* @param {String} next.results[i].signal unix style signal such as SIGKILL or SIGHUP | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
spawnMultiple(commands, opts, next) { | ||
// Prepare | ||
[opts, next] = extractOptsAndCallback(opts, next) | ||
;[opts, next] = extractOptsAndCallback(opts, next) | ||
const results = [] | ||
// Be synchronous by default | ||
if ( opts.concurrency == null ) opts.concurrency = 1 | ||
if (opts.concurrency == null) opts.concurrency = 1 | ||
// Make sure we send back the arguments | ||
const tasks = new TaskGroup({concurrency: opts.concurrency}).done(function (err) { | ||
next(err, results) | ||
}) | ||
const tasks = new TaskGroup({ concurrency: opts.concurrency }).done( | ||
function(err) { | ||
next(err, results) | ||
} | ||
) | ||
// Prepare tasks | ||
if ( !typeChecker.isArray(commands) ) { | ||
if (!typeChecker.isArray(commands)) { | ||
commands = [commands] | ||
@@ -724,5 +748,5 @@ } | ||
// Add tasks | ||
commands.forEach(function (command) { | ||
tasks.addTask(function (complete) { | ||
safeps.spawn(command, opts, function (...args) { | ||
commands.forEach(function(command) { | ||
tasks.addTask(function(complete) { | ||
safeps.spawn(command, opts, function(...args) { | ||
const err = args[0] || null | ||
@@ -742,3 +766,2 @@ results.push(args) | ||
// ================================= | ||
@@ -748,34 +771,34 @@ // Exec | ||
/** | ||
* Syncronised version of safeps.exec. Runs a command in a shell and | ||
* buffers the output. Will not return until the | ||
* child process has fully closed. Results can be returned | ||
* from the method call or via a passed callback. Even if | ||
* a callback is passed to execSync, the method will still | ||
* be syncronised with the child process and the callback will | ||
* only return after the child process has closed. | ||
* Note: | ||
* Stdout and stderr should be Buffers but they are strings unless encoding:null | ||
* for now, nothing we should do, besides wait for joyent to reply | ||
* https://github.com/joyent/node/issues/5833#issuecomment-82189525. | ||
* @param {Object} command | ||
* @param {Object} [opts] | ||
* @param {Boolean} [opts.sync] true to execute sync rather than async | ||
* @param {String} [opts.cwd] Current working directory of the child process | ||
* @param {Object} [opts.env] Environment key-value pairs | ||
* @param {String} [opts.encoding='utf8'] | ||
* @param {String} [opts.shell] Shell to execute the command with (Default: '/bin/sh' on UNIX, 'cmd.exe' on Windows, The shell should understand the -c switch on UNIX or /s /c on Windows. On Windows, command line parsing should be compatible with cmd.exe.) | ||
* @param {Number} [opts.timeout=0] | ||
* @param {Number} [opts.maxBuffer=200*1024] Largest amount of data (in bytes) allowed on stdout or stderr - if exceeded child process is killed. | ||
* @param {String} [opts.killSignal='SIGTERM'] | ||
* @param {Number} [opts.uid] Sets the user identity of the process. | ||
* @param {Number} [opts.gid] Sets the group identity of the process. | ||
* @param {Function} next | ||
* @param {Error} next.err | ||
* @param {Buffer|String} next.stdout out buffer | ||
* @param {Buffer|String} next.stderr error buffer | ||
* @return {Object} {error, stdout, stderr} | ||
*/ | ||
execSync (command, opts, next) { | ||
* Syncronised version of safeps.exec. Runs a command in a shell and | ||
* buffers the output. Will not return until the | ||
* child process has fully closed. Results can be returned | ||
* from the method call or via a passed callback. Even if | ||
* a callback is passed to execSync, the method will still | ||
* be syncronised with the child process and the callback will | ||
* only return after the child process has closed. | ||
* Note: | ||
* Stdout and stderr should be Buffers but they are strings unless encoding:null | ||
* for now, nothing we should do, besides wait for joyent to reply | ||
* https://github.com/joyent/node/issues/5833#issuecomment-82189525. | ||
* @param {Object} command | ||
* @param {Object} [opts] | ||
* @param {Boolean} [opts.sync] true to execute sync rather than async | ||
* @param {String} [opts.cwd] Current working directory of the child process | ||
* @param {Object} [opts.env] Environment key-value pairs | ||
* @param {String} [opts.encoding='utf8'] | ||
* @param {String} [opts.shell] Shell to execute the command with (Default: '/bin/sh' on UNIX, 'cmd.exe' on Windows, The shell should understand the -c switch on UNIX or /s /c on Windows. On Windows, command line parsing should be compatible with cmd.exe.) | ||
* @param {Number} [opts.timeout=0] | ||
* @param {Number} [opts.maxBuffer=200*1024] Largest amount of data (in bytes) allowed on stdout or stderr - if exceeded child process is killed. | ||
* @param {String} [opts.killSignal='SIGTERM'] | ||
* @param {Number} [opts.uid] Sets the user identity of the process. | ||
* @param {Number} [opts.gid] Sets the group identity of the process. | ||
* @param {Function} next | ||
* @param {Error} next.err | ||
* @param {Buffer|String} next.stdout out buffer | ||
* @param {Buffer|String} next.stderr error buffer | ||
* @return {Object} {error, stdout, stderr} | ||
*/ | ||
execSync(command, opts, next) { | ||
// Prepare | ||
[opts, next] = extractOptsAndCallback(opts, next) | ||
;[opts, next] = extractOptsAndCallback(opts, next) | ||
opts = safeps.prepareExecutableOptions(opts) | ||
@@ -785,3 +808,3 @@ opts.sync = true | ||
// Output | ||
if ( opts.output === true && !opts.outputPrefix ) { | ||
if (opts.output === true && !opts.outputPrefix) { | ||
opts.stdio = 'inherit' | ||
@@ -795,4 +818,3 @@ opts.output = null | ||
stdout = require('child_process').execSync(command, opts) | ||
} | ||
catch ( err ) { | ||
} catch (err) { | ||
error = err | ||
@@ -802,10 +824,9 @@ } | ||
// Check result | ||
const result = {error, stdout} | ||
const result = { error, stdout } | ||
safeps.updateExecutableResult(result, opts) | ||
// Complete | ||
if ( next ) { | ||
if (next) { | ||
next(result.error, result.stdout, result.stderr) | ||
} | ||
else { | ||
} else { | ||
return result | ||
@@ -816,34 +837,34 @@ } | ||
/** | ||
* Wrapper around node's exec command for a cleaner, more robust and powerful API. | ||
* Runs a command in a shell and buffers the output. | ||
* Note: | ||
* Stdout and stderr should be Buffers but they are strings unless encoding:null | ||
* for now, nothing we should do, besides wait for joyent to reply | ||
* https://github.com/joyent/node/issues/5833#issuecomment-82189525. | ||
* @param {Object} command | ||
* @param {Object} [opts] | ||
* @param {Boolean} [opts.sync] true to execute sync rather than async | ||
* @param {String} [opts.cwd] Current working directory of the child process | ||
* @param {Object} [opts.env] Environment key-value pairs | ||
* @param {String} [opts.encoding='utf8'] | ||
* @param {String} [opts.shell] Shell to execute the command with (Default: '/bin/sh' on UNIX, 'cmd.exe' on Windows, The shell should understand the -c switch on UNIX or /s /c on Windows. On Windows, command line parsing should be compatible with cmd.exe.) | ||
* @param {Number} [opts.timeout=0] | ||
* @param {Number} [opts.maxBuffer=200*1024] Largest amount of data (in bytes) allowed on stdout or stderr - if exceeded child process is killed. | ||
* @param {String} [opts.killSignal='SIGTERM'] | ||
* @param {Number} [opts.uid] Sets the user identity of the process. | ||
* @param {Number} [opts.gid] Sets the group identity of the process. | ||
* @param {Function} next | ||
* @param {Error} next.err | ||
* @param {Buffer|String} next.stdout out buffer | ||
* @param {Buffer|String} next.stderr error buffer | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
exec (command, opts, next) { | ||
* Wrapper around node's exec command for a cleaner, more robust and powerful API. | ||
* Runs a command in a shell and buffers the output. | ||
* Note: | ||
* Stdout and stderr should be Buffers but they are strings unless encoding:null | ||
* for now, nothing we should do, besides wait for joyent to reply | ||
* https://github.com/joyent/node/issues/5833#issuecomment-82189525. | ||
* @param {Object} command | ||
* @param {Object} [opts] | ||
* @param {Boolean} [opts.sync] true to execute sync rather than async | ||
* @param {String} [opts.cwd] Current working directory of the child process | ||
* @param {Object} [opts.env] Environment key-value pairs | ||
* @param {String} [opts.encoding='utf8'] | ||
* @param {String} [opts.shell] Shell to execute the command with (Default: '/bin/sh' on UNIX, 'cmd.exe' on Windows, The shell should understand the -c switch on UNIX or /s /c on Windows. On Windows, command line parsing should be compatible with cmd.exe.) | ||
* @param {Number} [opts.timeout=0] | ||
* @param {Number} [opts.maxBuffer=200*1024] Largest amount of data (in bytes) allowed on stdout or stderr - if exceeded child process is killed. | ||
* @param {String} [opts.killSignal='SIGTERM'] | ||
* @param {Number} [opts.uid] Sets the user identity of the process. | ||
* @param {Number} [opts.gid] Sets the group identity of the process. | ||
* @param {Function} next | ||
* @param {Error} next.err | ||
* @param {Buffer|String} next.stdout out buffer | ||
* @param {Buffer|String} next.stderr error buffer | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
exec(command, opts, next) { | ||
// Prepare | ||
[opts, next] = extractOptsAndCallback(opts, next) | ||
;[opts, next] = extractOptsAndCallback(opts, next) | ||
opts = safeps.prepareExecutableOptions(opts) | ||
// Check if we want sync instead | ||
if ( opts.sync ) { | ||
if (opts.sync) { | ||
return safeps.execSync(command, opts, next) | ||
@@ -853,5 +874,5 @@ } | ||
// Patience | ||
safeps.openProcess(function (closeProcess) { | ||
safeps.openProcess(function(closeProcess) { | ||
// Output | ||
if ( opts.output === true && !opts.outputPrefix ) { | ||
if (opts.output === true && !opts.outputPrefix) { | ||
opts.stdio = 'inherit' | ||
@@ -862,3 +883,7 @@ opts.output = null | ||
// Execute command | ||
require('child_process').exec(command, opts, function (error, stdout, stderr) { | ||
require('child_process').exec(command, opts, function( | ||
error, | ||
stdout, | ||
stderr | ||
) { | ||
// Complete the task | ||
@@ -868,3 +893,3 @@ closeProcess() | ||
// Prepare result | ||
const result = {error, stdout, stderr} | ||
const result = { error, stdout, stderr } | ||
safeps.updateExecutableResult(result, opts) | ||
@@ -882,42 +907,44 @@ | ||
/** | ||
* Exec multiple processes in the one method call. | ||
* Launches new processes with the given array of commands. | ||
* Each item in the commands array represents a command parameter | ||
* sent to the safeps.exec method, so each item can be a command line | ||
* string or an array of command line inputs. It is also possible | ||
* to pass a single command string and in this case calling | ||
* execMultiple will be effectively the same as calling safeps.exec. | ||
* @param {Array|String} commands | ||
* @param {Object} [opts] | ||
* @param {Boolean} [opts.concurrency=1] Whether to exec processes concurrently. | ||
* @param {String} opts.cwd Current working directory of the child process. | ||
* @param {Array|String} opts.stdio Child's stdio configuration. | ||
* @param {Array} opts.customFds Deprecated File descriptors for the child to use for stdio. | ||
* @param {Object} opts.env Environment key-value pairs. | ||
* @param {Boolean} opts.detached The child will be a process group leader. | ||
* @param {Number} opts.uid Sets the user identity of the process. | ||
* @param {Number} opts.gid Sets the group identity of the process. | ||
* @param {Function} next callback | ||
* @param {Error} next.error | ||
* @param {Array} next.results array of exec results | ||
* @param {Stream} next.results[i].stdout out buffer | ||
* @param {Stream} next.results[i].stderr error buffer | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
execMultiple (commands, opts, next) { | ||
* Exec multiple processes in the one method call. | ||
* Launches new processes with the given array of commands. | ||
* Each item in the commands array represents a command parameter | ||
* sent to the safeps.exec method, so each item can be a command line | ||
* string or an array of command line inputs. It is also possible | ||
* to pass a single command string and in this case calling | ||
* execMultiple will be effectively the same as calling safeps.exec. | ||
* @param {Array|String} commands | ||
* @param {Object} [opts] | ||
* @param {Boolean} [opts.concurrency=1] Whether to exec processes concurrently. | ||
* @param {String} opts.cwd Current working directory of the child process. | ||
* @param {Array|String} opts.stdio Child's stdio configuration. | ||
* @param {Array} opts.customFds Deprecated File descriptors for the child to use for stdio. | ||
* @param {Object} opts.env Environment key-value pairs. | ||
* @param {Boolean} opts.detached The child will be a process group leader. | ||
* @param {Number} opts.uid Sets the user identity of the process. | ||
* @param {Number} opts.gid Sets the group identity of the process. | ||
* @param {Function} next callback | ||
* @param {Error} next.error | ||
* @param {Array} next.results array of exec results | ||
* @param {Stream} next.results[i].stdout out buffer | ||
* @param {Stream} next.results[i].stderr error buffer | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
execMultiple(commands, opts, next) { | ||
// Prepare | ||
[opts, next] = extractOptsAndCallback(opts, next) | ||
;[opts, next] = extractOptsAndCallback(opts, next) | ||
const results = [] | ||
// Be synchronous by default | ||
if ( opts.concurrency == null ) opts.concurrency = 1 | ||
if (opts.concurrency == null) opts.concurrency = 1 | ||
// Make sure we send back the arguments | ||
const tasks = new TaskGroup({concurrency: opts.concurrency}).done(function (err) { | ||
next(err, results) | ||
}) | ||
const tasks = new TaskGroup({ concurrency: opts.concurrency }).done( | ||
function(err) { | ||
next(err, results) | ||
} | ||
) | ||
// Prepare tasks | ||
if ( !typeChecker.isArray(commands) ) { | ||
if (!typeChecker.isArray(commands)) { | ||
commands = [commands] | ||
@@ -927,5 +954,5 @@ } | ||
// Add tasks | ||
commands.forEach(function (command) { | ||
tasks.addTask(function (complete) { | ||
safeps.exec(command, opts, function (...args) { | ||
commands.forEach(function(command) { | ||
tasks.addTask(function(complete) { | ||
safeps.exec(command, opts, function(...args) { | ||
const err = args[0] || null | ||
@@ -945,3 +972,2 @@ results.push(args) | ||
// ================================= | ||
@@ -951,24 +977,24 @@ // Paths | ||
/** | ||
* Determine an executable path from the passed array of possible file paths. | ||
* Called by getExecPath to find a path for a given executable name. | ||
* @access private | ||
* @param {Array} possibleExecPaths string array of file paths | ||
* @param {Object} [opts] | ||
* @param {Boolean} [opts.sync] true to execute sync rather than async | ||
* @param {Function} [next] | ||
* @param {Error} next.err | ||
* @param {String} next.execPath | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
determineExecPathSync (possibleExecPaths, opts, next) { | ||
* Determine an executable path from the passed array of possible file paths. | ||
* Called by getExecPath to find a path for a given executable name. | ||
* @access private | ||
* @param {Array} possibleExecPaths string array of file paths | ||
* @param {Object} [opts] | ||
* @param {Boolean} [opts.sync] true to execute sync rather than async | ||
* @param {Function} [next] | ||
* @param {Error} next.err | ||
* @param {String} next.execPath | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
determineExecPathSync(possibleExecPaths, opts, next) { | ||
// Prepare | ||
[opts, next] = extractOptsAndCallback(opts, next) | ||
;[opts, next] = extractOptsAndCallback(opts, next) | ||
let execPath = null | ||
// Handle | ||
possibleExecPaths.forEach(function (possibleExecPath) { | ||
possibleExecPaths.forEach(function(possibleExecPath) { | ||
// Check if we have found the valid exec path earlier, if so, skip | ||
// Check if the path is invalid, if it is, skip it | ||
if ( execPath || !possibleExecPath ) return | ||
if (execPath || !possibleExecPath) return | ||
@@ -979,4 +1005,7 @@ // Resolve the path as it may be a virtual or relative path | ||
// Check if the executeable exists | ||
safeps.isExecutableSync(possibleExecPath, opts, function (err, isExecutable) { | ||
if ( !err && isExecutable ) execPath = possibleExecPath | ||
safeps.isExecutableSync(possibleExecPath, opts, function( | ||
err, | ||
isExecutable | ||
) { | ||
if (!err && isExecutable) execPath = possibleExecPath | ||
}) | ||
@@ -986,7 +1015,6 @@ }) | ||
// Return | ||
if ( next ) { | ||
if (next) { | ||
next(null, execPath) | ||
return safeps | ||
} | ||
else { | ||
} else { | ||
return execPath | ||
@@ -997,23 +1025,23 @@ } | ||
/** | ||
* Determine an executable path from | ||
* the passed array of possible file paths. | ||
* Called by getExecPath to find a path for | ||
* a given executable name. | ||
* @access private | ||
* @param {Array} possibleExecPaths string array of file paths | ||
* @param {Object} [opts] | ||
* @param {Boolean} [opts.sync] true to execute sync rather than async | ||
* @param {Function} next | ||
* @param {Error} next.err | ||
* @param {String} next.execPath | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
determineExecPath (possibleExecPaths, opts, next) { | ||
* Determine an executable path from | ||
* the passed array of possible file paths. | ||
* Called by getExecPath to find a path for | ||
* a given executable name. | ||
* @access private | ||
* @param {Array} possibleExecPaths string array of file paths | ||
* @param {Object} [opts] | ||
* @param {Boolean} [opts.sync] true to execute sync rather than async | ||
* @param {Function} next | ||
* @param {Error} next.err | ||
* @param {String} next.execPath | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
determineExecPath(possibleExecPaths, opts, next) { | ||
// Prepare | ||
[opts, next] = extractOptsAndCallback(opts, next) | ||
;[opts, next] = extractOptsAndCallback(opts, next) | ||
let execPath = null | ||
// Sync? | ||
if ( opts.sync ) { | ||
if (opts.sync) { | ||
return safeps.determineExecPathSync(possibleExecPaths, opts, next) | ||
@@ -1023,3 +1051,3 @@ } | ||
// Group | ||
const tasks = new TaskGroup().done(function (err) { | ||
const tasks = new TaskGroup().done(function(err) { | ||
return next(err, execPath) | ||
@@ -1029,8 +1057,8 @@ }) | ||
// Handle | ||
possibleExecPaths.forEach(function (possibleExecPath) { | ||
possibleExecPaths.forEach(function(possibleExecPath) { | ||
// Check if the path is invalid, if it is, skip it | ||
if ( !possibleExecPath ) return | ||
tasks.addTask(function (complete) { | ||
if (!possibleExecPath) return | ||
tasks.addTask(function(complete) { | ||
// Check if we have found the valid exec path earlier, if so, skip | ||
if ( execPath ) return complete() | ||
if (execPath) return complete() | ||
@@ -1041,4 +1069,7 @@ // Resolve the path as it may be a virtual or relative path | ||
// Check if the executeable exists | ||
safeps.isExecutable(possibleExecPath, opts, function (err, isExecutable) { | ||
if ( !err && isExecutable ) execPath = possibleExecPath | ||
safeps.isExecutable(possibleExecPath, opts, function( | ||
err, | ||
isExecutable | ||
) { | ||
if (!err && isExecutable) execPath = possibleExecPath | ||
return complete() | ||
@@ -1057,6 +1088,6 @@ }) | ||
/** | ||
* Get the system's environment paths. | ||
* @return {Array} string array of file paths | ||
*/ | ||
getEnvironmentPaths () { | ||
* Get the system's environment paths. | ||
* @return {Array} string array of file paths | ||
*/ | ||
getEnvironmentPaths() { | ||
// Fetch system include paths with the correct delimiter for the system | ||
@@ -1070,13 +1101,13 @@ const environmentPaths = process.env.PATH.split(pathUtil.delimiter) | ||
/** | ||
* Get the possible paths for | ||
* the passed executable using the | ||
* standard environment paths. Basically, | ||
* get a list of places to look for the | ||
* executable. Only safe for non-Windows | ||
* systems. | ||
* @access private | ||
* @param {String} execName | ||
* @return {Array} string array of file paths | ||
*/ | ||
getStandardExecPaths (execName) { | ||
* Get the possible paths for | ||
* the passed executable using the | ||
* standard environment paths. Basically, | ||
* get a list of places to look for the | ||
* executable. Only safe for non-Windows | ||
* systems. | ||
* @access private | ||
* @param {String} execName | ||
* @return {Array} string array of file paths | ||
*/ | ||
getStandardExecPaths(execName) { | ||
// Fetch | ||
@@ -1086,4 +1117,4 @@ let standardExecPaths = [process.cwd()].concat(safeps.getEnvironmentPaths()) | ||
// Get the possible exec paths | ||
if ( execName ) { | ||
standardExecPaths = standardExecPaths.map(function (path) { | ||
if (execName) { | ||
standardExecPaths = standardExecPaths.map(function(path) { | ||
return pathUtil.join(path, execName) | ||
@@ -1098,22 +1129,22 @@ }) | ||
/** | ||
* Get the possible paths for | ||
* the passed executable using the | ||
* standard environment paths. Basically, | ||
* get a list of places to look for the | ||
* executable. Makes allowances for Windows | ||
* executables possibly needing an extension | ||
* to ensure execution (.exe, .cmd, .bat). | ||
* @access private | ||
* @param {String} execName | ||
* @return {Array} string array of file paths | ||
*/ | ||
getPossibleExecPaths (execName) { | ||
* Get the possible paths for | ||
* the passed executable using the | ||
* standard environment paths. Basically, | ||
* get a list of places to look for the | ||
* executable. Makes allowances for Windows | ||
* executables possibly needing an extension | ||
* to ensure execution (.exe, .cmd, .bat). | ||
* @access private | ||
* @param {String} execName | ||
* @return {Array} string array of file paths | ||
*/ | ||
getPossibleExecPaths(execName) { | ||
let possibleExecPaths | ||
// Fetch available paths | ||
if ( isWindows && execName.indexOf('.') === -1 ) { | ||
if (isWindows && execName.indexOf('.') === -1) { | ||
// we are for windows add the paths for .exe as well | ||
const standardExecPaths = safeps.getStandardExecPaths(execName) | ||
possibleExecPaths = [] | ||
for ( let i = 0; i < standardExecPaths.length; ++i ) { | ||
for (let i = 0; i < standardExecPaths.length; ++i) { | ||
const standardExecPath = standardExecPaths[i] | ||
@@ -1127,4 +1158,3 @@ possibleExecPaths.push( | ||
} | ||
} | ||
else { | ||
} else { | ||
// we are normal, try the paths | ||
@@ -1139,31 +1169,31 @@ possibleExecPaths = safeps.getStandardExecPaths(execName) | ||
/** | ||
* Cache of executable paths | ||
* @access private | ||
* @property execPathCache | ||
*/ | ||
* Cache of executable paths | ||
* @access private | ||
* @property execPathCache | ||
*/ | ||
execPathCache: {}, | ||
/** | ||
* Given an executable name, search and find | ||
* its actual path. Will search the standard | ||
* file paths defined by the environment to | ||
* see if the executable is in any of those paths. | ||
* @param {Object} execName | ||
* @param {Object} [opts] | ||
* @param {Boolean} [opts.cache=true] | ||
* @param {Function} next | ||
* @param {Error} next.err | ||
* @param {String} next.foundPath path to the executable | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
getExecPath (execName, opts, next) { | ||
* Given an executable name, search and find | ||
* its actual path. Will search the standard | ||
* file paths defined by the environment to | ||
* see if the executable is in any of those paths. | ||
* @param {Object} execName | ||
* @param {Object} [opts] | ||
* @param {Boolean} [opts.cache=true] | ||
* @param {Function} next | ||
* @param {Error} next.err | ||
* @param {String} next.foundPath path to the executable | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
getExecPath(execName, opts, next) { | ||
// Prepare | ||
[opts, next] = extractOptsAndCallback(opts, next) | ||
;[opts, next] = extractOptsAndCallback(opts, next) | ||
// By default read from the cache and write to the cache | ||
if ( opts.cache == null ) opts.cache = true | ||
if (opts.cache == null) opts.cache = true | ||
// Check for absolute path, as we would not be needed and would just currupt the output | ||
if ( execName.substr(0, 1) === '/' || execName.substr(1, 1) === ':' ) { | ||
if (execName.substr(0, 1) === '/' || execName.substr(1, 1) === ':') { | ||
next(null, execName) | ||
@@ -1178,8 +1208,7 @@ return safeps | ||
// Check for special case | ||
if ( safeps[getExecMethodName] ) { | ||
if (safeps[getExecMethodName]) { | ||
return safeps[getExecMethodName](opts, next) | ||
} | ||
else { | ||
} else { | ||
// Check for cache | ||
if ( opts.cache && safeps.execPathCache[execName] ) { | ||
if (opts.cache && safeps.execPathCache[execName]) { | ||
next(null, safeps.execPathCache[execName]) | ||
@@ -1194,13 +1223,14 @@ return safeps | ||
// Which will determine which path it is out of the possible paths | ||
safeps.determineExecPath(possibleExecPaths, opts, function (err, execPath) { | ||
if ( err ) { | ||
safeps.determineExecPath(possibleExecPaths, opts, function( | ||
err, | ||
execPath | ||
) { | ||
if (err) { | ||
next(err) | ||
} | ||
else if ( !execPath ) { | ||
} else if (!execPath) { | ||
err = new Error(`Could not locate the ${execName} executable path`) | ||
next(err) | ||
} | ||
else { | ||
} else { | ||
// Success, write the result to cache and send to our callback | ||
if ( opts.cache ) safeps.execPathCache[execName] = execPath | ||
if (opts.cache) safeps.execPathCache[execName] = execPath | ||
return next(null, execPath) | ||
@@ -1216,21 +1246,21 @@ } | ||
/** | ||
* Get home path. Returns the user's home directory. | ||
* Based upon home function from: https://github.com/isaacs/osenv | ||
* @param {Object} [opts] | ||
* @param {Object} [opts.cache=true] | ||
* @param {Function} next | ||
* @param {Error} next.err | ||
* @param {String} next.homePath | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
getHomePath (opts, next) { | ||
* Get home path. Returns the user's home directory. | ||
* Based upon home function from: https://github.com/isaacs/osenv | ||
* @param {Object} [opts] | ||
* @param {Object} [opts.cache=true] | ||
* @param {Function} next | ||
* @param {Error} next.err | ||
* @param {String} next.homePath | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
getHomePath(opts, next) { | ||
// Prepare | ||
[opts, next] = extractOptsAndCallback(opts, next) | ||
;[opts, next] = extractOptsAndCallback(opts, next) | ||
// By default read from the cache and write to the cache | ||
if ( opts.cache == null ) opts.cache = true | ||
if (opts.cache == null) opts.cache = true | ||
// Cached | ||
if ( opts.cache && safeps.cachedHomePath ) { | ||
if (opts.cache && safeps.cachedHomePath) { | ||
next(null, safeps.cachedHomePath) | ||
@@ -1244,3 +1274,3 @@ return safeps | ||
// Success, write the result to cache and send to our callback | ||
if ( opts.cache ) safeps.cachedHomePath = homePath | ||
if (opts.cache) safeps.cachedHomePath = homePath | ||
next(null, homePath) | ||
@@ -1253,21 +1283,21 @@ | ||
/** | ||
* Path to the evironment's temporary directory. | ||
* Based upon tmpdir function from: https://github.com/isaacs/osenv | ||
* @param {Object} [opts] | ||
* @param {Object} [opts.cache=true] | ||
* @param {Function} next | ||
* @param {Error} next.err | ||
* @param {String} next.tmpPath | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
getTmpPath (opts, next) { | ||
* Path to the evironment's temporary directory. | ||
* Based upon tmpdir function from: https://github.com/isaacs/osenv | ||
* @param {Object} [opts] | ||
* @param {Object} [opts.cache=true] | ||
* @param {Function} next | ||
* @param {Error} next.err | ||
* @param {String} next.tmpPath | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
getTmpPath(opts, next) { | ||
// Prepare | ||
[opts, next] = extractOptsAndCallback(opts, next) | ||
;[opts, next] = extractOptsAndCallback(opts, next) | ||
// By default read from the cache and write to the cache | ||
if ( opts.cache == null ) opts.cache = true | ||
if (opts.cache == null) opts.cache = true | ||
// Cached | ||
if ( opts.cache && safeps.cachedTmpPath ) { | ||
if (opts.cache && safeps.cachedTmpPath) { | ||
next(null, safeps.cachedTmpPath) | ||
@@ -1281,13 +1311,14 @@ return safeps | ||
// Try the OS environment temp path | ||
let tmpPath = process.env.TMPDIR || process.env.TMP || process.env.TEMP || null | ||
let tmpPath = | ||
process.env.TMPDIR || process.env.TMP || process.env.TEMP || null | ||
// Fallback | ||
if ( !tmpPath ) { | ||
if (!tmpPath) { | ||
// Try the user directory temp path | ||
safeps.getHomePath(opts, function (err, homePath) { | ||
if ( err ) return next(err) | ||
safeps.getHomePath(opts, function(err, homePath) { | ||
if (err) return next(err) | ||
tmpPath = pathUtil.resolve(homePath, tmpDirName) | ||
// Fallback | ||
if ( !tmpPath ) { | ||
if (!tmpPath) { | ||
// Try the system temp path | ||
@@ -1303,3 +1334,3 @@ // @TODO perhaps we should check if we have write access to this path | ||
// Check if we couldn't find it, we should always be able to find it | ||
if ( !tmpPath ) { | ||
if (!tmpPath) { | ||
const err = new Error("Wan't able to find a temporary path") | ||
@@ -1310,3 +1341,3 @@ next(err) | ||
// Success, write the result to cache and send to our callback | ||
if ( opts.cache ) safeps.cachedTmpPath = tmpPath | ||
if (opts.cache) safeps.cachedTmpPath = tmpPath | ||
next(null, tmpPath) | ||
@@ -1319,22 +1350,22 @@ | ||
/** | ||
* Path to the evironment's GIT directory. | ||
* As 'git' is not always available in the environment path, we should check | ||
* common path locations and if we find one that works, then we should use it. | ||
* @param {Object} [opts] | ||
* @param {Object} [opts.cache=true] | ||
* @param {Function} next | ||
* @param {Error} next.err | ||
* @param {String} next.gitPath | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
getGitPath (opts, next) { | ||
* Path to the evironment's GIT directory. | ||
* As 'git' is not always available in the environment path, we should check | ||
* common path locations and if we find one that works, then we should use it. | ||
* @param {Object} [opts] | ||
* @param {Object} [opts.cache=true] | ||
* @param {Function} next | ||
* @param {Error} next.err | ||
* @param {String} next.gitPath | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
getGitPath(opts, next) { | ||
// Prepare | ||
[opts, next] = extractOptsAndCallback(opts, next) | ||
;[opts, next] = extractOptsAndCallback(opts, next) | ||
// By default read from the cache and write to the cache | ||
if ( opts.cache == null ) opts.cache = true | ||
if (opts.cache == null) opts.cache = true | ||
// Cached | ||
if ( opts.cache && safeps.cachedGitPath ) { | ||
if (opts.cache && safeps.cachedGitPath) { | ||
next(null, safeps.cachedGitPath) | ||
@@ -1349,4 +1380,4 @@ return safeps | ||
// Add environment paths | ||
if ( process.env.GIT_PATH ) possibleExecPaths.push(process.env.GIT_PATH) | ||
if ( process.env.GITPATH ) possibleExecPaths.push(process.env.GITPATH) | ||
if (process.env.GIT_PATH) possibleExecPaths.push(process.env.GIT_PATH) | ||
if (process.env.GITPATH) possibleExecPaths.push(process.env.GITPATH) | ||
@@ -1357,3 +1388,3 @@ // Add standard paths | ||
// Add custom paths | ||
if ( isWindows ) { | ||
if (isWindows) { | ||
possibleExecPaths.push( | ||
@@ -1364,4 +1395,3 @@ `/Program Files (x64)/Git/bin/${execName}`, | ||
) | ||
} | ||
else { | ||
} else { | ||
possibleExecPaths.push( | ||
@@ -1375,13 +1405,11 @@ `/usr/local/bin/${execName}`, | ||
// Determine the right path | ||
safeps.determineExecPath(possibleExecPaths, opts, function (err, execPath) { | ||
if ( err ) { | ||
safeps.determineExecPath(possibleExecPaths, opts, function(err, execPath) { | ||
if (err) { | ||
next(err) | ||
} | ||
else if ( !execPath ) { | ||
} else if (!execPath) { | ||
err = new Error('Could not locate git binary') | ||
next(err) | ||
} | ||
else { | ||
} else { | ||
// Success, write the result to cache and send to our callback | ||
if ( opts.cache ) safeps.cachedGitPath = execPath | ||
if (opts.cache) safeps.cachedGitPath = execPath | ||
next(null, execPath) | ||
@@ -1396,22 +1424,22 @@ } | ||
/** | ||
* Path to the evironment's Node directory. | ||
* As 'node' is not always available in the environment path, we should check | ||
* common path locations and if we find one that works, then we should use it | ||
* @param {Object} [opts] | ||
* @param {Object} [opts.cache=true] | ||
* @param {Function} next | ||
* @param {Error} next.err | ||
* @param {String} next.nodePath | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
getNodePath (opts, next) { | ||
* Path to the evironment's Node directory. | ||
* As 'node' is not always available in the environment path, we should check | ||
* common path locations and if we find one that works, then we should use it | ||
* @param {Object} [opts] | ||
* @param {Object} [opts.cache=true] | ||
* @param {Function} next | ||
* @param {Error} next.err | ||
* @param {String} next.nodePath | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
getNodePath(opts, next) { | ||
// Prepare | ||
[opts, next] = extractOptsAndCallback(opts, next) | ||
;[opts, next] = extractOptsAndCallback(opts, next) | ||
// By default read from the cache and write to the cache | ||
if ( opts.cache == null ) opts.cache = true | ||
if (opts.cache == null) opts.cache = true | ||
// Cached | ||
if ( opts.cache && safeps.cachedNodePath ) { | ||
if (opts.cache && safeps.cachedNodePath) { | ||
next(null, safeps.cachedNodePath) | ||
@@ -1426,5 +1454,6 @@ return safeps | ||
// Add environment paths | ||
if ( process.env.NODE_PATH ) possibleExecPaths.push(process.env.NODE_PATH) | ||
if ( process.env.NODEPATH ) possibleExecPaths.push(process.env.NODEPATH) | ||
if ( /node(.exe)?$/.test(process.execPath) ) possibleExecPaths.push(process.execPath) | ||
if (process.env.NODE_PATH) possibleExecPaths.push(process.env.NODE_PATH) | ||
if (process.env.NODEPATH) possibleExecPaths.push(process.env.NODEPATH) | ||
if (/node(.exe)?$/.test(process.execPath)) | ||
possibleExecPaths.push(process.execPath) | ||
@@ -1435,3 +1464,3 @@ // Add standard paths | ||
// Add custom paths | ||
if ( isWindows ) { | ||
if (isWindows) { | ||
possibleExecPaths.push( | ||
@@ -1442,8 +1471,7 @@ `/Program Files (x64)/nodejs/${execName}`, | ||
) | ||
} | ||
else { | ||
} else { | ||
possibleExecPaths.push( | ||
`/usr/local/bin/${execName}`, | ||
`/usr/bin/${execName}`, | ||
`~/bin/${execName}` // User and Heroku | ||
`~/bin/${execName}` // User and Heroku | ||
) | ||
@@ -1453,13 +1481,11 @@ } | ||
// Determine the right path | ||
safeps.determineExecPath(possibleExecPaths, opts, function (err, execPath) { | ||
if ( err ) { | ||
safeps.determineExecPath(possibleExecPaths, opts, function(err, execPath) { | ||
if (err) { | ||
next(err) | ||
} | ||
else if ( !execPath ) { | ||
} else if (!execPath) { | ||
err = new Error('Could not locate node binary') | ||
next(err) | ||
} | ||
else { | ||
} else { | ||
// Success, write the result to cache and send to our callback | ||
if ( opts.cache ) safeps.cachedNodePath = execPath | ||
if (opts.cache) safeps.cachedNodePath = execPath | ||
next(null, execPath) | ||
@@ -1474,22 +1500,22 @@ } | ||
/** | ||
* Path to the evironment's NPM directory. | ||
* As 'npm' is not always available in the environment path, we should check | ||
* common path locations and if we find one that works, then we should use it | ||
* @param {Object} [opts] | ||
* @param {Object} [opts.cache=true] | ||
* @param {Function} next | ||
* @param {Error} next.err | ||
* @param {String} next.npmPath | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
getNpmPath (opts, next) { | ||
* Path to the evironment's NPM directory. | ||
* As 'npm' is not always available in the environment path, we should check | ||
* common path locations and if we find one that works, then we should use it | ||
* @param {Object} [opts] | ||
* @param {Object} [opts.cache=true] | ||
* @param {Function} next | ||
* @param {Error} next.err | ||
* @param {String} next.npmPath | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
getNpmPath(opts, next) { | ||
// Prepare | ||
[opts, next] = extractOptsAndCallback(opts, next) | ||
;[opts, next] = extractOptsAndCallback(opts, next) | ||
// By default read from the cache and write to the cache | ||
if ( opts.cache == null ) opts.cache = true | ||
if (opts.cache == null) opts.cache = true | ||
// Cached | ||
if ( opts.cache && safeps.cachedNpmPath ) { | ||
if (opts.cache && safeps.cachedNpmPath) { | ||
next(null, safeps.cachedNpmPath) | ||
@@ -1504,5 +1530,6 @@ return safeps | ||
// Add environment paths | ||
if ( process.env.NPM_PATH ) possibleExecPaths.push(process.env.NPM_PATH) | ||
if ( process.env.NPMPATH ) possibleExecPaths.push(process.env.NPMPATH) | ||
if ( /node(.exe)?$/.test(process.execPath) ) possibleExecPaths.push(process.execPath.replace(/node(.exe)?$/, execName)) | ||
if (process.env.NPM_PATH) possibleExecPaths.push(process.env.NPM_PATH) | ||
if (process.env.NPMPATH) possibleExecPaths.push(process.env.NPMPATH) | ||
if (/node(.exe)?$/.test(process.execPath)) | ||
possibleExecPaths.push(process.execPath.replace(/node(.exe)?$/, execName)) | ||
@@ -1513,3 +1540,3 @@ // Add standard paths | ||
// Add custom paths | ||
if ( isWindows ) { | ||
if (isWindows) { | ||
possibleExecPaths.push( | ||
@@ -1520,4 +1547,3 @@ `/Program Files (x64)/nodejs/${execName}`, | ||
) | ||
} | ||
else { | ||
} else { | ||
possibleExecPaths.push( | ||
@@ -1531,13 +1557,11 @@ `/usr/local/bin/${execName}`, | ||
// Determine the right path | ||
safeps.determineExecPath(possibleExecPaths, opts, function (err, execPath) { | ||
if ( err ) { | ||
safeps.determineExecPath(possibleExecPaths, opts, function(err, execPath) { | ||
if (err) { | ||
next(err) | ||
} | ||
else if ( !execPath ) { | ||
} else if (!execPath) { | ||
err = new Error('Could not locate npm binary') | ||
next(err) | ||
} | ||
else { | ||
} else { | ||
// Success, write the result to cache and send to our callback | ||
if ( opts.cache ) safeps.cachedNpmPath = execPath | ||
if (opts.cache) safeps.cachedNpmPath = execPath | ||
next(null, execPath) | ||
@@ -1551,3 +1575,2 @@ } | ||
// ================================= | ||
@@ -1558,16 +1581,16 @@ // Special Commands | ||
/** | ||
* Initialize a git repository, including submodules, and will prepare the given options if they are provided. | ||
* @param {Object} opts also forwarded to {@link spawnMultiple} | ||
* @param {String} [opts.cwd=process.cwd()] path to initiate the repository, can also be `opts.path` | ||
* @param {String} [opts.url] the remote url, e.g. `https://github.com/bevry/safeps.git` | ||
* @param {String} [opts.remote] the remote name, e.g. `origin` | ||
* @param {String} [opts.branch] the branch to use, e.g. `master` | ||
* @param {Function} next | ||
* @param {Error} next.err | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
initGitRepo (opts, next) { | ||
* Initialize a git repository, including submodules, and will prepare the given options if they are provided. | ||
* @param {Object} opts also forwarded to {@link spawnMultiple} | ||
* @param {String} [opts.cwd=process.cwd()] path to initiate the repository, can also be `opts.path` | ||
* @param {String} [opts.url] the remote url, e.g. `https://github.com/bevry/safeps.git` | ||
* @param {String} [opts.remote] the remote name, e.g. `origin` | ||
* @param {String} [opts.branch] the branch to use, e.g. `master` | ||
* @param {Function} next | ||
* @param {Error} next.err | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
initGitRepo(opts, next) { | ||
// Extract | ||
[opts, next] = extractOptsAndCallback(opts, next) | ||
;[opts, next] = extractOptsAndCallback(opts, next) | ||
@@ -1584,3 +1607,3 @@ // Defaults | ||
// Prepare | ||
function partTwo (err) { | ||
function partTwo(err) { | ||
if (err) return next(err) | ||
@@ -1596,4 +1619,3 @@ const commands = [] | ||
} | ||
} | ||
else if (opts.remote) { | ||
} else if (opts.remote) { | ||
commands.push(['git', 'pull', opts.remote]) | ||
@@ -1609,7 +1631,7 @@ } | ||
// Check if it exists | ||
safefs.ensurePath(opts.cwd, function (err) { | ||
safefs.ensurePath(opts.cwd, function(err) { | ||
if (err) return next(err) | ||
// Initialise git repo | ||
safeps.spawn(['git', 'init'], opts, function (err) { | ||
safeps.spawn(['git', 'init'], opts, function(err) { | ||
if (err) return next(err) | ||
@@ -1620,14 +1642,25 @@ | ||
// Check what remotes we have | ||
safeps.spawn(['git', 'remote', 'show'], opts, function (err, stdout) { | ||
safeps.spawn(['git', 'remote', 'show'], opts, function(err, stdout) { | ||
if (err) return next(err) | ||
// stdout will be null if there are no remotes | ||
// and will be buffer if there are remotes | ||
if (stdout && stdout.toString().split('\n').indexOf(opts.remote) !== -1) { | ||
if ( | ||
stdout && | ||
stdout | ||
.toString() | ||
.split('\n') | ||
.indexOf(opts.remote) !== -1 | ||
) { | ||
// Overwrite it if it does exist | ||
// @todo we could probably do a check here to see if it is different | ||
// but no need right now | ||
const command = ['git', 'remote', 'set-url', opts.remote, opts.url] | ||
const command = [ | ||
'git', | ||
'remote', | ||
'set-url', | ||
opts.remote, | ||
opts.url | ||
] | ||
safeps.spawn(command, opts, partTwo) | ||
} | ||
else { | ||
} else { | ||
// Add it if it doesn't exist | ||
@@ -1638,4 +1671,3 @@ const command = ['git', 'remote', 'add', opts.remote, opts.url] | ||
}) | ||
} | ||
else { | ||
} else { | ||
return partTwo() | ||
@@ -1651,17 +1683,17 @@ } | ||
/** | ||
* Init Node Modules with cross platform support | ||
* supports linux, heroku, osx, windows | ||
* @param {Object} opts also forwarded to {@link spawn} | ||
* @param {Function} next {@link spawn} completion callback | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
initNodeModules (opts, next) { | ||
* Init Node Modules with cross platform support | ||
* supports linux, heroku, osx, windows | ||
* @param {Object} opts also forwarded to {@link spawn} | ||
* @param {Function} next {@link spawn} completion callback | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
initNodeModules(opts, next) { | ||
// Prepare | ||
[opts, next] = extractOptsAndCallback(opts, next) | ||
;[opts, next] = extractOptsAndCallback(opts, next) | ||
// Defaults | ||
if ( !opts.cwd ) opts.cwd = process.cwd() | ||
if ( opts.args == null ) opts.args = [] | ||
if ( opts.force == null ) opts.force = false | ||
if (!opts.cwd) opts.cwd = process.cwd() | ||
if (opts.args == null) opts.args = [] | ||
if (opts.force == null) opts.force = false | ||
@@ -1673,6 +1705,6 @@ // Paths | ||
// Split this commands into parts | ||
function partTwo () { | ||
function partTwo() { | ||
// If there is no package.json file, then we can't do anything | ||
safefs.exists(packageJsonPath, function (exists) { | ||
if ( !exists ) return next() | ||
safefs.exists(packageJsonPath, function(exists) { | ||
if (!exists) return next() | ||
@@ -1686,11 +1718,10 @@ // Prepare command | ||
} | ||
function partOne () { | ||
function partOne() { | ||
// If we are not forcing, then skip if node_modules already exists | ||
if ( !opts.force ) { | ||
safefs.exists(nodeModulesPath, function (exists) { | ||
if ( exists ) return next() | ||
if (!opts.force) { | ||
safefs.exists(nodeModulesPath, function(exists) { | ||
if (exists) return next() | ||
partTwo() | ||
}) | ||
} | ||
else { | ||
} else { | ||
partTwo() | ||
@@ -1708,18 +1739,18 @@ } | ||
/** | ||
* Spawn Node Modules with cross platform support | ||
* supports linux, heroku, osx, windows | ||
* spawnNodeModule(name:string, args:array, opts:object, next:function) | ||
* Better than https://github.com/mafintosh/npm-execspawn as it uses safeps | ||
* @param {String} name | ||
* @param {Array} args | ||
* @param {Object} opts also forwarded to {@link spawn} | ||
* @param {String} opts.name name of node module | ||
* @param {String} [opts.cwd=process.cwd()] Current working directory of the child process. | ||
* @param {Function} next {@link spawn} completion callback | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
spawnNodeModule (...args) { | ||
* Spawn Node Modules with cross platform support | ||
* supports linux, heroku, osx, windows | ||
* spawnNodeModule(name:string, args:array, opts:object, next:function) | ||
* Better than https://github.com/mafintosh/npm-execspawn as it uses safeps | ||
* @param {String} name | ||
* @param {Array} args | ||
* @param {Object} opts also forwarded to {@link spawn} | ||
* @param {String} opts.name name of node module | ||
* @param {String} [opts.cwd=process.cwd()] Current working directory of the child process. | ||
* @param {Function} next {@link spawn} completion callback | ||
* @chainable | ||
* @return {this} | ||
*/ | ||
spawnNodeModule(...args) { | ||
// Prepare | ||
const opts = {cwd: process.cwd()} | ||
const opts = { cwd: process.cwd() } | ||
let next | ||
@@ -1731,7 +1762,6 @@ | ||
const type = typeof arg | ||
if ( Array.isArray(arg) ) { | ||
if (Array.isArray(arg)) { | ||
opts.args = arg | ||
} | ||
else if ( type === 'object' ) { | ||
if ( arg.next ) { | ||
} else if (type === 'object') { | ||
if (arg.next) { | ||
next = arg.next | ||
@@ -1745,7 +1775,5 @@ arg.next = null | ||
} | ||
} | ||
else if ( type === 'function' ) { | ||
} else if (type === 'function') { | ||
next = arg | ||
} | ||
else if ( type === 'string' ) { | ||
} else if (type === 'string') { | ||
opts.name = arg | ||
@@ -1757,7 +1785,6 @@ } | ||
let command | ||
if ( opts.name ) { | ||
if (opts.name) { | ||
command = [opts.name].concat(opts.args || []) | ||
opts.name = null | ||
} | ||
else { | ||
} else { | ||
command = [].concat(opts.args || []) | ||
@@ -1764,0 +1791,0 @@ } |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
128927
9
142
17
2893
1
17
+ Addedsafeps@7.0.1(transitive)
Updatededitions@^2.2.0
Updatedtaskgroup@^5.3.0
Updatedtypechecker@^4.8.0