Coverage

100%
51
51
0

/home/ubuntu/src/github.com/dalekjs/dalek-internal-config/index.js

100%
51
51
0
LineHitsSource
1/*!
2 *
3 * Copyright (c) 2013 Sebastian Golasch
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 */
24
251'use strict';
26
27// ext. libs
281var path = require('path');
291var fs = require('fs');
301var _ = require('lodash');
311var yaml = require('js-yaml');
321var JSON5 = require('json5');
331require('coffee-script');
34
35/**
36 * Configures the config instance
37 *
38 * @param {object} defaults Default parameter options
39 * @param {object} opts Command line options
40 * @constructor
41 */
42
431var Config = function (defaults, opts, advOpts) {
4413 this.customFilename = null;
4513 this.defaultFilename = 'Dalekfile';
4613 this.supportedExtensions = ['yml', 'json5', 'json', 'js', 'coffee'];
4713 this.advancedOptions = advOpts;
4813 this.config = this.load(defaults, opts.config, opts);
49};
50
51/**
52 * Parses config data & loads config files
53 *
54 * @module DalekJS
55 * @class Config
56 * @namespace Dalek
57 * @part Config
58 * @api
59 */
60
611Config.prototype = {
62
63 /**
64 * Checks if a config file is available
65 *
66 * @method checkAvailabilityOfConfigFile
67 * @param {String} pathname
68 * @return {String} config File path
69 */
70
71 checkAvailabilityOfConfigFile: function (pathname) {
72 // check if a pathname is given,
73 // then check if the file is available
7414 if (pathname && fs.existsSync(pathname)) {
751 return fs.realpathSync(pathname);
76 }
77
78 // check if any of the default configuration files is available
7913 return this.supportedExtensions.reduce(this._checkFile.bind(this));
80 },
81
82 /**
83 * Iterator function that checks the existance of a given file
84 *
85 * @method _checkFile
86 * @param {String} previousValue Last iterations result
87 * @param {String} ext File extension to check
88 * @param {integer} idx Iteration index
89 * @param {object} data File data
90 * @return {String} config File path
91 * @private
92 */
93
94 _checkFile: function (previousValue, ext, idx, data) {
9555 if (previousValue.length > 6) {
961 return previousValue;
97 }
98
9954 var fileToCheck = this.defaultFilename + '.' + previousValue;
10054 if (fs.existsSync(fileToCheck)) {
1011 return fs.realpathSync(fileToCheck);
102 }
103
10453 return this._checkDefaultFile(ext, data);
105 },
106
107 /**
108 * Iterator function that checks the existance of a the default file
109 *
110 * @method _checkDefaultFile
111 * @param {String} ext File extension to check
112 * @param {object} data File data
113 * @return {String} config File path
114 * @private
115 */
116
117 _checkDefaultFile: function (ext, data) {
11853 if (ext === data[data.length - 1]) {
11914 var fileToCheck = this.defaultFilename + '.' + ext;
12014 if (fs.existsSync(fileToCheck)) {
1211 return fs.realpathSync(fileToCheck);
122 }
123 }
124
12552 return ext;
126 },
127
128 /**
129 * Loads a file & merges the results with the
130 * commandline options & the default config
131 *
132 * @method load
133 * @param {object} defaults Default config
134 * @param {String} pathname Filename of the config file to load
135 * @param {object} opts Command line options
136 * @return {object} config Merged config data
137 */
138
139 load: function (defaults, pathname, opts) {
14013 var file = this.checkAvailabilityOfConfigFile(pathname);
14113 var data = {};
142
14313 if (!this.advancedOptions || this.advancedOptions.dalekfile !== false) {
14413 data = this.loadFile(file);
145 }
146
147 // remove the tests property if the array length is 0
14813 if (opts.tests.length === 0) {
14913 delete opts.tests;
150 }
151
15213 return _.merge(defaults, data, opts, (this.advancedOptions || {}));
153 },
154
155 /**
156 * Loads a config file & parses it based on the file extension
157 *
158 * @method loadFile
159 * @param {String} pathname Filename of the config file to load
160 * @return {object} data Config data
161 */
162
163 loadFile: function (pathname) {
16413 var ext = path.extname(pathname).replace('.', '');
16513 return this['read' + ext] ? this['read' + ext](pathname) : {};
166 },
167
168 /**
169 * Fetches & returns a config item
170 *
171 * @method get
172 * @param {String} item Key of the item to load
173 * @return {mixed|null} data Requested config data
174 */
175
176 get: function (item) {
1771 return this.config[item] || null;
178 },
179
180 /**
181 * Loads a json config file
182 *
183 * @method readjson
184 * @return {object} data Parsed config data
185 */
186
187 readjson: function (pathname) {
1881 var contents = fs.readFileSync((pathname || this.defaultFilename + '.json'), 'utf8');
1891 return JSON.parse(contents);
190 },
191
192 /**
193 * Loads a json5 config file
194 *
195 * @method readJson5
196 * @return {object} data Parsed config data
197 */
198
199 readjson5: function (pathname) {
2001 var contents = fs.readFileSync((pathname || this.defaultFilename + '.json5'), 'utf8');
2011 return JSON5.parse(contents);
202 },
203
204 /**
205 * Loads a yaml config file
206 *
207 * @method readyaml
208 * @return {object} data Parsed config data
209 */
210
211 readyml: function (pathname) {
2121 var contents = fs.readFileSync((pathname || this.defaultFilename + '.yml'), 'utf8');
2131 return yaml.load(contents);
214 },
215
216 /**
217 * Loads a javascript config file
218 *
219 * @method readjs
220 * @return {object} data Parsed config data
221 */
222
223 readjs: function (pathname) {
2241 return require((pathname || this.defaultFilename));
225 },
226
227 /**
228 * Loads a coffescript config file
229 *
230 * @method readcoffee
231 * @return {object} data Parsed config data
232 */
233
234 readcoffee: function (pathname) {
2351 return require((pathname || this.defaultFilename));
236 },
237
238 /**
239 * Verifies if a reporter is given, exists & is valid
240 *
241 * @method verifyReporters
242 * @return {array} data List of verified reporters
243 */
244
245 verifyReporters: function (reporters, reporter) {
2461 return _.compact(this._verify(reporters, 'isReporter', reporter));
247 },
248
249 /**
250 * Verifies if a driver is given, exists & is valid
251 *
252 * @method verifyDrivers
253 * @return {array} data List of verified drivers
254 */
255
256 verifyDrivers: function (drivers, driver) {
2571 return _.compact(this._verify(drivers, 'isDriver', driver));
258 },
259
260 /**
261 * Verifies if a driver is given, exists & is valid
262 *
263 * @method _verify
264 * @param {array} check Data that shoudl be mapped
265 * @param {string} fn Name of the function that should be invoked on the veryify object
266 * @param {object} instance Object instance where the verify function should be invoked
267 * @return {array} data List of verified items
268 * @private
269 */
270
271 _verify: function (check, fn, instance) {
2722 return check.map(this._verifyIterator.bind(this, fn, instance));
273 },
274
275 /**
276 * Verifies if a driver is given, exists & is valid
277 *
278 * @method _verifyIterator
279 * @param {string} fn Name of the function that should be invoked on the veryify object
280 * @param {object} instance Object instance where the verify function should be invoked
281 * @param {string} elm Name of the element that should be checked
282 * @return {string|null} element name of the verified element or false if checked failed
283 * @priavte
284 */
285
286 _verifyIterator: function (fn, instance, elm) {
2872 return instance[fn](elm) ? elm : false;
288 }
289};
290
291// export the module
2921module.exports = Config;
293