Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

fable-settings

Package Overview
Dependencies
Maintainers
3
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fable-settings - npm Package Compare versions

Comparing version 2.0.5 to 3.0.0

.config/code-server/config.yaml

774

dist/fable-settings.js

@@ -1,120 +0,694 @@

(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
module.exports={
"Product": "ApplicationNameHere",
"ProductVersion": "0.0.0",
(function (f) {
if (typeof exports === "object" && typeof module !== "undefined") {
module.exports = f();
} else if (typeof define === "function" && define.amd) {
define([], f);
} else {
var g;
if (typeof window !== "undefined") {
g = window;
} else if (typeof global !== "undefined") {
g = global;
} else if (typeof self !== "undefined") {
g = self;
} else {
g = this;
}
g.FableSettings = f();
}
})(function () {
var define, module, exports;
return function () {
function r(e, n, t) {
function o(i, f) {
if (!n[i]) {
if (!e[i]) {
var c = "function" == typeof require && require;
if (!f && c) return c(i, !0);
if (u) return u(i, !0);
var a = new Error("Cannot find module '" + i + "'");
throw a.code = "MODULE_NOT_FOUND", a;
}
var p = n[i] = {
exports: {}
};
e[i][0].call(p.exports, function (r) {
var n = e[i][1][r];
return o(n || r);
}, p, p.exports, r, e, n, t);
}
return n[i].exports;
}
for (var u = "function" == typeof require && require, i = 0; i < t.length; i++) o(t[i]);
return o;
}
return r;
}()({
1: [function (require, module, exports) {
/**
* Precedent Meta-Templating
*
* @license MIT
*
* @author Steven Velozo <steven@velozo.com>
*
* @description Process text streams, parsing out meta-template expressions.
*/
var libWordTree = require(`./WordTree.js`);
var libStringParser = require(`./StringParser.js`);
class Precedent {
/**
* Precedent Constructor
*/
constructor() {
this.WordTree = new libWordTree();
this.StringParser = new libStringParser();
this.ParseTree = this.WordTree.ParseTree;
}
"ConfigFile": false,
/**
* Add a Pattern to the Parse Tree
* @method addPattern
* @param {Object} pTree - A node on the parse tree to push the characters into
* @param {string} pPattern - The string to add to the tree
* @param {number} pIndex - callback function
* @return {bool} True if adding the pattern was successful
*/
addPattern(pPatternStart, pPatternEnd, pParser) {
return this.WordTree.addPattern(pPatternStart, pPatternEnd, pParser);
}
"LogStreams":
[
{
"level": "trace"
}
]
}
/**
* Parse a string with the existing parse tree
* @method parseString
* @param {string} pString - The string to parse
* @return {string} The result from the parser
*/
parseString(pString) {
return this.StringParser.parseString(pString, this.ParseTree);
}
}
module.exports = Precedent;
}, {
"./StringParser.js": 2,
"./WordTree.js": 3
}],
2: [function (require, module, exports) {
/**
* String Parser
*
* @license MIT
*
* @author Steven Velozo <steven@velozo.com>
*
* @description Parse a string, properly processing each matched token in the word tree.
*/
},{}],2:[function(require,module,exports){
/**
* Fable Settings Add-on
*
* @license MIT
*
* @author Steven Velozo <steven@velozo.com>
* @module Fable Settings
*/
class StringParser {
/**
* StringParser Constructor
*/
constructor() {}
/**
* Fable Solution Settings
*
* @class FableSettings
* @constructor
*/
/**
* Create a fresh parsing state object to work with.
* @method newParserState
* @param {Object} pParseTree - A node on the parse tree to begin parsing from (usually root)
* @return {Object} A new parser state object for running a character parser on
* @private
*/
newParserState(pParseTree) {
return {
ParseTree: pParseTree,
Output: '',
OutputBuffer: '',
Pattern: false,
PatternMatch: false,
PatternMatchOutputBuffer: ''
};
}
class FableSettings
{
constructor(pFableSettings)
{
this.default = this.buildDefaultSettings();
/**
* Assign a node of the parser tree to be the next potential match.
* If the node has a PatternEnd property, it is a valid match and supercedes the last valid match (or becomes the initial match).
* @method assignNode
* @param {Object} pNode - A node on the parse tree to assign
* @param {Object} pParserState - The state object for the current parsing task
* @private
*/
assignNode(pNode, pParserState) {
pParserState.PatternMatch = pNode;
// Construct a new settings object
let tmpSettings = this.merge(pFableSettings, this.buildDefaultSettings());
// If the pattern has a END we can assume it has a parse function...
if (pParserState.PatternMatch.hasOwnProperty('PatternEnd')) {
// ... this is the legitimate start of a pattern.
pParserState.Pattern = pParserState.PatternMatch;
}
}
// The base settings object (what they were on initialization, before other actors have altered them)
this.base = JSON.parse(JSON.stringify(tmpSettings));
/**
* Append a character to the output buffer in the parser state.
* This output buffer is used when a potential match is being explored, or a match is being explored.
* @method appendOutputBuffer
* @param {string} pCharacter - The character to append
* @param {Object} pParserState - The state object for the current parsing task
* @private
*/
appendOutputBuffer(pCharacter, pParserState) {
pParserState.OutputBuffer += pCharacter;
}
if (tmpSettings.DefaultConfigFile)
{
try
{
// If there is a DEFAULT configuration file, try to load and merge it.
tmpSettings = this.merge(require(tmpSettings.DefaultConfigFile), tmpSettings);
}
catch (pException)
{
// Why this? Often for an app we want settings to work out of the box, but
// would potentially want to have a config file for complex settings.
console.log('Fable-Settings Warning: Default configuration file specified but there was a problem loading it. Falling back to base.');
console.log(' Loading Exception: '+pException);
}
}
/**
* Flush the output buffer to the output and clear it.
* @method flushOutputBuffer
* @param {Object} pParserState - The state object for the current parsing task
* @private
*/
flushOutputBuffer(pParserState) {
pParserState.Output += pParserState.OutputBuffer;
pParserState.OutputBuffer = '';
}
if (tmpSettings.ConfigFile)
{
try
{
// If there is a configuration file, try to load and merge it.
tmpSettings = this.merge(require(tmpSettings.ConfigFile), tmpSettings);
}
catch (pException)
{
// Why this? Often for an app we want settings to work out of the box, but
// would potentially want to have a config file for complex settings.
console.log('Fable-Settings Warning: Configuration file specified but there was a problem loading it. Falling back to base.');
console.log(' Loading Exception: '+pException);
}
}
/**
* Check if the pattern has ended. If it has, properly flush the buffer and start looking for new patterns.
* @method checkPatternEnd
* @param {Object} pParserState - The state object for the current parsing task
* @private
*/
checkPatternEnd(pParserState) {
if (pParserState.OutputBuffer.length >= pParserState.Pattern.PatternEnd.length + pParserState.Pattern.PatternStart.length && pParserState.OutputBuffer.substr(-pParserState.Pattern.PatternEnd.length) === pParserState.Pattern.PatternEnd) {
// ... this is the end of a pattern, cut off the end tag and parse it.
// Trim the start and end tags off the output buffer now
pParserState.OutputBuffer = pParserState.Pattern.Parse(pParserState.OutputBuffer.substr(pParserState.Pattern.PatternStart.length, pParserState.OutputBuffer.length - (pParserState.Pattern.PatternStart.length + pParserState.Pattern.PatternEnd.length)));
// Flush the output buffer.
this.flushOutputBuffer(pParserState);
// End pattern mode
pParserState.Pattern = false;
pParserState.PatternMatch = false;
}
}
this.settings = tmpSettings;
}
/**
* Parse a character in the buffer.
* @method parseCharacter
* @param {string} pCharacter - The character to append
* @param {Object} pParserState - The state object for the current parsing task
* @private
*/
parseCharacter(pCharacter, pParserState) {
// (1) If we aren't in a pattern match, and we aren't potentially matching, and this may be the start of a new pattern....
if (!pParserState.PatternMatch && pParserState.ParseTree.hasOwnProperty(pCharacter)) {
// ... assign the node as the matched node.
this.assignNode(pParserState.ParseTree[pCharacter], pParserState);
this.appendOutputBuffer(pCharacter, pParserState);
}
// (2) If we are in a pattern match (actively seeing if this is part of a new pattern token)
else if (pParserState.PatternMatch) {
// If the pattern has a subpattern with this key
if (pParserState.PatternMatch.hasOwnProperty(pCharacter)) {
// Continue matching patterns.
this.assignNode(pParserState.PatternMatch[pCharacter], pParserState);
}
this.appendOutputBuffer(pCharacter, pParserState);
if (pParserState.Pattern) {
// ... Check if this is the end of the pattern (if we are matching a valid pattern)...
this.checkPatternEnd(pParserState);
}
}
// (3) If we aren't in a pattern match or pattern, and this isn't the start of a new pattern (RAW mode)....
else {
pParserState.Output += pCharacter;
}
}
// Build a default settings object. Use the JSON jimmy to ensure it is always a new object.
buildDefaultSettings()
{
return JSON.parse(JSON.stringify(require('./Fable-Settings-Default')))
}
/**
* Parse a string for matches, and process any template segments that occur.
* @method parseString
* @param {string} pString - The string to parse.
* @param {Object} pParseTree - The parse tree to begin parsing from (usually root)
*/
parseString(pString, pParseTree) {
let tmpParserState = this.newParserState(pParseTree);
for (var i = 0; i < pString.length; i++) {
// TODO: This is not fast.
this.parseCharacter(pString[i], tmpParserState);
}
this.flushOutputBuffer(tmpParserState);
return tmpParserState.Output;
}
}
module.exports = StringParser;
}, {}],
3: [function (require, module, exports) {
/**
* Word Tree
*
* @license MIT
*
* @author Steven Velozo <steven@velozo.com>
*
* @description Create a tree (directed graph) of Javascript objects, one character per object.
*/
// Merge some new object into the existing settings.
merge(pSettingsFrom, pSettingsTo)
{
// If an invalid settings from object is passed in (e.g. object constructor without passing in anything) this should still work
let tmpSettingsFrom = (typeof(pSettingsFrom) === 'object') ? pSettingsFrom : {};
// Default to the settings object if none is passed in for the merge.
let tmpSettingsTo = (typeof(pSettingsTo) === 'object') ? pSettingsTo : this.settings;
class WordTree {
/**
* WordTree Constructor
*/
constructor() {
this.ParseTree = {};
}
tmpSettingsTo = Object.assign(tmpSettingsTo, tmpSettingsFrom);
/**
* Add a child character to a Parse Tree node
* @method addChild
* @param {Object} pTree - A parse tree to push the characters into
* @param {string} pPattern - The string to add to the tree
* @param {number} pIndex - The index of the character in the pattern
* @returns {Object} The resulting leaf node that was added (or found)
* @private
*/
addChild(pTree, pPattern, pIndex) {
if (!pTree.hasOwnProperty(pPattern[pIndex])) pTree[pPattern[pIndex]] = {};
return pTree[pPattern[pIndex]];
}
return tmpSettingsTo;
}
/** Add a Pattern to the Parse Tree
* @method addPattern
* @param {Object} pPatternStart - The starting string for the pattern (e.g. "${")
* @param {string} pPatternEnd - The ending string for the pattern (e.g. "}")
* @param {number} pParser - The function to parse if this is the matched pattern, once the Pattern End is met. If this is a string, a simple replacement occurs.
* @return {bool} True if adding the pattern was successful
*/
addPattern(pPatternStart, pPatternEnd, pParser) {
if (pPatternStart.length < 1) return false;
if (typeof pPatternEnd === 'string' && pPatternEnd.length < 1) return false;
let tmpLeaf = this.ParseTree;
// Fill in settings gaps without overwriting settings that are already there
fill(pSettingsFrom)
{
// If an invalid settings from object is passed in (e.g. object constructor without passing in anything) this should still work
let tmpSettingsFrom = (typeof(pSettingsFrom) === 'object') ? pSettingsFrom : {};
// Add the tree of leaves iteratively
for (var i = 0; i < pPatternStart.length; i++) tmpLeaf = this.addChild(tmpLeaf, pPatternStart, i);
tmpLeaf.PatternStart = pPatternStart;
tmpLeaf.PatternEnd = typeof pPatternEnd === 'string' && pPatternEnd.length > 0 ? pPatternEnd : pPatternStart;
tmpLeaf.Parse = typeof pParser === 'function' ? pParser : typeof pParser === 'string' ? () => {
return pParser;
} : pData => {
return pData;
};
return true;
}
}
module.exports = WordTree;
}, {}],
4: [function (require, module, exports) {
// shim for using process in browser
var process = module.exports = {};
this.settings = Object.assign(tmpSettingsFrom, this.settings);
// cached from whatever global is present so that test runners that stub it
// don't break things. But we need to wrap it in a try catch in case it is
// wrapped in strict mode code which doesn't define any globals. It's inside a
// function because try/catches deoptimize in certain engines.
return this.settings;
}
};
var cachedSetTimeout;
var cachedClearTimeout;
function defaultSetTimout() {
throw new Error('setTimeout has not been defined');
}
function defaultClearTimeout() {
throw new Error('clearTimeout has not been defined');
}
(function () {
try {
if (typeof setTimeout === 'function') {
cachedSetTimeout = setTimeout;
} else {
cachedSetTimeout = defaultSetTimout;
}
} catch (e) {
cachedSetTimeout = defaultSetTimout;
}
try {
if (typeof clearTimeout === 'function') {
cachedClearTimeout = clearTimeout;
} else {
cachedClearTimeout = defaultClearTimeout;
}
} catch (e) {
cachedClearTimeout = defaultClearTimeout;
}
})();
function runTimeout(fun) {
if (cachedSetTimeout === setTimeout) {
//normal enviroments in sane situations
return setTimeout(fun, 0);
}
// if setTimeout wasn't available but was latter defined
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
cachedSetTimeout = setTimeout;
return setTimeout(fun, 0);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedSetTimeout(fun, 0);
} catch (e) {
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedSetTimeout.call(null, fun, 0);
} catch (e) {
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
return cachedSetTimeout.call(this, fun, 0);
}
}
}
function runClearTimeout(marker) {
if (cachedClearTimeout === clearTimeout) {
//normal enviroments in sane situations
return clearTimeout(marker);
}
// if clearTimeout wasn't available but was latter defined
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
cachedClearTimeout = clearTimeout;
return clearTimeout(marker);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedClearTimeout(marker);
} catch (e) {
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedClearTimeout.call(null, marker);
} catch (e) {
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
return cachedClearTimeout.call(this, marker);
}
}
}
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;
function cleanUpNextTick() {
if (!draining || !currentQueue) {
return;
}
draining = false;
if (currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
drainQueue();
}
}
function drainQueue() {
if (draining) {
return;
}
var timeout = runTimeout(cleanUpNextTick);
draining = true;
var len = queue.length;
while (len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
if (currentQueue) {
currentQueue[queueIndex].run();
}
}
queueIndex = -1;
len = queue.length;
}
currentQueue = null;
draining = false;
runClearTimeout(timeout);
}
process.nextTick = function (fun) {
var args = new Array(arguments.length - 1);
if (arguments.length > 1) {
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
}
queue.push(new Item(fun, args));
if (queue.length === 1 && !draining) {
runTimeout(drainQueue);
}
};
// This is for backwards compatibility
function autoConstruct(pSettings)
{
return new FableSettings(pSettings);
}
// v8 likes predictible objects
function Item(fun, array) {
this.fun = fun;
this.array = array;
}
Item.prototype.run = function () {
this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.prependListener = noop;
process.prependOnceListener = noop;
process.listeners = function (name) {
return [];
};
process.binding = function (name) {
throw new Error('process.binding is not supported');
};
process.cwd = function () {
return '/';
};
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
process.umask = function () {
return 0;
};
}, {}],
5: [function (require, module, exports) {
/**
* Simple browser shim loader - assign the npm module to a window global automatically
*
* @license MIT
* @author <steven@velozo.com>
*/
var libNPMModuleWrapper = require('./Fable-Settings.js');
if (typeof window === 'object' && !window.hasOwnProperty('FableSettings')) {
window.FableSettings = libNPMModuleWrapper;
}
module.exports = libNPMModuleWrapper;
}, {
"./Fable-Settings.js": 8
}],
6: [function (require, module, exports) {
module.exports = {
"Product": "ApplicationNameHere",
"ProductVersion": "0.0.0",
"ConfigFile": false,
"LogStreams": [{
"level": "trace"
}]
};
}, {}],
7: [function (require, module, exports) {
(function (process) {
(function () {
/**
* Fable Settings Template Processor
*
* This class allows environment variables to come in via templated expressions, and defaults to be set.
*
* @license MIT
*
* @author Steven Velozo <steven@velozo.com>
* @module Fable Settings
*/
module.exports = {new:autoConstruct, FableSettings:FableSettings};
// Needed to allow environment variables in strings cleanly
const libPrecedent = require('precedent');
class FableSettingsTemplateProcessor {
constructor() {
// Use a no-dependencies templating engine to parse out environment variables
this.templateProcessor = new libPrecedent();
},{"./Fable-Settings-Default":1}]},{},[2])
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJzb3VyY2UvRmFibGUtU2V0dGluZ3MtRGVmYXVsdC5qc29uIiwic291cmNlL0ZhYmxlLVNldHRpbmdzLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNiQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCJtb2R1bGUuZXhwb3J0cz17XG5cdFwiUHJvZHVjdFwiOiBcIkFwcGxpY2F0aW9uTmFtZUhlcmVcIixcblx0XCJQcm9kdWN0VmVyc2lvblwiOiBcIjAuMC4wXCIsXG5cblx0XCJDb25maWdGaWxlXCI6IGZhbHNlLFxuXG5cdFwiTG9nU3RyZWFtc1wiOlxuXHRbXG5cdFx0e1xuXHRcdFx0XCJsZXZlbFwiOiBcInRyYWNlXCJcblx0XHR9XG5cdF1cbn1cbiIsIi8qKlxuKiBGYWJsZSBTZXR0aW5ncyBBZGQtb25cbipcbiogQGxpY2Vuc2UgTUlUXG4qXG4qIEBhdXRob3IgU3RldmVuIFZlbG96byA8c3RldmVuQHZlbG96by5jb20+XG4qIEBtb2R1bGUgRmFibGUgU2V0dGluZ3NcbiovXG5cbi8qKlxuKiBGYWJsZSBTb2x1dGlvbiBTZXR0aW5nc1xuKlxuKiBAY2xhc3MgRmFibGVTZXR0aW5nc1xuKiBAY29uc3RydWN0b3JcbiovXG5cbmNsYXNzIEZhYmxlU2V0dGluZ3Ncbntcblx0Y29uc3RydWN0b3IocEZhYmxlU2V0dGluZ3MpXG5cdHtcblx0XHR0aGlzLmRlZmF1bHQgPSB0aGlzLmJ1aWxkRGVmYXVsdFNldHRpbmdzKCk7XG5cblx0XHQvLyBDb25zdHJ1Y3QgYSBuZXcgc2V0dGluZ3Mgb2JqZWN0XG5cdFx0bGV0IHRtcFNldHRpbmdzID0gdGhpcy5tZXJnZShwRmFibGVTZXR0aW5ncywgdGhpcy5idWlsZERlZmF1bHRTZXR0aW5ncygpKTtcblxuXHRcdC8vIFRoZSBiYXNlIHNldHRpbmdzIG9iamVjdCAod2hhdCB0aGV5IHdlcmUgb24gaW5pdGlhbGl6YXRpb24sIGJlZm9yZSBvdGhlciBhY3RvcnMgaGF2ZSBhbHRlcmVkIHRoZW0pXG5cdFx0dGhpcy5iYXNlID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeSh0bXBTZXR0aW5ncykpO1xuXG5cdFx0aWYgKHRtcFNldHRpbmdzLkRlZmF1bHRDb25maWdGaWxlKVxuXHRcdHtcblx0XHRcdHRyeVxuXHRcdFx0e1xuXHRcdFx0XHQvLyBJZiB0aGVyZSBpcyBhIERFRkFVTFQgY29uZmlndXJhdGlvbiBmaWxlLCB0cnkgdG8gbG9hZCBhbmQgbWVyZ2UgaXQuXG5cdFx0XHRcdHRtcFNldHRpbmdzID0gdGhpcy5tZXJnZShyZXF1aXJlKHRtcFNldHRpbmdzLkRlZmF1bHRDb25maWdGaWxlKSwgdG1wU2V0dGluZ3MpO1xuXHRcdFx0fVxuXHRcdFx0Y2F0Y2ggKHBFeGNlcHRpb24pXG5cdFx0XHR7XG5cdFx0XHRcdC8vIFdoeSB0aGlzPyAgT2Z0ZW4gZm9yIGFuIGFwcCB3ZSB3YW50IHNldHRpbmdzIHRvIHdvcmsgb3V0IG9mIHRoZSBib3gsIGJ1dFxuXHRcdFx0XHQvLyB3b3VsZCBwb3RlbnRpYWxseSB3YW50IHRvIGhhdmUgYSBjb25maWcgZmlsZSBmb3IgY29tcGxleCBzZXR0aW5ncy5cblx0XHRcdFx0Y29uc29sZS5sb2coJ0ZhYmxlLVNldHRpbmdzIFdhcm5pbmc6IERlZmF1bHQgY29uZmlndXJhdGlvbiBmaWxlIHNwZWNpZmllZCBidXQgdGhlcmUgd2FzIGEgcHJvYmxlbSBsb2FkaW5nIGl0LiAgRmFsbGluZyBiYWNrIHRvIGJhc2UuJyk7XG5cdFx0XHRcdGNvbnNvbGUubG9nKCcgICAgIExvYWRpbmcgRXhjZXB0aW9uOiAnK3BFeGNlcHRpb24pO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICh0bXBTZXR0aW5ncy5Db25maWdGaWxlKVxuXHRcdHtcblx0XHRcdHRyeVxuXHRcdFx0e1xuXHRcdFx0XHQvLyBJZiB0aGVyZSBpcyBhIGNvbmZpZ3VyYXRpb24gZmlsZSwgdHJ5IHRvIGxvYWQgYW5kIG1lcmdlIGl0LlxuXHRcdFx0XHR0bXBTZXR0aW5ncyA9IHRoaXMubWVyZ2UocmVxdWlyZSh0bXBTZXR0aW5ncy5Db25maWdGaWxlKSwgdG1wU2V0dGluZ3MpO1xuXHRcdFx0fVxuXHRcdFx0Y2F0Y2ggKHBFeGNlcHRpb24pXG5cdFx0XHR7XG5cdFx0XHRcdC8vIFdoeSB0aGlzPyAgT2Z0ZW4gZm9yIGFuIGFwcCB3ZSB3YW50IHNldHRpbmdzIHRvIHdvcmsgb3V0IG9mIHRoZSBib3gsIGJ1dFxuXHRcdFx0XHQvLyB3b3VsZCBwb3RlbnRpYWxseSB3YW50IHRvIGhhdmUgYSBjb25maWcgZmlsZSBmb3IgY29tcGxleCBzZXR0aW5ncy5cblx0XHRcdFx0Y29uc29sZS5sb2coJ0ZhYmxlLVNldHRpbmdzIFdhcm5pbmc6IENvbmZpZ3VyYXRpb24gZmlsZSBzcGVjaWZpZWQgYnV0IHRoZXJlIHdhcyBhIHByb2JsZW0gbG9hZGluZyBpdC4gIEZhbGxpbmcgYmFjayB0byBiYXNlLicpO1xuXHRcdFx0XHRjb25zb2xlLmxvZygnICAgICBMb2FkaW5nIEV4Y2VwdGlvbjogJytwRXhjZXB0aW9uKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHR0aGlzLnNldHRpbmdzID0gdG1wU2V0dGluZ3M7XG5cdH1cblxuXHQvLyBCdWlsZCBhIGRlZmF1bHQgc2V0dGluZ3Mgb2JqZWN0LiAgVXNlIHRoZSBKU09OIGppbW15IHRvIGVuc3VyZSBpdCBpcyBhbHdheXMgYSBuZXcgb2JqZWN0LlxuXHRidWlsZERlZmF1bHRTZXR0aW5ncygpXG5cdHtcblx0XHRyZXR1cm4gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShyZXF1aXJlKCcuL0ZhYmxlLVNldHRpbmdzLURlZmF1bHQnKSkpXG5cdH1cblxuXHQvLyBNZXJnZSBzb21lIG5ldyBvYmplY3QgaW50byB0aGUgZXhpc3Rpbmcgc2V0dGluZ3MuXG5cdG1lcmdlKHBTZXR0aW5nc0Zyb20sIHBTZXR0aW5nc1RvKVxuXHR7XG5cdFx0Ly8gSWYgYW4gaW52YWxpZCBzZXR0aW5ncyBmcm9tIG9iamVjdCBpcyBwYXNzZWQgaW4gKGUuZy4gb2JqZWN0IGNvbnN0cnVjdG9yIHdpdGhvdXQgcGFzc2luZyBpbiBhbnl0aGluZykgdGhpcyBzaG91bGQgc3RpbGwgd29ya1xuXHRcdGxldCB0bXBTZXR0aW5nc0Zyb20gPSAodHlwZW9mKHBTZXR0aW5nc0Zyb20pID09PSAnb2JqZWN0JykgPyBwU2V0dGluZ3NGcm9tIDoge307XG5cdFx0Ly8gRGVmYXVsdCB0byB0aGUgc2V0dGluZ3Mgb2JqZWN0IGlmIG5vbmUgaXMgcGFzc2VkIGluIGZvciB0aGUgbWVyZ2UuXG5cdFx0bGV0IHRtcFNldHRpbmdzVG8gPSAodHlwZW9mKHBTZXR0aW5nc1RvKSA9PT0gJ29iamVjdCcpID8gcFNldHRpbmdzVG8gOiB0aGlzLnNldHRpbmdzO1xuXG5cdFx0dG1wU2V0dGluZ3NUbyA9IE9iamVjdC5hc3NpZ24odG1wU2V0dGluZ3NUbywgdG1wU2V0dGluZ3NGcm9tKTtcblxuXHRcdHJldHVybiB0bXBTZXR0aW5nc1RvO1xuXHR9XG5cblx0Ly8gRmlsbCBpbiBzZXR0aW5ncyBnYXBzIHdpdGhvdXQgb3ZlcndyaXRpbmcgc2V0dGluZ3MgdGhhdCBhcmUgYWxyZWFkeSB0aGVyZVxuXHRmaWxsKHBTZXR0aW5nc0Zyb20pXG5cdHtcblx0XHQvLyBJZiBhbiBpbnZhbGlkIHNldHRpbmdzIGZyb20gb2JqZWN0IGlzIHBhc3NlZCBpbiAoZS5nLiBvYmplY3QgY29uc3RydWN0b3Igd2l0aG91dCBwYXNzaW5nIGluIGFueXRoaW5nKSB0aGlzIHNob3VsZCBzdGlsbCB3b3JrXG5cdFx0bGV0IHRtcFNldHRpbmdzRnJvbSA9ICh0eXBlb2YocFNldHRpbmdzRnJvbSkgPT09ICdvYmplY3QnKSA/IHBTZXR0aW5nc0Zyb20gOiB7fTtcblxuXHRcdHRoaXMuc2V0dGluZ3MgPSBPYmplY3QuYXNzaWduKHRtcFNldHRpbmdzRnJvbSwgdGhpcy5zZXR0aW5ncyk7XG5cblx0XHRyZXR1cm4gdGhpcy5zZXR0aW5ncztcblx0fVxufTtcblxuLy8gVGhpcyBpcyBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHlcbmZ1bmN0aW9uIGF1dG9Db25zdHJ1Y3QocFNldHRpbmdzKVxue1xuXHRyZXR1cm4gbmV3IEZhYmxlU2V0dGluZ3MocFNldHRpbmdzKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7bmV3OmF1dG9Db25zdHJ1Y3QsIEZhYmxlU2V0dGluZ3M6RmFibGVTZXR0aW5nc307XG4iXX0=
// TODO: Make the environment variable wrap expression demarcation characters configurable?
this.templateProcessor.addPattern('${', '}', pTemplateValue => {
let tmpTemplateValue = pTemplateValue.trim();
let tmpSeparatorIndex = tmpTemplateValue.indexOf('|');
// If there is no pipe, the default value will end up being whatever the variable name is.
let tmpDefaultValue = tmpTemplateValue.substring(tmpSeparatorIndex + 1);
let tmpEnvironmentVariableName = tmpSeparatorIndex > -1 ? tmpTemplateValue.substring(0, tmpSeparatorIndex) : tmpTemplateValue;
if (process.env.hasOwnProperty(tmpEnvironmentVariableName)) {
return process.env[tmpEnvironmentVariableName];
} else {
return tmpDefaultValue;
}
});
}
parseSetting(pString) {
return this.templateProcessor.parseString(pString);
}
}
module.exports = FableSettingsTemplateProcessor;
}).call(this);
}).call(this, require('_process'));
}, {
"_process": 4,
"precedent": 1
}],
8: [function (require, module, exports) {
/**
* Fable Settings Add-on
*
* @license MIT
*
* @author Steven Velozo <steven@velozo.com>
* @module Fable Settings
*/
const libFableSettingsTemplateProcessor = require('./Fable-Settings-TemplateProcessor.js');
class FableSettings {
constructor(pFableSettings) {
// Initialize the settings value template processor
this.settingsTemplateProcessor = new libFableSettingsTemplateProcessor();
// set straight away so anything that uses it respects the initial setting
this._configureEnvTemplating(pFableSettings);
this.default = this.buildDefaultSettings();
// Construct a new settings object
let tmpSettings = this.merge(pFableSettings, this.buildDefaultSettings());
// The base settings object (what they were on initialization, before other actors have altered them)
this.base = JSON.parse(JSON.stringify(tmpSettings));
if (tmpSettings.DefaultConfigFile) {
try {
// If there is a DEFAULT configuration file, try to load and merge it.
tmpSettings = this.merge(require(tmpSettings.DefaultConfigFile), tmpSettings);
} catch (pException) {
// Why this? Often for an app we want settings to work out of the box, but
// would potentially want to have a config file for complex settings.
console.log('Fable-Settings Warning: Default configuration file specified but there was a problem loading it. Falling back to base.');
console.log(' Loading Exception: ' + pException);
}
}
if (tmpSettings.ConfigFile) {
try {
// If there is a configuration file, try to load and merge it.
tmpSettings = this.merge(require(tmpSettings.ConfigFile), tmpSettings);
} catch (pException) {
// Why this? Often for an app we want settings to work out of the box, but
// would potentially want to have a config file for complex settings.
console.log('Fable-Settings Warning: Configuration file specified but there was a problem loading it. Falling back to base.');
console.log(' Loading Exception: ' + pException);
}
}
this.settings = tmpSettings;
}
// Build a default settings object. Use the JSON jimmy to ensure it is always a new object.
buildDefaultSettings() {
return JSON.parse(JSON.stringify(require('./Fable-Settings-Default')));
}
// Update the configuration for environment variable templating based on the current settings object
_configureEnvTemplating(pSettings) {
// default environment variable templating to on
this._PerformEnvTemplating = !pSettings || pSettings.NoEnvReplacement !== true;
}
// Resolve (recursive) any environment variables found in settings object.
_resolveEnv(pSettings) {
for (const tmpKey in pSettings) {
if (typeof pSettings[tmpKey] === 'object') {
this._resolveEnv(pSettings[tmpKey]);
} else if (typeof pSettings[tmpKey] === 'string') {
pSettings[tmpKey] = this.settingsTemplateProcessor.parseSetting(pSettings[tmpKey]);
}
}
}
/**
* Check to see if a value is an object (but not an array).
*/
_isObject(value) {
return typeof value === 'object' && !Array.isArray(value);
}
/**
* Merge two plain objects. Keys that are objects in both will be merged property-wise.
*/
_deepMergeObjects(toObject, fromObject) {
if (!fromObject || !this._isObject(fromObject)) {
return;
}
Object.keys(fromObject).forEach(key => {
const fromValue = fromObject[key];
if (this._isObject(fromValue)) {
const toValue = toObject[key];
if (toValue && this._isObject(toValue)) {
// both are objects, so do a recursive merge
this._deepMergeObjects(toValue, fromValue);
return;
}
}
toObject[key] = fromValue;
});
return toObject;
}
// Merge some new object into the existing settings.
merge(pSettingsFrom, pSettingsTo) {
// If an invalid settings from object is passed in (e.g. object constructor without passing in anything) this should still work
let tmpSettingsFrom = typeof pSettingsFrom === 'object' ? pSettingsFrom : {};
// Default to the settings object if none is passed in for the merge.
let tmpSettingsTo = typeof pSettingsTo === 'object' ? pSettingsTo : this.settings;
// do not mutate the From object property values
let tmpSettingsFromCopy = JSON.parse(JSON.stringify(tmpSettingsFrom));
tmpSettingsTo = this._deepMergeObjects(tmpSettingsTo, tmpSettingsFromCopy);
if (this._PerformEnvTemplating) {
this._resolveEnv(tmpSettingsTo);
}
// Update env tempating config, since we just updated the config object, and it may have changed
this._configureEnvTemplating(tmpSettingsTo);
return tmpSettingsTo;
}
// Fill in settings gaps without overwriting settings that are already there
fill(pSettingsFrom) {
// If an invalid settings from object is passed in (e.g. object constructor without passing in anything) this should still work
let tmpSettingsFrom = typeof pSettingsFrom === 'object' ? pSettingsFrom : {};
// do not mutate the From object property values
let tmpSettingsFromCopy = JSON.parse(JSON.stringify(tmpSettingsFrom));
this.settings = this._deepMergeObjects(tmpSettingsFromCopy, this.settings);
return this.settings;
}
}
;
// This is for backwards compatibility
function autoConstruct(pSettings) {
return new FableSettings(pSettings);
}
module.exports = {
new: autoConstruct,
FableSettings: FableSettings
};
}, {
"./Fable-Settings-Default": 6,
"./Fable-Settings-TemplateProcessor.js": 7
}]
}, {}, [5])(5);
});

