@zappinginc/zm2 6.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +8 -0
- package/.gitattributes +4 -0
- package/.mocharc.js +14 -0
- package/CHANGELOG.md +2416 -0
- package/CLAUDE.md +84 -0
- package/CONTRIBUTING.md +124 -0
- package/GNU-AGPL-3.0.txt +665 -0
- package/LICENSE +1 -0
- package/README.md +248 -0
- package/bin/zm2 +3 -0
- package/bin/zm2-dev +3 -0
- package/bin/zm2-docker +3 -0
- package/bin/zm2-runtime +3 -0
- package/bin/zm2-windows +3 -0
- package/bin/zm2.ps1 +3 -0
- package/bun.lock +421 -0
- package/constants.js +114 -0
- package/index.js +13 -0
- package/lib/API/Configuration.js +212 -0
- package/lib/API/Containerizer.js +335 -0
- package/lib/API/Dashboard.js +459 -0
- package/lib/API/Deploy.js +117 -0
- package/lib/API/Extra.js +775 -0
- package/lib/API/ExtraMgmt/Docker.js +30 -0
- package/lib/API/Log.js +315 -0
- package/lib/API/LogManagement.js +371 -0
- package/lib/API/Modules/LOCAL.js +122 -0
- package/lib/API/Modules/Modularizer.js +148 -0
- package/lib/API/Modules/NPM.js +445 -0
- package/lib/API/Modules/TAR.js +362 -0
- package/lib/API/Modules/flagExt.js +46 -0
- package/lib/API/Modules/index.js +120 -0
- package/lib/API/Monit.js +247 -0
- package/lib/API/Serve.js +343 -0
- package/lib/API/Startup.js +629 -0
- package/lib/API/UX/helpers.js +213 -0
- package/lib/API/UX/index.js +9 -0
- package/lib/API/UX/pm2-describe.js +193 -0
- package/lib/API/UX/pm2-ls-minimal.js +31 -0
- package/lib/API/UX/pm2-ls.js +483 -0
- package/lib/API/Version.js +382 -0
- package/lib/API/interpreter.json +12 -0
- package/lib/API/pm2-plus/PM2IO.js +372 -0
- package/lib/API/pm2-plus/auth-strategies/CliAuth.js +288 -0
- package/lib/API/pm2-plus/auth-strategies/WebAuth.js +187 -0
- package/lib/API/pm2-plus/helpers.js +97 -0
- package/lib/API/pm2-plus/link.js +126 -0
- package/lib/API/pm2-plus/pres/motd +16 -0
- package/lib/API/pm2-plus/pres/motd.update +26 -0
- package/lib/API/pm2-plus/pres/welcome +28 -0
- package/lib/API/pm2-plus/process-selector.js +52 -0
- package/lib/API/schema.json +379 -0
- package/lib/API.js +1931 -0
- package/lib/Client.js +776 -0
- package/lib/Common.js +911 -0
- package/lib/Configuration.js +304 -0
- package/lib/Daemon.js +456 -0
- package/lib/Event.js +37 -0
- package/lib/God/ActionMethods.js +909 -0
- package/lib/God/ClusterMode.js +97 -0
- package/lib/God/ForkMode.js +297 -0
- package/lib/God/Methods.js +265 -0
- package/lib/God/Reload.js +240 -0
- package/lib/God.js +632 -0
- package/lib/HttpInterface.js +76 -0
- package/lib/ProcessContainer.js +305 -0
- package/lib/ProcessContainerBun.js +360 -0
- package/lib/ProcessContainerFork.js +42 -0
- package/lib/ProcessContainerForkBun.js +33 -0
- package/lib/ProcessUtils.js +55 -0
- package/lib/TreeKill.js +118 -0
- package/lib/Utility.js +430 -0
- package/lib/VersionCheck.js +46 -0
- package/lib/Watcher.js +117 -0
- package/lib/Worker.js +169 -0
- package/lib/binaries/CLI.js +1041 -0
- package/lib/binaries/DevCLI.js +183 -0
- package/lib/binaries/Runtime.js +101 -0
- package/lib/binaries/Runtime4Docker.js +192 -0
- package/lib/completion.js +229 -0
- package/lib/completion.sh +40 -0
- package/lib/motd +36 -0
- package/lib/templates/Dockerfiles/Dockerfile-java.tpl +7 -0
- package/lib/templates/Dockerfiles/Dockerfile-nodejs.tpl +8 -0
- package/lib/templates/Dockerfiles/Dockerfile-ruby.tpl +7 -0
- package/lib/templates/ecosystem-es.tpl +24 -0
- package/lib/templates/ecosystem-simple-es.tpl +8 -0
- package/lib/templates/ecosystem-simple.tpl +6 -0
- package/lib/templates/ecosystem.tpl +22 -0
- package/lib/templates/init-scripts/launchd.tpl +35 -0
- package/lib/templates/init-scripts/openrc.tpl +52 -0
- package/lib/templates/init-scripts/pm2-init-amazon.sh +86 -0
- package/lib/templates/init-scripts/rcd-openbsd.tpl +41 -0
- package/lib/templates/init-scripts/rcd.tpl +44 -0
- package/lib/templates/init-scripts/smf.tpl +43 -0
- package/lib/templates/init-scripts/systemd-online.tpl +22 -0
- package/lib/templates/init-scripts/systemd.tpl +22 -0
- package/lib/templates/init-scripts/upstart.tpl +103 -0
- package/lib/templates/logrotate.d/pm2 +10 -0
- package/lib/templates/sample-apps/http-server/README.md +14 -0
- package/lib/templates/sample-apps/http-server/api.js +9 -0
- package/lib/templates/sample-apps/http-server/ecosystem.config.js +14 -0
- package/lib/templates/sample-apps/http-server/package.json +11 -0
- package/lib/templates/sample-apps/pm2-plus-metrics-actions/README.md +45 -0
- package/lib/templates/sample-apps/pm2-plus-metrics-actions/custom-metrics.js +66 -0
- package/lib/templates/sample-apps/pm2-plus-metrics-actions/ecosystem.config.js +12 -0
- package/lib/templates/sample-apps/pm2-plus-metrics-actions/package.json +11 -0
- package/lib/templates/sample-apps/python-app/README.md +4 -0
- package/lib/templates/sample-apps/python-app/echo.py +7 -0
- package/lib/templates/sample-apps/python-app/ecosystem.config.js +12 -0
- package/lib/templates/sample-apps/python-app/package.json +11 -0
- package/lib/tools/Config.js +248 -0
- package/lib/tools/IsAbsolute.js +20 -0
- package/lib/tools/copydirSync.js +101 -0
- package/lib/tools/deleteFolderRecursive.js +19 -0
- package/lib/tools/find-package-json.js +74 -0
- package/lib/tools/fmt.js +72 -0
- package/lib/tools/isbinaryfile.js +94 -0
- package/lib/tools/json5.js +752 -0
- package/lib/tools/open.js +63 -0
- package/lib/tools/passwd.js +58 -0
- package/lib/tools/promise.min.js +1 -0
- package/lib/tools/sexec.js +55 -0
- package/lib/tools/treeify.js +113 -0
- package/lib/tools/which.js +120 -0
- package/lib/tools/xdg-open +861 -0
- package/package.json +219 -0
- package/paths.js +93 -0
- package/pm2 +11 -0
- package/preinstall.js +24 -0
- package/run.sh +9 -0
- package/types/index.d.ts +722 -0
- package/types/tsconfig.json +14 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
var exec = require('child_process').exec
|
|
2
|
+
, path = require('path')
|
|
3
|
+
;
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* open a file or uri using the default application for the file type.
|
|
8
|
+
*
|
|
9
|
+
* @return {ChildProcess} - the child process object.
|
|
10
|
+
* @param {string} target - the file/uri to open.
|
|
11
|
+
* @param {string} appName - (optional) the application to be used to open the
|
|
12
|
+
* file (for example, "chrome", "firefox")
|
|
13
|
+
* @param {function(Error)} callback - called with null on success, or
|
|
14
|
+
* an error object that contains a property 'code' with the exit
|
|
15
|
+
* code of the process.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
module.exports = open;
|
|
19
|
+
|
|
20
|
+
function open(target, appName, callback) {
|
|
21
|
+
var opener;
|
|
22
|
+
|
|
23
|
+
if (typeof(appName) === 'function') {
|
|
24
|
+
callback = appName;
|
|
25
|
+
appName = null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
switch (process.platform) {
|
|
29
|
+
case 'darwin':
|
|
30
|
+
if (appName) {
|
|
31
|
+
opener = 'open -a "' + escape(appName) + '"';
|
|
32
|
+
} else {
|
|
33
|
+
opener = 'open';
|
|
34
|
+
}
|
|
35
|
+
break;
|
|
36
|
+
case 'win32':
|
|
37
|
+
// if the first parameter to start is quoted, it uses that as the title
|
|
38
|
+
// so we pass a blank title so we can quote the file we are opening
|
|
39
|
+
if (appName) {
|
|
40
|
+
opener = 'start "" "' + escape(appName) + '"';
|
|
41
|
+
} else {
|
|
42
|
+
opener = 'start ""';
|
|
43
|
+
}
|
|
44
|
+
break;
|
|
45
|
+
default:
|
|
46
|
+
if (appName) {
|
|
47
|
+
opener = escape(appName);
|
|
48
|
+
} else {
|
|
49
|
+
// use Portlands xdg-open everywhere else
|
|
50
|
+
opener = path.join(__dirname, './xdg-open');
|
|
51
|
+
}
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (process.env.SUDO_USER) {
|
|
56
|
+
opener = 'sudo -u ' + process.env.SUDO_USER + ' ' + opener;
|
|
57
|
+
}
|
|
58
|
+
return exec(opener + ' "' + escape(target) + '"', callback);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function escape(s) {
|
|
62
|
+
return s.replace(/"/g, '\\\"');
|
|
63
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
|
|
2
|
+
var fs = require('fs')
|
|
3
|
+
|
|
4
|
+
var getUsers = function() {
|
|
5
|
+
return fs.readFileSync('/etc/passwd')
|
|
6
|
+
.toString()
|
|
7
|
+
.split('\n')
|
|
8
|
+
.filter(function (user) {
|
|
9
|
+
return user.length && user[0] != '#';
|
|
10
|
+
})
|
|
11
|
+
.reduce(function(map, user) {
|
|
12
|
+
var fields = user.split(':');
|
|
13
|
+
|
|
14
|
+
map[fields[0]] = map[fields[2]] = {
|
|
15
|
+
username : fields[0],
|
|
16
|
+
password : fields[1],
|
|
17
|
+
userId : fields[2],
|
|
18
|
+
groupId : fields[3],
|
|
19
|
+
name : fields[4].split(',')[0],
|
|
20
|
+
homedir : fields[5],
|
|
21
|
+
shell : fields[6]
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
return map
|
|
25
|
+
}, {})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
var getGroups = function(cb) {
|
|
29
|
+
var groups
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
groups = fs.readFileSync('/etc/group')
|
|
33
|
+
} catch(e) {
|
|
34
|
+
return e
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return groups
|
|
38
|
+
.toString()
|
|
39
|
+
.split('\n')
|
|
40
|
+
.filter(function (group) {
|
|
41
|
+
return group.length && group[0] != '#';
|
|
42
|
+
})
|
|
43
|
+
.reduce(function(map, group) {
|
|
44
|
+
var fields = group.split(':');
|
|
45
|
+
map[fields[0]] = map[fields[2]] = {
|
|
46
|
+
name : fields[0],
|
|
47
|
+
password : fields[1],
|
|
48
|
+
id : fields[2],
|
|
49
|
+
members : fields[3].split(',')
|
|
50
|
+
};
|
|
51
|
+
return map;
|
|
52
|
+
}, {})
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
module.exports = {
|
|
56
|
+
getUsers,
|
|
57
|
+
getGroups
|
|
58
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(e){function n(){}function t(e,n){return function(){e.apply(n,arguments)}}function o(e){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=void 0,this._deferreds=[],s(e,this)}function i(e,n){for(;3===e._state;)e=e._value;return 0===e._state?void e._deferreds.push(n):(e._handled=!0,void o._immediateFn(function(){var t=1===e._state?n.onFulfilled:n.onRejected;if(null===t)return void(1===e._state?r:u)(n.promise,e._value);var o;try{o=t(e._value)}catch(e){return void u(n.promise,e)}r(n.promise,o)}))}function r(e,n){try{if(n===e)throw new TypeError("A promise cannot be resolved with itself.");if(n&&("object"==typeof n||"function"==typeof n)){var i=n.then;if(n instanceof o)return e._state=3,e._value=n,void f(e);if("function"==typeof i)return void s(t(i,n),e)}e._state=1,e._value=n,f(e)}catch(n){u(e,n)}}function u(e,n){e._state=2,e._value=n,f(e)}function f(e){2===e._state&&0===e._deferreds.length&&o._immediateFn(function(){e._handled||o._unhandledRejectionFn(e._value)});for(var n=0,t=e._deferreds.length;n<t;n++)i(e,e._deferreds[n]);e._deferreds=null}function c(e,n,t){this.onFulfilled="function"==typeof e?e:null,this.onRejected="function"==typeof n?n:null,this.promise=t}function s(e,n){var t=!1;try{e(function(e){t||(t=!0,r(n,e))},function(e){t||(t=!0,u(n,e))})}catch(e){if(t)return;t=!0,u(n,e)}}var a=setTimeout;o.prototype.catch=function(e){return this.then(null,e)},o.prototype.then=function(e,t){var o=new this.constructor(n);return i(this,new c(e,t,o)),o},o.all=function(e){var n=Array.prototype.slice.call(e);return new o(function(e,t){function o(r,u){try{if(u&&("object"==typeof u||"function"==typeof u)){var f=u.then;if("function"==typeof f)return void f.call(u,function(e){o(r,e)},t)}n[r]=u,0===--i&&e(n)}catch(e){t(e)}}if(0===n.length)return e([]);for(var i=n.length,r=0;r<n.length;r++)o(r,n[r])})},o.resolve=function(e){return e&&"object"==typeof e&&e.constructor===o?e:new o(function(n){n(e)})},o.reject=function(e){return new o(function(n,t){t(e)})},o.race=function(e){return new o(function(n,t){for(var o=0,i=e.length;o<i;o++)e[o].then(n,t)})},o._immediateFn="function"==typeof setImmediate&&function(e){setImmediate(e)}||function(e){a(e,0)},o._unhandledRejectionFn=function(e){"undefined"!=typeof console&&console&&console.warn("Possible Unhandled Promise Rejection:",e)},o._setImmediateFn=function(e){o._immediateFn=e},o._setUnhandledRejectionFn=function(e){o._unhandledRejectionFn=e},"undefined"!=typeof module&&module.exports?module.exports=o:e.Promise||(e.Promise=o)}(this);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
|
|
2
|
+
var path = require('path');
|
|
3
|
+
var fs = require('fs');
|
|
4
|
+
var child = require('child_process');
|
|
5
|
+
|
|
6
|
+
var DEFAULT_MAXBUFFER_SIZE = 20 * 1024 * 1024;
|
|
7
|
+
|
|
8
|
+
function _exec(command, options, callback) {
|
|
9
|
+
options = options || {};
|
|
10
|
+
|
|
11
|
+
if (typeof options === 'function') {
|
|
12
|
+
callback = options;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (typeof options === 'object' && typeof callback === 'function') {
|
|
16
|
+
options.async = true;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (!command) {
|
|
20
|
+
try {
|
|
21
|
+
console.error('[sexec] must specify command');
|
|
22
|
+
} catch (e) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
options = Object.assign({
|
|
28
|
+
silent: false,
|
|
29
|
+
cwd: path.resolve(process.cwd()).toString(),
|
|
30
|
+
env: process.env,
|
|
31
|
+
maxBuffer: DEFAULT_MAXBUFFER_SIZE,
|
|
32
|
+
encoding: 'utf8',
|
|
33
|
+
}, options);
|
|
34
|
+
|
|
35
|
+
var c = child.exec(command, options, function (err, stdout, stderr) {
|
|
36
|
+
if (callback) {
|
|
37
|
+
if (!err) {
|
|
38
|
+
callback(0, stdout, stderr);
|
|
39
|
+
} else if (err.code === undefined) {
|
|
40
|
+
// See issue #536
|
|
41
|
+
/* istanbul ignore next */
|
|
42
|
+
callback(1, stdout, stderr);
|
|
43
|
+
} else {
|
|
44
|
+
callback(err.code, stdout, stderr);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
if (!options.silent) {
|
|
50
|
+
c.stdout.pipe(process.stdout);
|
|
51
|
+
c.stderr.pipe(process.stderr);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
module.exports = _exec;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// treeify.js
|
|
2
|
+
// Luke Plaster <notatestuser@gmail.com>
|
|
3
|
+
// https://github.com/notatestuser/treeify.js
|
|
4
|
+
|
|
5
|
+
// do the universal module definition dance
|
|
6
|
+
(function (root, factory) {
|
|
7
|
+
|
|
8
|
+
if (typeof exports === 'object') {
|
|
9
|
+
module.exports = factory();
|
|
10
|
+
} else if (typeof define === 'function' && define.amd) {
|
|
11
|
+
define(factory);
|
|
12
|
+
} else {
|
|
13
|
+
root.treeify = factory();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
}(this, function() {
|
|
17
|
+
|
|
18
|
+
function makePrefix(key, last) {
|
|
19
|
+
var str = (last ? '└' : '├');
|
|
20
|
+
if (key) {
|
|
21
|
+
str += '─ ';
|
|
22
|
+
} else {
|
|
23
|
+
str += '──┐';
|
|
24
|
+
}
|
|
25
|
+
return str;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function filterKeys(obj, hideFunctions) {
|
|
29
|
+
var keys = [];
|
|
30
|
+
for (var branch in obj) {
|
|
31
|
+
// always exclude anything in the object's prototype
|
|
32
|
+
if (!obj.hasOwnProperty(branch)) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
// ... and hide any keys mapped to functions if we've been told to
|
|
36
|
+
if (hideFunctions && ((typeof obj[branch])==="function")) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
keys.push(branch);
|
|
40
|
+
}
|
|
41
|
+
return keys;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function growBranch(key, root, last, lastStates, showValues, hideFunctions, callback) {
|
|
45
|
+
var line = '', index = 0, lastKey, circular, lastStatesCopy = lastStates.slice(0);
|
|
46
|
+
|
|
47
|
+
if (lastStatesCopy.push([ root, last ]) && lastStates.length > 0) {
|
|
48
|
+
// based on the "was last element" states of whatever we're nested within,
|
|
49
|
+
// we need to append either blankness or a branch to our line
|
|
50
|
+
lastStates.forEach(function(lastState, idx) {
|
|
51
|
+
if (idx > 0) {
|
|
52
|
+
line += (lastState[1] ? ' ' : '│') + ' ';
|
|
53
|
+
}
|
|
54
|
+
if ( ! circular && lastState[0] === root) {
|
|
55
|
+
circular = true;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// the prefix varies based on whether the key contains something to show and
|
|
60
|
+
// whether we're dealing with the last element in this collection
|
|
61
|
+
line += makePrefix(key, last) + key;
|
|
62
|
+
|
|
63
|
+
// append values and the circular reference indicator
|
|
64
|
+
showValues && (typeof root !== 'object' || root instanceof Date) && (line += ': ' + root);
|
|
65
|
+
circular && (line += ' (circular ref.)');
|
|
66
|
+
|
|
67
|
+
callback(line);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// can we descend into the next item?
|
|
71
|
+
if ( ! circular && typeof root === 'object') {
|
|
72
|
+
var keys = filterKeys(root, hideFunctions);
|
|
73
|
+
keys.forEach(function(branch){
|
|
74
|
+
// the last key is always printed with a different prefix, so we'll need to know if we have it
|
|
75
|
+
lastKey = ++index === keys.length;
|
|
76
|
+
|
|
77
|
+
// hold your breath for recursive action
|
|
78
|
+
growBranch(branch, root[branch], lastKey, lastStatesCopy, showValues, hideFunctions, callback);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// --------------------
|
|
84
|
+
|
|
85
|
+
var Treeify = {};
|
|
86
|
+
|
|
87
|
+
// Treeify.asLines
|
|
88
|
+
// --------------------
|
|
89
|
+
// Outputs the tree line-by-line, calling the lineCallback when each one is available.
|
|
90
|
+
|
|
91
|
+
Treeify.asLines = function(obj, showValues, hideFunctions, lineCallback) {
|
|
92
|
+
/* hideFunctions and lineCallback are curried, which means we don't break apps using the older form */
|
|
93
|
+
var hideFunctionsArg = typeof hideFunctions !== 'function' ? hideFunctions : false;
|
|
94
|
+
growBranch('.', obj, false, [], showValues, hideFunctionsArg, lineCallback || hideFunctions);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// Treeify.asTree
|
|
98
|
+
// --------------------
|
|
99
|
+
// Outputs the entire tree, returning it as a string with line breaks.
|
|
100
|
+
|
|
101
|
+
Treeify.asTree = function(obj, showValues, hideFunctions) {
|
|
102
|
+
var tree = '';
|
|
103
|
+
growBranch('.', obj, false, [], showValues, hideFunctions, function(line) {
|
|
104
|
+
tree += line + '\n';
|
|
105
|
+
});
|
|
106
|
+
return tree;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// --------------------
|
|
110
|
+
|
|
111
|
+
return Treeify;
|
|
112
|
+
|
|
113
|
+
}));
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
|
|
2
|
+
var fs = require('fs');
|
|
3
|
+
var path = require('path');
|
|
4
|
+
var cst = require('../../constants.js')
|
|
5
|
+
|
|
6
|
+
// XP's system default value for `PATHEXT` system variable, just in case it's not
|
|
7
|
+
// set on Windows.
|
|
8
|
+
var XP_DEFAULT_PATHEXT = '.com;.exe;.bat;.cmd;.vbs;.vbe;.js;.jse;.wsf;.wsh';
|
|
9
|
+
|
|
10
|
+
// For earlier versions of NodeJS that doesn't have a list of constants (< v6)
|
|
11
|
+
var FILE_EXECUTABLE_MODE = 1;
|
|
12
|
+
|
|
13
|
+
function statFollowLinks() {
|
|
14
|
+
return fs.statSync.apply(fs, arguments);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function isWindowsPlatform() {
|
|
18
|
+
return cst.IS_WINDOWS;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Cross-platform method for splitting environment `PATH` variables
|
|
22
|
+
function splitPath(p) {
|
|
23
|
+
return p ? p.split(path.delimiter) : [];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Tests are running all cases for this func but it stays uncovered by codecov due to unknown reason
|
|
27
|
+
/* istanbul ignore next */
|
|
28
|
+
function isExecutable(pathName) {
|
|
29
|
+
try {
|
|
30
|
+
// TODO(node-support): replace with fs.constants.X_OK once remove support for node < v6
|
|
31
|
+
fs.accessSync(pathName, FILE_EXECUTABLE_MODE);
|
|
32
|
+
} catch (err) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function checkPath(pathName) {
|
|
39
|
+
return fs.existsSync(pathName) && !statFollowLinks(pathName).isDirectory()
|
|
40
|
+
&& (isWindowsPlatform() || isExecutable(pathName));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
//@
|
|
44
|
+
//@ ### which(command)
|
|
45
|
+
//@
|
|
46
|
+
//@ Examples:
|
|
47
|
+
//@
|
|
48
|
+
//@ ```javascript
|
|
49
|
+
//@ var nodeExec = which('node');
|
|
50
|
+
//@ ```
|
|
51
|
+
//@
|
|
52
|
+
//@ Searches for `command` in the system's `PATH`. On Windows, this uses the
|
|
53
|
+
//@ `PATHEXT` variable to append the extension if it's not already executable.
|
|
54
|
+
//@ Returns a [ShellString](#shellstringstr) containing the absolute path to
|
|
55
|
+
//@ `command`.
|
|
56
|
+
function _which(cmd) {
|
|
57
|
+
if (!cmd) console.error('must specify command');
|
|
58
|
+
|
|
59
|
+
var options = {}
|
|
60
|
+
|
|
61
|
+
var isWindows = isWindowsPlatform();
|
|
62
|
+
var pathArray = splitPath(process.env.PATH);
|
|
63
|
+
|
|
64
|
+
var queryMatches = [];
|
|
65
|
+
|
|
66
|
+
// No relative/absolute paths provided?
|
|
67
|
+
if (cmd.indexOf('/') === -1) {
|
|
68
|
+
// Assume that there are no extensions to append to queries (this is the
|
|
69
|
+
// case for unix)
|
|
70
|
+
var pathExtArray = [''];
|
|
71
|
+
if (isWindows) {
|
|
72
|
+
// In case the PATHEXT variable is somehow not set (e.g.
|
|
73
|
+
// child_process.spawn with an empty environment), use the XP default.
|
|
74
|
+
var pathExtEnv = process.env.PATHEXT || XP_DEFAULT_PATHEXT;
|
|
75
|
+
pathExtArray = splitPath(pathExtEnv.toUpperCase());
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Search for command in PATH
|
|
79
|
+
for (var k = 0; k < pathArray.length; k++) {
|
|
80
|
+
// already found it
|
|
81
|
+
if (queryMatches.length > 0 && !options.all) break;
|
|
82
|
+
|
|
83
|
+
var attempt = path.resolve(pathArray[k], cmd);
|
|
84
|
+
|
|
85
|
+
if (isWindows) {
|
|
86
|
+
attempt = attempt.toUpperCase();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
var match = attempt.match(/\.[^<>:"/|?*.]+$/);
|
|
90
|
+
if (match && pathExtArray.indexOf(match[0]) >= 0) { // this is Windows-only
|
|
91
|
+
// The user typed a query with the file extension, like
|
|
92
|
+
// `which('node.exe')`
|
|
93
|
+
if (checkPath(attempt)) {
|
|
94
|
+
queryMatches.push(attempt);
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
} else { // All-platforms
|
|
98
|
+
// Cycle through the PATHEXT array, and check each extension
|
|
99
|
+
// Note: the array is always [''] on Unix
|
|
100
|
+
for (var i = 0; i < pathExtArray.length; i++) {
|
|
101
|
+
var ext = pathExtArray[i];
|
|
102
|
+
var newAttempt = attempt + ext;
|
|
103
|
+
if (checkPath(newAttempt)) {
|
|
104
|
+
queryMatches.push(newAttempt);
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
} else if (checkPath(cmd)) { // a valid absolute or relative path
|
|
111
|
+
queryMatches.push(path.resolve(cmd));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (queryMatches.length > 0) {
|
|
115
|
+
return options.all ? queryMatches : queryMatches[0];
|
|
116
|
+
}
|
|
117
|
+
return options.all ? [] : null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
module.exports = _which;
|