@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.
Files changed (133) hide show
  1. package/.claude/settings.local.json +8 -0
  2. package/.gitattributes +4 -0
  3. package/.mocharc.js +14 -0
  4. package/CHANGELOG.md +2416 -0
  5. package/CLAUDE.md +84 -0
  6. package/CONTRIBUTING.md +124 -0
  7. package/GNU-AGPL-3.0.txt +665 -0
  8. package/LICENSE +1 -0
  9. package/README.md +248 -0
  10. package/bin/zm2 +3 -0
  11. package/bin/zm2-dev +3 -0
  12. package/bin/zm2-docker +3 -0
  13. package/bin/zm2-runtime +3 -0
  14. package/bin/zm2-windows +3 -0
  15. package/bin/zm2.ps1 +3 -0
  16. package/bun.lock +421 -0
  17. package/constants.js +114 -0
  18. package/index.js +13 -0
  19. package/lib/API/Configuration.js +212 -0
  20. package/lib/API/Containerizer.js +335 -0
  21. package/lib/API/Dashboard.js +459 -0
  22. package/lib/API/Deploy.js +117 -0
  23. package/lib/API/Extra.js +775 -0
  24. package/lib/API/ExtraMgmt/Docker.js +30 -0
  25. package/lib/API/Log.js +315 -0
  26. package/lib/API/LogManagement.js +371 -0
  27. package/lib/API/Modules/LOCAL.js +122 -0
  28. package/lib/API/Modules/Modularizer.js +148 -0
  29. package/lib/API/Modules/NPM.js +445 -0
  30. package/lib/API/Modules/TAR.js +362 -0
  31. package/lib/API/Modules/flagExt.js +46 -0
  32. package/lib/API/Modules/index.js +120 -0
  33. package/lib/API/Monit.js +247 -0
  34. package/lib/API/Serve.js +343 -0
  35. package/lib/API/Startup.js +629 -0
  36. package/lib/API/UX/helpers.js +213 -0
  37. package/lib/API/UX/index.js +9 -0
  38. package/lib/API/UX/pm2-describe.js +193 -0
  39. package/lib/API/UX/pm2-ls-minimal.js +31 -0
  40. package/lib/API/UX/pm2-ls.js +483 -0
  41. package/lib/API/Version.js +382 -0
  42. package/lib/API/interpreter.json +12 -0
  43. package/lib/API/pm2-plus/PM2IO.js +372 -0
  44. package/lib/API/pm2-plus/auth-strategies/CliAuth.js +288 -0
  45. package/lib/API/pm2-plus/auth-strategies/WebAuth.js +187 -0
  46. package/lib/API/pm2-plus/helpers.js +97 -0
  47. package/lib/API/pm2-plus/link.js +126 -0
  48. package/lib/API/pm2-plus/pres/motd +16 -0
  49. package/lib/API/pm2-plus/pres/motd.update +26 -0
  50. package/lib/API/pm2-plus/pres/welcome +28 -0
  51. package/lib/API/pm2-plus/process-selector.js +52 -0
  52. package/lib/API/schema.json +379 -0
  53. package/lib/API.js +1931 -0
  54. package/lib/Client.js +776 -0
  55. package/lib/Common.js +911 -0
  56. package/lib/Configuration.js +304 -0
  57. package/lib/Daemon.js +456 -0
  58. package/lib/Event.js +37 -0
  59. package/lib/God/ActionMethods.js +909 -0
  60. package/lib/God/ClusterMode.js +97 -0
  61. package/lib/God/ForkMode.js +297 -0
  62. package/lib/God/Methods.js +265 -0
  63. package/lib/God/Reload.js +240 -0
  64. package/lib/God.js +632 -0
  65. package/lib/HttpInterface.js +76 -0
  66. package/lib/ProcessContainer.js +305 -0
  67. package/lib/ProcessContainerBun.js +360 -0
  68. package/lib/ProcessContainerFork.js +42 -0
  69. package/lib/ProcessContainerForkBun.js +33 -0
  70. package/lib/ProcessUtils.js +55 -0
  71. package/lib/TreeKill.js +118 -0
  72. package/lib/Utility.js +430 -0
  73. package/lib/VersionCheck.js +46 -0
  74. package/lib/Watcher.js +117 -0
  75. package/lib/Worker.js +169 -0
  76. package/lib/binaries/CLI.js +1041 -0
  77. package/lib/binaries/DevCLI.js +183 -0
  78. package/lib/binaries/Runtime.js +101 -0
  79. package/lib/binaries/Runtime4Docker.js +192 -0
  80. package/lib/completion.js +229 -0
  81. package/lib/completion.sh +40 -0
  82. package/lib/motd +36 -0
  83. package/lib/templates/Dockerfiles/Dockerfile-java.tpl +7 -0
  84. package/lib/templates/Dockerfiles/Dockerfile-nodejs.tpl +8 -0
  85. package/lib/templates/Dockerfiles/Dockerfile-ruby.tpl +7 -0
  86. package/lib/templates/ecosystem-es.tpl +24 -0
  87. package/lib/templates/ecosystem-simple-es.tpl +8 -0
  88. package/lib/templates/ecosystem-simple.tpl +6 -0
  89. package/lib/templates/ecosystem.tpl +22 -0
  90. package/lib/templates/init-scripts/launchd.tpl +35 -0
  91. package/lib/templates/init-scripts/openrc.tpl +52 -0
  92. package/lib/templates/init-scripts/pm2-init-amazon.sh +86 -0
  93. package/lib/templates/init-scripts/rcd-openbsd.tpl +41 -0
  94. package/lib/templates/init-scripts/rcd.tpl +44 -0
  95. package/lib/templates/init-scripts/smf.tpl +43 -0
  96. package/lib/templates/init-scripts/systemd-online.tpl +22 -0
  97. package/lib/templates/init-scripts/systemd.tpl +22 -0
  98. package/lib/templates/init-scripts/upstart.tpl +103 -0
  99. package/lib/templates/logrotate.d/pm2 +10 -0
  100. package/lib/templates/sample-apps/http-server/README.md +14 -0
  101. package/lib/templates/sample-apps/http-server/api.js +9 -0
  102. package/lib/templates/sample-apps/http-server/ecosystem.config.js +14 -0
  103. package/lib/templates/sample-apps/http-server/package.json +11 -0
  104. package/lib/templates/sample-apps/pm2-plus-metrics-actions/README.md +45 -0
  105. package/lib/templates/sample-apps/pm2-plus-metrics-actions/custom-metrics.js +66 -0
  106. package/lib/templates/sample-apps/pm2-plus-metrics-actions/ecosystem.config.js +12 -0
  107. package/lib/templates/sample-apps/pm2-plus-metrics-actions/package.json +11 -0
  108. package/lib/templates/sample-apps/python-app/README.md +4 -0
  109. package/lib/templates/sample-apps/python-app/echo.py +7 -0
  110. package/lib/templates/sample-apps/python-app/ecosystem.config.js +12 -0
  111. package/lib/templates/sample-apps/python-app/package.json +11 -0
  112. package/lib/tools/Config.js +248 -0
  113. package/lib/tools/IsAbsolute.js +20 -0
  114. package/lib/tools/copydirSync.js +101 -0
  115. package/lib/tools/deleteFolderRecursive.js +19 -0
  116. package/lib/tools/find-package-json.js +74 -0
  117. package/lib/tools/fmt.js +72 -0
  118. package/lib/tools/isbinaryfile.js +94 -0
  119. package/lib/tools/json5.js +752 -0
  120. package/lib/tools/open.js +63 -0
  121. package/lib/tools/passwd.js +58 -0
  122. package/lib/tools/promise.min.js +1 -0
  123. package/lib/tools/sexec.js +55 -0
  124. package/lib/tools/treeify.js +113 -0
  125. package/lib/tools/which.js +120 -0
  126. package/lib/tools/xdg-open +861 -0
  127. package/package.json +219 -0
  128. package/paths.js +93 -0
  129. package/pm2 +11 -0
  130. package/preinstall.js +24 -0
  131. package/run.sh +9 -0
  132. package/types/index.d.ts +722 -0
  133. 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;