Completed
Push — master ( 1c9e42...b99ff4 )
by Jean
01:59
created

configure.js ➔ ... ➔ ???   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
rs 10
c 1
b 0
f 0
1
/**
2
 * @file Module 'configure'
3
 * @author woshilapin <[email protected]>
4
 * @version 0.3.0
5
 */
6
/**
7
 * Manage global configuration for Codingame's connector
8
 * @module configure
9
 */
10
import fs from 'fs';
11
import readline from 'readline';
12
import subprocess from 'child_process';
13
14
let parameters = {};
15
16
/**
17
 * Load the configuration file
18
 *
19
 * @name load
20
 * @function
21
 * @param {string} path Path of the configuration file
22
 * @param {Object} [options] Additionnal parameters which will replace parameters from configuration file
0 ignored issues
show
Documentation Bug introduced by
The parameter [options] does not exist. Did you maybe mean options instead?
Loading history...
23
 * @returns {Promise<Object>} Configuration parameters
24
 * @memberof module:configure
25
 * @instance
26
 */
27
let load = function load(path, options) {
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable load already seems to be declared on line 27. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
28
	return new Promise(function(resolve, reject) {
29
		let resolvefromerror = function resolvefromerror(error) {
30
			if (options !== undefined && typeof options === `object`) {
31
				Object.assign(parameters, options);
32
				resolve(options);
33
			} else {
34
				reject(error);
35
			}
36
		};
37
		try {
38
			fs.readFile(path, `utf8`, function(error, file) {
39
				if (error) {
40
					resolvefromerror(error);
41
				} else {
42
					try {
43
						parameters = JSON.parse(file);
44
					} catch (error) {
45
						reject(error);
46
					}
47
					Object.assign(parameters, options);
48
					resolve(parameters);
49
				}
50
			});
51
		} catch (error) {
52
			resolvefromerror(error);
53
		}
54
	});
55
};
56
57
/**
58
 * Get result of a shell command
59
 *
60
 * @name getShell
61
 * @function
62
 * @param {string} cmd Shell command to run
63
 * @returns {Promise<string>} A promise of the output of the shell command
64
 */
65
let getShell = function getShell(cmd) {
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable getShell already seems to be declared on line 65. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
66
	return new Promise(function(resolve, reject) {
67
		subprocess.exec(cmd, function(error, stdout, stderr) {
68
			if (error) {
69
				console.error(stderr);
70
				reject(error);
71
			} else {
72
				let result = stdout.trim();
73
				resolve(result);
74
			}
75
		});
76
	})
77
};
78
79
/**
80
 * Get content of a file
81
 *
82
 * @name getFile
83
 * @function
84
 * @param {string} path Path to the file
85
 * @returns {Promise<Object>} A promise of an object with `path` and `content`
86
 */
87
let getFile = function getFile(path) {
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable getFile already seems to be declared on line 87. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
88
	return new Promise(function(resolve, reject) {
89
		fs.readFile(path, `utf8`, function(error, file) {
90
			if (error) {
91
				reject(error);
92
			} else {
93
				resolve({
94
					"path": path,
95
					"data": file
96
				});
97
			}
98
		});
99
	});
100
};
101
102
/**
103
 * Get answer to a question asked to the end-user
104
 *
105
 * @name getQuestion
106
 * @function
107
 * @param {string} question Question to ask to the end-user
108
 * @returns {Promise<string>} A promise of the answer of the end-user
109
 */
110
let getQuestion = function getQuestion(question) {
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable getQuestion already seems to be declared on line 110. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
111
	return new Promise(function(resolve, reject) {
112
		const rl = readline.createInterface({
113
			"input": process.stdin,
114
			"output": process.stdout
115
		});
116
		if (question !== undefined && typeof question === `string`) {
117
			rl.question(question, (result) => {
118
				rl.close();
119
				resolve(result);
120
			});
121
		} else {
122
			rl.close();
123
			reject(new Error(`'configure.get()' second parameter must be a string.`));
124
		}
125
	});
126
};
127
128
/**
129
 * Get the value from configuration
130
 *
131
 * @name get
132
 * @function
133
 * @param {string} name Name of the parameter
134
 * @param {string} [option] 'shell' if value may be executed as shell command, 'file' if value is a path and content of file should be returned
0 ignored issues
show
Documentation Bug introduced by
The parameter [option] does not exist. Did you maybe mean option instead?
Loading history...
135
 * @param {string} [question] If present and value not found, will be shown to the user to ask for the value on 'stdin'
0 ignored issues
show
Documentation Bug introduced by
The parameter [question] does not exist. Did you maybe mean question instead?
Loading history...
136
 * @returns {Promise<string|Array|Object>} The value of the parameter
137
 * @memberof module:configure
138
 * @instance
139
 */
140
let get = function get(name, option, question) {
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable get already seems to be declared on line 140. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
141
	return new Promise(function(resolve, reject) {
142
		if (!name || typeof name !== `string`) {
143
			reject(new Error(`'configure.get()' takes at least one string parameter.`));
144
		}
145
		let property = parameters[name];
146
		if (property !== undefined && option !== undefined && option === `shell` && Array.isArray(property)) {
147
			getShell(property.join(` `)).then(function(result) {
148
				parameters[name] = result;
149
				resolve(result);
150
			}, function(error) {
151
				reject(error);
152
			});
153
		} else if (property !== undefined && option !== undefined && option === `file`) {
154
			resolve(getFile(property));
155
		} else if (property !== undefined) {
156
			resolve(property);
157
		} else {
158
			getQuestion(question).then(function(result) {
159
				parameters[name] = result;
160
				resolve(result);
161
			}, function(error) {
162
				reject(error);
163
			});
164
		}
165
	});
166
};
167
168
/**
169
 * Ask configure module to delete a parameter
170
 *
171
 * @name forget
172
 * @function
173
 * @param {string} name Name of the parameter
174
 * @memberof module:configure
175
 * @instance
176
 */
177
let forget = function forget(name) {
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable forget already seems to be declared on line 177. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
178
	if (typeof name !== `string`) {
179
		throw new Error(`'configure.forget()' function takes one string parameter.`);
180
	} else {
181
		delete parameters[name];
182
	}
183
};
184
185
export default {
186
	"load": load,
187
	"get": get,
188
	"forget": forget
189
};
190