@@ -1,2 +0,59 @@

!function(){return function e(t,i,n){function r(s,l){if(!i[s]){if(!t[s]){var a="function"==typeof require&&require;if(!l&&a)return a(s,!0);if(o)return o(s,!0);var f=new Error("Cannot find module '"+s+"'");throw f.code="MODULE_NOT_FOUND",f}var u=i[s]={exports:{}};t[s][0].call(u.exports,function(e){return r(t[s][1][e]||e)},u,u.exports,e,t,i,n)}return i[s].exports}for(var o="function"==typeof require&&require,s=0;s<n.length;s++)r(n[s]);return r}}()({1:[function(e,t,i){t.exports={Product:"ApplicationNameHere",ProductVersion:"0.0.0",ConfigFile:!1,LogStreams:[{level:"trace"}]}},{}],2:[function(e,t,i){class n{constructor(t){this.default=this.buildDefaultSettings();let i=this.merge(t,this.buildDefaultSettings());if(this.base=JSON.parse(JSON.stringify(i)),i.DefaultConfigFile)try{i=this.merge(e(i.DefaultConfigFile),i)}catch(e){console.log("Fable-Settings Warning: Default configuration file specified but there was a problem loading it. Falling back to base."),console.log(" Loading Exception: "+e)}if(i.ConfigFile)try{i=this.merge(e(i.ConfigFile),i)}catch(e){console.log("Fable-Settings Warning: Configuration file specified but there was a problem loading it. Falling back to base."),console.log(" Loading Exception: "+e)}this.settings=i}buildDefaultSettings(){return JSON.parse(JSON.stringify(e("./Fable-Settings-Default")))}merge(e,t){let i="object"==typeof e?e:{},n="object"==typeof t?t:this.settings;return n=Object.assign(n,i)}fill(e){let t="object"==typeof e?e:{};return this.settings=Object.assign(t,this.settings),this.settings}}t.exports={new:function(e){return new n(e)},FableSettings:n}},{"./Fable-Settings-Default":1}]},{},[2]);
!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).FableSettings=t()}}((function(){return function t(e,r,n){function i(o,a){if(!r[o]){if(!e[o]){var u="function"==typeof require&&require;if(!a&&u)return u(o,!0);if(s)return s(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var c=r[o]={exports:{}};e[o][0].call(c.exports,(function(t){return i(e[o][1][t]||t)}),c,c.exports,t,e,r,n)}return r[o].exports}for(var s="function"==typeof require&&require,o=0;o<n.length;o++)i(n[o]);return i}({1:[function(t,e,r){
/**
* Precedent Meta-Templating
*
* @license MIT
*
* @author Steven Velozo <steven@velozo.com>
*
* @description Process text streams, parsing out meta-template expressions.
*/
var n=t("./WordTree.js"),i=t("./StringParser.js");e.exports=class{constructor(){this.WordTree=new n,this.StringParser=new i,this.ParseTree=this.WordTree.ParseTree}addPattern(t,e,r){return this.WordTree.addPattern(t,e,r)}parseString(t){return this.StringParser.parseString(t,this.ParseTree)}}},{"./StringParser.js":2,"./WordTree.js":3}],2:[function(t,e,r){e.exports=
/**
* String Parser
*
* @license MIT
*
* @author Steven Velozo <steven@velozo.com>
*
* @description Parse a string, properly processing each matched token in the word tree.
*/
class{constructor(){}newParserState(t){return{ParseTree:t,Output:"",OutputBuffer:"",Pattern:!1,PatternMatch:!1,PatternMatchOutputBuffer:""}}assignNode(t,e){e.PatternMatch=t,e.PatternMatch.hasOwnProperty("PatternEnd")&&(e.Pattern=e.PatternMatch)}appendOutputBuffer(t,e){e.OutputBuffer+=t}flushOutputBuffer(t){t.Output+=t.OutputBuffer,t.OutputBuffer=""}checkPatternEnd(t){t.OutputBuffer.length>=t.Pattern.PatternEnd.length+t.Pattern.PatternStart.length&&t.OutputBuffer.substr(-t.Pattern.PatternEnd.length)===t.Pattern.PatternEnd&&(t.OutputBuffer=t.Pattern.Parse(t.OutputBuffer.substr(t.Pattern.PatternStart.length,t.OutputBuffer.length-(t.Pattern.PatternStart.length+t.Pattern.PatternEnd.length))),this.flushOutputBuffer(t),t.Pattern=!1,t.PatternMatch=!1)}parseCharacter(t,e){!e.PatternMatch&&e.ParseTree.hasOwnProperty(t)?(this.assignNode(e.ParseTree[t],e),this.appendOutputBuffer(t,e)):e.PatternMatch?(e.PatternMatch.hasOwnProperty(t)&&this.assignNode(e.PatternMatch[t],e),this.appendOutputBuffer(t,e),e.Pattern&&this.checkPatternEnd(e)):e.Output+=t}parseString(t,e){let r=this.newParserState(e);for(var n=0;n<t.length;n++)this.parseCharacter(t[n],r);return this.flushOutputBuffer(r),r.Output}}},{}],3:[function(t,e,r){e.exports=
/**
* Word Tree
*
* @license MIT
*
* @author Steven Velozo <steven@velozo.com>
*
* @description Create a tree (directed graph) of Javascript objects, one character per object.
*/
class{constructor(){this.ParseTree={}}addChild(t,e,r){return t.hasOwnProperty(e[r])||(t[e[r]]={}),t[e[r]]}addPattern(t,e,r){if(t.length<1)return!1;if("string"==typeof e&&e.length<1)return!1;let n=this.ParseTree;for(var i=0;i<t.length;i++)n=this.addChild(n,t,i);return n.PatternStart=t,n.PatternEnd="string"==typeof e&&e.length>0?e:t,n.Parse="function"==typeof r?r:"string"==typeof r?()=>r:t=>t,!0}}},{}],4:[function(t,e,r){var n,i,s=e.exports={};function o(){throw new Error("setTimeout has not been defined")}function a(){throw new Error("clearTimeout has not been defined")}function u(t){if(n===setTimeout)return setTimeout(t,0);if((n===o||!n)&&setTimeout)return n=setTimeout,setTimeout(t,0);try{return n(t,0)}catch(e){try{return n.call(null,t,0)}catch(e){return n.call(this,t,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:o}catch(t){n=o}try{i="function"==typeof clearTimeout?clearTimeout:a}catch(t){i=a}}();var f,c=[],l=!1,h=-1;function p(){l&&f&&(l=!1,f.length?c=f.concat(c):h=-1,c.length&&g())}function g(){if(!l){var t=u(p);l=!0;for(var e=c.length;e;){for(f=c,c=[];++h<e;)f&&f[h].run();h=-1,e=c.length}f=null,l=!1,function(t){if(i===clearTimeout)return clearTimeout(t);if((i===a||!i)&&clearTimeout)return i=clearTimeout,clearTimeout(t);try{return i(t)}catch(e){try{return i.call(null,t)}catch(e){return i.call(this,t)}}}(t)}}function d(t,e){this.fun=t,this.array=e}function P(){}s.nextTick=function(t){var e=new Array(arguments.length-1);if(arguments.length>1)for(var r=1;r<arguments.length;r++)e[r-1]=arguments[r];c.push(new d(t,e)),1!==c.length||l||u(g)},d.prototype.run=function(){this.fun.apply(null,this.array)},s.title="browser",s.browser=!0,s.env={},s.argv=[],s.version="",s.versions={},s.on=P,s.addListener=P,s.once=P,s.off=P,s.removeListener=P,s.removeAllListeners=P,s.emit=P,s.prependListener=P,s.prependOnceListener=P,s.listeners=function(t){return[]},s.binding=function(t){throw new Error("process.binding is not supported")},s.cwd=function(){return"/"},s.chdir=function(t){throw new Error("process.chdir is not supported")},s.umask=function(){return 0}},{}],5:[function(t,e,r){
/**
* Simple browser shim loader - assign the npm module to a window global automatically
*
* @license MIT
* @author <steven@velozo.com>
*/
var n=t("./Fable-Settings.js");"object"!=typeof window||window.hasOwnProperty("FableSettings")||(window.FableSettings=n),e.exports=n},{"./Fable-Settings.js":8}],6:[function(t,e,r){e.exports={Product:"ApplicationNameHere",ProductVersion:"0.0.0",ConfigFile:!1,LogStreams:[{level:"trace"}]}},{}],7:[function(t,e,r){(function(r){(function(){
/**
* Fable Settings Template Processor
*
* This class allows environment variables to come in via templated expressions, and defaults to be set.
*
* @license MIT
*
* @author Steven Velozo <steven@velozo.com>
* @module Fable Settings
*/
const n=t("precedent");e.exports=class{constructor(){this.templateProcessor=new n,this.templateProcessor.addPattern("${","}",(t=>{let e=t.trim(),n=e.indexOf("|"),i=e.substring(n+1),s=n>-1?e.substring(0,n):e;return r.env.hasOwnProperty(s)?r.env[s]:i}))}parseSetting(t){return this.templateProcessor.parseString(t)}}}).call(this)}).call(this,t("_process"))},{_process:4,precedent:1}],8:[function(t,e,r){
/**
* Fable Settings Add-on
*
* @license MIT
*
* @author Steven Velozo <steven@velozo.com>
* @module Fable Settings
*/
const n=t("./Fable-Settings-TemplateProcessor.js");class i{constructor(e){this.settingsTemplateProcessor=new n,this._configureEnvTemplating(e),this.default=this.buildDefaultSettings();let r=this.merge(e,this.buildDefaultSettings());if(this.base=JSON.parse(JSON.stringify(r)),r.DefaultConfigFile)try{r=this.merge(t(r.DefaultConfigFile),r)}catch(t){console.log("Fable-Settings Warning: Default configuration file specified but there was a problem loading it. Falling back to base."),console.log(" Loading Exception: "+t)}if(r.ConfigFile)try{r=this.merge(t(r.ConfigFile),r)}catch(t){console.log("Fable-Settings Warning: Configuration file specified but there was a problem loading it. Falling back to base."),console.log(" Loading Exception: "+t)}this.settings=r}buildDefaultSettings(){return JSON.parse(JSON.stringify(t("./Fable-Settings-Default")))}_configureEnvTemplating(t){this._PerformEnvTemplating=!t||!0!==t.NoEnvReplacement}_resolveEnv(t){for(const e in t)"object"==typeof t[e]?this._resolveEnv(t[e]):"string"==typeof t[e]&&(t[e]=this.settingsTemplateProcessor.parseSetting(t[e]))}_isObject(t){return"object"==typeof t&&!Array.isArray(t)}_deepMergeObjects(t,e){if(e&&this._isObject(e))return Object.keys(e).forEach((r=>{const n=e[r];if(this._isObject(n)){const e=t[r];if(e&&this._isObject(e))return void this._deepMergeObjects(e,n)}t[r]=n})),t}merge(t,e){let r="object"==typeof t?t:{},n="object"==typeof e?e:this.settings,i=JSON.parse(JSON.stringify(r));return n=this._deepMergeObjects(n,i),this._PerformEnvTemplating&&this._resolveEnv(n),this._configureEnvTemplating(n),n}fill(t){let e="object"==typeof t?t:{},r=JSON.parse(JSON.stringify(e));return this.settings=this._deepMergeObjects(r,this.settings),this.settings}}e.exports={new:function(t){return new i(t)},FableSettings:i}},{"./Fable-Settings-Default":6,"./Fable-Settings-TemplateProcessor.js":7}]},{},[5])(5)}));
//# sourceMappingURL=fable-settings.min.js.map

78

gulpfile.js
'use strict';
// We aren't abstracting this yet but here's the ... "Config"
const _CONFIG = (
{
// The input source file that should be passed to browserify:
// (if you need to auto-instantiate an object, for instance)
EntrypointInputSourceFile: `${__dirname}/source/Fable-Settings-Browser-Shim.js`,
// The name of the packaged object to be passed to browserify:
// (browserify sets this to global scope and window.SOMEOBJECTNAMEHERE where SOMEOBJECTNAMEHERE is the string below)
LibraryObjectName: `FableSettings`,
// The folder to write the library files and maps out to:
LibraryOutputFolder: `${__dirname}/dist/`,
// The name of the unminified version of the packaged library, for easy debugging:
LibraryUniminifiedFileName: `fable-settings.js`,
// The name of the minified version of the packaged library, for production release:
LibraryMinifiedFileName: `fable-settings.min.js`
});
// ---> Boilerplate Browser Uglification and Packaging <--- \\
const libBrowserify = require('browserify');

@@ -9,34 +32,31 @@ const libGulp = require('gulp');

const libTerser = require('gulp-terser');
const libSourcemaps = require('gulp-sourcemaps');
const libGulpUtil = require('gulp-util');
const libGulpBabel = require('gulp-babel');
const libBabel = require('gulp-babel');
const libTerser = require('gulp-terser');
// Build the module for the browser
// This gulp task is taken from the gulp recipe repository:
// https://github.com/gulpjs/gulp/blob/master/docs/recipes/browserify-uglify-sourcemap.md
libGulp.task('minified',
() => {
// set up the custom browserify instance for this task
var tmpBrowserify = libBrowserify(
{
entries: './source/Fable-Settings.js',
debug: true
});
//tmpBrowserify.ignore('underscore');
return tmpBrowserify.bundle()
.pipe(libVinylSourceStream('fable-settings.min.js'))
.pipe(libVinylBuffer())
.pipe(libSourcemaps.init({loadMaps: true}))
// Add transformation tasks to the pipeline here.
.pipe(libTerser())
.on('error', libGulpUtil.log)
.pipe(libSourcemaps.write('./'))
.pipe(libGulp.dest('./dist/'));
() => {
// set up the custom browserify instance for this task
var tmpBrowserify = libBrowserify(
{
entries: _CONFIG.EntrypointInputSourceFile,
standalone: _CONFIG.LibraryObjectName,
debug: true
});
return tmpBrowserify.bundle()
.pipe(libVinylSourceStream(_CONFIG.LibraryMinifiedFileName))
.pipe(libVinylBuffer())
.pipe(libSourcemaps.init({loadMaps: true}))
// Add transformation tasks to the pipeline here.
.pipe(libBabel())
.pipe(libTerser())
.on('error', libGulpUtil.log)
.pipe(libSourcemaps.write('./'))
.pipe(libGulp.dest(_CONFIG.LibraryOutputFolder));
});
// Build the module for the browser
// This gulp task is taken from the gulp recipe repository:
// https://github.com/gulpjs/gulp/blob/master/docs/recipes/browserify-uglify-sourcemap.md
libGulp.task('debug',

@@ -47,3 +67,4 @@ () => {

{
entries: './source/Fable-Settings.js',
entries: _CONFIG.EntrypointInputSourceFile,
standalone: _CONFIG.LibraryObjectName,
debug: true

@@ -53,6 +74,7 @@ });

return tmpBrowserify.bundle()
.pipe(libVinylSourceStream('fable-settings.js'))
.pipe(libVinylSourceStream(_CONFIG.LibraryUniminifiedFileName))
.pipe(libVinylBuffer())
.pipe(libBabel())
.on('error', libGulpUtil.log)
.pipe(libGulp.dest('./dist/'));
.pipe(libGulp.dest(_CONFIG.LibraryOutputFolder));
});

@@ -64,2 +86,2 @@

libGulp.series('debug', 'minified')
);
);
{
"name": "fable-settings",
"version": "2.0.5",
"version": "3.0.0",
"description": "A simple, tolerant configuration chain.",

@@ -8,5 +8,26 @@ "main": "source/Fable-Settings.js",

"start": "node source/Fable-Settings.js",
"coverage": "nyc npm run test --reporter=lcov",
"test": "./node_modules/mocha/bin/_mocha -u tdd -R spec"
"coverage": "./node_modules/.bin/nyc --reporter=lcov --reporter=text-lcov ./node_modules/mocha/bin/_mocha -- -u tdd -R spec",
"test": "./node_modules/.bin/mocha -u tdd -R spec",
"build": "./node_modules/.bin/gulp build",
"docker-dev-build-image": "docker build ./ -f Dockerfile_LUXURYCode -t retold/fable-settings:local",
"docker-dev-run": "docker run -it -d --name retold-fable-settings-dev -p 30003:8080 -v \"$PWD/.config:/home/coder/.config\" -v \"$PWD:/home/coder/fable-settings\" -u \"$(id -u):$(id -g)\" -e \"DOCKER_USER=$USER\" retold/fable-settings:local"
},
"mocha": {
"diff": true,
"extension": [
"js"
],
"package": "./package.json",
"reporter": "spec",
"slow": "75",
"timeout": "5000",
"ui": "tdd",
"watch-files": [
"source/**/*.js",
"test/**/*.js"
],
"watch-ignore": [
"lib/vendor"
]
},
"repository": {

@@ -26,14 +47,11 @@ "type": "git",

"devDependencies": {
"@babel/core": "^7.4.4",
"@babel/preset-env": "^7.4.4",
"async": "^2.6.2",
"browserify": "^16.2.3",
"chai": "4.2.0",
"browserify": "^17.0.0",
"chai": "4.3.7",
"gulp": "^4.0.2",
"gulp-babel": "^8.0.0",
"gulp-sourcemaps": "^2.6.5",
"gulp-terser": "^1.1.7",
"gulp-sourcemaps": "^3.0.0",
"gulp-terser": "^2.1.0",
"gulp-util": "^3.0.8",
"mocha": "6.1.4",
"nyc": "^14.1.0",
"mocha": "10.2.0",
"nyc": "^15.1.0",
"vinyl-buffer": "^1.0.1",

@@ -43,4 +61,4 @@ "vinyl-source-stream": "^2.0.0"

"dependencies": {
"match-all": "^1.2.6"
"precedent": "^1.0.9"
}
}

@@ -9,13 +9,4 @@ /**

*/
const libFableSettingsTemplateProcessor = require('./Fable-Settings-TemplateProcessor.js');
// needed since String.matchAll wasn't added to node until v12
const libMatchAll = require('match-all');
/**
* Fable Solution Settings
*
* @class FableSettings
* @constructor
*/
class FableSettings

@@ -25,2 +16,5 @@ {

{
// Initialize the settings value template processor
this.settingsTemplateProcessor = new libFableSettingsTemplateProcessor();
// set straight away so anything that uses it respects the initial setting

@@ -90,26 +84,9 @@ this._configureEnvTemplating(pFableSettings);

{
const tmpValue = pSettings[tmpKey];
if (typeof(tmpValue) === 'object') // && !Array.isArray(tmpValue))
if (typeof(pSettings[tmpKey]) === 'object')
{
this._resolveEnv(tmpValue);
this._resolveEnv(pSettings[tmpKey]);
}
else if (typeof(tmpValue) === 'string')
else if (typeof(pSettings[tmpKey]) === 'string')
{
if (tmpValue.indexOf('${') >= 0)
{
//pick out and resolve env constiables from the settings value.
const tmpMatches = libMatchAll(tmpValue, /\$\{(.*?)\}/g).toArray();
tmpMatches.forEach((tmpMatch) =>
{
//format: VAR_NAME|DEFAULT_VALUE
const tmpParts = tmpMatch.split('|');
let tmpResolvedValue = process.env[tmpParts[0]] || '';
if (!tmpResolvedValue && tmpParts.length > 1)
{
tmpResolvedValue = tmpParts[1];
}
pSettings[tmpKey] = pSettings[tmpKey].replace('${' + tmpMatch + '}', tmpResolvedValue);
});
}
pSettings[tmpKey] = this.settingsTemplateProcessor.parseSetting(pSettings[tmpKey]);
}

@@ -170,3 +147,3 @@ }

}
// update env tempating config, since we just updated the config object, and it may have changed
// Update env tempating config, since we just updated the config object, and it may have changed
this._configureEnvTemplating(tmpSettingsTo);

@@ -198,2 +175,2 @@

module.exports = {new:autoConstruct, FableSettings:FableSettings};
module.exports = {new:autoConstruct, FableSettings:FableSettings};

@@ -79,2 +79,11 @@ /**

(
'deep merging with a bad object passed in',
function()
{
var tmpFableSettings = require('../source/Fable-Settings.js').new({Product:'TestProduct1'});
Expect(tmpFableSettings._deepMergeObjects({},null)).to.be.undefined;
}
);
test
(
'manually defining a settings object',

@@ -81,0 +90,0 @@ function()

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc