Skip to content

Commit

Permalink
drop real-executable-path-callback dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
shinnn committed Jan 15, 2018
1 parent 6877764 commit c63c81f
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 24 deletions.
60 changes: 47 additions & 13 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,58 @@
'use strict';

const realExecutablePathCallback = require('real-executable-path-callback');
const {promisify} = require('util');
const {realpath} = require('fs');

const inspectWithKind = require('inspect-with-kind');
const isPlainObj = require('is-plain-obj');
const which = require('which');

const ARG_ERROR = 'Expected 1 or 2 arguments (<string>[, <Object>])';
const TYPE_ERROR = 'Expected an executable name inside the PATH (<string>), for exmaple `ls`, `git` and `node`';
const OPTION_ERROR = 'Expected an option object to be passed to `node-which` https://www.npmjs.com/package/which (`null` by default)';
const promisifiedRealpath = promisify(realpath);
const promisifiedWhich = promisify(which);

module.exports = async function realExecutablePath(...args) {
const argLen = args.length;

if (argLen === 0) {
const error = new RangeError(`${ARG_ERROR}, but got no arguments.`);
error.code = 'ERR_MISSING_ARGS';

throw error;
}

if (argLen !== 1 && argLen !== 2) {
throw new RangeError(`Expected 1 or 2 arguments (<string>[, <Object>]), but got ${
argLen === 0 ? 'no' : argLen
} arguments.`);
throw new RangeError(`${ARG_ERROR}, but got ${argLen} arguments.`);
}

const [cmd, options] = args;

if (typeof cmd !== 'string') {
const error = new TypeError(`${TYPE_ERROR}, but got a non-string value ${inspectWithKind(cmd)}.`);
error.code = 'ERR_INVALID_ARG_TYPE';

throw error;
}

if (cmd.length === 0) {
throw new Error(`${TYPE_ERROR.replace(' (<string>)', '')}, but got '' (empty string).`);
}

if (argLen === 1) {
return promisifiedRealpath(await promisifiedWhich(cmd));
}

if (!isPlainObj(options)) {
throw new TypeError(`${OPTION_ERROR}, but got ${inspectWithKind(options)}.`);
}

return new Promise((resolve, reject) => {
realExecutablePathCallback(...args, (err, filePath) => {
if (err) {
reject(err);
return;
}
if (options.all) {
throw new Error(`\`all\` option is not supported, but a value ${
inspectWithKind(options.all)
} was provided.`);
}

resolve(filePath);
});
});
return promisifiedRealpath(await promisifiedWhich(cmd, options));
};
10 changes: 0 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@
"asynchronously"
],
"dependencies": {
"real-executable-path-callback": "^3.0.0"
"inspect-with-kind": "^1.0.4",
"is-plain-obj": "^1.1.0",
"which": "^1.3.0"
},
"devDependencies": {
"@shinnn/eslint-config-node": "^5.0.0",
Expand Down
30 changes: 30 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,36 @@ test('realExecutablePath()', async t => {
);
}

try {
await realExecutablePath('');
} catch ({message}) {
t.equal(
message,
'Expected an executable name inside the PATH, for exmaple `ls`, `git` and `node`, but got \'\' (empty string).',
'should fail when it takes an empty path.'
);
}

try {
await realExecutablePath('_', [{}]);
} catch ({message}) {
t.equal(
message,
'Expected an option object to be passed to `node-which` https://www.npmjs.com/package/which (`null` by default), but got [ {} ] (array).',
'should fail when it takes a non-plain options object.'
);
}

try {
await realExecutablePath('_', {all: true});
} catch ({message}) {
t.equal(
message,
'`all` option is not supported, but a value true (boolean) was provided.',
'should fail when `all` option is enabled.'
);
}

try {
await realExecutablePath();
} catch ({message}) {
Expand Down

0 comments on commit c63c81f

Please sign in to comment.