Completed
Push — master ( e4da3f...33c5b3 )
by Jean
49s
created

configure.js ➔ ???   B

Complexity

Conditions 1
Paths 2

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 2
nop 2
dl 0
loc 29
rs 8.8571
c 0
b 0
f 0

1 Function

Rating   Name   Duplication   Size   Complexity  
B configure.js ➔ ... ➔ ??? 0 27 2
1
/**
2
 * @file Module 'configure'
3
 * @author woshilapin <[email protected]>
4
 */
5
/**
6
 * Manage global configuration for Codingame's connector
7
 * @module configure
8
 */
9
import fs from 'fs';
10
import readline from 'readline';
11
import subprocess from 'child_process';
12
13
let parameters = {};
14
15
/**
16
 * Load the configuration file
17
 *
18
 * @name load
19
 * @function
20
 * @param {string} path - Path of the configuration file
21
 * @param {Object} [options] - Additionnal parameters which will replace parameters from configuration file
22
 * @returns {Promise<Object>} Configuration parameters
23
 * @memberof module:configure
24
 * @instance
25
 */
26
let load = (path, options) => {
27
	return new Promise((resolve, reject) => {
28
		let resolvefromerror = (error) => {
29
			if (options !== undefined && typeof options === `object`) {
30
				Object.assign(parameters, options);
31
				resolve(options);
32
			} else {
33
				reject(error);
34
			}
35
		};
36
		try {
37
			fs.readFile(path, `utf8`, (error, file) => {
38
				if (error) {
39
					resolvefromerror(error);
40
				} else {
41
					try {
42
						parameters = JSON.parse(file);
43
					} catch (error) {
44
						reject(error);
45
					}
46
					Object.assign(parameters, options);
47
					resolve(parameters);
48
				}
49
			});
50
		} catch (error) {
51
			resolvefromerror(error);
52
		}
53
	});
54
};
55
56
/**
57
 * Get result of a shell command
58
 *
59
 * @name getShell
60
 * @function
61
 * @param {string} cmd - Shell command to run
62
 * @returns {Promise<string>} A promise of the output of the shell command
63
 */
64
let getShell = (cmd) => {
65
	return new Promise((resolve, reject) => {
66
		subprocess.exec(cmd, (error, stdout, stderr) => {
67
			if (error) {
68
				console.error(stderr);
69
				reject(error);
70
			} else {
71
				let result = stdout.trim();
72
				resolve(result);
73
			}
74
		});
75
	});
76
};
77
78
/**
79
 * Get content of a file
80
 *
81
 * @name getFile
82
 * @function
83
 * @param {string} path - Path to the file
84
 * @returns {Promise<Object>} A promise of an object with `path` and `content`
85
 */
86
let getFile = (path) => {
87
	return new Promise((resolve, reject) => {
88
		fs.readFile(path, `utf8`, (error, data) => {
89
			if (error) {
90
				console.error(error.message);
91
				reject(error);
92
			} else {
93
				resolve({
94
					"path": path,
95
					"data": data
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 = (question) => {
111
	return new Promise((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
135
 * @param {string} [question] - If present and value not found, will be shown to the user to ask for the value on 'stdin'
136
 * @returns {Promise<string|Array|Object>} The value of the parameter
137
 * @memberof module:configure
138
 * @instance
139
 */
140
let get = (name, option, question) => {
141
	return new Promise((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((result) => {
148
				parameters[name] = result;
149
				resolve(result);
150
			}, (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((result) => {
159
				parameters[name] = result;
160
				resolve(result);
161
			}, (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 = (name) => {
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