UNPKG

30.7 kBJavaScriptView Raw
1/**
2 * @license
3 * MOST Web Framework 2.0 Codename Blueshift
4 * Copyright (c) 2017, THEMOST LP All rights reserved
5 *
6 * Use of this source code is governed by an BSD-3-Clause license that can be
7 * found in the LICENSE file at https://themost.io/license
8 */
9///
10var _ = require('lodash');
11var isNode = Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]';
12var sprintf = require("sprintf").sprintf;
13var Symbol = require("symbol");
14
15var UUID_CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
16var HEX_CHARS = 'abcdef1234567890';
17var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
18
19
20var DateTimeRegex = /^\d{4}-([0]\d|1[0-2])-([0-2]\d|3[01])(?:[T ](\d+):(\d+)(?::(\d+)(?:\.(\d+))?)?)?(?:Z(-?\d*))?$/g;
21var BooleanTrueRegex = /^true$/ig;
22var BooleanFalseRegex = /^false$/ig;
23var NullRegex = /^null$/ig;
24var UndefinedRegex = /^undefined$/ig;
25var IntegerRegex =/^[-+]?\d+$/g;
26var FloatRegex =/^[+-]?\d+(\.\d+)?$/g;
27var GuidRegex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
28
29/**
30 * @class
31 * @constructor
32 */
33function UnknownPropertyDescriptor(obj, name) {
34 Object.defineProperty(this, 'value', { configurable:false, enumerable:true, get: function() { return obj[name]; }, set: function(value) { obj[name]=value; } });
35 Object.defineProperty(this, 'name', { configurable:false, enumerable:true, get: function() { return name; } });
36}
37
38
39/**
40 * @class
41 * @constructor
42 */
43function LangUtils() {
44 //
45}
46
47/**
48 * Inherit the prototype methods from one constructor into another.
49 * @param {Function} ctor
50 * @param {Function|*} superCtor
51 * @example
52function Animal() {
53 //
54}
55
56function Dog() {
57 Dog.super_.bind(this)();
58}
59LangUtils.inherits(Dog,Animal);
60 */
61LangUtils.inherits = function(ctor, superCtor) {
62
63 if (typeof superCtor !== "function" && superCtor !== null) {
64 throw new TypeError("Super expression must either be null or a function, not " + typeof superCtor);
65 }
66
67 //if process is running under node js
68 if (isNode) {
69 var utilModule = "util";
70 var util = require(utilModule);
71 //call util.inherits() function
72 return util.inherits(ctor, superCtor);
73 }
74
75 ctor.prototype = Object.create(superCtor && superCtor.prototype, {
76 constructor: {
77 value: ctor,
78 enumerable: false,
79 writable: true,
80 configurable: true
81 }
82 });
83 if (superCtor) {
84 /**
85 * @function setPrototypeOf
86 * @param {*} obj
87 * @param {*} prototype
88 * @memberOf Object
89 * @static
90 */
91 if (typeof Object.setPrototypeOf === 'function') {
92 Object.setPrototypeOf(ctor, superCtor)
93 }
94 else {
95 ctor.__proto__ = superCtor
96 }
97 }
98 //node.js As an additional convenience, superConstructor will be accessible through the constructor.super_ property.
99 ctor.super_ = ctor.__proto__;
100};
101
102/**
103 * Returns an array of strings which represents the arguments' names of the given function
104 * @param {Function} fn
105 * @returns {Array}
106 */
107LangUtils.getFunctionParams = function(fn) {
108 if (!_.isFunction(fn))
109 return [];
110 var fnStr = fn.toString().replace(STRIP_COMMENTS, '');
111 var result = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')')).match(/([^\s,]+)/g);
112 if(result === null)
113 result = [];
114 return result;
115};
116
117
118/**
119 * @param {string} value
120 */
121LangUtils.convert = function(value) {
122 var result;
123 if ((typeof value === 'string'))
124 {
125 if (value.length===0) {
126 result = value
127 }
128 if (value.match(BooleanTrueRegex)) {
129 result = true;
130 }
131 else if (value.match(BooleanFalseRegex)) {
132 result = false;
133 }
134 else if (value.match(NullRegex) || value.match(UndefinedRegex)) {
135 result = null;
136 }
137 else if (value.match(IntegerRegex)) {
138 result = parseInt(value);
139 }
140 else if (value.match(FloatRegex)) {
141 result = parseFloat(value);
142 }
143 else if (value.match(DateTimeRegex)) {
144 result = new Date(Date.parse(value));
145 }
146 else {
147 result = value;
148 }
149 }
150 else {
151 result = value;
152 }
153 return result;
154};
155
156/**
157 *
158 * @param {*} origin
159 * @param {string} expr
160 * @param {string} value
161 * @param {*=} options
162 * @returns {*}
163 */
164LangUtils.extend = function(origin, expr, value, options) {
165
166 options = options || { convertValues:false };
167 //find base notation
168 var match = /(^\w+)\[/.exec(expr), name, descriptor, expr1;
169 if (match) {
170 //get property name
171 name = match[1];
172 //validate array property
173 if (/^\d+$/g.test(name)) {
174 //property is an array
175 if (!_.isArray(origin.value))
176 origin.value = [];
177 // get new expression
178 expr1 = expr.substr(match.index + match[1].length);
179 LangUtils.extend(origin, expr1, value, options);
180 }
181 else {
182 //set property value (unknown)
183 origin[name] = origin[name] || new LangUtils();
184 descriptor = new UnknownPropertyDescriptor(origin, name);
185 // get new expression
186 expr1 = expr.substr(match.index + match[1].length);
187 LangUtils.extend(descriptor, expr1, value, options);
188 }
189 }
190 else if (expr.indexOf('[')===0) {
191 //get property
192 var re = /\[(.*?)\]/g;
193 match = re.exec(expr);
194 if (match) {
195 name = match[1];
196 // get new expression
197 expr1 = expr.substr(match.index + match[0].length);
198 if (/^\d+$/g.test(name)) {
199 //property is an array
200 if (!_.isArray(origin.value))
201 origin.value = [];
202 }
203 if (expr1.length===0) {
204 if (origin.value instanceof LangUtils) {
205 origin.value = {};
206 }
207 var typedValue;
208 //convert string value
209 if ((typeof value === 'string') && options.convertValues) {
210 typedValue = LangUtils.convert(value);
211 }
212 else {
213 typedValue = value;
214 }
215 if (_.isArray(origin.value))
216 origin.value.push(typedValue);
217 else
218 origin.value[name] = typedValue;
219 }
220 else {
221 if (origin.value instanceof LangUtils) {
222 origin.value = { };
223 }
224 origin.value[name] = origin.value[name] || new LangUtils();
225 descriptor = new UnknownPropertyDescriptor(origin.value, name);
226 LangUtils.extend(descriptor, expr1, value, options);
227 }
228 }
229 else {
230 throw new Error('Invalid object property notation. Expected [name]');
231 }
232 }
233 else if (/^\w+$/.test(expr)) {
234 if (options.convertValues)
235 origin[expr] = LangUtils.convert(value);
236 else
237 origin[expr] = value;
238 }
239 else {
240 throw new Error('Invalid object property notation. Expected property[name] or [name]');
241 }
242 return origin;
243};
244
245
246/**
247 *
248 * @param {*} form
249 * @param {*=} options
250 * @returns {*}
251 */
252LangUtils.parseForm = function (form, options) {
253 var result = {};
254 if (typeof form === 'undefined' || form===null)
255 return result;
256 var keys = Object.keys(form);
257 keys.forEach(function(key) {
258 if (form.hasOwnProperty(key))
259 {
260 LangUtils.extend(result, key, form[key], options)
261 }
262 });
263 return result;
264};
265/**
266 * Parses any value or string and returns the resulted object.
267 * @param {*} any
268 * @returns {*}
269 */
270LangUtils.parseValue = function(any) {
271 return LangUtils.convert(any);
272};
273/**
274 * Parses any value and returns the equivalent integer.
275 * @param {*} any
276 * @returns {*}
277 */
278LangUtils.parseInt = function(any) {
279 return parseInt(any) || 0;
280};
281/**
282 * Parses any value and returns the equivalent float number.
283 * @param {*} any
284 * @returns {*}
285 */
286LangUtils.parseFloat = function(any) {
287 return parseFloat(any) || 0;
288};
289/**
290 * Parses any value and returns the equivalent boolean.
291 * @param {*} any
292 * @returns {*}
293 */
294LangUtils.parseBoolean = function(any) {
295 if (typeof any === 'undefined' || any === null)
296 return false;
297 else if (typeof any === 'number')
298 return any !== 0;
299 else if (typeof any === 'string') {
300 if (any.match(IntegerRegex) || any.match(FloatRegex)) {
301 return parseInt(any, 10) !== 0;
302 }
303 else if (any.match(BooleanTrueRegex))
304 return true;
305 else if (any.match(BooleanFalseRegex))
306 return false;
307 else if (/^yes$|^on$|^y$|^valid$/i.test(any))
308 return true;
309 else if (/^no$|^off$|^n$|^invalid$/i.test(any))
310 return false;
311 else
312 return false;
313 }
314 else if (typeof any === 'boolean')
315 return any;
316 else {
317 return (parseInt(any) || 0) !== 0;
318 }
319};
320/**
321 * @static
322 * Checks if the given value is a valid date
323 * @param {*} value
324 * @returns {boolean}
325 */
326LangUtils.isDate = function(value) {
327 if (value instanceof Date) {
328 return true;
329 }
330 return DateTimeRegex.test(value);
331};
332
333/**
334 * @function captureStackTrace
335 * @memberOf Error
336 * @param {Error} thisArg
337 * @param {string} name
338 * @static
339 */
340
341/**
342 * @class
343 * @constructor
344 */
345function Args() {
346 //
347}
348
349/**
350 * Checks the expression and throws an exception if the condition is not met.
351 * @param {*} expr
352 * @param {string|Error} err
353 */
354Args.check = function(expr, err) {
355 Args.notNull(expr,"Expression");
356 var res;
357 if (typeof expr === 'function') {
358 res = !(expr.call());
359 }
360 else {
361 res = (!expr);
362 }
363 if (res) {
364 if (err instanceof Error) {
365 throw err;
366 }
367 throw new ArgumentError(err, "ECHECK");
368 }
369};
370
371/**
372 *
373 * @param {*} arg
374 * @param {string} name
375 */
376Args.notNull = function(arg, name) {
377 if (typeof arg === 'undefined' || arg === null) {
378 throw new ArgumentError(name + " may not be null or undefined", "ENULL");
379 }
380};
381
382/**
383 * @param {*} arg
384 * @param {string} name
385 */
386Args.notString = function(arg, name) {
387 if (typeof arg !== 'string') {
388 throw new ArgumentError(name + " must be a string", "EARG");
389 }
390};
391
392/**
393 * @param {*} arg
394 * @param {string} name
395 */
396Args.notFunction = function(arg, name) {
397 if (typeof arg !== 'function') {
398 throw new ArgumentError(name + " must be a function", "EARG");
399 }
400};
401
402/**
403 * @param {*} arg
404 * @param {string} name
405 */
406Args.notNumber = function(arg, name) {
407 if ((typeof arg !== 'number') || isNaN(arg)) {
408 throw new ArgumentError(name + " must be number", "EARG");
409 }
410};
411
412/**
413 * @param {string|*} arg
414 * @param {string} name
415 */
416Args.notEmpty = function(arg, name) {
417 Args.notNull(arg,name);
418 if ((Object.prototype.toString.bind(arg)() === '[object Array]') && (arg.length === 0)) {
419 throw new ArgumentError(name + " may not be empty","EEMPTY");
420 }
421 else if ((typeof arg === 'string') && (arg.length===0)) {
422 throw new ArgumentError(name + " may not be empty","EEMPTY");
423 }
424};
425
426/**
427 * @param {number|*} arg
428 * @param {string} name
429 */
430Args.notNegative = function(arg, name) {
431 Args.notNumber(arg,name);
432 if (arg<0) {
433 throw new ArgumentError(name + " may not be negative", "ENEG");
434 }
435};
436
437/**
438 * @param {number|*} arg
439 * @param {string} name
440 */
441Args.notPositive = function(arg, name) {
442 Args.notNumber(arg,name);
443 if (arg<=0) {
444 throw new ArgumentError(name + " may not be negative or zero", "EPOS");
445 }
446};
447
448
449/**
450 * @class
451 * @constructor
452 */
453function TextUtils() {
454
455}
456
457 /**
458 * Converts the given parameter to MD5 hex string
459 * @static
460 * @param {*} value
461 * @returns {string|undefined}
462 */
463 TextUtils.toMD5 = function(value) {
464
465 if (typeof value === 'undefined' || value === null) {
466 return;
467 }
468 //browser implementation
469 var md5, md5module;
470 if (typeof window !== 'undefined') {
471 md5module = 'blueimp-md5';
472 md5 = require(md5module);
473 if (typeof value === 'string') {
474 return md5(value);
475 }
476 else if (value instanceof Date) {
477 return md5(value.toUTCString());
478 }
479 else {
480 return md5(JSON.stringify(value));
481 }
482 }
483 //node.js implementation
484 md5module = 'crypto';
485 var crypto = require(md5module);
486 md5 = crypto.createHash('md5');
487 if (typeof value === 'string') {
488 md5.update(value);
489 }
490 else if (value instanceof Date) {
491 md5.update(value.toUTCString());
492 }
493 else {
494 md5.update(JSON.stringify(value));
495 }
496 return md5.digest('hex');
497 };
498
499 /**
500 * Converts the given parameter to SHA1 hex string
501 * @static
502 * @param {*} value
503 * @returns {string|undefined}
504 */
505 TextUtils.toSHA1 = function(value) {
506
507 var cryptoModule = 'crypto';
508 if (typeof window !== 'undefined') {
509 throw new Error('This method is not implemented for this environment')
510 }
511
512 var crypto = require(cryptoModule);
513 if (typeof value === 'undefined' || value === null) {
514 return;
515 }
516 var sha1 = crypto.createHash('sha1');
517 if (typeof value === 'string') {
518 sha1.update(value);
519 }
520 else if (value instanceof Date) {
521 sha1.update(value.toUTCString());
522 }
523 else {
524 sha1.update(JSON.stringify(value));
525 }
526 return sha1.digest('hex');
527 };
528
529 /**
530 * Converts the given parameter to SHA256 hex string
531 * @static
532 * @param {*} value
533 * @returns {string|undefined}
534 */
535 TextUtils.toSHA256 = function(value) {
536
537 var cryptoModule = 'crypto';
538 if (typeof window !== 'undefined') {
539 throw new Error('This method is not implemented for this environment')
540 }
541
542 var crypto = require(cryptoModule);
543 if (typeof value === 'undefined' || value === null) {
544 return;
545 }
546 var sha256 = crypto.createHash('sha256');
547 if (typeof value === 'string') {
548 sha256.update(value);
549 }
550 else if (value instanceof Date) {
551 sha256.update(value.toUTCString());
552 }
553 else {
554 sha256.update(JSON.stringify(value));
555 }
556 return sha256.digest('hex');
557 };
558
559 /**
560 * Returns a random GUID/UUID string
561 * @static
562 * @returns {string}
563 */
564 TextUtils.newUUID = function() {
565 var chars = UUID_CHARS;
566 var uuid = [];
567 // rfc4122, version 4 form
568 var r = void 0;
569 // rfc4122 requires these characters
570 uuid[8] = uuid[13] = uuid[18] = uuid[23] = "-";
571 uuid[14] = "4";
572
573 // Fill in random data. At i==19 set the high bits of clock sequence as
574 // per rfc4122, sec. 4.1.5
575 for (var i = 0; i < 36; i++) {
576 if (!uuid[i]) {
577 r = 0 | Math.random() * 16;
578 uuid[i] = chars[i === 19 ? r & 0x3 | 0x8 : r];
579 }
580 }
581 return uuid.join("");
582 };
583
584 var loggerProperty = Symbol("logger");
585
586/**
587 * @class
588 * @constructor
589 */
590function TraceUtils() {
591
592 }
593
594 TraceUtils[loggerProperty] = new TraceLogger();
595
596 TraceUtils.useLogger = function(logger) {
597 TraceUtils[loggerProperty] = logger;
598 };
599
600 TraceUtils.level = function(level) {
601 TraceUtils[loggerProperty].level(level);
602 };
603
604 /**
605 * @static
606 * @param {...*} data
607 */
608// eslint-disable-next-line no-unused-vars
609 TraceUtils.log = function(data) {
610 TraceUtils[loggerProperty].log.apply(TraceUtils[loggerProperty], Array.prototype.slice.call(arguments));
611 };
612
613 /**
614 * @static
615 * @param {...*} data
616 */
617// eslint-disable-next-line no-unused-vars
618 TraceUtils.error = function(data) {
619 TraceUtils[loggerProperty].error.apply(TraceUtils[loggerProperty], Array.prototype.slice.call(arguments));
620 };
621
622 /**
623 *
624 * @static
625 * @param {...*} data
626 */
627// eslint-disable-next-line no-unused-vars
628 TraceUtils.info = function(data) {
629 TraceUtils[loggerProperty].info.apply(TraceUtils[loggerProperty], Array.prototype.slice.call(arguments));
630 };
631
632 /**
633 *
634 * @static
635 * @param {*} data
636 */
637// eslint-disable-next-line no-unused-vars
638 TraceUtils.warn= function(data) {
639 TraceUtils[loggerProperty].warn.apply(TraceUtils[loggerProperty], Array.prototype.slice.call(arguments));
640 };
641
642 /**
643 *
644 * @static
645 * @param {*} data
646 */
647 // eslint-disable-next-line no-unused-vars
648 TraceUtils.verbose = function(data) {
649 TraceUtils[loggerProperty].verbose.apply(TraceUtils[loggerProperty], Array.prototype.slice.call(arguments));
650 };
651
652 /**
653 *
654 * @static
655 * @param {...*} data
656 */
657 // eslint-disable-next-line no-unused-vars
658 TraceUtils.debug = function(data) {
659 TraceUtils[loggerProperty].debug.apply(TraceUtils[loggerProperty], Array.prototype.slice.call(arguments));
660 };
661
662/**
663 * @class
664 * @constructor
665 */
666function RandomUtils() {
667 //
668 }
669
670 /**
671 * Returns a random string based on the length specified
672 * @param {Number} length
673 */
674 RandomUtils.randomChars = function(length) {
675 length = length || 8;
676 var chars = "abcdefghkmnopqursuvwxz2456789ABCDEFHJKLMNPQURSTUVWXYZ";
677 var str = "";
678 for(var i = 0; i < length; i++) {
679 str += chars.substr(this.randomInt(0, chars.length-1),1);
680 }
681 return str;
682 };
683
684 /**
685 * Returns a random integer between a minimum and a maximum value
686 * @param {number} min
687 * @param {number} max
688 */
689 RandomUtils.randomInt = function(min, max) {
690 return Math.floor(Math.random() * (max - min + 1)) + min;
691 };
692
693 /**
694 * Returns a random string based on the length specified
695 * @static
696 * @param {number} length
697 * @returns {string}
698 */
699 RandomUtils.randomHex = function(length) {
700 length = (length || 8)*2;
701 var str = "";
702 for(var i = 0; i < length; i++) {
703 str += HEX_CHARS.substr(this.randomInt(0, HEX_CHARS.length-1),1);
704 }
705 return str;
706 };
707
708/**
709 * @class
710 * @constructor
711 */
712function NumberUtils() {
713 //
714 }
715
716 /**
717 * Converts a base-26 formatted string to the equivalent integer
718 * @static
719 * @param {string} s A base-26 formatted string e.g. aaaaaaaa for 0, baaaaaaa for 1 etc
720 * @return {number} The equivalent integer value
721 */
722 NumberUtils.fromBase26 = function(s) {
723 var num = 0;
724 if (!/[a-z]{8}/.test(s)) {
725 throw new Error('Invalid base-26 format.');
726 }
727 var a = 'a'.charCodeAt(0);
728 for (var i = 7; i >=0; i--) {
729 num = (num * 26) + (s[i].charCodeAt(0) - a);
730 }
731 return num;
732 };
733
734 /**
735 * Converts an integer to the equivalent base-26 formatted string
736 * @static
737 * @param {number} x The integer to be converted
738 * @return {string} The equivalent string value
739 */
740 NumberUtils.toBase26 = function(x) {
741 //noinspection ES6ConvertVarToLetConst
742 var num = parseInt(x);
743 if (num<0) {
744 throw new Error('A non-positive integer cannot be converted to base-26 format.');
745 }
746 if (num>208827064575) {
747 throw new Error('A positive integer bigger than 208827064575 cannot be converted to base-26 format.');
748 }
749 var out = "";
750 var length= 1;
751 var a = 'a'.charCodeAt(0);
752 while(length<=8)
753 {
754 out += String.fromCharCode(a + (num % 26));
755 num = Math.floor(num / 26);
756 length += 1;
757 }
758 return out;
759 };
760
761/**
762 * @class
763 * @constructor
764 */
765function PathUtils() {
766 //
767}
768
769/**
770 *
771 * @param {...string} part
772 * @returns {string}
773 */
774// eslint-disable-next-line no-unused-vars
775PathUtils.join = function (part) {
776 var pathModule = "path";
777 if (isNode) {
778 var path = require(pathModule);
779 return path.join.apply(null, Array.prototype.slice.call(arguments));
780 }
781 // Split the inputs into a list of path commands.
782 var parts = [], i, l;
783 for (i = 0, l = arguments.length; i < l; i++) {
784 parts = parts.concat(arguments[i].split("/"));
785 }
786// Interpret the path commands to get the new resolved path.
787 var newParts = [];
788 for (i = 0, l = parts.length; i < l; i++) {
789 var part1 = parts[i];
790 // Remove leading and trailing slashes
791 // Also remove "." segments
792 if (!part1 || part1 === ".") continue;
793 // Interpret ".." to pop the last segment
794 if (part1 === "..") newParts.pop();
795 // Push new path segments.
796 else newParts.push(part1);
797 }
798// Preserve the initial slash if there was one.
799 if (parts[0] === "") newParts.unshift("");
800// Turn back into a single string path.
801 return newParts.join("/") || (newParts.length ? "/" : ".");
802};
803
804var Reset = "\x1b[0m";
805var FgBlack = "\x1b[30m";
806var FgRed = "\x1b[31m";
807var FgGreen = "\x1b[32m";
808// eslint-disable-next-line no-unused-vars
809var FgYellow = "\x1b[33m";
810var FgBlue = "\x1b[34m";
811var FgMagenta = "\x1b[35m";
812// eslint-disable-next-line no-unused-vars
813var FgCyan = "\x1b[36m";
814// eslint-disable-next-line no-unused-vars
815var FgWhite = "\x1b[37m";
816
817var Bold = "\x1b[1m";
818
819var LogLevels = {
820 error: 0,
821 warn: 1,
822 info: 2,
823 verbose: 3,
824 debug: 4
825};
826
827var LogLevelColors = {
828 error: FgRed,
829 warn: FgMagenta,
830 info: FgBlack,
831 verbose: FgBlue,
832 debug: Bold + FgGreen
833};
834
835/**
836 * @private
837 * @returns {string}
838 */
839function timestamp() {
840 return (new Date()).toUTCString();
841}
842
843/**
844 * @private
845 * @this TraceLogger
846 * @param level
847 * @param err
848 */
849function writeError(level, err) {
850
851 var keys = _.filter(_.keys(err), function(x) {
852 return err.hasOwnProperty(x) && x!=='message' && typeof err[x] !== 'undefined' && err[x] != null;
853 });
854 if (err instanceof Error) {
855 if (err.hasOwnProperty('stack')) {
856 this.write(level, err.stack);
857 }
858 else {
859 this.write(level, err.toString());
860 }
861 }
862 else {
863 this.write(level, err.toString());
864 }
865 if (keys.length>0) {
866 this.write(level, "Error: " + _.map(keys, function(x) {
867 return "[" + x + "]=" + err[x].toString()
868 }).join(', '));
869 }
870}
871
872/**
873 * @class
874 * @param {*} options
875 * @constructor
876 */
877function TraceLogger(options) {
878 this.options = {
879 colors:false,
880 level:"info"
881 };
882 if (typeof options === "undefined" && options !== null && isNode) {
883 if (isNode && process.env.NODE_ENV === "development") {
884 this.options.level = "debug";
885 }
886 }
887 if (typeof options !== "undefined" && options !== null ) {
888 this.options = options;
889 //validate logging level
890 Args.check(LogLevels.hasOwnProperty(this.options.level), "Invalid logging level. Expected error, warn, info, verbose or debug.");
891 }
892}
893
894/**
895 * @param {string} level
896 * @returns {*}
897 */
898TraceLogger.prototype.level = function(level) {
899 Args.check(LogLevels.hasOwnProperty(level), "Invalid logging level. Expected error, warn, info, verbose or debug.");
900 this.options.level = level;
901 return this;
902};
903/**
904 * @param {...*} data
905 */
906// eslint-disable-next-line no-unused-vars
907TraceLogger.prototype.log = function(data) {
908 var args = Array.prototype.slice.call(arguments);
909 if (typeof data === 'undefined' || data === null) {
910 return;
911 }
912 if (data instanceof Error) {
913 return writeError.bind(this)("info",data);
914 }
915 if (typeof data !== 'string') {
916 return this.write("info", data.toString());
917 }
918 if (args.length>1) {
919 return this.write("info", sprintf.apply(null, args));
920 }
921 this.write("info", data);
922};
923/**
924 * @param {...*} data
925 */
926// eslint-disable-next-line no-unused-vars
927TraceLogger.prototype.info = function(data) {
928 var args = Array.prototype.slice.call(arguments);
929 if (typeof data === 'undefined' || data === null) {
930 return;
931 }
932 if (data instanceof Error) {
933 return writeError.bind(this)("info",data);
934 }
935 if (typeof data !== 'string') {
936 return this.write("info", data.toString());
937 }
938 if (args.length>1) {
939 return this.write("info", sprintf.apply(null, args));
940 }
941 this.write("info", data);
942};
943/**
944 * @param {...*} data
945 */
946// eslint-disable-next-line no-unused-vars
947TraceLogger.prototype.error = function(data) {
948 var args = Array.prototype.slice.call(arguments);
949 if (typeof data === 'undefined' || data === null) {
950 return;
951 }
952 if (data instanceof Error) {
953 return writeError.bind(this)("error",data);
954 }
955 if (typeof data !== 'string') {
956 return this.write("error", data.toString());
957 }
958 if (args.length>1) {
959 return this.write("error", sprintf.apply(null, args));
960 }
961 this.write("error", data);
962};
963/**
964 * @param {...*} data
965 */
966// eslint-disable-next-line no-unused-vars
967TraceLogger.prototype.warn = function(data) {
968 var args = Array.prototype.slice.call(arguments);
969 if (typeof data === 'undefined' || data === null) {
970 return;
971 }
972 if (data instanceof Error) {
973 return writeError.bind(this)("warn",data);
974 }
975 if (typeof data !== 'string') {
976 return this.write("warn", data.toString());
977 }
978 if (args.length>1) {
979 return this.write("warn", sprintf.apply(null, args));
980 }
981 this.write("warn", data);
982};
983/**
984 * @param {...*} data
985 */
986// eslint-disable-next-line no-unused-vars
987TraceLogger.prototype.verbose = function(data) {
988 var args = Array.prototype.slice.call(arguments);
989 if (typeof data === 'undefined' || data === null) {
990 return;
991 }
992 if (data instanceof Error) {
993 return writeError.bind(this)("verbose",data);
994 }
995 if (typeof data !== 'string') {
996 return this.write("verbose", data.toString());
997 }
998 if (args.length>1) {
999 return this.write("verbose", sprintf.apply(null, args));
1000 }
1001 this.write("verbose", data);
1002};
1003/**
1004 * @param {...*} data
1005 */
1006// eslint-disable-next-line no-unused-vars
1007TraceLogger.prototype.debug = function(data) {
1008 var args = Array.prototype.slice.call(arguments);
1009 if (typeof data === 'undefined' || data === null) {
1010 return;
1011 }
1012 if (data instanceof Error) {
1013 return writeError.bind(this)("debug",data);
1014 }
1015 if (typeof data !== 'string') {
1016 return this.write("debug", data.toString());
1017 }
1018 if (args.length>1) {
1019 return this.write("debug", sprintf.apply(null, args));
1020 }
1021 this.write("debug", data);
1022
1023};
1024
1025TraceLogger.prototype.write = function(level, text) {
1026 if (LogLevels[level]>LogLevels[this.options.level]) {
1027 return;
1028 }
1029 if (this.options.colors) {
1030// eslint-disable-next-line no-console
1031 console.log(LogLevelColors[level] + timestamp() + " [" + level.toUpperCase() + "] " + text, Reset);
1032 } else {
1033// eslint-disable-next-line no-console
1034 console.log(timestamp() + " [" + level.toUpperCase() + "] " + text);
1035 }
1036};
1037
1038/**
1039 * @param {number} value
1040 * @constructor
1041 */
1042function Base26Number(value) {
1043
1044 var thisValue = value;
1045 this.toString = function() {
1046 return Base26Number.toBase26(thisValue);
1047 }
1048}
1049
1050/**
1051 *
1052 * @param {number} x
1053 * @returns {string}
1054 */
1055Base26Number.toBase26 = function(x) {
1056 var num = Math.floor(x | 0);
1057 if (num<0) {
1058 throw new Error("A non-positive integer cannot be converted to base-26 format.");
1059 }
1060 if (num>208827064575) {
1061 throw new Error("A positive integer bigger than 208827064575 cannot be converted to base-26 format.");
1062 }
1063 var out = "";
1064 var length= 1;
1065 var a = "a".charCodeAt(0);
1066 while(length<=8) {
1067 out += String.fromCharCode(a + (num % 26));
1068 num = Math.floor(num / 26);
1069 length += 1;
1070 }
1071 return out;
1072};
1073/**
1074 *
1075 * @param {string} s
1076 * @returns {number}
1077 */
1078Base26Number.fromBase26 = function(s) {
1079 var num = 0;
1080 if (!/[a-z]{8}/.test(s)) {
1081 throw new Error("Invalid base-26 format.");
1082 }
1083 var a = "a".charCodeAt(0);
1084 for (var i = 7; i >=0; i--) {
1085 num = (num * 26) + (s[i].charCodeAt(0) - a);
1086 }
1087 return num;
1088};
1089
1090var valueProperty = Symbol("value");
1091/**
1092 * @class
1093 * @param {string=} value
1094 * @constructor
1095 */
1096function Guid(value) {
1097 if (typeof value === "string") {
1098 var test = value.replace(/^{/,"").replace(/{$/,"");
1099 Args.check(GuidRegex.test(test),"Value must be a valid UUID");
1100 this[valueProperty] = test;
1101 return;
1102 }
1103 this[valueProperty] = TextUtils.newUUID();
1104}
1105
1106Guid.prototype.toJSON = function() {
1107 return this[valueProperty];
1108};
1109
1110Guid.prototype.valueOf = function() {
1111 return this[valueProperty];
1112};
1113
1114Guid.prototype.toString = function() {
1115 return this[valueProperty];
1116};
1117
1118/**
1119 * @param {string|*} s
1120 * @returns {boolean}
1121 */
1122Guid.isGuid = function (s) {
1123 if (s instanceof Guid) {
1124 return true;
1125 }
1126 if (typeof s !== "string") {
1127 return false;
1128 }
1129 return GuidRegex.test(s);
1130};
1131/**
1132 * @returns {Guid}
1133 */
1134Guid.newGuid = function() {
1135 return new Guid();
1136};
1137
1138
1139/**
1140 * @param {string} msg
1141 * @param {string} code
1142 * @constructor
1143 * @extends TypeError
1144 */
1145function ArgumentError(msg, code) {
1146 ArgumentError.super_.bind(this)(msg);
1147 this.message = msg;
1148 this.code = code || "EARG";
1149 if (typeof Error.captureStackTrace === 'function') {
1150 Error.captureStackTrace(this, this.constructor);
1151 }
1152}
1153
1154LangUtils.inherits(ArgumentError, TypeError);
1155
1156if (typeof exports !== 'undefined') {
1157 module.exports.ArgumentError = ArgumentError;
1158 module.exports.Args = Args;
1159 module.exports.UnknownPropertyDescriptor = UnknownPropertyDescriptor;
1160 module.exports.LangUtils = LangUtils;
1161 module.exports.NumberUtils = NumberUtils;
1162 module.exports.RandomUtils = RandomUtils;
1163 module.exports.TraceUtils = TraceUtils;
1164 module.exports.TextUtils = TextUtils;
1165 module.exports.PathUtils = PathUtils;
1166 module.exports.Base26Number = Base26Number;
1167 module.exports.Guid = Guid;
1168}