-
Notifications
You must be signed in to change notification settings - Fork 0
/
parse-argv.js
91 lines (73 loc) · 2.46 KB
/
parse-argv.js
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
const filenameRgx = /^[\\\/\w\s\._-]+$/;
// configure the cli commands and options
const commands = ["create", "commit", "rollback"];
let options = {
"--all": { valid_for: ["commit", "rollback"], default: false },
"--env": { valid_for: ["commit", "rollback"], expect: filenameRgx, default: ".env" },
"--migrations": { valid_for: commands, expect: filenameRgx, default: "postgres_migrations" },
"--prefix": { valid_for: ["create"], expect: /time/, default: "time" }
};
const aliases = {
"-a": "--all",
"-e": "--env",
"-m": "--migrations",
"-p": "--prefix"
};
/*
* Initial validation
* */
// quit early if the arguments supplied are insufficient
if(process.argv.length < 3)
throw new Error(`Incorrect usage of migres. "Expected: ${commands.join("|")} [options]`);
// quit early if the command is invalid
const cmd = process.argv[2];
if(!commands.includes(cmd))
throw new Error(`Command is invalid. Got: ${cmd} Expected: ${commands.join(", ")}`)
// iterator generator
const iter = (function* () {
for(const arg of process.argv.slice(3)) {
yield arg;
}
})();
/*
* Parse the arguments
* */
while(true) {
let {value: arg, done} = iter.next();
// no more args to parse
if(done) break;
// argument name (or alias) is invalid
arg = options[arg] ? arg : aliases[arg];
if(!options[arg]) {
const optionKeys = Object.keys(options).join(", ");
throw new Error(`Argument ${arg} is invalid. Options: ${optionKeys} `)
}
// parse boolean flags
if(!options[arg].expect) {
options[arg].value = true;
continue;
}
// parse value flags
const {value} = iter.next();
// no value provided
if(!value) {
throw new Error(`No value provided for arg ${arg} where one was expected`);
}
// invalid value provided
if(!options[arg].expect.test(value)) {
throw new Error(`Invalid value for argument ${arg}. Got: "${value}", Expected: ${ options[arg].expect }`)
}
options[arg].value = value;
}
/*
* Verify mandatory fields are filled and overwrite empty values with defaults
* */
let exported = { cmd };
for(const op in options) {
// todo: don't continue over mandatory fields (future feature)
// if(!options[op].value) continue;
options[op].value = options[op].value || options[op].default;
// make the keys easier to reference by removing prefixed hyphens
exported[op.replace(/-/g, "")] = options[op].value;
}
module.exports = exported;