Plato on Github
Report Home
index.js
Maintainability
78.25
Lines of code
268
Difficulty
29.89
Estimated Errors
1.14
Function weight
By Complexity
By SLOC
/*! * * Copyright (c) 2013 Sebastian Golasch * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * */ 'use strict'; // ext. libs var path = require('path'); var fs = require('fs'); var _ = require('lodash'); var yaml = require('js-yaml'); var JSON5 = require('json5'); require('coffee-script'); /** * Configures the config instance * * @param {object} defaults Default parameter options * @param {object} opts Command line options * @constructor */ var Config = function (defaults, opts, advOpts) { this.customFilename = null; this.defaultFilename = 'Dalekfile'; this.supportedExtensions = ['yml', 'json5', 'json', 'js', 'coffee']; this.advancedOptions = advOpts; this.config = this.load(defaults, opts.config, opts); }; /** * Parses config data & loads config files * * @module DalekJS * @class Config * @namespace Dalek * @part Config * @api */ Config.prototype = { /** * Checks if a config file is available * * @method checkAvailabilityOfConfigFile * @param {String} pathname * @return {String} config File path */ checkAvailabilityOfConfigFile: function (pathname) { // check if a pathname is given, // then check if the file is available if (pathname && fs.existsSync(pathname)) { return fs.realpathSync(pathname); } // check if any of the default configuration files is available return this.supportedExtensions.reduce(this._checkFile.bind(this)); }, /** * Iterator function that checks the existance of a given file * * @method _checkFile * @param {String} previousValue Last iterations result * @param {String} ext File extension to check * @param {integer} idx Iteration index * @param {object} data File data * @return {String} config File path * @private */ _checkFile: function (previousValue, ext, idx, data) { if (previousValue.length > 6) { return previousValue; } var fileToCheck = this.defaultFilename + '.' + previousValue; if (fs.existsSync(fileToCheck)) { return fs.realpathSync(fileToCheck); } return this._checkDefaultFile(ext, data); }, /** * Iterator function that checks the existance of a the default file * * @method _checkDefaultFile * @param {String} ext File extension to check * @param {object} data File data * @return {String} config File path * @private */ _checkDefaultFile: function (ext, data) { if (ext === data[data.length - 1]) { var fileToCheck = this.defaultFilename + '.' + ext; if (fs.existsSync(fileToCheck)) { return fs.realpathSync(fileToCheck); } } return ext; }, /** * Loads a file & merges the results with the * commandline options & the default config * * @method load * @param {object} defaults Default config * @param {String} pathname Filename of the config file to load * @param {object} opts Command line options * @return {object} config Merged config data */ load: function (defaults, pathname, opts) { var file = this.checkAvailabilityOfConfigFile(pathname); var data = {}; if (!this.advancedOptions || this.advancedOptions.dalekfile !== false) { data = this.loadFile(file); } // remove the tests property if the array length is 0 if (opts.tests.length === 0) { delete opts.tests; } return _.merge(defaults, data, opts, (this.advancedOptions || {})); }, /** * Loads a config file & parses it based on the file extension * * @method loadFile * @param {String} pathname Filename of the config file to load * @return {object} data Config data */ loadFile: function (pathname) { var ext = path.extname(pathname).replace('.', ''); return this['read' + ext] ? this['read' + ext](pathname) : {}; }, /** * Fetches & returns a config item * * @method get * @param {String} item Key of the item to load * @return {mixed|null} data Requested config data */ get: function (item) { return this.config[item] || null; }, /** * Loads a json config file * * @method readjson * @return {object} data Parsed config data */ readjson: function (pathname) { var contents = fs.readFileSync((pathname || this.defaultFilename + '.json'), 'utf8'); return JSON.parse(contents); }, /** * Loads a json5 config file * * @method readJson5 * @return {object} data Parsed config data */ readjson5: function (pathname) { var contents = fs.readFileSync((pathname || this.defaultFilename + '.json5'), 'utf8'); return JSON5.parse(contents); }, /** * Loads a yaml config file * * @method readyaml * @return {object} data Parsed config data */ readyml: function (pathname) { var contents = fs.readFileSync((pathname || this.defaultFilename + '.yml'), 'utf8'); return yaml.load(contents); }, /** * Loads a javascript config file * * @method readjs * @return {object} data Parsed config data */ readjs: function (pathname) { return require((pathname || this.defaultFilename)); }, /** * Loads a coffescript config file * * @method readcoffee * @return {object} data Parsed config data */ readcoffee: function (pathname) { return require((pathname || this.defaultFilename)); }, /** * Verifies if a reporter is given, exists & is valid * * @method verifyReporters * @return {array} data List of verified reporters */ verifyReporters: function (reporters, reporter) { return _.compact(this._verify(reporters, 'isReporter', reporter)); }, /** * Verifies if a driver is given, exists & is valid * * @method verifyDrivers * @return {array} data List of verified drivers */ verifyDrivers: function (drivers, driver) { return _.compact(this._verify(drivers, 'isDriver', driver)); }, /** * Verifies if a driver is given, exists & is valid * * @method _verify * @param {array} check Data that shoudl be mapped * @param {string} fn Name of the function that should be invoked on the veryify object * @param {object} instance Object instance where the verify function should be invoked * @return {array} data List of verified items * @private */ _verify: function (check, fn, instance) { return check.map(this._verifyIterator.bind(this, fn, instance)); }, /** * Verifies if a driver is given, exists & is valid * * @method _verifyIterator * @param {string} fn Name of the function that should be invoked on the veryify object * @param {object} instance Object instance where the verify function should be invoked * @param {string} elm Name of the element that should be checked * @return {string|null} element name of the verified element or false if checked failed * @priavte */ _verifyIterator: function (fn, instance, elm) { return instance[fn](elm) ? elm : false; } }; // export the module module.exports = Config;