New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

safeps

Package Overview
Dependencies
Maintainers
2
Versions
114
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

safeps - npm Package Compare versions

Comparing version 7.0.1 to 8.0.0-next.1573414430.53c4cd7b292d3b083ac24ef130e06e0c7a76ad1f

.dependabot/config.yml

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.

{
"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 @@

@@ -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 @@ }

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc