-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcli.js
More file actions
executable file
·111 lines (90 loc) · 2.83 KB
/
Copy pathcli.js
File metadata and controls
executable file
·111 lines (90 loc) · 2.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#!/usr/bin/env node
"use strict";
// Builds a fresh parser per call instead of reusing the singleton from
// require("yargs"), which would otherwise accumulate aliases/examples
// across repeated main() calls in the same process.
const yargsFactory = require("yargs/yargs");
// --------------------------------------------------------------------
const hashy = require("./");
// ====================================================================
async function main(argv) {
const yargs = yargsFactory();
// TESTABILITY: makes yargs throw instead of exiting, including from its
// built-in --help/--version handling (which prints and would otherwise
// call process.exit() before main() below ever gets to run).
yargs.exitProcess(false);
yargs.fail((msg) => {
const help = yargs.help();
throw msg ? `${help}\n${msg}` : help;
});
const options = yargs
.usage("Usage: hashy [<option>...]")
.example("hashy [ -a <algorithm> ] <secret>", "hash the secret")
.example("hashy <secret> <hash>", "verify the secret using the hash")
// Aliases rather than options: yargs already owns "help" and
// "version" as built-in commands and warns if they are redefined.
.alias("h", "help")
.alias("v", "version")
.options({
a: {
default: hashy.DEFAULT_ALGO,
describe: "algorithm to use for hashing",
},
c: {
alias: "cost",
describe: "cost for Bcrypt",
},
})
.parse(argv);
// yargs' built-in --help/--version handling already printed the
// relevant text as a side effect of .parse() above.
if (options.help || options.version) {
return;
}
if (options.cost) {
hashy.options.bcrypt.cost = +options.cost;
}
const args = options._;
if (args.length === 1) {
console.log(await hashy.hash(args[0], options.a));
return;
}
if (args.length === 2) {
const [password, hash] = args;
if (!(await hashy.verify(password, hash))) {
throw new Error("not ok");
}
return hashy.needsRehash(hash, options.a)
? "ok but password should be rehashed"
: "ok";
}
throw new Error("incorrect number of arguments");
}
exports = module.exports = main;
// ====================================================================
function prettyFormat(value) {
if (typeof value === "string") {
return value;
}
if (value instanceof Error) {
return `${value.message}\n${value.stack}`;
}
return JSON.stringify(value, null, 2);
}
if (require.main === module) {
main(process.argv.slice(2)).then(
(value) => {
if (typeof value === "number" && value % 1 === 0) {
return process.exit(value);
}
if (value !== undefined) {
console.log(prettyFormat(value));
}
process.exit(0);
},
(error) => {
console.error(prettyFormat(error));
process.exit(1);
},
);
}