Skip to content

Commit d1bf418

Browse files
shubhekshakumar303
authored andcommitted
feat: Added config parsing utility functions aimed at global options, more to come (#744)
1 parent be62a54 commit d1bf418

File tree

4 files changed

+388
-0
lines changed

4 files changed

+388
-0
lines changed

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"babel-polyfill": "6.20.0",
5050
"babel-runtime": "6.20.0",
5151
"bunyan": "1.8.5",
52+
"camelcase": "4.0.0",
5253
"debounce": "1.0.0",
5354
"es6-error": "4.0.1",
5455
"es6-promisify": "5.0.0",
@@ -63,6 +64,8 @@
6364
"node-notifier": "5.0.2",
6465
"parse-json": "2.2.0",
6566
"regenerator-runtime": "0.10.1",
67+
"require-uncached": "1.0.3",
68+
"stream-to-promise": "2.2.0",
6669
"sign-addon": "0.2.1",
6770
"source-map-support": "0.4.11",
6871
"tmp": "0.0.30",

src/config.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/* @flow */
2+
import path from 'path';
3+
4+
import requireUncached from 'require-uncached';
5+
6+
import {createLogger} from './util/logger';
7+
import {UsageError} from './errors';
8+
9+
const log = createLogger(__filename);
10+
11+
type ApplyConfigToArgvParams = {|
12+
argv: Object,
13+
configObject: Object,
14+
defaultValues: Object,
15+
|};
16+
17+
export function applyConfigToArgv({
18+
argv,
19+
configObject,
20+
defaultValues = {},
21+
}: ApplyConfigToArgvParams): Object {
22+
const newArgv = {...argv};
23+
for (const option in configObject) {
24+
// we assume the value was set on the CLI if the default value is
25+
// not the same as that on the argv object as there is a very rare chance
26+
// this happening
27+
const wasValueSetOnCLI = typeof(argv[option]) !== 'undefined' &&
28+
(argv[option] !== defaultValues[option]);
29+
if (wasValueSetOnCLI) {
30+
log.debug(`Favoring CLI: ${option}=${argv[option]} over ` +
31+
`configuration: ${option}=${configObject[option]}`);
32+
continue;
33+
}
34+
if (!argv.hasOwnProperty(option)) {
35+
log.debug(`Ignoring configuration: ${option}=${configObject[option]} ` +
36+
'because this is an unknown option');
37+
continue;
38+
}
39+
newArgv[option] = configObject[option];
40+
}
41+
return newArgv;
42+
}
43+
44+
export function loadJSConfigFile(filePath: string): Object {
45+
const resolvedFilePath = path.resolve(filePath);
46+
log.debug(
47+
`Loading JS config file: "${filePath}" ` +
48+
`(resolved to "${resolvedFilePath}")`);
49+
let configObject;
50+
try {
51+
configObject = requireUncached(resolvedFilePath);
52+
} catch (error) {
53+
log.debug('Handling error:', error);
54+
throw new UsageError(
55+
`Cannot read config file: ${resolvedFilePath}\n` +
56+
`Error: ${error.message}`);
57+
}
58+
if (Object.keys(configObject).length === 0) {
59+
log.debug(`Config file ${resolvedFilePath} did not define any options. ` +
60+
'Did you set module.exports = {...}?');
61+
}
62+
return configObject;
63+
}

src/program.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {readFileSync} from 'fs';
44

55
import git from 'git-rev-sync';
66
import yargs from 'yargs';
7+
import camelCase from 'camelcase';
78

89
import defaultCommands from './cmd';
910
import {UsageError} from './errors';
@@ -36,6 +37,7 @@ export class Program {
3637
yargs: any;
3738
commands: { [key: string]: Function };
3839
shouldExitProgram: boolean;
40+
defaultValues: Object;
3941

4042
constructor(
4143
argv: ?Array<string>,
@@ -90,7 +92,15 @@ export class Program {
9092
// This is a convenience for setting global options.
9193
// An option is only global (i.e. available to all sub commands)
9294
// with the `global` flag so this makes sure every option has it.
95+
this.defaultValues = {};
9396
Object.keys(options).forEach((key) => {
97+
const camelCasedKey = camelCase(key);
98+
if (options[key].type === 'boolean') {
99+
this.defaultValues[camelCasedKey] = false;
100+
}
101+
if (typeof(options[key].default) !== 'undefined') {
102+
this.defaultValues[camelCasedKey] = options[key].default;
103+
}
94104
options[key].global = true;
95105
if (options[key].demand === undefined) {
96106
// By default, all options should be "demanded" otherwise

0 commit comments

Comments
 (0)