orator 3.0.0 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/orator.js +986 -0
- package/dist/orator.min.js +135 -0
- package/dist/orator.min.js.map +1 -0
- package/gulpfile.js +83 -0
- package/package.json +4 -2
- package/source/Orator-Browser-Shim.js +14 -0
- package/source/Orator-Default-ServiceServers-Web.js +21 -0
- package/source/Orator-ServiceServer-IPC.js +7 -5
package/dist/orator.js
ADDED
|
@@ -0,0 +1,986 @@
|
|
|
1
|
+
(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.Orator=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){(function(global){(function(){'use strict';var objectAssign=require('object-assign');// compare and isBuffer taken from https://github.com/feross/buffer/blob/680e9e5e488f22aac27599a57dc844a6315928dd/index.js
|
|
2
|
+
// original notice:
|
|
3
|
+
/*!
|
|
4
|
+
* The buffer module from node.js, for the browser.
|
|
5
|
+
*
|
|
6
|
+
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/function compare(a,b){if(a===b){return 0;}var x=a.length;var y=b.length;for(var i=0,len=Math.min(x,y);i<len;++i){if(a[i]!==b[i]){x=a[i];y=b[i];break;}}if(x<y){return-1;}if(y<x){return 1;}return 0;}function isBuffer(b){if(global.Buffer&&typeof global.Buffer.isBuffer==='function'){return global.Buffer.isBuffer(b);}return!!(b!=null&&b._isBuffer);}// based on node assert, original notice:
|
|
9
|
+
// NB: The URL to the CommonJS spec is kept just for tradition.
|
|
10
|
+
// node-assert has evolved a lot since then, both in API and behavior.
|
|
11
|
+
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
|
|
12
|
+
//
|
|
13
|
+
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
|
|
14
|
+
//
|
|
15
|
+
// Originally from narwhal.js (http://narwhaljs.org)
|
|
16
|
+
// Copyright (c) 2009 Thomas Robinson <280north.com>
|
|
17
|
+
//
|
|
18
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
19
|
+
// of this software and associated documentation files (the 'Software'), to
|
|
20
|
+
// deal in the Software without restriction, including without limitation the
|
|
21
|
+
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
22
|
+
// sell copies of the Software, and to permit persons to whom the Software is
|
|
23
|
+
// furnished to do so, subject to the following conditions:
|
|
24
|
+
//
|
|
25
|
+
// The above copyright notice and this permission notice shall be included in
|
|
26
|
+
// all copies or substantial portions of the Software.
|
|
27
|
+
//
|
|
28
|
+
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
29
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
30
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
31
|
+
// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
32
|
+
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
33
|
+
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
34
|
+
var util=require('util/');var hasOwn=Object.prototype.hasOwnProperty;var pSlice=Array.prototype.slice;var functionsHaveNames=function(){return function foo(){}.name==='foo';}();function pToString(obj){return Object.prototype.toString.call(obj);}function isView(arrbuf){if(isBuffer(arrbuf)){return false;}if(typeof global.ArrayBuffer!=='function'){return false;}if(typeof ArrayBuffer.isView==='function'){return ArrayBuffer.isView(arrbuf);}if(!arrbuf){return false;}if(arrbuf instanceof DataView){return true;}if(arrbuf.buffer&&arrbuf.buffer instanceof ArrayBuffer){return true;}return false;}// 1. The assert module provides functions that throw
|
|
35
|
+
// AssertionError's when particular conditions are not met. The
|
|
36
|
+
// assert module must conform to the following interface.
|
|
37
|
+
var assert=module.exports=ok;// 2. The AssertionError is defined in assert.
|
|
38
|
+
// new assert.AssertionError({ message: message,
|
|
39
|
+
// actual: actual,
|
|
40
|
+
// expected: expected })
|
|
41
|
+
var regex=/\s*function\s+([^\(\s]*)\s*/;// based on https://github.com/ljharb/function.prototype.name/blob/adeeeec8bfcc6068b187d7d9fb3d5bb1d3a30899/implementation.js
|
|
42
|
+
function getName(func){if(!util.isFunction(func)){return;}if(functionsHaveNames){return func.name;}var str=func.toString();var match=str.match(regex);return match&&match[1];}assert.AssertionError=function AssertionError(options){this.name='AssertionError';this.actual=options.actual;this.expected=options.expected;this.operator=options.operator;if(options.message){this.message=options.message;this.generatedMessage=false;}else{this.message=getMessage(this);this.generatedMessage=true;}var stackStartFunction=options.stackStartFunction||fail;if(Error.captureStackTrace){Error.captureStackTrace(this,stackStartFunction);}else{// non v8 browsers so we can have a stacktrace
|
|
43
|
+
var err=new Error();if(err.stack){var out=err.stack;// try to strip useless frames
|
|
44
|
+
var fn_name=getName(stackStartFunction);var idx=out.indexOf('\n'+fn_name);if(idx>=0){// once we have located the function frame
|
|
45
|
+
// we need to strip out everything before it (and its line)
|
|
46
|
+
var next_line=out.indexOf('\n',idx+1);out=out.substring(next_line+1);}this.stack=out;}}};// assert.AssertionError instanceof Error
|
|
47
|
+
util.inherits(assert.AssertionError,Error);function truncate(s,n){if(typeof s==='string'){return s.length<n?s:s.slice(0,n);}else{return s;}}function inspect(something){if(functionsHaveNames||!util.isFunction(something)){return util.inspect(something);}var rawname=getName(something);var name=rawname?': '+rawname:'';return'[Function'+name+']';}function getMessage(self){return truncate(inspect(self.actual),128)+' '+self.operator+' '+truncate(inspect(self.expected),128);}// At present only the three keys mentioned above are used and
|
|
48
|
+
// understood by the spec. Implementations or sub modules can pass
|
|
49
|
+
// other keys to the AssertionError's constructor - they will be
|
|
50
|
+
// ignored.
|
|
51
|
+
// 3. All of the following functions must throw an AssertionError
|
|
52
|
+
// when a corresponding condition is not met, with a message that
|
|
53
|
+
// may be undefined if not provided. All assertion methods provide
|
|
54
|
+
// both the actual and expected values to the assertion error for
|
|
55
|
+
// display purposes.
|
|
56
|
+
function fail(actual,expected,message,operator,stackStartFunction){throw new assert.AssertionError({message:message,actual:actual,expected:expected,operator:operator,stackStartFunction:stackStartFunction});}// EXTENSION! allows for well behaved errors defined elsewhere.
|
|
57
|
+
assert.fail=fail;// 4. Pure assertion tests whether a value is truthy, as determined
|
|
58
|
+
// by !!guard.
|
|
59
|
+
// assert.ok(guard, message_opt);
|
|
60
|
+
// This statement is equivalent to assert.equal(true, !!guard,
|
|
61
|
+
// message_opt);. To test strictly for the value true, use
|
|
62
|
+
// assert.strictEqual(true, guard, message_opt);.
|
|
63
|
+
function ok(value,message){if(!value)fail(value,true,message,'==',assert.ok);}assert.ok=ok;// 5. The equality assertion tests shallow, coercive equality with
|
|
64
|
+
// ==.
|
|
65
|
+
// assert.equal(actual, expected, message_opt);
|
|
66
|
+
assert.equal=function equal(actual,expected,message){if(actual!=expected)fail(actual,expected,message,'==',assert.equal);};// 6. The non-equality assertion tests for whether two objects are not equal
|
|
67
|
+
// with != assert.notEqual(actual, expected, message_opt);
|
|
68
|
+
assert.notEqual=function notEqual(actual,expected,message){if(actual==expected){fail(actual,expected,message,'!=',assert.notEqual);}};// 7. The equivalence assertion tests a deep equality relation.
|
|
69
|
+
// assert.deepEqual(actual, expected, message_opt);
|
|
70
|
+
assert.deepEqual=function deepEqual(actual,expected,message){if(!_deepEqual(actual,expected,false)){fail(actual,expected,message,'deepEqual',assert.deepEqual);}};assert.deepStrictEqual=function deepStrictEqual(actual,expected,message){if(!_deepEqual(actual,expected,true)){fail(actual,expected,message,'deepStrictEqual',assert.deepStrictEqual);}};function _deepEqual(actual,expected,strict,memos){// 7.1. All identical values are equivalent, as determined by ===.
|
|
71
|
+
if(actual===expected){return true;}else if(isBuffer(actual)&&isBuffer(expected)){return compare(actual,expected)===0;// 7.2. If the expected value is a Date object, the actual value is
|
|
72
|
+
// equivalent if it is also a Date object that refers to the same time.
|
|
73
|
+
}else if(util.isDate(actual)&&util.isDate(expected)){return actual.getTime()===expected.getTime();// 7.3 If the expected value is a RegExp object, the actual value is
|
|
74
|
+
// equivalent if it is also a RegExp object with the same source and
|
|
75
|
+
// properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
|
|
76
|
+
}else if(util.isRegExp(actual)&&util.isRegExp(expected)){return actual.source===expected.source&&actual.global===expected.global&&actual.multiline===expected.multiline&&actual.lastIndex===expected.lastIndex&&actual.ignoreCase===expected.ignoreCase;// 7.4. Other pairs that do not both pass typeof value == 'object',
|
|
77
|
+
// equivalence is determined by ==.
|
|
78
|
+
}else if((actual===null||typeof actual!=='object')&&(expected===null||typeof expected!=='object')){return strict?actual===expected:actual==expected;// If both values are instances of typed arrays, wrap their underlying
|
|
79
|
+
// ArrayBuffers in a Buffer each to increase performance
|
|
80
|
+
// This optimization requires the arrays to have the same type as checked by
|
|
81
|
+
// Object.prototype.toString (aka pToString). Never perform binary
|
|
82
|
+
// comparisons for Float*Arrays, though, since e.g. +0 === -0 but their
|
|
83
|
+
// bit patterns are not identical.
|
|
84
|
+
}else if(isView(actual)&&isView(expected)&&pToString(actual)===pToString(expected)&&!(actual instanceof Float32Array||actual instanceof Float64Array)){return compare(new Uint8Array(actual.buffer),new Uint8Array(expected.buffer))===0;// 7.5 For all other Object pairs, including Array objects, equivalence is
|
|
85
|
+
// determined by having the same number of owned properties (as verified
|
|
86
|
+
// with Object.prototype.hasOwnProperty.call), the same set of keys
|
|
87
|
+
// (although not necessarily the same order), equivalent values for every
|
|
88
|
+
// corresponding key, and an identical 'prototype' property. Note: this
|
|
89
|
+
// accounts for both named and indexed properties on Arrays.
|
|
90
|
+
}else if(isBuffer(actual)!==isBuffer(expected)){return false;}else{memos=memos||{actual:[],expected:[]};var actualIndex=memos.actual.indexOf(actual);if(actualIndex!==-1){if(actualIndex===memos.expected.indexOf(expected)){return true;}}memos.actual.push(actual);memos.expected.push(expected);return objEquiv(actual,expected,strict,memos);}}function isArguments(object){return Object.prototype.toString.call(object)=='[object Arguments]';}function objEquiv(a,b,strict,actualVisitedObjects){if(a===null||a===undefined||b===null||b===undefined)return false;// if one is a primitive, the other must be same
|
|
91
|
+
if(util.isPrimitive(a)||util.isPrimitive(b))return a===b;if(strict&&Object.getPrototypeOf(a)!==Object.getPrototypeOf(b))return false;var aIsArgs=isArguments(a);var bIsArgs=isArguments(b);if(aIsArgs&&!bIsArgs||!aIsArgs&&bIsArgs)return false;if(aIsArgs){a=pSlice.call(a);b=pSlice.call(b);return _deepEqual(a,b,strict);}var ka=objectKeys(a);var kb=objectKeys(b);var key,i;// having the same number of owned properties (keys incorporates
|
|
92
|
+
// hasOwnProperty)
|
|
93
|
+
if(ka.length!==kb.length)return false;//the same set of keys (although not necessarily the same order),
|
|
94
|
+
ka.sort();kb.sort();//~~~cheap key test
|
|
95
|
+
for(i=ka.length-1;i>=0;i--){if(ka[i]!==kb[i])return false;}//equivalent values for every corresponding key, and
|
|
96
|
+
//~~~possibly expensive deep test
|
|
97
|
+
for(i=ka.length-1;i>=0;i--){key=ka[i];if(!_deepEqual(a[key],b[key],strict,actualVisitedObjects))return false;}return true;}// 8. The non-equivalence assertion tests for any deep inequality.
|
|
98
|
+
// assert.notDeepEqual(actual, expected, message_opt);
|
|
99
|
+
assert.notDeepEqual=function notDeepEqual(actual,expected,message){if(_deepEqual(actual,expected,false)){fail(actual,expected,message,'notDeepEqual',assert.notDeepEqual);}};assert.notDeepStrictEqual=notDeepStrictEqual;function notDeepStrictEqual(actual,expected,message){if(_deepEqual(actual,expected,true)){fail(actual,expected,message,'notDeepStrictEqual',notDeepStrictEqual);}}// 9. The strict equality assertion tests strict equality, as determined by ===.
|
|
100
|
+
// assert.strictEqual(actual, expected, message_opt);
|
|
101
|
+
assert.strictEqual=function strictEqual(actual,expected,message){if(actual!==expected){fail(actual,expected,message,'===',assert.strictEqual);}};// 10. The strict non-equality assertion tests for strict inequality, as
|
|
102
|
+
// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
|
|
103
|
+
assert.notStrictEqual=function notStrictEqual(actual,expected,message){if(actual===expected){fail(actual,expected,message,'!==',assert.notStrictEqual);}};function expectedException(actual,expected){if(!actual||!expected){return false;}if(Object.prototype.toString.call(expected)=='[object RegExp]'){return expected.test(actual);}try{if(actual instanceof expected){return true;}}catch(e){// Ignore. The instanceof check doesn't work for arrow functions.
|
|
104
|
+
}if(Error.isPrototypeOf(expected)){return false;}return expected.call({},actual)===true;}function _tryBlock(block){var error;try{block();}catch(e){error=e;}return error;}function _throws(shouldThrow,block,expected,message){var actual;if(typeof block!=='function'){throw new TypeError('"block" argument must be a function');}if(typeof expected==='string'){message=expected;expected=null;}actual=_tryBlock(block);message=(expected&&expected.name?' ('+expected.name+').':'.')+(message?' '+message:'.');if(shouldThrow&&!actual){fail(actual,expected,'Missing expected exception'+message);}var userProvidedMessage=typeof message==='string';var isUnwantedException=!shouldThrow&&util.isError(actual);var isUnexpectedException=!shouldThrow&&actual&&!expected;if(isUnwantedException&&userProvidedMessage&&expectedException(actual,expected)||isUnexpectedException){fail(actual,expected,'Got unwanted exception'+message);}if(shouldThrow&&actual&&expected&&!expectedException(actual,expected)||!shouldThrow&&actual){throw actual;}}// 11. Expected to throw an error:
|
|
105
|
+
// assert.throws(block, Error_opt, message_opt);
|
|
106
|
+
assert.throws=function(block,/*optional*/error,/*optional*/message){_throws(true,block,error,message);};// EXTENSION! This is annoying to write outside this module.
|
|
107
|
+
assert.doesNotThrow=function(block,/*optional*/error,/*optional*/message){_throws(false,block,error,message);};assert.ifError=function(err){if(err)throw err;};// Expose a strict only variant of assert
|
|
108
|
+
function strict(value,message){if(!value)fail(value,true,message,'==',strict);}assert.strict=objectAssign(strict,assert,{equal:assert.strictEqual,deepEqual:assert.deepStrictEqual,notEqual:assert.notStrictEqual,notDeepEqual:assert.notDeepStrictEqual});assert.strict.strict=assert.strict;var objectKeys=Object.keys||function(obj){var keys=[];for(var key in obj){if(hasOwn.call(obj,key))keys.push(key);}return keys;};}).call(this);}).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{});},{"object-assign":47,"util/":4}],2:[function(require,module,exports){if(typeof Object.create==='function'){// implementation from standard node.js 'util' module
|
|
109
|
+
module.exports=function inherits(ctor,superCtor){ctor.super_=superCtor;ctor.prototype=Object.create(superCtor.prototype,{constructor:{value:ctor,enumerable:false,writable:true,configurable:true}});};}else{// old school shim for old browsers
|
|
110
|
+
module.exports=function inherits(ctor,superCtor){ctor.super_=superCtor;var TempCtor=function(){};TempCtor.prototype=superCtor.prototype;ctor.prototype=new TempCtor();ctor.prototype.constructor=ctor;};}},{}],3:[function(require,module,exports){module.exports=function isBuffer(arg){return arg&&typeof arg==='object'&&typeof arg.copy==='function'&&typeof arg.fill==='function'&&typeof arg.readUInt8==='function';};},{}],4:[function(require,module,exports){(function(process,global){(function(){// Copyright Joyent, Inc. and other Node contributors.
|
|
111
|
+
//
|
|
112
|
+
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
113
|
+
// copy of this software and associated documentation files (the
|
|
114
|
+
// "Software"), to deal in the Software without restriction, including
|
|
115
|
+
// without limitation the rights to use, copy, modify, merge, publish,
|
|
116
|
+
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
117
|
+
// persons to whom the Software is furnished to do so, subject to the
|
|
118
|
+
// following conditions:
|
|
119
|
+
//
|
|
120
|
+
// The above copyright notice and this permission notice shall be included
|
|
121
|
+
// in all copies or substantial portions of the Software.
|
|
122
|
+
//
|
|
123
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
124
|
+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
125
|
+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
126
|
+
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
127
|
+
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
128
|
+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
129
|
+
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
130
|
+
var formatRegExp=/%[sdj%]/g;exports.format=function(f){if(!isString(f)){var objects=[];for(var i=0;i<arguments.length;i++){objects.push(inspect(arguments[i]));}return objects.join(' ');}var i=1;var args=arguments;var len=args.length;var str=String(f).replace(formatRegExp,function(x){if(x==='%%')return'%';if(i>=len)return x;switch(x){case'%s':return String(args[i++]);case'%d':return Number(args[i++]);case'%j':try{return JSON.stringify(args[i++]);}catch(_){return'[Circular]';}default:return x;}});for(var x=args[i];i<len;x=args[++i]){if(isNull(x)||!isObject(x)){str+=' '+x;}else{str+=' '+inspect(x);}}return str;};// Mark that a method should not be used.
|
|
131
|
+
// Returns a modified function which warns once by default.
|
|
132
|
+
// If --no-deprecation is set, then it is a no-op.
|
|
133
|
+
exports.deprecate=function(fn,msg){// Allow for deprecating things in the process of starting up.
|
|
134
|
+
if(isUndefined(global.process)){return function(){return exports.deprecate(fn,msg).apply(this,arguments);};}if(process.noDeprecation===true){return fn;}var warned=false;function deprecated(){if(!warned){if(process.throwDeprecation){throw new Error(msg);}else if(process.traceDeprecation){console.trace(msg);}else{console.error(msg);}warned=true;}return fn.apply(this,arguments);}return deprecated;};var debugs={};var debugEnviron;exports.debuglog=function(set){if(isUndefined(debugEnviron))debugEnviron=process.env.NODE_DEBUG||'';set=set.toUpperCase();if(!debugs[set]){if(new RegExp('\\b'+set+'\\b','i').test(debugEnviron)){var pid=process.pid;debugs[set]=function(){var msg=exports.format.apply(exports,arguments);console.error('%s %d: %s',set,pid,msg);};}else{debugs[set]=function(){};}}return debugs[set];};/**
|
|
135
|
+
* Echos the value of a value. Trys to print the value out
|
|
136
|
+
* in the best way possible given the different types.
|
|
137
|
+
*
|
|
138
|
+
* @param {Object} obj The object to print out.
|
|
139
|
+
* @param {Object} opts Optional options object that alters the output.
|
|
140
|
+
*/ /* legacy: obj, showHidden, depth, colors*/function inspect(obj,opts){// default options
|
|
141
|
+
var ctx={seen:[],stylize:stylizeNoColor};// legacy...
|
|
142
|
+
if(arguments.length>=3)ctx.depth=arguments[2];if(arguments.length>=4)ctx.colors=arguments[3];if(isBoolean(opts)){// legacy...
|
|
143
|
+
ctx.showHidden=opts;}else if(opts){// got an "options" object
|
|
144
|
+
exports._extend(ctx,opts);}// set default options
|
|
145
|
+
if(isUndefined(ctx.showHidden))ctx.showHidden=false;if(isUndefined(ctx.depth))ctx.depth=2;if(isUndefined(ctx.colors))ctx.colors=false;if(isUndefined(ctx.customInspect))ctx.customInspect=true;if(ctx.colors)ctx.stylize=stylizeWithColor;return formatValue(ctx,obj,ctx.depth);}exports.inspect=inspect;// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
|
|
146
|
+
inspect.colors={'bold':[1,22],'italic':[3,23],'underline':[4,24],'inverse':[7,27],'white':[37,39],'grey':[90,39],'black':[30,39],'blue':[34,39],'cyan':[36,39],'green':[32,39],'magenta':[35,39],'red':[31,39],'yellow':[33,39]};// Don't use 'blue' not visible on cmd.exe
|
|
147
|
+
inspect.styles={'special':'cyan','number':'yellow','boolean':'yellow','undefined':'grey','null':'bold','string':'green','date':'magenta',// "name": intentionally not styling
|
|
148
|
+
'regexp':'red'};function stylizeWithColor(str,styleType){var style=inspect.styles[styleType];if(style){return'\u001b['+inspect.colors[style][0]+'m'+str+'\u001b['+inspect.colors[style][1]+'m';}else{return str;}}function stylizeNoColor(str,styleType){return str;}function arrayToHash(array){var hash={};array.forEach(function(val,idx){hash[val]=true;});return hash;}function formatValue(ctx,value,recurseTimes){// Provide a hook for user-specified inspect functions.
|
|
149
|
+
// Check that value is an object with an inspect function on it
|
|
150
|
+
if(ctx.customInspect&&value&&isFunction(value.inspect)&&// Filter out the util module, it's inspect function is special
|
|
151
|
+
value.inspect!==exports.inspect&&// Also filter out any prototype objects using the circular check.
|
|
152
|
+
!(value.constructor&&value.constructor.prototype===value)){var ret=value.inspect(recurseTimes,ctx);if(!isString(ret)){ret=formatValue(ctx,ret,recurseTimes);}return ret;}// Primitive types cannot have properties
|
|
153
|
+
var primitive=formatPrimitive(ctx,value);if(primitive){return primitive;}// Look up the keys of the object.
|
|
154
|
+
var keys=Object.keys(value);var visibleKeys=arrayToHash(keys);if(ctx.showHidden){keys=Object.getOwnPropertyNames(value);}// IE doesn't make error fields non-enumerable
|
|
155
|
+
// http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
|
|
156
|
+
if(isError(value)&&(keys.indexOf('message')>=0||keys.indexOf('description')>=0)){return formatError(value);}// Some type of object without properties can be shortcutted.
|
|
157
|
+
if(keys.length===0){if(isFunction(value)){var name=value.name?': '+value.name:'';return ctx.stylize('[Function'+name+']','special');}if(isRegExp(value)){return ctx.stylize(RegExp.prototype.toString.call(value),'regexp');}if(isDate(value)){return ctx.stylize(Date.prototype.toString.call(value),'date');}if(isError(value)){return formatError(value);}}var base='',array=false,braces=['{','}'];// Make Array say that they are Array
|
|
158
|
+
if(isArray(value)){array=true;braces=['[',']'];}// Make functions say that they are functions
|
|
159
|
+
if(isFunction(value)){var n=value.name?': '+value.name:'';base=' [Function'+n+']';}// Make RegExps say that they are RegExps
|
|
160
|
+
if(isRegExp(value)){base=' '+RegExp.prototype.toString.call(value);}// Make dates with properties first say the date
|
|
161
|
+
if(isDate(value)){base=' '+Date.prototype.toUTCString.call(value);}// Make error with message first say the error
|
|
162
|
+
if(isError(value)){base=' '+formatError(value);}if(keys.length===0&&(!array||value.length==0)){return braces[0]+base+braces[1];}if(recurseTimes<0){if(isRegExp(value)){return ctx.stylize(RegExp.prototype.toString.call(value),'regexp');}else{return ctx.stylize('[Object]','special');}}ctx.seen.push(value);var output;if(array){output=formatArray(ctx,value,recurseTimes,visibleKeys,keys);}else{output=keys.map(function(key){return formatProperty(ctx,value,recurseTimes,visibleKeys,key,array);});}ctx.seen.pop();return reduceToSingleString(output,base,braces);}function formatPrimitive(ctx,value){if(isUndefined(value))return ctx.stylize('undefined','undefined');if(isString(value)){var simple='\''+JSON.stringify(value).replace(/^"|"$/g,'').replace(/'/g,"\\'").replace(/\\"/g,'"')+'\'';return ctx.stylize(simple,'string');}if(isNumber(value))return ctx.stylize(''+value,'number');if(isBoolean(value))return ctx.stylize(''+value,'boolean');// For some reason typeof null is "object", so special case here.
|
|
163
|
+
if(isNull(value))return ctx.stylize('null','null');}function formatError(value){return'['+Error.prototype.toString.call(value)+']';}function formatArray(ctx,value,recurseTimes,visibleKeys,keys){var output=[];for(var i=0,l=value.length;i<l;++i){if(hasOwnProperty(value,String(i))){output.push(formatProperty(ctx,value,recurseTimes,visibleKeys,String(i),true));}else{output.push('');}}keys.forEach(function(key){if(!key.match(/^\d+$/)){output.push(formatProperty(ctx,value,recurseTimes,visibleKeys,key,true));}});return output;}function formatProperty(ctx,value,recurseTimes,visibleKeys,key,array){var name,str,desc;desc=Object.getOwnPropertyDescriptor(value,key)||{value:value[key]};if(desc.get){if(desc.set){str=ctx.stylize('[Getter/Setter]','special');}else{str=ctx.stylize('[Getter]','special');}}else{if(desc.set){str=ctx.stylize('[Setter]','special');}}if(!hasOwnProperty(visibleKeys,key)){name='['+key+']';}if(!str){if(ctx.seen.indexOf(desc.value)<0){if(isNull(recurseTimes)){str=formatValue(ctx,desc.value,null);}else{str=formatValue(ctx,desc.value,recurseTimes-1);}if(str.indexOf('\n')>-1){if(array){str=str.split('\n').map(function(line){return' '+line;}).join('\n').substr(2);}else{str='\n'+str.split('\n').map(function(line){return' '+line;}).join('\n');}}}else{str=ctx.stylize('[Circular]','special');}}if(isUndefined(name)){if(array&&key.match(/^\d+$/)){return str;}name=JSON.stringify(''+key);if(name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)){name=name.substr(1,name.length-2);name=ctx.stylize(name,'name');}else{name=name.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'");name=ctx.stylize(name,'string');}}return name+': '+str;}function reduceToSingleString(output,base,braces){var numLinesEst=0;var length=output.reduce(function(prev,cur){numLinesEst++;if(cur.indexOf('\n')>=0)numLinesEst++;return prev+cur.replace(/\u001b\[\d\d?m/g,'').length+1;},0);if(length>60){return braces[0]+(base===''?'':base+'\n ')+' '+output.join(',\n ')+' '+braces[1];}return braces[0]+base+' '+output.join(', ')+' '+braces[1];}// NOTE: These type checking functions intentionally don't use `instanceof`
|
|
164
|
+
// because it is fragile and can be easily faked with `Object.create()`.
|
|
165
|
+
function isArray(ar){return Array.isArray(ar);}exports.isArray=isArray;function isBoolean(arg){return typeof arg==='boolean';}exports.isBoolean=isBoolean;function isNull(arg){return arg===null;}exports.isNull=isNull;function isNullOrUndefined(arg){return arg==null;}exports.isNullOrUndefined=isNullOrUndefined;function isNumber(arg){return typeof arg==='number';}exports.isNumber=isNumber;function isString(arg){return typeof arg==='string';}exports.isString=isString;function isSymbol(arg){return typeof arg==='symbol';}exports.isSymbol=isSymbol;function isUndefined(arg){return arg===void 0;}exports.isUndefined=isUndefined;function isRegExp(re){return isObject(re)&&objectToString(re)==='[object RegExp]';}exports.isRegExp=isRegExp;function isObject(arg){return typeof arg==='object'&&arg!==null;}exports.isObject=isObject;function isDate(d){return isObject(d)&&objectToString(d)==='[object Date]';}exports.isDate=isDate;function isError(e){return isObject(e)&&(objectToString(e)==='[object Error]'||e instanceof Error);}exports.isError=isError;function isFunction(arg){return typeof arg==='function';}exports.isFunction=isFunction;function isPrimitive(arg){return arg===null||typeof arg==='boolean'||typeof arg==='number'||typeof arg==='string'||typeof arg==='symbol'||// ES6 symbol
|
|
166
|
+
typeof arg==='undefined';}exports.isPrimitive=isPrimitive;exports.isBuffer=require('./support/isBuffer');function objectToString(o){return Object.prototype.toString.call(o);}function pad(n){return n<10?'0'+n.toString(10):n.toString(10);}var months=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];// 26 Feb 16:19:34
|
|
167
|
+
function timestamp(){var d=new Date();var time=[pad(d.getHours()),pad(d.getMinutes()),pad(d.getSeconds())].join(':');return[d.getDate(),months[d.getMonth()],time].join(' ');}// log is just a thin wrapper to console.log that prepends a timestamp
|
|
168
|
+
exports.log=function(){console.log('%s - %s',timestamp(),exports.format.apply(exports,arguments));};/**
|
|
169
|
+
* Inherit the prototype methods from one constructor into another.
|
|
170
|
+
*
|
|
171
|
+
* The Function.prototype.inherits from lang.js rewritten as a standalone
|
|
172
|
+
* function (not on Function.prototype). NOTE: If this file is to be loaded
|
|
173
|
+
* during bootstrapping this function needs to be rewritten using some native
|
|
174
|
+
* functions as prototype setup using normal JavaScript does not work as
|
|
175
|
+
* expected during bootstrapping (see mirror.js in r114903).
|
|
176
|
+
*
|
|
177
|
+
* @param {function} ctor Constructor function which needs to inherit the
|
|
178
|
+
* prototype.
|
|
179
|
+
* @param {function} superCtor Constructor function to inherit prototype from.
|
|
180
|
+
*/exports.inherits=require('inherits');exports._extend=function(origin,add){// Don't do anything if add isn't an object
|
|
181
|
+
if(!add||!isObject(add))return origin;var keys=Object.keys(add);var i=keys.length;while(i--){origin[keys[i]]=add[keys[i]];}return origin;};function hasOwnProperty(obj,prop){return Object.prototype.hasOwnProperty.call(obj,prop);}}).call(this);}).call(this,require('_process'),typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{});},{"./support/isBuffer":3,"_process":52,"inherits":2}],5:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.default=asyncify;var _initialParams=require('./internal/initialParams.js');var _initialParams2=_interopRequireDefault(_initialParams);var _setImmediate=require('./internal/setImmediate.js');var _setImmediate2=_interopRequireDefault(_setImmediate);var _wrapAsync=require('./internal/wrapAsync.js');function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}/**
|
|
182
|
+
* Take a sync function and make it async, passing its return value to a
|
|
183
|
+
* callback. This is useful for plugging sync functions into a waterfall,
|
|
184
|
+
* series, or other async functions. Any arguments passed to the generated
|
|
185
|
+
* function will be passed to the wrapped function (except for the final
|
|
186
|
+
* callback argument). Errors thrown will be passed to the callback.
|
|
187
|
+
*
|
|
188
|
+
* If the function passed to `asyncify` returns a Promise, that promises's
|
|
189
|
+
* resolved/rejected state will be used to call the callback, rather than simply
|
|
190
|
+
* the synchronous return value.
|
|
191
|
+
*
|
|
192
|
+
* This also means you can asyncify ES2017 `async` functions.
|
|
193
|
+
*
|
|
194
|
+
* @name asyncify
|
|
195
|
+
* @static
|
|
196
|
+
* @memberOf module:Utils
|
|
197
|
+
* @method
|
|
198
|
+
* @alias wrapSync
|
|
199
|
+
* @category Util
|
|
200
|
+
* @param {Function} func - The synchronous function, or Promise-returning
|
|
201
|
+
* function to convert to an {@link AsyncFunction}.
|
|
202
|
+
* @returns {AsyncFunction} An asynchronous wrapper of the `func`. To be
|
|
203
|
+
* invoked with `(args..., callback)`.
|
|
204
|
+
* @example
|
|
205
|
+
*
|
|
206
|
+
* // passing a regular synchronous function
|
|
207
|
+
* async.waterfall([
|
|
208
|
+
* async.apply(fs.readFile, filename, "utf8"),
|
|
209
|
+
* async.asyncify(JSON.parse),
|
|
210
|
+
* function (data, next) {
|
|
211
|
+
* // data is the result of parsing the text.
|
|
212
|
+
* // If there was a parsing error, it would have been caught.
|
|
213
|
+
* }
|
|
214
|
+
* ], callback);
|
|
215
|
+
*
|
|
216
|
+
* // passing a function returning a promise
|
|
217
|
+
* async.waterfall([
|
|
218
|
+
* async.apply(fs.readFile, filename, "utf8"),
|
|
219
|
+
* async.asyncify(function (contents) {
|
|
220
|
+
* return db.model.create(contents);
|
|
221
|
+
* }),
|
|
222
|
+
* function (model, next) {
|
|
223
|
+
* // `model` is the instantiated model object.
|
|
224
|
+
* // If there was an error, this function would be skipped.
|
|
225
|
+
* }
|
|
226
|
+
* ], callback);
|
|
227
|
+
*
|
|
228
|
+
* // es2017 example, though `asyncify` is not needed if your JS environment
|
|
229
|
+
* // supports async functions out of the box
|
|
230
|
+
* var q = async.queue(async.asyncify(async function(file) {
|
|
231
|
+
* var intermediateStep = await processFile(file);
|
|
232
|
+
* return await somePromise(intermediateStep)
|
|
233
|
+
* }));
|
|
234
|
+
*
|
|
235
|
+
* q.push(files);
|
|
236
|
+
*/function asyncify(func){if((0,_wrapAsync.isAsync)(func)){return function(...args/*, callback*/){const callback=args.pop();const promise=func.apply(this,args);return handlePromise(promise,callback);};}return(0,_initialParams2.default)(function(args,callback){var result;try{result=func.apply(this,args);}catch(e){return callback(e);}// if result is Promise object
|
|
237
|
+
if(result&&typeof result.then==='function'){return handlePromise(result,callback);}else{callback(null,result);}});}function handlePromise(promise,callback){return promise.then(value=>{invokeCallback(callback,null,value);},err=>{invokeCallback(callback,err&&err.message?err:new Error(err));});}function invokeCallback(callback,error,value){try{callback(error,value);}catch(err){(0,_setImmediate2.default)(e=>{throw e;},err);}}module.exports=exports['default'];},{"./internal/initialParams.js":13,"./internal/setImmediate.js":18,"./internal/wrapAsync.js":19}],6:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _eachOfLimit2=require('./internal/eachOfLimit.js');var _eachOfLimit3=_interopRequireDefault(_eachOfLimit2);var _wrapAsync=require('./internal/wrapAsync.js');var _wrapAsync2=_interopRequireDefault(_wrapAsync);var _awaitify=require('./internal/awaitify.js');var _awaitify2=_interopRequireDefault(_awaitify);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}/**
|
|
238
|
+
* The same as [`eachOf`]{@link module:Collections.eachOf} but runs a maximum of `limit` async operations at a
|
|
239
|
+
* time.
|
|
240
|
+
*
|
|
241
|
+
* @name eachOfLimit
|
|
242
|
+
* @static
|
|
243
|
+
* @memberOf module:Collections
|
|
244
|
+
* @method
|
|
245
|
+
* @see [async.eachOf]{@link module:Collections.eachOf}
|
|
246
|
+
* @alias forEachOfLimit
|
|
247
|
+
* @category Collection
|
|
248
|
+
* @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
|
|
249
|
+
* @param {number} limit - The maximum number of async operations at a time.
|
|
250
|
+
* @param {AsyncFunction} iteratee - An async function to apply to each
|
|
251
|
+
* item in `coll`. The `key` is the item's key, or index in the case of an
|
|
252
|
+
* array.
|
|
253
|
+
* Invoked with (item, key, callback).
|
|
254
|
+
* @param {Function} [callback] - A callback which is called when all
|
|
255
|
+
* `iteratee` functions have finished, or an error occurs. Invoked with (err).
|
|
256
|
+
* @returns {Promise} a promise, if a callback is omitted
|
|
257
|
+
*/function eachOfLimit(coll,limit,iteratee,callback){return(0,_eachOfLimit3.default)(limit)(coll,(0,_wrapAsync2.default)(iteratee),callback);}exports.default=(0,_awaitify2.default)(eachOfLimit,4);module.exports=exports['default'];},{"./internal/awaitify.js":9,"./internal/eachOfLimit.js":11,"./internal/wrapAsync.js":19}],7:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _eachOfLimit=require('./eachOfLimit.js');var _eachOfLimit2=_interopRequireDefault(_eachOfLimit);var _awaitify=require('./internal/awaitify.js');var _awaitify2=_interopRequireDefault(_awaitify);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}/**
|
|
258
|
+
* The same as [`eachOf`]{@link module:Collections.eachOf} but runs only a single async operation at a time.
|
|
259
|
+
*
|
|
260
|
+
* @name eachOfSeries
|
|
261
|
+
* @static
|
|
262
|
+
* @memberOf module:Collections
|
|
263
|
+
* @method
|
|
264
|
+
* @see [async.eachOf]{@link module:Collections.eachOf}
|
|
265
|
+
* @alias forEachOfSeries
|
|
266
|
+
* @category Collection
|
|
267
|
+
* @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
|
|
268
|
+
* @param {AsyncFunction} iteratee - An async function to apply to each item in
|
|
269
|
+
* `coll`.
|
|
270
|
+
* Invoked with (item, key, callback).
|
|
271
|
+
* @param {Function} [callback] - A callback which is called when all `iteratee`
|
|
272
|
+
* functions have finished, or an error occurs. Invoked with (err).
|
|
273
|
+
* @returns {Promise} a promise, if a callback is omitted
|
|
274
|
+
*/function eachOfSeries(coll,iteratee,callback){return(0,_eachOfLimit2.default)(coll,1,iteratee,callback);}exports.default=(0,_awaitify2.default)(eachOfSeries,3);module.exports=exports['default'];},{"./eachOfLimit.js":6,"./internal/awaitify.js":9}],8:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.default=asyncEachOfLimit;var _breakLoop=require('./breakLoop.js');var _breakLoop2=_interopRequireDefault(_breakLoop);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}// for async generators
|
|
275
|
+
function asyncEachOfLimit(generator,limit,iteratee,callback){let done=false;let canceled=false;let awaiting=false;let running=0;let idx=0;function replenish(){//console.log('replenish')
|
|
276
|
+
if(running>=limit||awaiting||done)return;//console.log('replenish awaiting')
|
|
277
|
+
awaiting=true;generator.next().then(({value,done:iterDone})=>{//console.log('got value', value)
|
|
278
|
+
if(canceled||done)return;awaiting=false;if(iterDone){done=true;if(running<=0){//console.log('done nextCb')
|
|
279
|
+
callback(null);}return;}running++;iteratee(value,idx,iterateeCallback);idx++;replenish();}).catch(handleError);}function iterateeCallback(err,result){//console.log('iterateeCallback')
|
|
280
|
+
running-=1;if(canceled)return;if(err)return handleError(err);if(err===false){done=true;canceled=true;return;}if(result===_breakLoop2.default||done&&running<=0){done=true;//console.log('done iterCb')
|
|
281
|
+
return callback(null);}replenish();}function handleError(err){if(canceled)return;awaiting=false;done=true;callback(err);}replenish();}module.exports=exports['default'];},{"./breakLoop.js":10}],9:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.default=awaitify;// conditionally promisify a function.
|
|
282
|
+
// only return a promise if a callback is omitted
|
|
283
|
+
function awaitify(asyncFn,arity=asyncFn.length){if(!arity)throw new Error('arity is undefined');function awaitable(...args){if(typeof args[arity-1]==='function'){return asyncFn.apply(this,args);}return new Promise((resolve,reject)=>{args[arity-1]=(err,...cbArgs)=>{if(err)return reject(err);resolve(cbArgs.length>1?cbArgs:cbArgs[0]);};asyncFn.apply(this,args);});}return awaitable;}module.exports=exports['default'];},{}],10:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});// A temporary value used to identify if the loop should be broken.
|
|
284
|
+
// See #1064, #1293
|
|
285
|
+
const breakLoop={};exports.default=breakLoop;module.exports=exports["default"];},{}],11:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _once=require('./once.js');var _once2=_interopRequireDefault(_once);var _iterator=require('./iterator.js');var _iterator2=_interopRequireDefault(_iterator);var _onlyOnce=require('./onlyOnce.js');var _onlyOnce2=_interopRequireDefault(_onlyOnce);var _wrapAsync=require('./wrapAsync.js');var _asyncEachOfLimit=require('./asyncEachOfLimit.js');var _asyncEachOfLimit2=_interopRequireDefault(_asyncEachOfLimit);var _breakLoop=require('./breakLoop.js');var _breakLoop2=_interopRequireDefault(_breakLoop);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}exports.default=limit=>{return(obj,iteratee,callback)=>{callback=(0,_once2.default)(callback);if(limit<=0){throw new RangeError('concurrency limit cannot be less than 1');}if(!obj){return callback(null);}if((0,_wrapAsync.isAsyncGenerator)(obj)){return(0,_asyncEachOfLimit2.default)(obj,limit,iteratee,callback);}if((0,_wrapAsync.isAsyncIterable)(obj)){return(0,_asyncEachOfLimit2.default)(obj[Symbol.asyncIterator](),limit,iteratee,callback);}var nextElem=(0,_iterator2.default)(obj);var done=false;var canceled=false;var running=0;var looping=false;function iterateeCallback(err,value){if(canceled)return;running-=1;if(err){done=true;callback(err);}else if(err===false){done=true;canceled=true;}else if(value===_breakLoop2.default||done&&running<=0){done=true;return callback(null);}else if(!looping){replenish();}}function replenish(){looping=true;while(running<limit&&!done){var elem=nextElem();if(elem===null){done=true;if(running<=0){callback(null);}return;}running+=1;iteratee(elem.value,elem.key,(0,_onlyOnce2.default)(iterateeCallback));}looping=false;}replenish();};};module.exports=exports['default'];},{"./asyncEachOfLimit.js":8,"./breakLoop.js":10,"./iterator.js":15,"./once.js":16,"./onlyOnce.js":17,"./wrapAsync.js":19}],12:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.default=function(coll){return coll[Symbol.iterator]&&coll[Symbol.iterator]();};module.exports=exports["default"];},{}],13:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.default=function(fn){return function(...args/*, callback*/){var callback=args.pop();return fn.call(this,args,callback);};};module.exports=exports["default"];},{}],14:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.default=isArrayLike;function isArrayLike(value){return value&&typeof value.length==='number'&&value.length>=0&&value.length%1===0;}module.exports=exports['default'];},{}],15:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.default=createIterator;var _isArrayLike=require('./isArrayLike.js');var _isArrayLike2=_interopRequireDefault(_isArrayLike);var _getIterator=require('./getIterator.js');var _getIterator2=_interopRequireDefault(_getIterator);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}function createArrayIterator(coll){var i=-1;var len=coll.length;return function next(){return++i<len?{value:coll[i],key:i}:null;};}function createES2015Iterator(iterator){var i=-1;return function next(){var item=iterator.next();if(item.done)return null;i++;return{value:item.value,key:i};};}function createObjectIterator(obj){var okeys=obj?Object.keys(obj):[];var i=-1;var len=okeys.length;return function next(){var key=okeys[++i];if(key==='__proto__'){return next();}return i<len?{value:obj[key],key}:null;};}function createIterator(coll){if((0,_isArrayLike2.default)(coll)){return createArrayIterator(coll);}var iterator=(0,_getIterator2.default)(coll);return iterator?createES2015Iterator(iterator):createObjectIterator(coll);}module.exports=exports['default'];},{"./getIterator.js":12,"./isArrayLike.js":14}],16:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.default=once;function once(fn){function wrapper(...args){if(fn===null)return;var callFn=fn;fn=null;callFn.apply(this,args);}Object.assign(wrapper,fn);return wrapper;}module.exports=exports["default"];},{}],17:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.default=onlyOnce;function onlyOnce(fn){return function(...args){if(fn===null)throw new Error("Callback was already called.");var callFn=fn;fn=null;callFn.apply(this,args);};}module.exports=exports["default"];},{}],18:[function(require,module,exports){(function(process,setImmediate){(function(){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.fallback=fallback;exports.wrap=wrap;/* istanbul ignore file */var hasQueueMicrotask=exports.hasQueueMicrotask=typeof queueMicrotask==='function'&&queueMicrotask;var hasSetImmediate=exports.hasSetImmediate=typeof setImmediate==='function'&&setImmediate;var hasNextTick=exports.hasNextTick=typeof process==='object'&&typeof process.nextTick==='function';function fallback(fn){setTimeout(fn,0);}function wrap(defer){return(fn,...args)=>defer(()=>fn(...args));}var _defer;if(hasQueueMicrotask){_defer=queueMicrotask;}else if(hasSetImmediate){_defer=setImmediate;}else if(hasNextTick){_defer=process.nextTick;}else{_defer=fallback;}exports.default=wrap(_defer);}).call(this);}).call(this,require('_process'),require("timers").setImmediate);},{"_process":52,"timers":59}],19:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.isAsyncIterable=exports.isAsyncGenerator=exports.isAsync=undefined;var _asyncify=require('../asyncify.js');var _asyncify2=_interopRequireDefault(_asyncify);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}function isAsync(fn){return fn[Symbol.toStringTag]==='AsyncFunction';}function isAsyncGenerator(fn){return fn[Symbol.toStringTag]==='AsyncGenerator';}function isAsyncIterable(obj){return typeof obj[Symbol.asyncIterator]==='function';}function wrapAsync(asyncFn){if(typeof asyncFn!=='function')throw new Error('expected a function');return isAsync(asyncFn)?(0,_asyncify2.default)(asyncFn):asyncFn;}exports.default=wrapAsync;exports.isAsync=isAsync;exports.isAsyncGenerator=isAsyncGenerator;exports.isAsyncIterable=isAsyncIterable;},{"../asyncify.js":5}],20:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _once=require('./internal/once.js');var _once2=_interopRequireDefault(_once);var _onlyOnce=require('./internal/onlyOnce.js');var _onlyOnce2=_interopRequireDefault(_onlyOnce);var _wrapAsync=require('./internal/wrapAsync.js');var _wrapAsync2=_interopRequireDefault(_wrapAsync);var _awaitify=require('./internal/awaitify.js');var _awaitify2=_interopRequireDefault(_awaitify);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}/**
|
|
286
|
+
* Runs the `tasks` array of functions in series, each passing their results to
|
|
287
|
+
* the next in the array. However, if any of the `tasks` pass an error to their
|
|
288
|
+
* own callback, the next function is not executed, and the main `callback` is
|
|
289
|
+
* immediately called with the error.
|
|
290
|
+
*
|
|
291
|
+
* @name waterfall
|
|
292
|
+
* @static
|
|
293
|
+
* @memberOf module:ControlFlow
|
|
294
|
+
* @method
|
|
295
|
+
* @category Control Flow
|
|
296
|
+
* @param {Array} tasks - An array of [async functions]{@link AsyncFunction}
|
|
297
|
+
* to run.
|
|
298
|
+
* Each function should complete with any number of `result` values.
|
|
299
|
+
* The `result` values will be passed as arguments, in order, to the next task.
|
|
300
|
+
* @param {Function} [callback] - An optional callback to run once all the
|
|
301
|
+
* functions have completed. This will be passed the results of the last task's
|
|
302
|
+
* callback. Invoked with (err, [results]).
|
|
303
|
+
* @returns {Promise} a promise, if a callback is omitted
|
|
304
|
+
* @example
|
|
305
|
+
*
|
|
306
|
+
* async.waterfall([
|
|
307
|
+
* function(callback) {
|
|
308
|
+
* callback(null, 'one', 'two');
|
|
309
|
+
* },
|
|
310
|
+
* function(arg1, arg2, callback) {
|
|
311
|
+
* // arg1 now equals 'one' and arg2 now equals 'two'
|
|
312
|
+
* callback(null, 'three');
|
|
313
|
+
* },
|
|
314
|
+
* function(arg1, callback) {
|
|
315
|
+
* // arg1 now equals 'three'
|
|
316
|
+
* callback(null, 'done');
|
|
317
|
+
* }
|
|
318
|
+
* ], function (err, result) {
|
|
319
|
+
* // result now equals 'done'
|
|
320
|
+
* });
|
|
321
|
+
*
|
|
322
|
+
* // Or, with named functions:
|
|
323
|
+
* async.waterfall([
|
|
324
|
+
* myFirstFunction,
|
|
325
|
+
* mySecondFunction,
|
|
326
|
+
* myLastFunction,
|
|
327
|
+
* ], function (err, result) {
|
|
328
|
+
* // result now equals 'done'
|
|
329
|
+
* });
|
|
330
|
+
* function myFirstFunction(callback) {
|
|
331
|
+
* callback(null, 'one', 'two');
|
|
332
|
+
* }
|
|
333
|
+
* function mySecondFunction(arg1, arg2, callback) {
|
|
334
|
+
* // arg1 now equals 'one' and arg2 now equals 'two'
|
|
335
|
+
* callback(null, 'three');
|
|
336
|
+
* }
|
|
337
|
+
* function myLastFunction(arg1, callback) {
|
|
338
|
+
* // arg1 now equals 'three'
|
|
339
|
+
* callback(null, 'done');
|
|
340
|
+
* }
|
|
341
|
+
*/function waterfall(tasks,callback){callback=(0,_once2.default)(callback);if(!Array.isArray(tasks))return callback(new Error('First argument to waterfall must be an array of functions'));if(!tasks.length)return callback();var taskIndex=0;function nextTask(args){var task=(0,_wrapAsync2.default)(tasks[taskIndex++]);task(...args,(0,_onlyOnce2.default)(next));}function next(err,...args){if(err===false)return;if(err||taskIndex===tasks.length){return callback(err,...args);}nextTask(args);}nextTask([]);}exports.default=(0,_awaitify2.default)(waterfall);module.exports=exports['default'];},{"./internal/awaitify.js":9,"./internal/once.js":16,"./internal/onlyOnce.js":17,"./internal/wrapAsync.js":19}],21:[function(require,module,exports){/**
|
|
342
|
+
* Base Logger Class
|
|
343
|
+
*
|
|
344
|
+
* @license MIT
|
|
345
|
+
*
|
|
346
|
+
* @author Steven Velozo <steven@velozo.com>
|
|
347
|
+
*/class BaseLogger{constructor(pLogStreamSettings,pFableLog){// This should not possibly be able to be instantiated without a settings object
|
|
348
|
+
this._Settings=pLogStreamSettings;// The base logger does nothing but associate a UUID with itself
|
|
349
|
+
// We added this as the mechanism for tracking loggers to allow multiple simultaneous streams
|
|
350
|
+
// to the same provider.
|
|
351
|
+
this.loggerUUID=this.generateInsecureUUID();// Eventually we can use this array to ompute which levels the provider allows.
|
|
352
|
+
// For now it's just used to precompute some string concatenations.
|
|
353
|
+
this.levels=["trace","debug","info","warn","error","fatal"];}// This is meant to generate programmatically insecure UUIDs to identify loggers
|
|
354
|
+
generateInsecureUUID(){let tmpDate=new Date().getTime();let tmpUUID='LOGSTREAM-xxxxxx-yxxxxx'.replace(/[xy]/g,pCharacter=>{// Funny algorithm from w3resource that is twister-ish without the deep math and security
|
|
355
|
+
// ..but good enough for unique log stream identifiers
|
|
356
|
+
let tmpRandomData=(tmpDate+Math.random()*16)%16|0;tmpDate=Math.floor(tmpDate/16);return(pCharacter=='x'?tmpRandomData:tmpRandomData&0x3|0x8).toString(16);});return tmpUUID;}initialize(){// No operation.
|
|
357
|
+
}trace(pLogText,pLogObject){this.write("trace",pLogText,pLogObject);}debug(pLogText,pLogObject){this.write("debug",pLogText,pLogObject);}info(pLogText,pLogObject){this.write("info",pLogText,pLogObject);}warn(pLogText,pLogObject){this.write("warn",pLogText,pLogObject);}error(pLogText,pLogObject){this.write("error",pLogText,pLogObject);}fatal(pLogText,pLogObject){this.write("fatal",pLogText,pLogObject);}write(pLogLevel,pLogText,pLogObject){// The base logger does nothing.
|
|
358
|
+
return true;}}module.exports=BaseLogger;},{}],22:[function(require,module,exports){/**
|
|
359
|
+
* Default Logger Provider Function
|
|
360
|
+
*
|
|
361
|
+
* @license MIT
|
|
362
|
+
*
|
|
363
|
+
* @author Steven Velozo <steven@velozo.com>
|
|
364
|
+
*/ // Return the providers that are available without extensions loaded
|
|
365
|
+
getDefaultProviders=()=>{let tmpDefaultProviders={};tmpDefaultProviders.console=require('./Fable-Log-Logger-Console.js');tmpDefaultProviders.default=tmpDefaultProviders.console;return tmpDefaultProviders;};module.exports=getDefaultProviders();},{"./Fable-Log-Logger-Console.js":24}],23:[function(require,module,exports){module.exports=[{"loggertype":"console","streamtype":"console","level":"trace"}];},{}],24:[function(require,module,exports){let libBaseLogger=require('./Fable-Log-BaseLogger.js');class ConsoleLogger extends libBaseLogger{constructor(pLogStreamSettings,pFableLog){super(pLogStreamSettings);this._ShowTimeStamps=pLogStreamSettings.hasOwnProperty('showtimestamps')?pLogStreamSettings.showtimestamps==true:false;this._FormattedTimeStamps=pLogStreamSettings.hasOwnProperty('formattedtimestamps')?pLogStreamSettings.formattedtimestamps==true:false;this._ContextMessage=pLogStreamSettings.hasOwnProperty('Context')?`(${pLogStreamSettings.Context})`:pFableLog._Settings.hasOwnProperty('Product')?`(${pFableLog._Settings.Product})`:'Unnamed_Log_Context';// Allow the user to decide what gets output to the console
|
|
366
|
+
this._OutputLogLinesToConsole=pLogStreamSettings.hasOwnProperty('outputloglinestoconsole')?pLogStreamSettings.outputloglinestoconsole:true;this._OutputObjectsToConsole=pLogStreamSettings.hasOwnProperty('outputobjectstoconsole')?pLogStreamSettings.outputobjectstoconsole:true;// Precompute the prefix for each level
|
|
367
|
+
this.prefixCache={};for(let i=0;i<=this.levels.length;i++){this.prefixCache[this.levels[i]]=`[${this.levels[i]}] ${this._ContextMessage}: `;if(this._ShowTimeStamps){// If there is a timestamp we need a to prepend space before the prefixcache string, since the timestamp comes first
|
|
368
|
+
this.prefixCache[this.levels[i]]=' '+this.prefixCache[this.levels[i]];}}}write(pLevel,pLogText,pObject){let tmpTimeStamp='';if(this._ShowTimeStamps&&this._FormattedTimeStamps){tmpTimeStamp=new Date().toISOString();}else if(this._ShowTimeStamps){tmpTimeStamp=+new Date();}let tmpLogLine=`${tmpTimeStamp}${this.prefixCache[pLevel]}${pLogText}`;if(this._OutputLogLinesToConsole){console.log(tmpLogLine);}// Write out the object on a separate line if it is passed in
|
|
369
|
+
if(this._OutputObjectsToConsole&&typeof pObject!=='undefined'){console.log(JSON.stringify(pObject,null,2));}// Provide an easy way to be overridden and be consistent
|
|
370
|
+
return tmpLogLine;}}module.exports=ConsoleLogger;},{"./Fable-Log-BaseLogger.js":21}],25:[function(require,module,exports){/**
|
|
371
|
+
* Fable Logging Add-on
|
|
372
|
+
*
|
|
373
|
+
* @license MIT
|
|
374
|
+
*
|
|
375
|
+
* @author Steven Velozo <steven@velozo.com>
|
|
376
|
+
* @module Fable Logger
|
|
377
|
+
*/ /**
|
|
378
|
+
* Fable Solution Log Wrapper Main Class
|
|
379
|
+
*
|
|
380
|
+
* @class FableLog
|
|
381
|
+
* @constructor
|
|
382
|
+
*/class FableLog{constructor(pFableSettings,pFable){let tmpSettings=typeof pFableSettings==='object'?pFableSettings:{};this._Settings=tmpSettings;this._Providers=require('./Fable-Log-DefaultProviders-Node.js');this._StreamDefinitions=tmpSettings.hasOwnProperty('LogStreams')?tmpSettings.LogStreams:require('./Fable-Log-DefaultStreams.json');this.logStreams=[];// This object gets decorated for one-time instantiated providers that
|
|
383
|
+
// have multiple outputs, such as bunyan.
|
|
384
|
+
this.logProviders={};// A hash list of the GUIDs for each log stream, so they can't be added to the set more than one time
|
|
385
|
+
this.activeLogStreams={};this.logStreamsTrace=[];this.logStreamsDebug=[];this.logStreamsInfo=[];this.logStreamsWarn=[];this.logStreamsError=[];this.logStreamsFatal=[];this.datumDecorator=pDatum=>pDatum;this.uuid=typeof tmpSettings.Product==='string'?tmpSettings.Product:'Default';}addLogger(pLogger,pLevel){// Bail out if we've already created one.
|
|
386
|
+
if(this.activeLogStreams.hasOwnProperty(pLogger.loggerUUID)){return false;}// Add it to the streams and to the mutex
|
|
387
|
+
this.logStreams.push(pLogger);this.activeLogStreams[pLogger.loggerUUID]=true;// Make sure a kosher level was passed in
|
|
388
|
+
switch(pLevel){case'trace':this.logStreamsTrace.push(pLogger);case'debug':this.logStreamsDebug.push(pLogger);case'info':this.logStreamsInfo.push(pLogger);case'warn':this.logStreamsWarn.push(pLogger);case'error':this.logStreamsError.push(pLogger);case'fatal':this.logStreamsFatal.push(pLogger);break;}return true;}setDatumDecorator(fDatumDecorator){if(typeof fDatumDecorator==='function'){this.datumDecorator=fDatumDecorator;}else{this.datumDecorator=pDatum=>pDatum;}}trace(pMessage,pDatum){const tmpDecoratedDatum=this.datumDecorator(pDatum);for(let i=0;i<this.logStreamsTrace.length;i++){this.logStreamsTrace[i].trace(pMessage,tmpDecoratedDatum);}}debug(pMessage,pDatum){const tmpDecoratedDatum=this.datumDecorator(pDatum);for(let i=0;i<this.logStreamsDebug.length;i++){this.logStreamsDebug[i].debug(pMessage,tmpDecoratedDatum);}}info(pMessage,pDatum){const tmpDecoratedDatum=this.datumDecorator(pDatum);for(let i=0;i<this.logStreamsInfo.length;i++){this.logStreamsInfo[i].info(pMessage,tmpDecoratedDatum);}}warn(pMessage,pDatum){const tmpDecoratedDatum=this.datumDecorator(pDatum);for(let i=0;i<this.logStreamsWarn.length;i++){this.logStreamsWarn[i].warn(pMessage,tmpDecoratedDatum);}}error(pMessage,pDatum){const tmpDecoratedDatum=this.datumDecorator(pDatum);for(let i=0;i<this.logStreamsError.length;i++){this.logStreamsError[i].error(pMessage,tmpDecoratedDatum);}}fatal(pMessage,pDatum){const tmpDecoratedDatum=this.datumDecorator(pDatum);for(let i=0;i<this.logStreamsFatal.length;i++){this.logStreamsFatal[i].fatal(pMessage,tmpDecoratedDatum);}}initialize(){// "initialize" each logger as defined in the logging parameters
|
|
389
|
+
for(let i=0;i<this._StreamDefinitions.length;i++){let tmpStreamDefinition=Object.assign({loggertype:'default',streamtype:'console',level:'info'},this._StreamDefinitions[i]);if(!this._Providers.hasOwnProperty(tmpStreamDefinition.loggertype)){console.log(`Error initializing log stream: bad loggertype in stream definition ${JSON.stringify(tmpStreamDefinition)}`);}else{this.addLogger(new this._Providers[tmpStreamDefinition.loggertype](tmpStreamDefinition,this),tmpStreamDefinition.level);}}// Now initialize each one.
|
|
390
|
+
for(let i=0;i<this.logStreams.length;i++){this.logStreams[i].initialize();}}logTime(pMessage,pDatum){let tmpMessage=typeof pMessage!=='undefined'?pMessage:'Time';let tmpTime=new Date();this.info(`${tmpMessage} ${tmpTime} (epoch ${+tmpTime})`,pDatum);}// Get a timestamp
|
|
391
|
+
getTimeStamp(){return+new Date();}getTimeDelta(pTimeStamp){let tmpEndTime=+new Date();return tmpEndTime-pTimeStamp;}// Log the delta between a timestamp, and now with a message
|
|
392
|
+
logTimeDelta(pTimeDelta,pMessage,pDatum){let tmpMessage=typeof pMessage!=='undefined'?pMessage:'Time Measurement';let tmpDatum=typeof pDatum==='object'?pDatum:{};let tmpEndTime=+new Date();this.info(`${tmpMessage} logged at (epoch ${+tmpEndTime}) took (${pTimeDelta}ms)`,pDatum);}logTimeDeltaHuman(pTimeDelta,pMessage,pDatum){let tmpMessage=typeof pMessage!=='undefined'?pMessage:'Time Measurement';let tmpEndTime=+new Date();let tmpMs=parseInt(pTimeDelta%1000);let tmpSeconds=parseInt(pTimeDelta/1000%60);let tmpMinutes=parseInt(pTimeDelta/(1000*60)%60);let tmpHours=parseInt(pTimeDelta/(1000*60*60));tmpMs=tmpMs<10?"00"+tmpMs:tmpMs<100?"0"+tmpMs:tmpMs;tmpSeconds=tmpSeconds<10?"0"+tmpSeconds:tmpSeconds;tmpMinutes=tmpMinutes<10?"0"+tmpMinutes:tmpMinutes;tmpHours=tmpHours<10?"0"+tmpHours:tmpHours;this.info(`${tmpMessage} logged at (epoch ${+tmpEndTime}) took (${pTimeDelta}ms) or (${tmpHours}:${tmpMinutes}:${tmpSeconds}.${tmpMs})`,pDatum);}logTimeDeltaRelative(pStartTime,pMessage,pDatum){this.logTimeDelta(this.getTimeDelta(pStartTime),pMessage,pDatum);}logTimeDeltaRelativeHuman(pStartTime,pMessage,pDatum){this.logTimeDeltaHuman(this.getTimeDelta(pStartTime),pMessage,pDatum);}}// This is for backwards compatibility
|
|
393
|
+
function autoConstruct(pSettings){return new FableLog(pSettings);}module.exports={new:autoConstruct,FableLog:FableLog};},{"./Fable-Log-DefaultProviders-Node.js":22,"./Fable-Log-DefaultStreams.json":23}],26:[function(require,module,exports){module.exports={"Product":"ApplicationNameHere","ProductVersion":"0.0.0","ConfigFile":false,"LogStreams":[{"level":"trace"}]};},{}],27:[function(require,module,exports){(function(process){(function(){/**
|
|
394
|
+
* Fable Settings Template Processor
|
|
395
|
+
*
|
|
396
|
+
* This class allows environment variables to come in via templated expressions, and defaults to be set.
|
|
397
|
+
*
|
|
398
|
+
* @license MIT
|
|
399
|
+
*
|
|
400
|
+
* @author Steven Velozo <steven@velozo.com>
|
|
401
|
+
* @module Fable Settings
|
|
402
|
+
*/class FableSettingsTemplateProcessor{constructor(pDependencies){// Use a no-dependencies templating engine to parse out environment variables
|
|
403
|
+
this.templateProcessor=new pDependencies.precedent();// TODO: Make the environment variable wrap expression demarcation characters configurable?
|
|
404
|
+
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.
|
|
405
|
+
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":52}],28:[function(require,module,exports){/**
|
|
406
|
+
* Fable Settings Add-on
|
|
407
|
+
*
|
|
408
|
+
* @license MIT
|
|
409
|
+
*
|
|
410
|
+
* @author Steven Velozo <steven@velozo.com>
|
|
411
|
+
* @module Fable Settings
|
|
412
|
+
*/const libPrecedent=require('precedent');const libFableSettingsTemplateProcessor=require('./Fable-Settings-TemplateProcessor.js');class FableSettings{constructor(pFableSettings){// Expose the dependencies for downstream re-use
|
|
413
|
+
this.dependencies={precedent:libPrecedent};// Initialize the settings value template processor
|
|
414
|
+
this.settingsTemplateProcessor=new libFableSettingsTemplateProcessor(this.dependencies);// set straight away so anything that uses it respects the initial setting
|
|
415
|
+
this._configureEnvTemplating(pFableSettings);this.default=this.buildDefaultSettings();// Construct a new settings object
|
|
416
|
+
let tmpSettings=this.merge(pFableSettings,this.buildDefaultSettings());// The base settings object (what they were on initialization, before other actors have altered them)
|
|
417
|
+
this.base=JSON.parse(JSON.stringify(tmpSettings));if(tmpSettings.DefaultConfigFile){try{// If there is a DEFAULT configuration file, try to load and merge it.
|
|
418
|
+
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
|
|
419
|
+
// would potentially want to have a config file for complex settings.
|
|
420
|
+
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.
|
|
421
|
+
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
|
|
422
|
+
// would potentially want to have a config file for complex settings.
|
|
423
|
+
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.
|
|
424
|
+
buildDefaultSettings(){return JSON.parse(JSON.stringify(require('./Fable-Settings-Default')));}// Update the configuration for environment variable templating based on the current settings object
|
|
425
|
+
_configureEnvTemplating(pSettings){// default environment variable templating to on
|
|
426
|
+
this._PerformEnvTemplating=!pSettings||pSettings.NoEnvReplacement!==true;}// Resolve (recursive) any environment variables found in settings object.
|
|
427
|
+
_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]);}}}/**
|
|
428
|
+
* Check to see if a value is an object (but not an array).
|
|
429
|
+
*/_isObject(value){return typeof value==='object'&&!Array.isArray(value);}/**
|
|
430
|
+
* Merge two plain objects. Keys that are objects in both will be merged property-wise.
|
|
431
|
+
*/_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
|
|
432
|
+
this._deepMergeObjects(toValue,fromValue);return;}}toObject[key]=fromValue;});return toObject;}// Merge some new object into the existing settings.
|
|
433
|
+
merge(pSettingsFrom,pSettingsTo){// If an invalid settings from object is passed in (e.g. object constructor without passing in anything) this should still work
|
|
434
|
+
let tmpSettingsFrom=typeof pSettingsFrom==='object'?pSettingsFrom:{};// Default to the settings object if none is passed in for the merge.
|
|
435
|
+
let tmpSettingsTo=typeof pSettingsTo==='object'?pSettingsTo:this.settings;// do not mutate the From object property values
|
|
436
|
+
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
|
|
437
|
+
this._configureEnvTemplating(tmpSettingsTo);return tmpSettingsTo;}// Fill in settings gaps without overwriting settings that are already there
|
|
438
|
+
fill(pSettingsFrom){// If an invalid settings from object is passed in (e.g. object constructor without passing in anything) this should still work
|
|
439
|
+
let tmpSettingsFrom=typeof pSettingsFrom==='object'?pSettingsFrom:{};// do not mutate the From object property values
|
|
440
|
+
let tmpSettingsFromCopy=JSON.parse(JSON.stringify(tmpSettingsFrom));this.settings=this._deepMergeObjects(tmpSettingsFromCopy,this.settings);return this.settings;}};// This is for backwards compatibility
|
|
441
|
+
function autoConstruct(pSettings){return new FableSettings(pSettings);}module.exports={new:autoConstruct,FableSettings:FableSettings};},{"./Fable-Settings-Default":26,"./Fable-Settings-TemplateProcessor.js":27,"precedent":49}],29:[function(require,module,exports){/**
|
|
442
|
+
* Random Byte Generator - Browser version
|
|
443
|
+
*
|
|
444
|
+
* @license MIT
|
|
445
|
+
*
|
|
446
|
+
* @author Steven Velozo <steven@velozo.com>
|
|
447
|
+
*/ // Adapted from node-uuid (https://github.com/kelektiv/node-uuid)
|
|
448
|
+
// Unique ID creation requires a high quality random # generator. In the
|
|
449
|
+
// browser this is a little complicated due to unknown quality of Math.random()
|
|
450
|
+
// and inconsistent support for the `crypto` API. We do the best we can via
|
|
451
|
+
// feature-detection
|
|
452
|
+
class RandomBytes{constructor(){// getRandomValues needs to be invoked in a context where "this" is a Crypto
|
|
453
|
+
// implementation. Also, find the complete implementation of crypto on IE11.
|
|
454
|
+
this.getRandomValues=typeof crypto!='undefined'&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||typeof msCrypto!='undefined'&&typeof window.msCrypto.getRandomValues=='function'&&msCrypto.getRandomValues.bind(msCrypto);}// WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto
|
|
455
|
+
generateWhatWGBytes(){let tmpBuffer=new Uint8Array(16);// eslint-disable-line no-undef
|
|
456
|
+
this.getRandomValues(tmpBuffer);return tmpBuffer;}// Math.random()-based (RNG)
|
|
457
|
+
generateRandomBytes(){// If all else fails, use Math.random(). It's fast, but is of unspecified
|
|
458
|
+
// quality.
|
|
459
|
+
let tmpBuffer=new Uint8Array(16);// eslint-disable-line no-undef
|
|
460
|
+
for(let i=0,tmpValue;i<16;i++){if((i&0x03)===0){tmpValue=Math.random()*0x100000000;}tmpBuffer[i]=tmpValue>>>((i&0x03)<<3)&0xff;}return tmpBuffer;}generate(){if(this.getRandomValues){return this.generateWhatWGBytes();}else{return this.generateRandomBytes();}}}module.exports=RandomBytes;},{}],30:[function(require,module,exports){/**
|
|
461
|
+
* Fable UUID Generator
|
|
462
|
+
*
|
|
463
|
+
* @license MIT
|
|
464
|
+
*
|
|
465
|
+
* @author Steven Velozo <steven@velozo.com>
|
|
466
|
+
* @module Fable UUID
|
|
467
|
+
*/ /**
|
|
468
|
+
* Fable Solution UUID Generation Main Class
|
|
469
|
+
*
|
|
470
|
+
* @class FableUUID
|
|
471
|
+
* @constructor
|
|
472
|
+
*/var libRandomByteGenerator=require('./Fable-UUID-Random.js');class FableUUID{constructor(pSettings){// Determine if the module is in "Random UUID Mode" which means just use the random character function rather than the v4 random UUID spec.
|
|
473
|
+
// Note this allows UUIDs of various lengths (including very short ones) although guaranteed uniqueness goes downhill fast.
|
|
474
|
+
this._UUIDModeRandom=typeof pSettings==='object'&&pSettings.hasOwnProperty('UUIDModeRandom')?pSettings.UUIDModeRandom==true:false;// These two properties are only useful if we are in Random mode. Otherwise it generates a v4 spec
|
|
475
|
+
// Length for "Random UUID Mode" is set -- if not set it to 8
|
|
476
|
+
this._UUIDLength=typeof pSettings==='object'&&pSettings.hasOwnProperty('UUIDLength')?pSettings.UUIDLength+0:8;// Dictionary for "Random UUID Mode"
|
|
477
|
+
this._UUIDRandomDictionary=typeof pSettings==='object'&&pSettings.hasOwnProperty('UUIDDictionary')?pSettings.UUIDDictionary+0:'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';this.randomByteGenerator=new libRandomByteGenerator();// Lookup table for hex codes
|
|
478
|
+
this._HexLookup=[];for(let i=0;i<256;++i){this._HexLookup[i]=(i+0x100).toString(16).substr(1);}}// Adapted from node-uuid (https://github.com/kelektiv/node-uuid)
|
|
479
|
+
bytesToUUID(pBuffer){let i=0;// join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
|
|
480
|
+
return[this._HexLookup[pBuffer[i++]],this._HexLookup[pBuffer[i++]],this._HexLookup[pBuffer[i++]],this._HexLookup[pBuffer[i++]],'-',this._HexLookup[pBuffer[i++]],this._HexLookup[pBuffer[i++]],'-',this._HexLookup[pBuffer[i++]],this._HexLookup[pBuffer[i++]],'-',this._HexLookup[pBuffer[i++]],this._HexLookup[pBuffer[i++]],'-',this._HexLookup[pBuffer[i++]],this._HexLookup[pBuffer[i++]],this._HexLookup[pBuffer[i++]],this._HexLookup[pBuffer[i++]],this._HexLookup[pBuffer[i++]],this._HexLookup[pBuffer[i++]]].join('');}// Adapted from node-uuid (https://github.com/kelektiv/node-uuid)
|
|
481
|
+
generateUUIDv4(){let tmpBuffer=new Array(16);var tmpRandomBytes=this.randomByteGenerator.generate();// Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
|
|
482
|
+
tmpRandomBytes[6]=tmpRandomBytes[6]&0x0f|0x40;tmpRandomBytes[8]=tmpRandomBytes[8]&0x3f|0x80;return this.bytesToUUID(tmpRandomBytes);}// Simple random UUID generation
|
|
483
|
+
generateRandom(){let tmpUUID='';for(let i=0;i<this._UUIDLength;i++){tmpUUID+=this._UUIDRandomDictionary.charAt(Math.floor(Math.random()*(this._UUIDRandomDictionary.length-1)));}return tmpUUID;}// Adapted from node-uuid (https://github.com/kelektiv/node-uuid)
|
|
484
|
+
getUUID(){if(this._UUIDModeRandom){return this.generateRandom();}else{return this.generateUUIDv4();}}}// This is for backwards compatibility
|
|
485
|
+
function autoConstruct(pSettings){return new FableUUID(pSettings);}module.exports={new:autoConstruct,FableUUID:FableUUID};},{"./Fable-UUID-Random.js":29}],31:[function(require,module,exports){// ##### Part of the **[retold](https://stevenvelozo.github.io/retold/)** system
|
|
486
|
+
/**
|
|
487
|
+
* @license MIT
|
|
488
|
+
* @author <steven@velozo.com>
|
|
489
|
+
*/const libFableSettings=require('fable-settings').FableSettings;const libFableUUID=require('fable-uuid').FableUUID;const libFableLog=require('fable-log').FableLog;/**
|
|
490
|
+
* Fable Application Services Support Library
|
|
491
|
+
*
|
|
492
|
+
* @class Fable
|
|
493
|
+
*/class Fable{constructor(pSettings){let tmpSettings=new libFableSettings(pSettings);this.settingsManager=tmpSettings;// Instantiate the UUID generator
|
|
494
|
+
this.libUUID=new libFableUUID(this.settingsManager.settings);this.log=new libFableLog(this.settingsManager.settings);this.log.initialize();}get settings(){return this.settingsManager.settings;}get fable(){return this;}getUUID(){return this.libUUID.getUUID();}}// This is for backwards compatibility
|
|
495
|
+
function autoConstruct(pSettings){return new Fable(pSettings);}module.exports=Fable;},{"fable-log":25,"fable-settings":28,"fable-uuid":30}],32:[function(require,module,exports){'use strict';var UTF8_ACCEPT=12;var UTF8_REJECT=0;var UTF8_DATA=[// The first part of the table maps bytes to character to a transition.
|
|
496
|
+
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,7,7,7,7,7,7,7,7,7,7,7,7,8,7,7,10,9,9,9,11,4,4,4,4,4,4,4,4,4,4,4,// The second part of the table maps a state to a new state when adding a
|
|
497
|
+
// transition.
|
|
498
|
+
0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,24,36,48,60,72,84,96,0,12,12,12,0,0,0,0,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,0,0,24,24,24,0,0,0,0,0,0,0,0,0,24,24,0,0,0,0,0,0,0,0,0,0,48,48,48,0,0,0,0,0,0,0,0,0,0,48,48,0,0,0,0,0,0,0,0,0,48,0,0,0,0,0,0,0,0,0,0,// The third part maps the current transition to a mask that needs to apply
|
|
499
|
+
// to the byte.
|
|
500
|
+
0x7F,0x3F,0x3F,0x3F,0x00,0x1F,0x0F,0x0F,0x0F,0x07,0x07,0x07];function decodeURIComponent(uri){var percentPosition=uri.indexOf('%');if(percentPosition===-1)return uri;var length=uri.length;var decoded='';var last=0;var codepoint=0;var startOfOctets=percentPosition;var state=UTF8_ACCEPT;while(percentPosition>-1&&percentPosition<length){var high=hexCodeToInt(uri[percentPosition+1],4);var low=hexCodeToInt(uri[percentPosition+2],0);var byte=high|low;var type=UTF8_DATA[byte];state=UTF8_DATA[256+state+type];codepoint=codepoint<<6|byte&UTF8_DATA[364+type];if(state===UTF8_ACCEPT){decoded+=uri.slice(last,startOfOctets);decoded+=codepoint<=0xFFFF?String.fromCharCode(codepoint):String.fromCharCode(0xD7C0+(codepoint>>10),0xDC00+(codepoint&0x3FF));codepoint=0;last=percentPosition+3;percentPosition=startOfOctets=uri.indexOf('%',last);}else if(state===UTF8_REJECT){return null;}else{percentPosition+=3;if(percentPosition<length&&uri.charCodeAt(percentPosition)===37)continue;return null;}}return decoded+uri.slice(last);}var HEX={'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9,'a':10,'A':10,'b':11,'B':11,'c':12,'C':12,'d':13,'D':13,'e':14,'E':14,'f':15,'F':15};function hexCodeToInt(c,shift){var i=HEX[c];return i===undefined?255:i<<shift;}module.exports=decodeURIComponent;},{}],33:[function(require,module,exports){'use strict';// do not edit .js files directly - edit src/index.jst
|
|
501
|
+
module.exports=function equal(a,b){if(a===b)return true;if(a&&b&&typeof a=='object'&&typeof b=='object'){if(a.constructor!==b.constructor)return false;var length,i,keys;if(Array.isArray(a)){length=a.length;if(length!=b.length)return false;for(i=length;i--!==0;)if(!equal(a[i],b[i]))return false;return true;}if(a.constructor===RegExp)return a.source===b.source&&a.flags===b.flags;if(a.valueOf!==Object.prototype.valueOf)return a.valueOf()===b.valueOf();if(a.toString!==Object.prototype.toString)return a.toString()===b.toString();keys=Object.keys(a);length=keys.length;if(length!==Object.keys(b).length)return false;for(i=length;i--!==0;)if(!Object.prototype.hasOwnProperty.call(b,keys[i]))return false;for(i=length;i--!==0;){var key=keys[i];if(!equal(a[key],b[key]))return false;}return true;}// true if both NaN, false otherwise
|
|
502
|
+
return a!==a&&b!==b;};},{}],34:[function(require,module,exports){"use strict";const parse=require("./parse");const stringify=require("./stringify");const fastQuerystring={parse,stringify};/**
|
|
503
|
+
* Enable TS and JS support
|
|
504
|
+
*
|
|
505
|
+
* - `const qs = require('fast-querystring')`
|
|
506
|
+
* - `import qs from 'fast-querystring'`
|
|
507
|
+
*/module.exports=fastQuerystring;module.exports.default=fastQuerystring;module.exports.parse=parse;module.exports.stringify=stringify;},{"./parse":36,"./stringify":37}],35:[function(require,module,exports){// This file is taken from Node.js project.
|
|
508
|
+
// Full implementation can be found from https://github.com/nodejs/node/blob/main/lib/internal/querystring.js
|
|
509
|
+
const hexTable=Array.from({length:256},(_,i)=>"%"+((i<16?"0":"")+i.toString(16)).toUpperCase());// These characters do not need escaping when generating query strings:
|
|
510
|
+
// ! - . _ ~
|
|
511
|
+
// ' ( ) *
|
|
512
|
+
// digits
|
|
513
|
+
// alpha (uppercase)
|
|
514
|
+
// alpha (lowercase)
|
|
515
|
+
// rome-ignore format: the array should not be formatted
|
|
516
|
+
const noEscape=new Int8Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,// 0 - 15
|
|
517
|
+
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,// 16 - 31
|
|
518
|
+
0,1,0,0,0,0,0,1,1,1,1,0,0,1,1,0,// 32 - 47
|
|
519
|
+
1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,// 48 - 63
|
|
520
|
+
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 64 - 79
|
|
521
|
+
1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,// 80 - 95
|
|
522
|
+
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 96 - 111
|
|
523
|
+
1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,0// 112 - 127
|
|
524
|
+
]);/**
|
|
525
|
+
* @param {string} str
|
|
526
|
+
* @returns {string}
|
|
527
|
+
*/function encodeString(str){const len=str.length;if(len===0)return"";let out="";let lastPos=0;let i=0;outer:for(;i<len;i++){let c=str.charCodeAt(i);// ASCII
|
|
528
|
+
while(c<0x80){if(noEscape[c]!==1){if(lastPos<i)out+=str.slice(lastPos,i);lastPos=i+1;out+=hexTable[c];}if(++i===len)break outer;c=str.charCodeAt(i);}if(lastPos<i)out+=str.slice(lastPos,i);// Multi-byte characters ...
|
|
529
|
+
if(c<0x800){lastPos=i+1;out+=hexTable[0xc0|c>>6]+hexTable[0x80|c&0x3f];continue;}if(c<0xd800||c>=0xe000){lastPos=i+1;out+=hexTable[0xe0|c>>12]+hexTable[0x80|c>>6&0x3f]+hexTable[0x80|c&0x3f];continue;}// Surrogate pair
|
|
530
|
+
++i;// This branch should never happen because all URLSearchParams entries
|
|
531
|
+
// should already be converted to USVString. But, included for
|
|
532
|
+
// completion's sake anyway.
|
|
533
|
+
if(i>=len){throw new Error("URI malformed");}const c2=str.charCodeAt(i)&0x3ff;lastPos=i+1;c=0x10000+((c&0x3ff)<<10|c2);out+=hexTable[0xf0|c>>18]+hexTable[0x80|c>>12&0x3f]+hexTable[0x80|c>>6&0x3f]+hexTable[0x80|c&0x3f];}if(lastPos===0)return str;if(lastPos<len)return out+str.slice(lastPos);return out;}module.exports={encodeString};},{}],36:[function(require,module,exports){"use strict";const fastDecode=require("fast-decode-uri-component");const plusRegex=/\+/g;const Empty=function(){};Empty.prototype=Object.create(null);/**
|
|
534
|
+
* @callback parse
|
|
535
|
+
* @param {string} input
|
|
536
|
+
*/function parse(input){// Optimization: Use new Empty() instead of Object.create(null) for performance
|
|
537
|
+
// v8 has a better optimization for initializing functions compared to Object
|
|
538
|
+
const result=new Empty();if(typeof input!=="string"){return result;}let inputLength=input.length;let key="";let value="";let startingIndex=-1;let equalityIndex=-1;let shouldDecodeKey=false;let shouldDecodeValue=false;let keyHasPlus=false;let valueHasPlus=false;let hasBothKeyValuePair=false;let c=0;// Have a boundary of input.length + 1 to access last pair inside the loop.
|
|
539
|
+
for(let i=0;i<inputLength+1;i++){c=i!==inputLength?input.charCodeAt(i):38;// Handle '&' and end of line to pass the current values to result
|
|
540
|
+
if(c===38){hasBothKeyValuePair=equalityIndex>startingIndex;// Optimization: Reuse equality index to store the end of key
|
|
541
|
+
if(!hasBothKeyValuePair){equalityIndex=i;}key=input.slice(startingIndex+1,equalityIndex);// Add key/value pair only if the range size is greater than 1; a.k.a. contains at least "="
|
|
542
|
+
if(hasBothKeyValuePair||key.length>0){// Optimization: Replace '+' with space
|
|
543
|
+
if(keyHasPlus){key=key.replace(plusRegex," ");}// Optimization: Do not decode if it's not necessary.
|
|
544
|
+
if(shouldDecodeKey){key=fastDecode(key)||key;}if(hasBothKeyValuePair){value=input.slice(equalityIndex+1,i);if(valueHasPlus){value=value.replace(plusRegex," ");}if(shouldDecodeValue){value=fastDecode(value)||value;}}const currentValue=result[key];if(currentValue===undefined){result[key]=value;}else{// Optimization: value.pop is faster than Array.isArray(value)
|
|
545
|
+
if(currentValue.pop){currentValue.push(value);}else{result[key]=[currentValue,value];}}}// Reset reading key value pairs
|
|
546
|
+
value="";startingIndex=i;equalityIndex=i;shouldDecodeKey=false;shouldDecodeValue=false;keyHasPlus=false;valueHasPlus=false;}// Check '='
|
|
547
|
+
else if(c===61){if(equalityIndex<=startingIndex){equalityIndex=i;}// If '=' character occurs again, we should decode the input.
|
|
548
|
+
else{shouldDecodeValue=true;}}// Check '+', and remember to replace it with empty space.
|
|
549
|
+
else if(c===43){if(equalityIndex>startingIndex){valueHasPlus=true;}else{keyHasPlus=true;}}// Check '%' character for encoding
|
|
550
|
+
else if(c===37){if(equalityIndex>startingIndex){shouldDecodeValue=true;}else{shouldDecodeKey=true;}}}return result;}module.exports=parse;},{"fast-decode-uri-component":32}],37:[function(require,module,exports){"use strict";const{encodeString}=require("./internals/querystring");function getAsPrimitive(value){const type=typeof value;if(type==="string"){// Length check is handled inside encodeString function
|
|
551
|
+
return encodeString(value);}else if(type==="bigint"){return value.toString();}else if(type==="boolean"){return value?"true":"false";}else if(type==="number"&&Number.isFinite(value)){return value<1e21?""+value:encodeString(""+value);}return"";}/**
|
|
552
|
+
* @param {Record<string, string | number | boolean
|
|
553
|
+
* | ReadonlyArray<string | number | boolean> | null>} input
|
|
554
|
+
* @returns {string}
|
|
555
|
+
*/function stringify(input){let result="";if(input===null||typeof input!=="object"){return result;}const separator="&";const keys=Object.keys(input);const keyLength=keys.length;let valueLength=0;for(let i=0;i<keyLength;i++){const key=keys[i];const value=input[key];const encodedKey=encodeString(key)+"=";if(i){result+=separator;}if(Array.isArray(value)){valueLength=value.length;for(let j=0;j<valueLength;j++){if(j){result+=separator;}// Optimization: Dividing into multiple lines improves the performance.
|
|
556
|
+
// Since v8 does not need to care about the '+' character if it was one-liner.
|
|
557
|
+
result+=encodedKey;result+=getAsPrimitive(value[j]);}}else{result+=encodedKey;result+=getAsPrimitive(value);}}return result;}module.exports=stringify;},{"./internals/querystring":35}],38:[function(require,module,exports){'use strict';const HandlerStorage=require('./handler_storage');const NODE_TYPES={STATIC:0,PARAMETRIC:1,WILDCARD:2};class Node{constructor(){this.handlerStorage=new HandlerStorage();}}class ParentNode extends Node{constructor(){super();this.staticChildren={};}findStaticMatchingChild(path,pathIndex){const staticChild=this.staticChildren[path.charAt(pathIndex)];if(staticChild===undefined||!staticChild.matchPrefix(path,pathIndex)){return null;}return staticChild;}createStaticChild(path){if(path.length===0){return this;}let staticChild=this.staticChildren[path.charAt(0)];if(staticChild){let i=1;for(;i<staticChild.prefix.length;i++){if(path.charCodeAt(i)!==staticChild.prefix.charCodeAt(i)){staticChild=staticChild.split(this,i);break;}}return staticChild.createStaticChild(path.slice(i));}const label=path.charAt(0);this.staticChildren[label]=new StaticNode(path);return this.staticChildren[label];}}class StaticNode extends ParentNode{constructor(prefix){super();this.prefix=prefix;this.wildcardChild=null;this.parametricChildren=[];this.kind=NODE_TYPES.STATIC;this._compilePrefixMatch();}createParametricChild(regex,staticSuffix){const regexpSource=regex&®ex.source;let parametricChild=this.parametricChildren.find(child=>{const childRegexSource=child.regex&&child.regex.source;return childRegexSource===regexpSource;});if(parametricChild){return parametricChild;}parametricChild=new ParametricNode(regex,staticSuffix);this.parametricChildren.push(parametricChild);this.parametricChildren.sort((child1,child2)=>{if(!child1.isRegex)return 1;if(!child2.isRegex)return-1;if(child1.staticSuffix===null)return 1;if(child2.staticSuffix===null)return-1;if(child2.staticSuffix.endsWith(child1.staticSuffix))return 1;if(child1.staticSuffix.endsWith(child2.staticSuffix))return-1;return 0;});return parametricChild;}createWildcardChild(){if(this.wildcardChild){return this.wildcardChild;}this.wildcardChild=new WildcardNode();return this.wildcardChild;}split(parentNode,length){const parentPrefix=this.prefix.slice(0,length);const childPrefix=this.prefix.slice(length);this.prefix=childPrefix;this._compilePrefixMatch();const staticNode=new StaticNode(parentPrefix);staticNode.staticChildren[childPrefix.charAt(0)]=this;parentNode.staticChildren[parentPrefix.charAt(0)]=staticNode;return staticNode;}getNextNode(path,pathIndex,nodeStack,paramsCount){let node=this.findStaticMatchingChild(path,pathIndex);let parametricBrotherNodeIndex=0;if(node===null){if(this.parametricChildren.length===0){return this.wildcardChild;}node=this.parametricChildren[0];parametricBrotherNodeIndex=1;}if(this.wildcardChild!==null){nodeStack.push({paramsCount,brotherPathIndex:pathIndex,brotherNode:this.wildcardChild});}for(let i=this.parametricChildren.length-1;i>=parametricBrotherNodeIndex;i--){nodeStack.push({paramsCount,brotherPathIndex:pathIndex,brotherNode:this.parametricChildren[i]});}return node;}_compilePrefixMatch(){if(this.prefix.length===1){this.matchPrefix=()=>true;return;}const lines=[];for(let i=1;i<this.prefix.length;i++){const charCode=this.prefix.charCodeAt(i);lines.push(`path.charCodeAt(i + ${i}) === ${charCode}`);}this.matchPrefix=new Function('path','i',`return ${lines.join(' && ')}`);// eslint-disable-line
|
|
558
|
+
}}class ParametricNode extends ParentNode{constructor(regex,staticSuffix){super();this.isRegex=!!regex;this.regex=regex||null;this.staticSuffix=staticSuffix||null;this.kind=NODE_TYPES.PARAMETRIC;}getNextNode(path,pathIndex){return this.findStaticMatchingChild(path,pathIndex);}}class WildcardNode extends Node{constructor(){super();this.kind=NODE_TYPES.WILDCARD;}getNextNode(){return null;}}module.exports={StaticNode,ParametricNode,WildcardNode,NODE_TYPES};},{"./handler_storage":39}],39:[function(require,module,exports){'use strict';class HandlerStorage{constructor(){this.unconstrainedHandler=null;// optimized reference to the handler that will match most of the time
|
|
559
|
+
this.constraints=[];this.handlers=[];// unoptimized list of handler objects for which the fast matcher function will be compiled
|
|
560
|
+
this.constrainedHandlerStores=null;}// This is the hot path for node handler finding -- change with care!
|
|
561
|
+
getMatchingHandler(derivedConstraints){if(derivedConstraints===undefined){return this.unconstrainedHandler;}return this._getHandlerMatchingConstraints(derivedConstraints);}addHandler(handler,params,store,constrainer,constraints){const handlerObject={handler,params,constraints,store:store||null,_createParamsObject:this._compileCreateParamsObject(params)};if(Object.keys(constraints).length===0){this.unconstrainedHandler=handlerObject;}for(const constraint of Object.keys(constraints)){if(!this.constraints.includes(constraint)){if(constraint==='version'){// always check the version constraint first as it is the most selective
|
|
562
|
+
this.constraints.unshift(constraint);}else{this.constraints.push(constraint);}}}if(this.handlers.length>=32){throw new Error('find-my-way supports a maximum of 32 route handlers per node when there are constraints, limit reached');}this.handlers.push(handlerObject);// Sort the most constrained handlers to the front of the list of handlers so they are tested first.
|
|
563
|
+
this.handlers.sort((a,b)=>Object.keys(a.constraints).length-Object.keys(b.constraints).length);this._compileGetHandlerMatchingConstraints(constrainer,constraints);}_compileCreateParamsObject(params){const lines=[];for(let i=0;i<params.length;i++){lines.push(`'${params[i]}': paramsArray[${i}]`);}return new Function('paramsArray',`return {${lines.join(',')}}`);// eslint-disable-line
|
|
564
|
+
}_getHandlerMatchingConstraints(){return null;}// Builds a store object that maps from constraint values to a bitmap of handler indexes which pass the constraint for a value
|
|
565
|
+
// So for a host constraint, this might look like { "fastify.io": 0b0010, "google.ca": 0b0101 }, meaning the 3rd handler is constrainted to fastify.io, and the 2nd and 4th handlers are constrained to google.ca.
|
|
566
|
+
// The store's implementation comes from the strategies provided to the Router.
|
|
567
|
+
_buildConstraintStore(store,constraint){for(let i=0;i<this.handlers.length;i++){const handler=this.handlers[i];const constraintValue=handler.constraints[constraint];if(constraintValue!==undefined){let indexes=store.get(constraintValue)||0;indexes|=1<<i;// set the i-th bit for the mask because this handler is constrained by this value https://stackoverflow.com/questions/1436438/how-do-you-set-clear-and-toggle-a-single-bit-in-javascrip
|
|
568
|
+
store.set(constraintValue,indexes);}}}// Builds a bitmask for a given constraint that has a bit for each handler index that is 0 when that handler *is* constrained and 1 when the handler *isnt* constrainted. This is opposite to what might be obvious, but is just for convienience when doing the bitwise operations.
|
|
569
|
+
_constrainedIndexBitmask(constraint){let mask=0;for(let i=0;i<this.handlers.length;i++){const handler=this.handlers[i];const constraintValue=handler.constraints[constraint];if(constraintValue!==undefined){mask|=1<<i;}}return~mask;}// Compile a fast function to match the handlers for this node
|
|
570
|
+
// The function implements a general case multi-constraint matching algorithm.
|
|
571
|
+
// The general idea is this: we have a bunch of handlers, each with a potentially different set of constraints, and sometimes none at all. We're given a list of constraint values and we have to use the constraint-value-comparison strategies to see which handlers match the constraint values passed in.
|
|
572
|
+
// We do this by asking each constraint store which handler indexes match the given constraint value for each store. Trickily, the handlers that a store says match are the handlers constrained by that store, but handlers that aren't constrained at all by that store could still match just fine. So, each constraint store can only describe matches for it, and it won't have any bearing on the handlers it doesn't care about. For this reason, we have to ask each stores which handlers match and track which have been matched (or not cared about) by all of them.
|
|
573
|
+
// We use bitmaps to represent these lists of matches so we can use bitwise operations to implement this efficiently. Bitmaps are cheap to allocate, let us implement this masking behaviour in one CPU instruction, and are quite compact in memory. We start with a bitmap set to all 1s representing every handler that is a match candidate, and then for each constraint, see which handlers match using the store, and then mask the result by the mask of handlers that that store applies to, and bitwise AND with the candidate list. Phew.
|
|
574
|
+
// We consider all this compiling function complexity to be worth it, because the naive implementation that just loops over the handlers asking which stores match is quite a bit slower.
|
|
575
|
+
_compileGetHandlerMatchingConstraints(constrainer){this.constrainedHandlerStores={};for(const constraint of this.constraints){const store=constrainer.newStoreForConstraint(constraint);this.constrainedHandlerStores[constraint]=store;this._buildConstraintStore(store,constraint);}const lines=[];lines.push(`
|
|
576
|
+
let candidates = ${(1<<this.handlers.length)-1}
|
|
577
|
+
let mask, matches
|
|
578
|
+
`);for(const constraint of this.constraints){// Setup the mask for indexes this constraint applies to. The mask bits are set to 1 for each position if the constraint applies.
|
|
579
|
+
lines.push(`
|
|
580
|
+
mask = ${this._constrainedIndexBitmask(constraint)}
|
|
581
|
+
value = derivedConstraints.${constraint}
|
|
582
|
+
`);// If there's no constraint value, none of the handlers constrained by this constraint can match. Remove them from the candidates.
|
|
583
|
+
// If there is a constraint value, get the matching indexes bitmap from the store, and mask it down to only the indexes this constraint applies to, and then bitwise and with the candidates list to leave only matching candidates left.
|
|
584
|
+
const strategy=constrainer.strategies[constraint];const matchMask=strategy.mustMatchWhenDerived?'matches':'(matches | mask)';lines.push(`
|
|
585
|
+
if (value === undefined) {
|
|
586
|
+
candidates &= mask
|
|
587
|
+
} else {
|
|
588
|
+
matches = this.constrainedHandlerStores.${constraint}.get(value) || 0
|
|
589
|
+
candidates &= ${matchMask}
|
|
590
|
+
}
|
|
591
|
+
if (candidates === 0) return null;
|
|
592
|
+
`);}// There are some constraints that can be derived and marked as "must match", where if they are derived, they only match routes that actually have a constraint on the value, like the SemVer version constraint.
|
|
593
|
+
// An example: a request comes in for version 1.x, and this node has a handler that matches the path, but there's no version constraint. For SemVer, the find-my-way semantics do not match this handler to that request.
|
|
594
|
+
// This function is used by Nodes with handlers to match when they don't have any constrained routes to exclude request that do have must match derived constraints present.
|
|
595
|
+
for(const constraint in constrainer.strategies){const strategy=constrainer.strategies[constraint];if(strategy.mustMatchWhenDerived&&!this.constraints.includes(constraint)){lines.push(`if (derivedConstraints.${constraint} !== undefined) return null`);}}// Return the first handler who's bit is set in the candidates https://stackoverflow.com/questions/18134985/how-to-find-index-of-first-set-bit
|
|
596
|
+
lines.push('return this.handlers[Math.floor(Math.log2(candidates))]');this._getHandlerMatchingConstraints=new Function('derivedConstraints',lines.join('\n'));// eslint-disable-line
|
|
597
|
+
}}module.exports=HandlerStorage;},{}],40:[function(require,module,exports){'use strict';/*
|
|
598
|
+
Char codes:
|
|
599
|
+
'!': 33 - !
|
|
600
|
+
'#': 35 - %23
|
|
601
|
+
'$': 36 - %24
|
|
602
|
+
'%': 37 - %25
|
|
603
|
+
'&': 38 - %26
|
|
604
|
+
''': 39 - '
|
|
605
|
+
'(': 40 - (
|
|
606
|
+
')': 41 - )
|
|
607
|
+
'*': 42 - *
|
|
608
|
+
'+': 43 - %2B
|
|
609
|
+
',': 44 - %2C
|
|
610
|
+
'-': 45 - -
|
|
611
|
+
'.': 46 - .
|
|
612
|
+
'/': 47 - %2F
|
|
613
|
+
':': 58 - %3A
|
|
614
|
+
';': 59 - %3B
|
|
615
|
+
'=': 61 - %3D
|
|
616
|
+
'?': 63 - %3F
|
|
617
|
+
'@': 64 - %40
|
|
618
|
+
'_': 95 - _
|
|
619
|
+
'~': 126 - ~
|
|
620
|
+
*/const assert=require('assert');const querystring=require('fast-querystring');const isRegexSafe=require('safe-regex2');const deepEqual=require('fast-deep-equal');const{flattenNode,compressFlattenedNode,prettyPrintFlattenedNode,prettyPrintRoutesArray}=require('./lib/pretty-print');const{StaticNode,NODE_TYPES}=require('./custom_node');const Constrainer=require('./lib/constrainer');const httpMethods=require('./lib/http-methods');const{safeDecodeURI,safeDecodeURIComponent}=require('./lib/url-sanitizer');const FULL_PATH_REGEXP=/^https?:\/\/.*?\//;const OPTIONAL_PARAM_REGEXP=/(\/:[^/()]*?)\?(\/?)/;if(!isRegexSafe(FULL_PATH_REGEXP)){throw new Error('the FULL_PATH_REGEXP is not safe, update this module');}if(!isRegexSafe(OPTIONAL_PARAM_REGEXP)){throw new Error('the OPTIONAL_PARAM_REGEXP is not safe, update this module');}function Router(opts){if(!(this instanceof Router)){return new Router(opts);}opts=opts||{};if(opts.defaultRoute){assert(typeof opts.defaultRoute==='function','The default route must be a function');this.defaultRoute=opts.defaultRoute;}else{this.defaultRoute=null;}if(opts.onBadUrl){assert(typeof opts.onBadUrl==='function','The bad url handler must be a function');this.onBadUrl=opts.onBadUrl;}else{this.onBadUrl=null;}if(opts.buildPrettyMeta){assert(typeof opts.buildPrettyMeta==='function','buildPrettyMeta must be a function');this.buildPrettyMeta=opts.buildPrettyMeta;}else{this.buildPrettyMeta=defaultBuildPrettyMeta;}if(opts.querystringParser){assert(typeof opts.querystringParser==='function','querystringParser must be a function');this.querystringParser=opts.querystringParser;}else{this.querystringParser=query=>query===''?{}:querystring.parse(query);}this.caseSensitive=opts.caseSensitive===undefined?true:opts.caseSensitive;this.ignoreTrailingSlash=opts.ignoreTrailingSlash||false;this.ignoreDuplicateSlashes=opts.ignoreDuplicateSlashes||false;this.maxParamLength=opts.maxParamLength||100;this.allowUnsafeRegex=opts.allowUnsafeRegex||false;this.routes=[];this.trees={};this.constrainer=new Constrainer(opts.constraints);this._routesPatterns={};}Router.prototype.on=function on(method,path,opts,handler,store){if(typeof opts==='function'){if(handler!==undefined){store=handler;}handler=opts;opts={};}// path validation
|
|
621
|
+
assert(typeof path==='string','Path should be a string');assert(path.length>0,'The path could not be empty');assert(path[0]==='/'||path[0]==='*','The first character of a path should be `/` or `*`');// handler validation
|
|
622
|
+
assert(typeof handler==='function','Handler should be a function');// path ends with optional parameter
|
|
623
|
+
const optionalParamMatch=path.match(OPTIONAL_PARAM_REGEXP);if(optionalParamMatch){assert(path.length===optionalParamMatch.index+optionalParamMatch[0].length,'Optional Parameter needs to be the last parameter of the path');const pathFull=path.replace(OPTIONAL_PARAM_REGEXP,'$1$2');const pathOptional=path.replace(OPTIONAL_PARAM_REGEXP,'$2');this.on(method,pathFull,opts,handler,store);this.on(method,pathOptional,opts,handler,store);return;}const route=path;if(this.ignoreDuplicateSlashes){path=removeDuplicateSlashes(path);}if(this.ignoreTrailingSlash){path=trimLastSlash(path);}const methods=Array.isArray(method)?method:[method];for(const method of methods){this._on(method,path,opts,handler,store,route);this.routes.push({method,path,opts,handler,store});}};Router.prototype._on=function _on(method,path,opts,handler,store){assert(typeof method==='string','Method should be a string');assert(httpMethods.includes(method),`Method '${method}' is not an http method.`);let constraints={};if(opts.constraints!==undefined){assert(typeof opts.constraints==='object'&&opts.constraints!==null,'Constraints should be an object');if(Object.keys(opts.constraints).length!==0){constraints=opts.constraints;}}this.constrainer.validateConstraints(constraints);// Let the constrainer know if any constraints are being used now
|
|
624
|
+
this.constrainer.noteUsage(constraints);// Boot the tree for this method if it doesn't exist yet
|
|
625
|
+
if(this.trees[method]===undefined){this.trees[method]=new StaticNode('/');this._routesPatterns[method]=[];}if(path==='*'&&this.trees[method].prefix.length!==0){const currentRoot=this.trees[method];this.trees[method]=new StaticNode('');this.trees[method].staticChildren['/']=currentRoot;}let currentNode=this.trees[method];let parentNodePathIndex=currentNode.prefix.length;const params=[];for(let i=0;i<=path.length;i++){if(path.charCodeAt(i)===58&&path.charCodeAt(i+1)===58){// It's a double colon
|
|
626
|
+
i++;continue;}const isParametricNode=path.charCodeAt(i)===58&&path.charCodeAt(i+1)!==58;const isWildcardNode=path.charCodeAt(i)===42;if(isParametricNode||isWildcardNode||i===path.length&&i!==parentNodePathIndex){let staticNodePath=path.slice(parentNodePathIndex,i);if(!this.caseSensitive){staticNodePath=staticNodePath.toLowerCase();}staticNodePath=staticNodePath.split('::').join(':');staticNodePath=staticNodePath.split('%').join('%25');// add the static part of the route to the tree
|
|
627
|
+
currentNode=currentNode.createStaticChild(staticNodePath);}if(isParametricNode){let isRegexNode=false;const regexps=[];let lastParamStartIndex=i+1;for(let j=lastParamStartIndex;;j++){const charCode=path.charCodeAt(j);const isRegexParam=charCode===40;const isStaticPart=charCode===45||charCode===46;const isEndOfNode=charCode===47||j===path.length;if(isRegexParam||isStaticPart||isEndOfNode){const paramName=path.slice(lastParamStartIndex,j);params.push(paramName);isRegexNode=isRegexNode||isRegexParam||isStaticPart;if(isRegexParam){const endOfRegexIndex=getClosingParenthensePosition(path,j);const regexString=path.slice(j,endOfRegexIndex+1);if(!this.allowUnsafeRegex){assert(isRegexSafe(new RegExp(regexString)),`The regex '${regexString}' is not safe!`);}regexps.push(trimRegExpStartAndEnd(regexString));j=endOfRegexIndex+1;}else{regexps.push('(.*?)');}const staticPartStartIndex=j;for(;j<path.length;j++){const charCode=path.charCodeAt(j);if(charCode===47)break;if(charCode===58){const nextCharCode=path.charCodeAt(j+1);if(nextCharCode===58)j++;else break;}}let staticPart=path.slice(staticPartStartIndex,j);if(staticPart){staticPart=staticPart.split('::').join(':');staticPart=staticPart.split('%').join('%25');regexps.push(escapeRegExp(staticPart));}lastParamStartIndex=j+1;if(isEndOfNode||path.charCodeAt(j)===47||j===path.length){const nodePattern=isRegexNode?'()'+staticPart:staticPart;path=path.slice(0,i+1)+nodePattern+path.slice(j);i+=nodePattern.length;const regex=isRegexNode?new RegExp('^'+regexps.join('')+'$'):null;currentNode=currentNode.createParametricChild(regex,staticPart||null);parentNodePathIndex=i+1;break;}}}}else if(isWildcardNode){// add the wildcard parameter
|
|
628
|
+
params.push('*');currentNode=currentNode.createWildcardChild();parentNodePathIndex=i+1;if(i!==path.length-1){throw new Error('Wildcard must be the last character in the route');}}}if(!this.caseSensitive){path=path.toLowerCase();}if(path==='*'){path='/*';}for(const existRoute of this._routesPatterns[method]){if(existRoute.path===path&&deepEqual(existRoute.constraints,constraints)){throw new Error(`Method '${method}' already declared for route '${path}' with constraints '${JSON.stringify(constraints)}'`);}}this._routesPatterns[method].push({path,params,constraints});currentNode.handlerStorage.addHandler(handler,params,store,this.constrainer,constraints);};Router.prototype.hasConstraintStrategy=function(strategyName){return this.constrainer.hasConstraintStrategy(strategyName);};Router.prototype.addConstraintStrategy=function(constraints){this.constrainer.addConstraintStrategy(constraints);this._rebuild(this.routes);};Router.prototype.reset=function reset(){this.trees={};this.routes=[];this._routesPatterns={};};Router.prototype.off=function off(method,path,constraints){// path validation
|
|
629
|
+
assert(typeof path==='string','Path should be a string');assert(path.length>0,'The path could not be empty');assert(path[0]==='/'||path[0]==='*','The first character of a path should be `/` or `*`');// options validation
|
|
630
|
+
assert(typeof constraints==='undefined'||typeof constraints==='object'&&!Array.isArray(constraints)&&constraints!==null,'Constraints should be an object or undefined.');// path ends with optional parameter
|
|
631
|
+
const optionalParamMatch=path.match(OPTIONAL_PARAM_REGEXP);if(optionalParamMatch){assert(path.length===optionalParamMatch.index+optionalParamMatch[0].length,'Optional Parameter needs to be the last parameter of the path');const pathFull=path.replace(OPTIONAL_PARAM_REGEXP,'$1$2');const pathOptional=path.replace(OPTIONAL_PARAM_REGEXP,'$2');this.off(method,pathFull,constraints);this.off(method,pathOptional,constraints);return;}if(this.ignoreDuplicateSlashes){path=removeDuplicateSlashes(path);}if(this.ignoreTrailingSlash){path=trimLastSlash(path);}const methods=Array.isArray(method)?method:[method];for(const method of methods){this._off(method,path,constraints);}};Router.prototype._off=function _off(method,path,constraints){// method validation
|
|
632
|
+
assert(typeof method==='string','Method should be a string');assert(httpMethods.includes(method),`Method '${method}' is not an http method.`);function matcherWithoutConstraints(route){return method!==route.method||path!==route.path;}function matcherWithConstraints(route){return matcherWithoutConstraints(route)||!deepEqual(constraints,route.opts.constraints||{});}const predicate=constraints?matcherWithConstraints:matcherWithoutConstraints;// Rebuild tree without the specific route
|
|
633
|
+
const newRoutes=this.routes.filter(predicate);this._rebuild(newRoutes);};Router.prototype.lookup=function lookup(req,res,ctx,done){if(typeof ctx==='function'){done=ctx;ctx=undefined;}if(done===undefined){const constraints=this.constrainer.deriveConstraints(req,ctx);const handle=this.find(req.method,req.url,constraints);return this.callHandler(handle,req,res,ctx);}this.constrainer.deriveConstraints(req,ctx,(err,constraints)=>{if(err!==null){done(err);return;}try{const handle=this.find(req.method,req.url,constraints);const result=this.callHandler(handle,req,res,ctx);done(null,result);}catch(err){done(err);}});};Router.prototype.callHandler=function callHandler(handle,req,res,ctx){if(handle===null)return this._defaultRoute(req,res,ctx);return ctx===undefined?handle.handler(req,res,handle.params,handle.store,handle.searchParams):handle.handler.call(ctx,req,res,handle.params,handle.store,handle.searchParams);};Router.prototype.find=function find(method,path,derivedConstraints){let currentNode=this.trees[method];if(currentNode===undefined)return null;if(path.charCodeAt(0)!==47){// 47 is '/'
|
|
634
|
+
path=path.replace(FULL_PATH_REGEXP,'/');}// This must be run before sanitizeUrl as the resulting function
|
|
635
|
+
// .sliceParameter must be constructed with same URL string used
|
|
636
|
+
// throughout the rest of this function.
|
|
637
|
+
if(this.ignoreDuplicateSlashes){path=removeDuplicateSlashes(path);}let sanitizedUrl;let querystring;let shouldDecodeParam;try{sanitizedUrl=safeDecodeURI(path);path=sanitizedUrl.path;querystring=sanitizedUrl.querystring;shouldDecodeParam=sanitizedUrl.shouldDecodeParam;}catch(error){return this._onBadUrl(path);}if(this.ignoreTrailingSlash){path=trimLastSlash(path);}const originPath=path;if(this.caseSensitive===false){path=path.toLowerCase();}const maxParamLength=this.maxParamLength;let pathIndex=currentNode.prefix.length;const params=[];const pathLen=path.length;const brothersNodesStack=[];while(true){if(pathIndex===pathLen){const handle=currentNode.handlerStorage.getMatchingHandler(derivedConstraints);if(handle!==null){return{handler:handle.handler,store:handle.store,params:handle._createParamsObject(params),searchParams:this.querystringParser(querystring)};}}let node=currentNode.getNextNode(path,pathIndex,brothersNodesStack,params.length);if(node===null){if(brothersNodesStack.length===0){return null;}const brotherNodeState=brothersNodesStack.pop();pathIndex=brotherNodeState.brotherPathIndex;params.splice(brotherNodeState.paramsCount);node=brotherNodeState.brotherNode;}currentNode=node;// static route
|
|
638
|
+
if(currentNode.kind===NODE_TYPES.STATIC){pathIndex+=currentNode.prefix.length;continue;}if(currentNode.kind===NODE_TYPES.WILDCARD){let param=originPath.slice(pathIndex);if(shouldDecodeParam){param=safeDecodeURIComponent(param);}params.push(param);pathIndex=pathLen;continue;}if(currentNode.kind===NODE_TYPES.PARAMETRIC){let paramEndIndex=originPath.indexOf('/',pathIndex);if(paramEndIndex===-1){paramEndIndex=pathLen;}let param=originPath.slice(pathIndex,paramEndIndex);if(shouldDecodeParam){param=safeDecodeURIComponent(param);}if(currentNode.isRegex){const matchedParameters=currentNode.regex.exec(param);if(matchedParameters===null)continue;for(let i=1;i<matchedParameters.length;i++){const matchedParam=matchedParameters[i];if(matchedParam.length>maxParamLength){return null;}params.push(matchedParam);}}else{if(param.length>maxParamLength){return null;}params.push(param);}pathIndex=paramEndIndex;}}};Router.prototype._rebuild=function(routes){this.reset();for(const route of routes){const{method,path,opts,handler,store}=route;this._on(method,path,opts,handler,store);this.routes.push({method,path,opts,handler,store});}};Router.prototype._defaultRoute=function(req,res,ctx){if(this.defaultRoute!==null){return ctx===undefined?this.defaultRoute(req,res):this.defaultRoute.call(ctx,req,res);}else{res.statusCode=404;res.end();}};Router.prototype._onBadUrl=function(path){if(this.onBadUrl===null){return null;}const onBadUrl=this.onBadUrl;return{handler:(req,res,ctx)=>onBadUrl(path,req,res),params:{},store:null};};Router.prototype.prettyPrint=function(opts={}){opts.commonPrefix=opts.commonPrefix===undefined?true:opts.commonPrefix;// default to original behaviour
|
|
639
|
+
if(!opts.commonPrefix)return prettyPrintRoutesArray.call(this,this.routes,opts);const root={prefix:'/',nodes:[],children:{}};for(const method in this.trees){const node=this.trees[method];if(node){flattenNode(root,node,method);}}compressFlattenedNode(root);return prettyPrintFlattenedNode.call(this,root,'',true,opts);};for(var i in httpMethods){/* eslint no-prototype-builtins: "off" */if(!httpMethods.hasOwnProperty(i))continue;const m=httpMethods[i];const methodName=m.toLowerCase();if(Router.prototype[methodName])throw new Error('Method already exists: '+methodName);Router.prototype[methodName]=function(path,handler,store){return this.on(m,path,handler,store);};}Router.prototype.all=function(path,handler,store){this.on(httpMethods,path,handler,store);};module.exports=Router;function escapeRegExp(string){return string.replace(/[.*+?^${}()|[\]\\]/g,'\\$&');}function removeDuplicateSlashes(path){return path.replace(/\/\/+/g,'/');}function trimLastSlash(path){if(path.length>1&&path.charCodeAt(path.length-1)===47){return path.slice(0,-1);}return path;}function trimRegExpStartAndEnd(regexString){// removes chars that marks start "^" and end "$" of regexp
|
|
640
|
+
if(regexString.charCodeAt(1)===94){regexString=regexString.slice(0,1)+regexString.slice(2);}if(regexString.charCodeAt(regexString.length-2)===36){regexString=regexString.slice(0,regexString.length-2)+regexString.slice(regexString.length-1);}return regexString;}function getClosingParenthensePosition(path,idx){// `path.indexOf()` will always return the first position of the closing parenthese,
|
|
641
|
+
// but it's inefficient for grouped or wrong regexp expressions.
|
|
642
|
+
// see issues #62 and #63 for more info
|
|
643
|
+
var parentheses=1;while(idx<path.length){idx++;// ignore skipped chars
|
|
644
|
+
if(path[idx]==='\\'){idx++;continue;}if(path[idx]===')'){parentheses--;}else if(path[idx]==='('){parentheses++;}if(!parentheses)return idx;}throw new TypeError('Invalid regexp expression in "'+path+'"');}function defaultBuildPrettyMeta(route){// buildPrettyMeta function must return an object, which will be parsed into key/value pairs for display
|
|
645
|
+
if(!route)return{};if(!route.store)return{};return Object.assign({},route.store);}},{"./custom_node":38,"./lib/constrainer":41,"./lib/http-methods":42,"./lib/pretty-print":43,"./lib/url-sanitizer":46,"assert":1,"fast-deep-equal":33,"fast-querystring":34,"safe-regex2":53}],41:[function(require,module,exports){'use strict';const acceptVersionStrategy=require('./strategies/accept-version');const acceptHostStrategy=require('./strategies/accept-host');const assert=require('assert');class Constrainer{constructor(customStrategies){this.strategies={version:acceptVersionStrategy,host:acceptHostStrategy};this.strategiesInUse=new Set();this.asyncStrategiesInUse=new Set();// validate and optimize prototypes of given custom strategies
|
|
646
|
+
if(customStrategies){for(const strategy of Object.values(customStrategies)){this.addConstraintStrategy(strategy);}}}isStrategyUsed(strategyName){return this.strategiesInUse.has(strategyName)||this.asyncStrategiesInUse.has(strategyName);}hasConstraintStrategy(strategyName){const customConstraintStrategy=this.strategies[strategyName];if(customConstraintStrategy!==undefined){return customConstraintStrategy.isCustom||this.isStrategyUsed(strategyName);}return false;}addConstraintStrategy(strategy){assert(typeof strategy.name==='string'&&strategy.name!=='','strategy.name is required.');assert(strategy.storage&&typeof strategy.storage==='function','strategy.storage function is required.');assert(strategy.deriveConstraint&&typeof strategy.deriveConstraint==='function','strategy.deriveConstraint function is required.');if(this.strategies[strategy.name]&&this.strategies[strategy.name].isCustom){throw new Error(`There already exists a custom constraint with the name ${strategy.name}.`);}if(this.isStrategyUsed(strategy.name)){throw new Error(`There already exists a route with ${strategy.name} constraint.`);}strategy.isCustom=true;strategy.isAsync=strategy.deriveConstraint.length===3;this.strategies[strategy.name]=strategy;if(strategy.mustMatchWhenDerived){this.noteUsage({[strategy.name]:strategy});}}deriveConstraints(req,ctx,done){const constraints=this.deriveSyncConstraints(req,ctx);if(done===undefined){return constraints;}this.deriveAsyncConstraints(constraints,req,ctx,done);}deriveSyncConstraints(req,ctx){return undefined;}// When new constraints start getting used, we need to rebuild the deriver to derive them. Do so if we see novel constraints used.
|
|
647
|
+
noteUsage(constraints){if(constraints){const beforeSize=this.strategiesInUse.size;for(const key in constraints){const strategy=this.strategies[key];if(strategy.isAsync){this.asyncStrategiesInUse.add(key);}else{this.strategiesInUse.add(key);}}if(beforeSize!==this.strategiesInUse.size){this._buildDeriveConstraints();}}}newStoreForConstraint(constraint){if(!this.strategies[constraint]){throw new Error(`No strategy registered for constraint key ${constraint}`);}return this.strategies[constraint].storage();}validateConstraints(constraints){for(const key in constraints){const value=constraints[key];if(typeof value==='undefined'){throw new Error('Can\'t pass an undefined constraint value, must pass null or no key at all');}const strategy=this.strategies[key];if(!strategy){throw new Error(`No strategy registered for constraint key ${key}`);}if(strategy.validate){strategy.validate(value);}}}deriveAsyncConstraints(constraints,req,ctx,done){let asyncConstraintsCount=this.asyncStrategiesInUse.size;if(asyncConstraintsCount===0){done(null,constraints);return;}constraints=constraints||{};for(const key of this.asyncStrategiesInUse){const strategy=this.strategies[key];strategy.deriveConstraint(req,ctx,(err,constraintValue)=>{if(err!==null){done(err);return;}constraints[key]=constraintValue;if(--asyncConstraintsCount===0){done(null,constraints);}});}}// Optimization: build a fast function for deriving the constraints for all the strategies at once. We inline the definitions of the version constraint and the host constraint for performance.
|
|
648
|
+
// If no constraining strategies are in use (no routes constrain on host, or version, or any custom strategies) then we don't need to derive constraints for each route match, so don't do anything special, and just return undefined
|
|
649
|
+
// This allows us to not allocate an object to hold constraint values if no constraints are defined.
|
|
650
|
+
_buildDeriveConstraints(){if(this.strategiesInUse.size===0)return;const lines=['return {'];for(const key of this.strategiesInUse){const strategy=this.strategies[key];// Optimization: inline the derivation for the common built in constraints
|
|
651
|
+
if(!strategy.isCustom){if(key==='version'){lines.push(' version: req.headers[\'accept-version\'],');}else if(key==='host'){lines.push(' host: req.headers.host || req.headers[\':authority\'],');}else{throw new Error('unknown non-custom strategy for compiling constraint derivation function');}}else{lines.push(` ${strategy.name}: this.strategies.${key}.deriveConstraint(req, ctx),`);}}lines.push('}');this.deriveSyncConstraints=new Function('req','ctx',lines.join('\n')).bind(this);// eslint-disable-line
|
|
652
|
+
}}module.exports=Constrainer;},{"./strategies/accept-host":44,"./strategies/accept-version":45,"assert":1}],42:[function(require,module,exports){'use strict';// defined by Node.js http module, a snapshot from Node.js 18.12.0
|
|
653
|
+
const httpMethods=['ACL','BIND','CHECKOUT','CONNECT','COPY','DELETE','GET','HEAD','LINK','LOCK','M-SEARCH','MERGE','MKACTIVITY','MKCALENDAR','MKCOL','MOVE','NOTIFY','OPTIONS','PATCH','POST','PROPFIND','PROPPATCH','PURGE','PUT','REBIND','REPORT','SEARCH','SOURCE','SUBSCRIBE','TRACE','UNBIND','UNLINK','UNLOCK','UNSUBSCRIBE'];module.exports=httpMethods;},{}],43:[function(require,module,exports){'use strict';/* eslint-disable no-multi-spaces */const indent=' ';const branchIndent='│ ';const midBranchIndent='├── ';const endBranchIndent='└── ';const wildcardDelimiter='*';const pathDelimiter='/';const pathRegExp=/(?=\/)/;/* eslint-enable */function parseFunctionName(fn){let fName=fn.name||'';fName=fName.replace('bound','').trim();fName=(fName||'anonymous')+'()';return fName;}function parseMeta(meta){if(Array.isArray(meta))return meta.map(m=>parseMeta(m));if(typeof meta==='symbol')return meta.toString();if(typeof meta==='function')return parseFunctionName(meta);return meta;}function buildMetaObject(route,metaArray){const out={};const cleanMeta=this.buildPrettyMeta(route);if(!Array.isArray(metaArray))metaArray=cleanMeta?Reflect.ownKeys(cleanMeta):[];metaArray.forEach(m=>{const metaKey=typeof m==='symbol'?m.toString():m;if(cleanMeta&&cleanMeta[m]){out[metaKey]=parseMeta(cleanMeta[m]);}});return out;}function prettyPrintRoutesArray(routeArray,opts={}){if(!this.buildPrettyMeta)throw new Error('buildPrettyMeta not defined');opts.includeMeta=opts.includeMeta||null;// array of meta objects to display
|
|
654
|
+
const mergedRouteArray=[];let tree='';routeArray.sort((a,b)=>{if(!a.path||!b.path)return 0;return a.path.localeCompare(b.path);});// merge alike paths
|
|
655
|
+
for(let i=0;i<routeArray.length;i++){const route=routeArray[i];const pathExists=mergedRouteArray.find(r=>route.path===r.path);if(pathExists){// path already declared, add new method and break out of loop
|
|
656
|
+
pathExists.handlers.push({method:route.method,opts:route.opts.constraints||undefined,meta:opts.includeMeta?buildMetaObject.call(this,route,opts.includeMeta):null});continue;}const routeHandler={method:route.method,opts:route.opts.constraints||undefined,meta:opts.includeMeta?buildMetaObject.call(this,route,opts.includeMeta):null};mergedRouteArray.push({path:route.path,methods:[route.method],opts:[route.opts],handlers:[routeHandler]});}// insert root level path if none defined
|
|
657
|
+
if(!mergedRouteArray.filter(r=>r.path===pathDelimiter).length){const rootPath={path:pathDelimiter,truncatedPath:'',methods:[],opts:[],handlers:[{}]};// if wildcard route exists, insert root level after wildcard
|
|
658
|
+
if(mergedRouteArray.filter(r=>r.path===wildcardDelimiter).length){mergedRouteArray.splice(1,0,rootPath);}else{mergedRouteArray.unshift(rootPath);}}// build tree
|
|
659
|
+
const routeTree=buildRouteTree(mergedRouteArray);// draw tree
|
|
660
|
+
routeTree.forEach((rootBranch,idx)=>{tree+=drawBranch(rootBranch,null,idx===routeTree.length-1,false,true);tree+='\n';// newline characters inserted at beginning of drawing function to allow for nested paths
|
|
661
|
+
});return tree;}function buildRouteTree(mergedRouteArray){const result=[];const temp={result};mergedRouteArray.forEach((route,idx)=>{let splitPath=route.path.split(pathRegExp);// add preceding slash for proper nesting
|
|
662
|
+
if(splitPath[0]!==pathDelimiter){// handle wildcard route
|
|
663
|
+
if(splitPath[0]!==wildcardDelimiter)splitPath=[pathDelimiter,splitPath[0].slice(1),...splitPath.slice(1)];}// build tree
|
|
664
|
+
splitPath.reduce((acc,path,pidx)=>{if(!acc[path]){acc[path]={result:[]};const pathSeg={path,children:acc[path].result};if(pidx===splitPath.length-1)pathSeg.handlers=route.handlers;acc.result.push(pathSeg);}return acc[path];},temp);});// unfold root object from array
|
|
665
|
+
return result;}function drawBranch(pathSeg,prefix,endBranch,noPrefix,rootBranch){let branch='';if(!noPrefix&&!rootBranch)branch+='\n';if(!noPrefix)branch+=`${prefix||''}${endBranch?endBranchIndent:midBranchIndent}`;branch+=`${pathSeg.path}`;if(pathSeg.handlers){const flatHandlers=pathSeg.handlers.reduce((acc,curr)=>{const match=acc.findIndex(h=>JSON.stringify(h.opts)===JSON.stringify(curr.opts));if(match!==-1){acc[match].method=[acc[match].method,curr.method].join(', ');}else{acc.push(curr);}return acc;},[]);flatHandlers.forEach((handler,idx)=>{if(idx>0)branch+=`${noPrefix?'':prefix||''}${endBranch?indent:branchIndent}${pathSeg.path}`;branch+=` (${handler.method||'-'})`;if(handler.opts&&JSON.stringify(handler.opts)!=='{}')branch+=` ${JSON.stringify(handler.opts)}`;if(handler.meta){Reflect.ownKeys(handler.meta).forEach((m,hidx)=>{branch+=`\n${noPrefix?'':prefix||''}${endBranch?indent:branchIndent}`;branch+=`• (${m}) ${JSON.stringify(handler.meta[m])}`;});}if(flatHandlers.length>1&&idx!==flatHandlers.length-1)branch+='\n';});}else{if(pathSeg.children.length>1)branch+=' (-)';}if(!noPrefix)prefix=`${prefix||''}${endBranch?indent:branchIndent}`;pathSeg.children.forEach((child,idx)=>{const endBranch=idx===pathSeg.children.length-1;const skipPrefix=!pathSeg.handlers&&pathSeg.children.length===1;branch+=drawBranch(child,prefix,endBranch,skipPrefix);});return branch;}function prettyPrintFlattenedNode(flattenedNode,prefix,tail,opts){if(!this.buildPrettyMeta)throw new Error('buildPrettyMeta not defined');opts.includeMeta=opts.includeMeta||null;// array of meta items to display
|
|
666
|
+
let paramName='';const printHandlers=[];for(const{node,method}of flattenedNode.nodes){for(const handler of node.handlerStorage.handlers){printHandlers.push({method,...handler});}}if(printHandlers.length){printHandlers.forEach((handler,index)=>{let suffix=`(${handler.method||'-'})`;if(Object.keys(handler.constraints).length>0){suffix+=' '+JSON.stringify(handler.constraints);}let name='';// find locations of parameters in prefix
|
|
667
|
+
const paramIndices=flattenedNode.prefix.split('').map((ch,idx)=>ch===':'?idx:null).filter(idx=>idx!==null);if(paramIndices.length){let prevLoc=0;paramIndices.forEach((loc,idx)=>{// find parameter in prefix
|
|
668
|
+
name+=flattenedNode.prefix.slice(prevLoc,loc+1);// insert parameters
|
|
669
|
+
name+=handler.params[handler.params.length-paramIndices.length+idx];if(idx===paramIndices.length-1)name+=flattenedNode.prefix.slice(loc+1);prevLoc=loc+1;});}else{// there are no parameters, return full object
|
|
670
|
+
name=flattenedNode.prefix;}if(index===0){paramName+=`${name} ${suffix}`;}else{paramName+=`\n${prefix}${tail?indent:branchIndent}${name} ${suffix}`;}if(opts.includeMeta){const meta=buildMetaObject.call(this,handler,opts.includeMeta);Object.keys(meta).forEach((m,hidx)=>{paramName+=`\n${prefix||''}${tail?indent:branchIndent}`;paramName+=`• (${m}) ${JSON.stringify(meta[m])}`;});}});}else{paramName=flattenedNode.prefix;}let tree=`${prefix}${tail?endBranchIndent:midBranchIndent}${paramName}\n`;prefix=`${prefix}${tail?indent:branchIndent}`;const labels=Object.keys(flattenedNode.children);for(let i=0;i<labels.length;i++){const child=flattenedNode.children[labels[i]];tree+=prettyPrintFlattenedNode.call(this,child,prefix,i===labels.length-1,opts);}return tree;}function flattenNode(flattened,node,method){if(node.handlerStorage.handlers.length!==0){flattened.nodes.push({method,node});}if(node.parametricChildren&&node.parametricChildren[0]){if(!flattened.children[':']){flattened.children[':']={prefix:':',nodes:[],children:{}};}flattenNode(flattened.children[':'],node.parametricChildren[0],method);}if(node.wildcardChild){if(!flattened.children['*']){flattened.children['*']={prefix:'*',nodes:[],children:{}};}flattenNode(flattened.children['*'],node.wildcardChild,method);}if(node.staticChildren){for(const child of Object.values(node.staticChildren)){// split on the slash separator but use a regex to lookahead and not actually match it, preserving it in the returned string segments
|
|
671
|
+
const childPrefixSegments=child.prefix.split(pathRegExp);let cursor=flattened;let parent;for(const segment of childPrefixSegments){parent=cursor;cursor=cursor.children[segment];if(!cursor){cursor={prefix:segment,nodes:[],children:{}};parent.children[segment]=cursor;}}flattenNode(cursor,child,method);}}}function compressFlattenedNode(flattenedNode){const childKeys=Object.keys(flattenedNode.children);if(flattenedNode.nodes.length===0&&childKeys.length===1){const child=flattenedNode.children[childKeys[0]];if(child.nodes.length<=1){compressFlattenedNode(child);flattenedNode.nodes=child.nodes;flattenedNode.prefix+=child.prefix;flattenedNode.children=child.children;return flattenedNode;}}for(const key of Object.keys(flattenedNode.children)){compressFlattenedNode(flattenedNode.children[key]);}return flattenedNode;}module.exports={flattenNode,compressFlattenedNode,prettyPrintFlattenedNode,prettyPrintRoutesArray};},{}],44:[function(require,module,exports){'use strict';const assert=require('assert');function HostStorage(){const hosts={};const regexHosts=[];return{get:host=>{const exact=hosts[host];if(exact){return exact;}for(const regex of regexHosts){if(regex.host.test(host)){return regex.value;}}},set:(host,value)=>{if(host instanceof RegExp){regexHosts.push({host,value});}else{hosts[host]=value;}}};}module.exports={name:'host',mustMatchWhenDerived:false,storage:HostStorage,validate(value){assert(typeof value==='string'||Object.prototype.toString.call(value)==='[object RegExp]','Host should be a string or a RegExp');}};},{"assert":1}],45:[function(require,module,exports){'use strict';const assert=require('assert');function SemVerStore(){if(!(this instanceof SemVerStore)){return new SemVerStore();}this.store={};this.maxMajor=0;this.maxMinors={};this.maxPatches={};}SemVerStore.prototype.set=function(version,store){if(typeof version!=='string'){throw new TypeError('Version should be a string');}let[major,minor,patch]=version.split('.');major=Number(major)||0;minor=Number(minor)||0;patch=Number(patch)||0;if(major>=this.maxMajor){this.maxMajor=major;this.store.x=store;this.store['*']=store;this.store['x.x']=store;this.store['x.x.x']=store;}if(minor>=(this.maxMinors[major]||0)){this.maxMinors[major]=minor;this.store[`${major}.x`]=store;this.store[`${major}.x.x`]=store;}if(patch>=(this.store[`${major}.${minor}`]||0)){this.maxPatches[`${major}.${minor}`]=patch;this.store[`${major}.${minor}.x`]=store;}this.store[`${major}.${minor}.${patch}`]=store;return this;};SemVerStore.prototype.get=function(version){return this.store[version];};module.exports={name:'version',mustMatchWhenDerived:true,storage:SemVerStore,validate(value){assert(typeof value==='string','Version should be a string');}};},{"assert":1}],46:[function(require,module,exports){'use strict';// It must spot all the chars where decodeURIComponent(x) !== decodeURI(x)
|
|
672
|
+
// The chars are: # $ & + , / : ; = ? @
|
|
673
|
+
function decodeComponentChar(highCharCode,lowCharCode){if(highCharCode===50){if(lowCharCode===53)return'%';if(lowCharCode===51)return'#';if(lowCharCode===52)return'$';if(lowCharCode===54)return'&';if(lowCharCode===66)return'+';if(lowCharCode===98)return'+';if(lowCharCode===67)return',';if(lowCharCode===99)return',';if(lowCharCode===70)return'/';if(lowCharCode===102)return'/';return null;}if(highCharCode===51){if(lowCharCode===65)return':';if(lowCharCode===97)return':';if(lowCharCode===66)return';';if(lowCharCode===98)return';';if(lowCharCode===68)return'=';if(lowCharCode===100)return'=';if(lowCharCode===70)return'?';if(lowCharCode===102)return'?';return null;}if(highCharCode===52&&lowCharCode===48){return'@';}return null;}function safeDecodeURI(path){let shouldDecode=false;let shouldDecodeParam=false;let querystring='';for(let i=1;i<path.length;i++){const charCode=path.charCodeAt(i);if(charCode===37){const highCharCode=path.charCodeAt(i+1);const lowCharCode=path.charCodeAt(i+2);if(decodeComponentChar(highCharCode,lowCharCode)===null){shouldDecode=true;}else{shouldDecodeParam=true;// %25 - encoded % char. We need to encode one more time to prevent double decoding
|
|
674
|
+
if(highCharCode===50&&lowCharCode===53){shouldDecode=true;path=path.slice(0,i+1)+'25'+path.slice(i+1);i+=2;}i+=2;}// Some systems do not follow RFC and separate the path and query
|
|
675
|
+
// string with a `;` character (code 59), e.g. `/foo;jsessionid=123456`.
|
|
676
|
+
// Thus, we need to split on `;` as well as `?` and `#`.
|
|
677
|
+
}else if(charCode===63||charCode===59||charCode===35){querystring=path.slice(i+1);path=path.slice(0,i);break;}}const decodedPath=shouldDecode?decodeURI(path):path;return{path:decodedPath,querystring,shouldDecodeParam};}function safeDecodeURIComponent(uriComponent){const startIndex=uriComponent.indexOf('%');if(startIndex===-1)return uriComponent;let decoded='';let lastIndex=startIndex;for(let i=startIndex;i<uriComponent.length;i++){if(uriComponent.charCodeAt(i)===37){const highCharCode=uriComponent.charCodeAt(i+1);const lowCharCode=uriComponent.charCodeAt(i+2);const decodedChar=decodeComponentChar(highCharCode,lowCharCode);decoded+=uriComponent.slice(lastIndex,i)+decodedChar;lastIndex=i+3;}}return uriComponent.slice(0,startIndex)+decoded+uriComponent.slice(lastIndex);}module.exports={safeDecodeURI,safeDecodeURIComponent};},{}],47:[function(require,module,exports){/*
|
|
678
|
+
object-assign
|
|
679
|
+
(c) Sindre Sorhus
|
|
680
|
+
@license MIT
|
|
681
|
+
*/'use strict';/* eslint-disable no-unused-vars */var getOwnPropertySymbols=Object.getOwnPropertySymbols;var hasOwnProperty=Object.prototype.hasOwnProperty;var propIsEnumerable=Object.prototype.propertyIsEnumerable;function toObject(val){if(val===null||val===undefined){throw new TypeError('Object.assign cannot be called with null or undefined');}return Object(val);}function shouldUseNative(){try{if(!Object.assign){return false;}// Detect buggy property enumeration order in older V8 versions.
|
|
682
|
+
// https://bugs.chromium.org/p/v8/issues/detail?id=4118
|
|
683
|
+
var test1=new String('abc');// eslint-disable-line no-new-wrappers
|
|
684
|
+
test1[5]='de';if(Object.getOwnPropertyNames(test1)[0]==='5'){return false;}// https://bugs.chromium.org/p/v8/issues/detail?id=3056
|
|
685
|
+
var test2={};for(var i=0;i<10;i++){test2['_'+String.fromCharCode(i)]=i;}var order2=Object.getOwnPropertyNames(test2).map(function(n){return test2[n];});if(order2.join('')!=='0123456789'){return false;}// https://bugs.chromium.org/p/v8/issues/detail?id=3056
|
|
686
|
+
var test3={};'abcdefghijklmnopqrst'.split('').forEach(function(letter){test3[letter]=letter;});if(Object.keys(Object.assign({},test3)).join('')!=='abcdefghijklmnopqrst'){return false;}return true;}catch(err){// We don't expect any of the above to throw, but better to be safe.
|
|
687
|
+
return false;}}module.exports=shouldUseNative()?Object.assign:function(target,source){var from;var to=toObject(target);var symbols;for(var s=1;s<arguments.length;s++){from=Object(arguments[s]);for(var key in from){if(hasOwnProperty.call(from,key)){to[key]=from[key];}}if(getOwnPropertySymbols){symbols=getOwnPropertySymbols(from);for(var i=0;i<symbols.length;i++){if(propIsEnumerable.call(from,symbols[i])){to[symbols[i]]=from[symbols[i]];}}}}return to;};},{}],48:[function(require,module,exports){class OratorServiceServerBase{constructor(pOrator){this.orator=pOrator;this.log=pOrator.log;this.Name=this.orator.settings.Product;this.URL='BASE_SERVICE_SERVER';this.Port=this.orator.settings.ServicePort;this.Active=false;}/*
|
|
688
|
+
* Service Lifecycle Functions
|
|
689
|
+
*************************************************************************/listen(pPort,fCallback){// Sometimes, listen does not listen on network calls.
|
|
690
|
+
this.Active=true;return fCallback();}close(fCallback){this.Active=false;return fCallback();}/*************************************************************************
|
|
691
|
+
* End of Service Lifecycle Functions
|
|
692
|
+
*/ /*
|
|
693
|
+
* Service Route Creation Functions
|
|
694
|
+
*
|
|
695
|
+
* These base functions provide basic validation for the routes, but don't actually
|
|
696
|
+
* do anything with them. The design intent here is to allow derived classes to call
|
|
697
|
+
* these functions to validate that they conform to expected standards.
|
|
698
|
+
*
|
|
699
|
+
* Something like:
|
|
700
|
+
|
|
701
|
+
get (pRoute, ...fRouteProcessingFunctions)
|
|
702
|
+
{
|
|
703
|
+
if (!super.get(pRoute, ...fRouteProcessingFunctions))
|
|
704
|
+
{
|
|
705
|
+
this.log.error(`Restify provider failed to map route [${pRoute}]!`);
|
|
706
|
+
return false;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
//...now we can do our actual get mapping function!....
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
* This pattern and calling super is totally optional, obviously.
|
|
713
|
+
*************************************************************************/get(pRoute,...fRouteProcessingFunctions){if(typeof pRoute!='string'){this.log.error(`Orator GET Route mapping failed -- route parameter was ${typeof pRoute} instead of a string.`);return false;}return true;}put(pRoute,...fRouteProcessingFunctions){if(typeof pRoute!='string'){this.log.error(`Orator PUT Route mapping failed -- route parameter was ${typeof pRoute} instead of a string.`);return false;}return true;}post(pRoute,...fRouteProcessingFunctions){if(typeof pRoute!='string'){this.log.error(`Orator POST Route mapping failed -- route parameter was ${typeof pRoute} instead of a string.`);return false;}return true;}del(pRoute,...fRouteProcessingFunctions){if(typeof pRoute!='string'){this.log.error(`Orator DEL Route mapping failed -- route parameter was ${typeof pRoute} instead of a string.`);return false;}return true;}patch(pRoute,...fRouteProcessingFunctions){if(typeof pRoute!='string'){this.log.error(`Orator PATCH Route mapping failed -- route parameter was ${typeof pRoute} instead of a string.`);return false;}return true;}opts(pRoute,...fRouteProcessingFunctions){if(typeof pRoute!='string'){this.log.error(`Orator OPTS Route mapping failed -- route parameter was ${typeof pRoute} instead of a string.`);return false;}return true;}head(pRoute,...fRouteProcessingFunctions){if(typeof pRoute!='string'){this.log.error(`Orator HEAD Route mapping failed -- route parameter was ${typeof pRoute} instead of a string.`);return false;}return true;}/*************************************************************************
|
|
714
|
+
* End of Service Route Creation Functions
|
|
715
|
+
*/ // Programmatically invoke a route
|
|
716
|
+
invoke(pMethod,pRoute,pData,fCallback){// The base class version of this does nothing
|
|
717
|
+
this.log.debug(`Orator invoke called for route [${pRoute}] and landed on the base class; the service provider likely does not implement programmatic invoke capabilities.`,pData);return false;}}module.exports=OratorServiceServerBase;},{}],49:[function(require,module,exports){/**
|
|
718
|
+
* Precedent Meta-Templating
|
|
719
|
+
*
|
|
720
|
+
* @license MIT
|
|
721
|
+
*
|
|
722
|
+
* @author Steven Velozo <steven@velozo.com>
|
|
723
|
+
*
|
|
724
|
+
* @description Process text streams, parsing out meta-template expressions.
|
|
725
|
+
*/var libWordTree=require(`./WordTree.js`);var libStringParser=require(`./StringParser.js`);class Precedent{/**
|
|
726
|
+
* Precedent Constructor
|
|
727
|
+
*/constructor(){this.WordTree=new libWordTree();this.StringParser=new libStringParser();this.ParseTree=this.WordTree.ParseTree;}/**
|
|
728
|
+
* Add a Pattern to the Parse Tree
|
|
729
|
+
* @method addPattern
|
|
730
|
+
* @param {Object} pTree - A node on the parse tree to push the characters into
|
|
731
|
+
* @param {string} pPattern - The string to add to the tree
|
|
732
|
+
* @param {number} pIndex - callback function
|
|
733
|
+
* @return {bool} True if adding the pattern was successful
|
|
734
|
+
*/addPattern(pPatternStart,pPatternEnd,pParser){return this.WordTree.addPattern(pPatternStart,pPatternEnd,pParser);}/**
|
|
735
|
+
* Parse a string with the existing parse tree
|
|
736
|
+
* @method parseString
|
|
737
|
+
* @param {string} pString - The string to parse
|
|
738
|
+
* @return {string} The result from the parser
|
|
739
|
+
*/parseString(pString){return this.StringParser.parseString(pString,this.ParseTree);}}module.exports=Precedent;},{"./StringParser.js":50,"./WordTree.js":51}],50:[function(require,module,exports){/**
|
|
740
|
+
* String Parser
|
|
741
|
+
*
|
|
742
|
+
* @license MIT
|
|
743
|
+
*
|
|
744
|
+
* @author Steven Velozo <steven@velozo.com>
|
|
745
|
+
*
|
|
746
|
+
* @description Parse a string, properly processing each matched token in the word tree.
|
|
747
|
+
*/class StringParser{/**
|
|
748
|
+
* StringParser Constructor
|
|
749
|
+
*/constructor(){}/**
|
|
750
|
+
* Create a fresh parsing state object to work with.
|
|
751
|
+
* @method newParserState
|
|
752
|
+
* @param {Object} pParseTree - A node on the parse tree to begin parsing from (usually root)
|
|
753
|
+
* @return {Object} A new parser state object for running a character parser on
|
|
754
|
+
* @private
|
|
755
|
+
*/newParserState(pParseTree){return{ParseTree:pParseTree,Output:'',OutputBuffer:'',Pattern:false,PatternMatch:false,PatternMatchOutputBuffer:''};}/**
|
|
756
|
+
* Assign a node of the parser tree to be the next potential match.
|
|
757
|
+
* If the node has a PatternEnd property, it is a valid match and supercedes the last valid match (or becomes the initial match).
|
|
758
|
+
* @method assignNode
|
|
759
|
+
* @param {Object} pNode - A node on the parse tree to assign
|
|
760
|
+
* @param {Object} pParserState - The state object for the current parsing task
|
|
761
|
+
* @private
|
|
762
|
+
*/assignNode(pNode,pParserState){pParserState.PatternMatch=pNode;// If the pattern has a END we can assume it has a parse function...
|
|
763
|
+
if(pParserState.PatternMatch.hasOwnProperty('PatternEnd')){// ... this is the legitimate start of a pattern.
|
|
764
|
+
pParserState.Pattern=pParserState.PatternMatch;}}/**
|
|
765
|
+
* Append a character to the output buffer in the parser state.
|
|
766
|
+
* This output buffer is used when a potential match is being explored, or a match is being explored.
|
|
767
|
+
* @method appendOutputBuffer
|
|
768
|
+
* @param {string} pCharacter - The character to append
|
|
769
|
+
* @param {Object} pParserState - The state object for the current parsing task
|
|
770
|
+
* @private
|
|
771
|
+
*/appendOutputBuffer(pCharacter,pParserState){pParserState.OutputBuffer+=pCharacter;}/**
|
|
772
|
+
* Flush the output buffer to the output and clear it.
|
|
773
|
+
* @method flushOutputBuffer
|
|
774
|
+
* @param {Object} pParserState - The state object for the current parsing task
|
|
775
|
+
* @private
|
|
776
|
+
*/flushOutputBuffer(pParserState){pParserState.Output+=pParserState.OutputBuffer;pParserState.OutputBuffer='';}/**
|
|
777
|
+
* Check if the pattern has ended. If it has, properly flush the buffer and start looking for new patterns.
|
|
778
|
+
* @method checkPatternEnd
|
|
779
|
+
* @param {Object} pParserState - The state object for the current parsing task
|
|
780
|
+
* @private
|
|
781
|
+
*/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.
|
|
782
|
+
// Trim the start and end tags off the output buffer now
|
|
783
|
+
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.
|
|
784
|
+
this.flushOutputBuffer(pParserState);// End pattern mode
|
|
785
|
+
pParserState.Pattern=false;pParserState.PatternMatch=false;}}/**
|
|
786
|
+
* Parse a character in the buffer.
|
|
787
|
+
* @method parseCharacter
|
|
788
|
+
* @param {string} pCharacter - The character to append
|
|
789
|
+
* @param {Object} pParserState - The state object for the current parsing task
|
|
790
|
+
* @private
|
|
791
|
+
*/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....
|
|
792
|
+
if(!pParserState.PatternMatch&&pParserState.ParseTree.hasOwnProperty(pCharacter)){// ... assign the node as the matched node.
|
|
793
|
+
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)
|
|
794
|
+
else if(pParserState.PatternMatch){// If the pattern has a subpattern with this key
|
|
795
|
+
if(pParserState.PatternMatch.hasOwnProperty(pCharacter)){// Continue matching patterns.
|
|
796
|
+
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)...
|
|
797
|
+
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)....
|
|
798
|
+
else{pParserState.Output+=pCharacter;}}/**
|
|
799
|
+
* Parse a string for matches, and process any template segments that occur.
|
|
800
|
+
* @method parseString
|
|
801
|
+
* @param {string} pString - The string to parse.
|
|
802
|
+
* @param {Object} pParseTree - The parse tree to begin parsing from (usually root)
|
|
803
|
+
*/parseString(pString,pParseTree){let tmpParserState=this.newParserState(pParseTree);for(var i=0;i<pString.length;i++){// TODO: This is not fast.
|
|
804
|
+
this.parseCharacter(pString[i],tmpParserState);}this.flushOutputBuffer(tmpParserState);return tmpParserState.Output;}}module.exports=StringParser;},{}],51:[function(require,module,exports){/**
|
|
805
|
+
* Word Tree
|
|
806
|
+
*
|
|
807
|
+
* @license MIT
|
|
808
|
+
*
|
|
809
|
+
* @author Steven Velozo <steven@velozo.com>
|
|
810
|
+
*
|
|
811
|
+
* @description Create a tree (directed graph) of Javascript objects, one character per object.
|
|
812
|
+
*/class WordTree{/**
|
|
813
|
+
* WordTree Constructor
|
|
814
|
+
*/constructor(){this.ParseTree={};}/**
|
|
815
|
+
* Add a child character to a Parse Tree node
|
|
816
|
+
* @method addChild
|
|
817
|
+
* @param {Object} pTree - A parse tree to push the characters into
|
|
818
|
+
* @param {string} pPattern - The string to add to the tree
|
|
819
|
+
* @param {number} pIndex - The index of the character in the pattern
|
|
820
|
+
* @returns {Object} The resulting leaf node that was added (or found)
|
|
821
|
+
* @private
|
|
822
|
+
*/addChild(pTree,pPattern,pIndex){if(!pTree.hasOwnProperty(pPattern[pIndex]))pTree[pPattern[pIndex]]={};return pTree[pPattern[pIndex]];}/** Add a Pattern to the Parse Tree
|
|
823
|
+
* @method addPattern
|
|
824
|
+
* @param {Object} pPatternStart - The starting string for the pattern (e.g. "${")
|
|
825
|
+
* @param {string} pPatternEnd - The ending string for the pattern (e.g. "}")
|
|
826
|
+
* @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.
|
|
827
|
+
* @return {bool} True if adding the pattern was successful
|
|
828
|
+
*/addPattern(pPatternStart,pPatternEnd,pParser){if(pPatternStart.length<1)return false;if(typeof pPatternEnd==='string'&&pPatternEnd.length<1)return false;let tmpLeaf=this.ParseTree;// Add the tree of leaves iteratively
|
|
829
|
+
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;},{}],52:[function(require,module,exports){// shim for using process in browser
|
|
830
|
+
var process=module.exports={};// cached from whatever global is present so that test runners that stub it
|
|
831
|
+
// don't break things. But we need to wrap it in a try catch in case it is
|
|
832
|
+
// wrapped in strict mode code which doesn't define any globals. It's inside a
|
|
833
|
+
// function because try/catches deoptimize in certain engines.
|
|
834
|
+
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
|
|
835
|
+
return setTimeout(fun,0);}// if setTimeout wasn't available but was latter defined
|
|
836
|
+
if((cachedSetTimeout===defaultSetTimout||!cachedSetTimeout)&&setTimeout){cachedSetTimeout=setTimeout;return setTimeout(fun,0);}try{// when when somebody has screwed with setTimeout but no I.E. maddness
|
|
837
|
+
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
|
|
838
|
+
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
|
|
839
|
+
return cachedSetTimeout.call(this,fun,0);}}}function runClearTimeout(marker){if(cachedClearTimeout===clearTimeout){//normal enviroments in sane situations
|
|
840
|
+
return clearTimeout(marker);}// if clearTimeout wasn't available but was latter defined
|
|
841
|
+
if((cachedClearTimeout===defaultClearTimeout||!cachedClearTimeout)&&clearTimeout){cachedClearTimeout=clearTimeout;return clearTimeout(marker);}try{// when when somebody has screwed with setTimeout but no I.E. maddness
|
|
842
|
+
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
|
|
843
|
+
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.
|
|
844
|
+
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
|
|
845
|
+
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);}};// v8 likes predictible objects
|
|
846
|
+
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
|
|
847
|
+
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;};},{}],53:[function(require,module,exports){'use strict';var parse=require('ret');var types=parse.types;module.exports=function(re,opts){if(!opts)opts={};var replimit=opts.limit===undefined?25:opts.limit;if(isRegExp(re))re=re.source;else if(typeof re!=='string')re=String(re);try{re=parse(re);}catch(err){return false;}var reps=0;return function walk(node,starHeight){var i;var ok;var len;if(node.type===types.REPETITION){starHeight++;reps++;if(starHeight>1)return false;if(reps>replimit)return false;}if(node.options){for(i=0,len=node.options.length;i<len;i++){ok=walk({stack:node.options[i]},starHeight);if(!ok)return false;}}var stack=node.stack||node.value&&node.value.stack;if(!stack)return true;for(i=0;i<stack.length;i++){ok=walk(stack[i],starHeight);if(!ok)return false;}return true;}(re,0);};function isRegExp(x){return{}.toString.call(x)==='[object RegExp]';}},{"ret":54}],54:[function(require,module,exports){const util=require('./util');const types=require('./types');const sets=require('./sets');const positions=require('./positions');module.exports=regexpStr=>{var i=0,l,c,start={type:types.ROOT,stack:[]},// Keep track of last clause/group and stack.
|
|
848
|
+
lastGroup=start,last=start.stack,groupStack=[];var repeatErr=i=>{util.error(regexpStr,`Nothing to repeat at column ${i-1}`);};// Decode a few escaped characters.
|
|
849
|
+
var str=util.strToChars(regexpStr);l=str.length;// Iterate through each character in string.
|
|
850
|
+
while(i<l){c=str[i++];switch(c){// Handle escaped characters, inclues a few sets.
|
|
851
|
+
case'\\':c=str[i++];switch(c){case'b':last.push(positions.wordBoundary());break;case'B':last.push(positions.nonWordBoundary());break;case'w':last.push(sets.words());break;case'W':last.push(sets.notWords());break;case'd':last.push(sets.ints());break;case'D':last.push(sets.notInts());break;case's':last.push(sets.whitespace());break;case'S':last.push(sets.notWhitespace());break;default:// Check if c is integer.
|
|
852
|
+
// In which case it's a reference.
|
|
853
|
+
if(/\d/.test(c)){last.push({type:types.REFERENCE,value:parseInt(c,10)});// Escaped character.
|
|
854
|
+
}else{last.push({type:types.CHAR,value:c.charCodeAt(0)});}}break;// Positionals.
|
|
855
|
+
case'^':last.push(positions.begin());break;case'$':last.push(positions.end());break;// Handle custom sets.
|
|
856
|
+
case'[':// Check if this class is 'anti' i.e. [^abc].
|
|
857
|
+
var not;if(str[i]==='^'){not=true;i++;}else{not=false;}// Get all the characters in class.
|
|
858
|
+
var classTokens=util.tokenizeClass(str.slice(i),regexpStr);// Increase index by length of class.
|
|
859
|
+
i+=classTokens[1];last.push({type:types.SET,set:classTokens[0],not});break;// Class of any character except \n.
|
|
860
|
+
case'.':last.push(sets.anyChar());break;// Push group onto stack.
|
|
861
|
+
case'(':// Create group.
|
|
862
|
+
var group={type:types.GROUP,stack:[],remember:true};c=str[i];// If if this is a special kind of group.
|
|
863
|
+
if(c==='?'){c=str[i+1];i+=2;// Match if followed by.
|
|
864
|
+
if(c==='='){group.followedBy=true;// Match if not followed by.
|
|
865
|
+
}else if(c==='!'){group.notFollowedBy=true;}else if(c!==':'){util.error(regexpStr,`Invalid group, character '${c}'`+` after '?' at column ${i-1}`);}group.remember=false;}// Insert subgroup into current group stack.
|
|
866
|
+
last.push(group);// Remember the current group for when the group closes.
|
|
867
|
+
groupStack.push(lastGroup);// Make this new group the current group.
|
|
868
|
+
lastGroup=group;last=group.stack;break;// Pop group out of stack.
|
|
869
|
+
case')':if(groupStack.length===0){util.error(regexpStr,`Unmatched ) at column ${i-1}`);}lastGroup=groupStack.pop();// Check if this group has a PIPE.
|
|
870
|
+
// To get back the correct last stack.
|
|
871
|
+
last=lastGroup.options?lastGroup.options[lastGroup.options.length-1]:lastGroup.stack;break;// Use pipe character to give more choices.
|
|
872
|
+
case'|':// Create array where options are if this is the first PIPE
|
|
873
|
+
// in this clause.
|
|
874
|
+
if(!lastGroup.options){lastGroup.options=[lastGroup.stack];delete lastGroup.stack;}// Create a new stack and add to options for rest of clause.
|
|
875
|
+
var stack=[];lastGroup.options.push(stack);last=stack;break;// Repetition.
|
|
876
|
+
// For every repetition, remove last element from last stack
|
|
877
|
+
// then insert back a RANGE object.
|
|
878
|
+
// This design is chosen because there could be more than
|
|
879
|
+
// one repetition symbols in a regex i.e. `a?+{2,3}`.
|
|
880
|
+
case'{':var rs=/^(\d+)(,(\d+)?)?\}/.exec(str.slice(i)),min,max;if(rs!==null){if(last.length===0){repeatErr(i);}min=parseInt(rs[1],10);max=rs[2]?rs[3]?parseInt(rs[3],10):Infinity:min;i+=rs[0].length;last.push({type:types.REPETITION,min,max,value:last.pop()});}else{last.push({type:types.CHAR,value:123});}break;case'?':if(last.length===0){repeatErr(i);}last.push({type:types.REPETITION,min:0,max:1,value:last.pop()});break;case'+':if(last.length===0){repeatErr(i);}last.push({type:types.REPETITION,min:1,max:Infinity,value:last.pop()});break;case'*':if(last.length===0){repeatErr(i);}last.push({type:types.REPETITION,min:0,max:Infinity,value:last.pop()});break;// Default is a character that is not `\[](){}?+*^$`.
|
|
881
|
+
default:last.push({type:types.CHAR,value:c.charCodeAt(0)});}}// Check if any groups have not been closed.
|
|
882
|
+
if(groupStack.length!==0){util.error(regexpStr,'Unterminated group');}return start;};module.exports.types=types;},{"./positions":55,"./sets":56,"./types":57,"./util":58}],55:[function(require,module,exports){const types=require('./types');exports.wordBoundary=()=>({type:types.POSITION,value:'b'});exports.nonWordBoundary=()=>({type:types.POSITION,value:'B'});exports.begin=()=>({type:types.POSITION,value:'^'});exports.end=()=>({type:types.POSITION,value:'$'});},{"./types":57}],56:[function(require,module,exports){const types=require('./types');const INTS=()=>[{type:types.RANGE,from:48,to:57}];const WORDS=()=>{return[{type:types.CHAR,value:95},{type:types.RANGE,from:97,to:122},{type:types.RANGE,from:65,to:90}].concat(INTS());};const WHITESPACE=()=>{return[{type:types.CHAR,value:9},{type:types.CHAR,value:10},{type:types.CHAR,value:11},{type:types.CHAR,value:12},{type:types.CHAR,value:13},{type:types.CHAR,value:32},{type:types.CHAR,value:160},{type:types.CHAR,value:5760},{type:types.RANGE,from:8192,to:8202},{type:types.CHAR,value:8232},{type:types.CHAR,value:8233},{type:types.CHAR,value:8239},{type:types.CHAR,value:8287},{type:types.CHAR,value:12288},{type:types.CHAR,value:65279}];};const NOTANYCHAR=()=>{return[{type:types.CHAR,value:10},{type:types.CHAR,value:13},{type:types.CHAR,value:8232},{type:types.CHAR,value:8233}];};// Predefined class objects.
|
|
883
|
+
exports.words=()=>({type:types.SET,set:WORDS(),not:false});exports.notWords=()=>({type:types.SET,set:WORDS(),not:true});exports.ints=()=>({type:types.SET,set:INTS(),not:false});exports.notInts=()=>({type:types.SET,set:INTS(),not:true});exports.whitespace=()=>({type:types.SET,set:WHITESPACE(),not:false});exports.notWhitespace=()=>({type:types.SET,set:WHITESPACE(),not:true});exports.anyChar=()=>({type:types.SET,set:NOTANYCHAR(),not:true});},{"./types":57}],57:[function(require,module,exports){module.exports={ROOT:0,GROUP:1,POSITION:2,SET:3,RANGE:4,REPETITION:5,REFERENCE:6,CHAR:7};},{}],58:[function(require,module,exports){const types=require('./types');const sets=require('./sets');const CTRL='@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ ?';const SLSH={'0':0,'t':9,'n':10,'v':11,'f':12,'r':13};/**
|
|
884
|
+
* Finds character representations in str and convert all to
|
|
885
|
+
* their respective characters
|
|
886
|
+
*
|
|
887
|
+
* @param {String} str
|
|
888
|
+
* @return {String}
|
|
889
|
+
*/exports.strToChars=function(str){/* jshint maxlen: false */var chars_regex=/(\[\\b\])|(\\)?\\(?:u([A-F0-9]{4})|x([A-F0-9]{2})|(0?[0-7]{2})|c([@A-Z[\\\]^?])|([0tnvfr]))/g;str=str.replace(chars_regex,function(s,b,lbs,a16,b16,c8,dctrl,eslsh){if(lbs){return s;}var code=b?8:a16?parseInt(a16,16):b16?parseInt(b16,16):c8?parseInt(c8,8):dctrl?CTRL.indexOf(dctrl):SLSH[eslsh];var c=String.fromCharCode(code);// Escape special regex characters.
|
|
890
|
+
if(/[[\]{}^$.|?*+()]/.test(c)){c='\\'+c;}return c;});return str;};/**
|
|
891
|
+
* turns class into tokens
|
|
892
|
+
* reads str until it encounters a ] not preceeded by a \
|
|
893
|
+
*
|
|
894
|
+
* @param {String} str
|
|
895
|
+
* @param {String} regexpStr
|
|
896
|
+
* @return {Array.<Array.<Object>, Number>}
|
|
897
|
+
*/exports.tokenizeClass=(str,regexpStr)=>{/* jshint maxlen: false */var tokens=[];var regexp=/\\(?:(w)|(d)|(s)|(W)|(D)|(S))|((?:(?:\\)(.)|([^\]\\]))-(?:\\)?([^\]]))|(\])|(?:\\)?([^])/g;var rs,c;while((rs=regexp.exec(str))!=null){if(rs[1]){tokens.push(sets.words());}else if(rs[2]){tokens.push(sets.ints());}else if(rs[3]){tokens.push(sets.whitespace());}else if(rs[4]){tokens.push(sets.notWords());}else if(rs[5]){tokens.push(sets.notInts());}else if(rs[6]){tokens.push(sets.notWhitespace());}else if(rs[7]){tokens.push({type:types.RANGE,from:(rs[8]||rs[9]).charCodeAt(0),to:rs[10].charCodeAt(0)});}else if(c=rs[12]){tokens.push({type:types.CHAR,value:c.charCodeAt(0)});}else{return[tokens,regexp.lastIndex];}}exports.error(regexpStr,'Unterminated character class');};/**
|
|
898
|
+
* Shortcut to throw errors.
|
|
899
|
+
*
|
|
900
|
+
* @param {String} regexp
|
|
901
|
+
* @param {String} msg
|
|
902
|
+
*/exports.error=(regexp,msg)=>{throw new SyntaxError('Invalid regular expression: /'+regexp+'/: '+msg);};},{"./sets":56,"./types":57}],59:[function(require,module,exports){(function(setImmediate,clearImmediate){(function(){var nextTick=require('process/browser.js').nextTick;var apply=Function.prototype.apply;var slice=Array.prototype.slice;var immediateIds={};var nextImmediateId=0;// DOM APIs, for completeness
|
|
903
|
+
exports.setTimeout=function(){return new Timeout(apply.call(setTimeout,window,arguments),clearTimeout);};exports.setInterval=function(){return new Timeout(apply.call(setInterval,window,arguments),clearInterval);};exports.clearTimeout=exports.clearInterval=function(timeout){timeout.close();};function Timeout(id,clearFn){this._id=id;this._clearFn=clearFn;}Timeout.prototype.unref=Timeout.prototype.ref=function(){};Timeout.prototype.close=function(){this._clearFn.call(window,this._id);};// Does not start the time, just sets up the members needed.
|
|
904
|
+
exports.enroll=function(item,msecs){clearTimeout(item._idleTimeoutId);item._idleTimeout=msecs;};exports.unenroll=function(item){clearTimeout(item._idleTimeoutId);item._idleTimeout=-1;};exports._unrefActive=exports.active=function(item){clearTimeout(item._idleTimeoutId);var msecs=item._idleTimeout;if(msecs>=0){item._idleTimeoutId=setTimeout(function onTimeout(){if(item._onTimeout)item._onTimeout();},msecs);}};// That's not how node.js implements it but the exposed api is the same.
|
|
905
|
+
exports.setImmediate=typeof setImmediate==="function"?setImmediate:function(fn){var id=nextImmediateId++;var args=arguments.length<2?false:slice.call(arguments,1);immediateIds[id]=true;nextTick(function onNextTick(){if(immediateIds[id]){// fn.call() is faster so we optimize for the common use-case
|
|
906
|
+
// @see http://jsperf.com/call-apply-segu
|
|
907
|
+
if(args){fn.apply(null,args);}else{fn.call(null);}// Prevent ids from leaking
|
|
908
|
+
exports.clearImmediate(id);}});return id;};exports.clearImmediate=typeof clearImmediate==="function"?clearImmediate:function(id){delete immediateIds[id];};}).call(this);}).call(this,require("timers").setImmediate,require("timers").clearImmediate);},{"process/browser.js":52,"timers":59}],60:[function(require,module,exports){/**
|
|
909
|
+
* Simple browser shim loader - assign the npm module to a window global automatically
|
|
910
|
+
*
|
|
911
|
+
* @license MIT
|
|
912
|
+
* @author <steven@velozo.com>
|
|
913
|
+
*/var libNPMModuleWrapper=require('./Orator.js');if(typeof window==='object'&&!window.hasOwnProperty('Orator')){window.Orator=libNPMModuleWrapper;}module.exports=libNPMModuleWrapper;},{"./Orator.js":66}],61:[function(require,module,exports){// Simple default configuration for application, when none is provided
|
|
914
|
+
module.exports={"Product":"Unnamed_Service","ProductVersion":"0.0.1","ServicePort":8080};},{}],62:[function(require,module,exports){/**
|
|
915
|
+
* Default Service Server Function
|
|
916
|
+
*
|
|
917
|
+
* @license MIT
|
|
918
|
+
*
|
|
919
|
+
* @author Steven Velozo <steven@velozo.com>
|
|
920
|
+
*/ // Return the servers that are available without extensions loaded
|
|
921
|
+
getDefaultServiceServers=()=>{let tmpDefaultServiceServers={};tmpDefaultServiceServers.ipc=require('./Orator-ServiceServer-IPC.js');tmpDefaultServiceServers.default=tmpDefaultServiceServers.ipc;return tmpDefaultServiceServers;};module.exports=getDefaultServiceServers();},{"./Orator-ServiceServer-IPC.js":65}],63:[function(require,module,exports){'use strict';// This is taken directly from the find-my-way documentation for custom constraints and only mildly edited
|
|
922
|
+
const ipcResponseTypeStrategy={// strategy name for referencing in the route handler `constraints` options
|
|
923
|
+
name:'ipc',isAsync:true,// storage factory for storing routes in the find-my-way route tree
|
|
924
|
+
storage:()=>{let handlers={};return{get:type=>{return handlers[type]||null;},set:(type,store)=>{handlers[type]=store;}};},// function to get the value of the constraint from each incoming request
|
|
925
|
+
deriveConstraint:(pRequest,pContext,fDone)=>{// If we wanted to deny the IPC request based on a constraint, we would do:
|
|
926
|
+
// fDone(new Error(`The request was denied because ____ in the Request object wasn't right...`));
|
|
927
|
+
return fDone(null,'IPC');},// optional flag marking if handlers without constraints can match requests that have a value for this constraint
|
|
928
|
+
mustMatchWhenDerived:true};module.exports=ipcResponseTypeStrategy;},{}],64:[function(require,module,exports){class OratorServiceServerIPCSynthesizedResponse{constructor(pLog,pRequestGUID){this.log=pLog;this.requestGUID=pRequestGUID;this.responseData=null;this.responseStatus=-1;}send(pData){if(typeof pData=='string'){// This is a string! Append it to the responsedata.
|
|
929
|
+
if(this.responseData===null){this.responseData=pData;return true;}else if(typeof this.responseData=='string'){this.responseData=this.responseData+pData;return true;}else{this.log(`Request ${this.requestGUID} has tried to send() a string value after send()ing data type ${typeof this.responseData}.`,pData);return false;}}else if(typeof pData=='object'){if(this.responseData===null){this.responseData=JSON.stringify(pData);return true;}else if(typeof this.responseData=='string'){// TODO: Discuss best way to handle this / if to handle this
|
|
930
|
+
this.responseData+=this.responseData+JSON.stringify(pData);return true;}else{this.log(`Request ${this.requestGUID} has tried to send() an object value to be auto stringified after send()ing data type ${typeof this.responseData}.`,pData);return false;}}}}module.exports=OratorServiceServerIPCSynthesizedResponse;},{}],65:[function(require,module,exports){const libOratorServiceServerBase=require('orator-serviceserver');// A synthesized response object, for simple IPC.
|
|
931
|
+
const libOratorServiceServerIPCSynthesizedResponse=require('./Orator-ServiceServer-IPC-SynthesizedResponse.js');// A simple constrainer for the find-my-way router since we aren't using any kind of headers to pass version or host
|
|
932
|
+
const libOratorServiceServerIPCCustomConstrainer=require('./Orator-ServiceServer-IPC-RouterConstrainer.js');// This library is the default router for our services
|
|
933
|
+
const libFindMyWay=require('find-my-way');//const libAsync = require('async');
|
|
934
|
+
const libAsyncWaterfall=require("async/waterfall");const libAsyncEachOfSeries=require('async/eachofseries');class OratorServiceServerIPC extends libOratorServiceServerBase{constructor(pOrator){super(pOrator);this.routerOptions=this.orator.settings.hasOwnProperty('router_options')&&typeof this.orator.settings.router_options=='object'?this.orator.settings.router_options:{};this.router=libFindMyWay(this.routerOptions);this.router.addConstraintStrategy(libOratorServiceServerIPCCustomConstrainer);this.URL='IPC';this.preBehaviorFunctions=[];this.behaviorMap={};this.postBehaviorFunctions=[];}executePreBehaviorFunctions(pRequest,pResponse,fNext){libAsyncEachOfSeries(this.preBehaviorFunctions,(fBehaviorFunction,pFunctionIndex,fCallback)=>{return fBehaviorFunction(pRequest,pResponse,fCallback);},pError=>{if(pError){this.log.error(`IPC Provider preBehaviorFunction ${pFunctionIndex} failed with error: ${pError}`,pError);}return fNext(pError);});}executePostBehaviorFunctions(pRequest,pResponse,fNext){libAsyncEachOfSeries(this.postBehaviorFunctions,(fBehaviorFunction,pFunctionIndex,fCallback)=>{return fBehaviorFunction(pRequest,pResponse,fCallback);},pError=>{if(pError){this.log.error(`IPC Provider postBehaviorFunction ${pFunctionIndex} failed with error: ${pError}`,pError);}return fNext(pError);});}/*
|
|
935
|
+
* Service Route Creation Functions
|
|
936
|
+
*
|
|
937
|
+
* These base functions provide basic validation for the routes, but don't actually
|
|
938
|
+
* do anything with them. The design intent here is to allow derived classes to call
|
|
939
|
+
* these functions to validate that they conform to expected standards.
|
|
940
|
+
*
|
|
941
|
+
* Something like:
|
|
942
|
+
|
|
943
|
+
get (pRoute, ...fRouteProcessingFunctions)
|
|
944
|
+
{
|
|
945
|
+
//...now we can do our actual get mapping function!....
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
* This pattern and calling super is totally optional, obviously.
|
|
949
|
+
*************************************************************************/addRouteProcessor(pMethod,pRoute,pRouteFunctionArray){// We have a constrainer on IPC so we can control channels eventually, if we like.
|
|
950
|
+
// For now it just makes sure it was added with an IPC service server.
|
|
951
|
+
this.router.on(pMethod,pRoute,{constraints:{"ipc":"IPC"}},(pRequest,pResponse,pParameters)=>{libAsyncWaterfall([fStageComplete=>{// Added to make this mimic what we saw with route parsing in the old restify
|
|
952
|
+
pRequest.params=pParameters;return fStageComplete();},fStageComplete=>{return this.executePreBehaviorFunctions(pRequest,pResponse,fStageComplete);},fStageComplete=>{libAsyncEachOfSeries(pRouteFunctionArray,(fBehaviorFunction,pFunctionIndex,fCallback)=>{return fBehaviorFunction(pRequest,pResponse,fCallback);},pBehaviorFunctionError=>{if(pBehaviorFunctionError){this.log.error(`IPC Provider behavior function ${pFunctionIndex} failed with error: ${pBehaviorFunctionError}`,pBehaviorFunctionError);return fNext(pError);}});},fStageComplete=>{return this.executePostBehaviorFunctions(pRequest,pResponse,fStageComplete);}],pRequestError=>{if(pRequestError){this.log.error(`IPC Provider behavior function ${pFunctionIndex} failed with error: ${pBehaviorFunctionError}`,pBehaviorFunctionError);}});});return true;}get(pRoute,...fRouteProcessingFunctions){if(!super.get(pRoute,...fRouteProcessingFunctions)){this.log.error(`IPC provider failed to map GET route [${pRoute}]!`);return false;}return this.addRouteProcessor('GET',pRoute,Array.from(fRouteProcessingFunctions));}put(pRoute,...fRouteProcessingFunctions){if(!super.get(pRoute,...fRouteProcessingFunctions)){this.log.error(`IPC provider failed to map PUT route [${pRoute}]!`);return false;}return true;}post(pRoute,...fRouteProcessingFunctions){if(!super.get(pRoute,...fRouteProcessingFunctions)){this.log.error(`IPC provider failed to map POST route [${pRoute}]!`);return false;}return true;}del(pRoute,...fRouteProcessingFunctions){if(!super.get(pRoute,...fRouteProcessingFunctions)){this.log.error(`IPC provider failed to map DEL route [${pRoute}]!`);return false;}return true;}/*************************************************************************
|
|
953
|
+
* End of Service Route Creation Functions
|
|
954
|
+
*/ // Programmatically invoke a route
|
|
955
|
+
invoke(pMethod,pRoute,pData,fCallback){// If the data is skipped and a callback is parameter 3, do the right thing
|
|
956
|
+
let tmpCallback=typeof fCallback=='function'?fCallback:typeof pData=='function'?pData:// This is here in case the developer passed no callback and just wants to fire and forget the IPC call which might not be async safe
|
|
957
|
+
()=>{};// Create a bare minimum request object for IPC to pass to our router
|
|
958
|
+
let tmpRequest={method:pMethod,url:pRoute,guid:this.orator.fable.getUUID()};// Create a container for the IPC response data to be aggregated to from send() methodds
|
|
959
|
+
let tmpSynthesizedResponseData=new libOratorServiceServerIPCSynthesizedResponse(this.log,tmpRequest.guid);return this.router.lookup(tmpRequest,tmpSynthesizedResponseData,(pError,pResults)=>{if(pError){this.log.error(`IPC Request Error Request GUID [${tmpRequest.guid}] handling route [${pRoute}]: ${pError}`,{Error:pError,Route:pRoute,Data:pData});}// by default, send data back through
|
|
960
|
+
return tmpCallback(pError,tmpSynthesizedResponseData.responseData,tmpSynthesizedResponseData,pResults);});}}module.exports=OratorServiceServerIPC;},{"./Orator-ServiceServer-IPC-RouterConstrainer.js":63,"./Orator-ServiceServer-IPC-SynthesizedResponse.js":64,"async/eachofseries":7,"async/waterfall":20,"find-my-way":40,"orator-serviceserver":48}],66:[function(require,module,exports){/**
|
|
961
|
+
* Orator Service Abstraction
|
|
962
|
+
*
|
|
963
|
+
* @license MIT
|
|
964
|
+
*
|
|
965
|
+
* @author Steven Velozo <steven@velozo.com>
|
|
966
|
+
* @module Orator Service
|
|
967
|
+
*/const libFable=require('fable');const defaultOratorConfiguration=require('./Orator-Default-Configuration.js');const defaultOratorServiceServers=require('./Orator-Default-ServiceServers-Node.js');class Orator{constructor(pFable,pServiceProvider){// Need to figure out if pFable is a Fable object or a Settings object or neither
|
|
968
|
+
if(typeof pFable==='object'&&pFable instanceof libFable){// We were passed a fully operational fable -- use this
|
|
969
|
+
this.fable=pFable;}else if(typeof pFable=='object'){this.fable=new libFable(pFable);}else{this.fable=new libFable(defaultOratorConfiguration);}// Carry core application requirements into the orator object for simplicity
|
|
970
|
+
this.settings=this.fable.settings;this.log=this.fable.log;// Create the empty, important logic containers
|
|
971
|
+
this.serviceServer=false;this.serviceServerProvider=false;if(typeof pServiceProvider!=='undefined'){this.serviceServerProvider=pServiceProvider;}// Now check to see that the ServicePort is set (this used to be APIServerPort)
|
|
972
|
+
if(!this.settings.hasOwnProperty('ServicePort')){if(this.settings.hasOwnProperty('APIServerPort')){// Automatically migrate the legacy APIServerPort to ServicePort
|
|
973
|
+
this.settings.ServicePort=this.fable.settings.APIServerPort;}else{// Default to whatever the ... default is!
|
|
974
|
+
this.settings.ServicePort=defaultOratorConfiguration.ServicePort;}}// Now check to see that the Product name is set
|
|
975
|
+
if(!this.settings.hasOwnProperty('Product')){this.settings.Product=defaultOratorConfiguration.Product;}}initializeServiceServer(fNext){var tmpNext=typeof fNext==='function'?fNext:()=>{};if(!this.serviceServer){// If the developer hasn't set this to a service provider class of their own choosing,
|
|
976
|
+
// use the built-in network-less one.
|
|
977
|
+
if(!this.serviceServerProvider){this.serviceServerProvider=defaultOratorServiceServers.default;}this.serviceServer=new this.serviceServerProvider(this);// For legacy reasons, we also will provide this under the "webServer" variable.
|
|
978
|
+
this.webServer=this.serviceServer;}else{this.log.warn(`Orator attempting to initialize a service server after initialization has already completed.`);}}_startServiceListener(fNext){return this.serviceServer.listen(this.settings.ServicePort,pError=>{this.log.info(`${this.serviceServer.Name} listening at ${this.serviceServer.URL} port ${this.serviceServer.Port}`);return fNext(pError);});}startService(fNext){var tmpNext=typeof fNext==='function'?fNext:()=>{};if(!this.serviceServer){this.initializeServiceServer();}return this._startServiceListener(tmpNext);}stopService(fNext){var tmpNext=typeof fNext==='function'?fNext:()=>{};if(!this.serviceServer){let tmpMessage=`Orator attempting to stop a service server but the service server has not been intialized yet.`;this.log.warn(tmpMessage);return tmpNext(tmpMessage);}if(!this.serviceServer.Active){let tmpMessage=`Orator attempting to stop a service server but the service server is not actively running.`;this.log.warn(tmpMessage);return tmpNext(tmpMessage);}return this.serviceServer.close(tmpNext);}invoke(pMethod,pRoute,pData,fCallback){return this.serviceServer.invoke(pMethod,pRoute,pData,fCallback);}/*
|
|
979
|
+
* Legacy Orator Functions
|
|
980
|
+
*************************************************************************/startWebServer(fNext){return this.startService(fNext);}// For legacy purposes
|
|
981
|
+
stopWebServer(fNext){return this.stopService(fNext);}// For legacy purposes
|
|
982
|
+
getWebServer(){// The old behavior was to lazily construct the service the first time
|
|
983
|
+
// this accessor function is called.
|
|
984
|
+
if(!this.serviceServer){this.initializeServiceServer();}return this.serviceServer;}/*************************************************************************
|
|
985
|
+
* End of Legacy Orator Functions
|
|
986
|
+
*/}module.exports=Orator;},{"./Orator-Default-Configuration.js":61,"./Orator-Default-ServiceServers-Node.js":62,"fable":31}]},{},[60])(60);});
|