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