@decaf-ts/decorator-validation
Version:
simple decorator based validation engine
254 lines • 35.5 kB
JavaScript
import "reflect-metadata";
import { DAYS_OF_WEEK_NAMES, MONTH_NAMES, } from "./../validation/Validators/constants.js";
import { sf } from "./strings.js";
/**
* @summary Reverses the process from {@link formatDate}
*
* @param {string} date the date string to be converted back into date
* @param {string} format the date format
* @return {Date} the date from the format or the standard new Date({@prop date}) if the string couldn't be parsed (are you sure the format matches the string?)
*
* @function dateFromFormat
* @memberOf module:decorator-validation
* @category Model
*/
export function dateFromFormat(date, format) {
let formatRegexp = format;
// Hour
if (formatRegexp.match(/hh/))
formatRegexp = formatRegexp.replace("hh", "(?<hour>\\d{2})");
else if (formatRegexp.match(/h/))
formatRegexp = formatRegexp.replace("h", "(?<hour>\\d{1,2})");
else if (formatRegexp.match(/HH/))
formatRegexp = formatRegexp.replace("HH", "(?<hour>\\d{2})");
else if (formatRegexp.match(/H/))
formatRegexp = formatRegexp.replace("H", "(?<hour>\\d{1,2})");
// Minutes
if (formatRegexp.match(/mm/))
formatRegexp = formatRegexp.replace("mm", "(?<minutes>\\d{2})");
else if (formatRegexp.match(/m/))
formatRegexp = formatRegexp.replace("m", "(?<minutes>\\d{1,2})");
// Seconds
if (formatRegexp.match(/ss/))
formatRegexp = formatRegexp.replace("ss", "(?<seconds>\\d{2})");
else if (formatRegexp.match(/s/))
formatRegexp = formatRegexp.replace("s", "(?<seconds>\\d{1,2})");
// Day
if (formatRegexp.match(/dd/))
formatRegexp = formatRegexp.replace("dd", "(?<day>\\d{2})");
else if (formatRegexp.match(/d/))
formatRegexp = formatRegexp.replace("d", "(?<day>\\d{1,2})");
// Day Of Week
if (formatRegexp.match(/EEEE/))
formatRegexp = formatRegexp.replace("EEEE", "(?<dayofweek>\\w+)");
// eslint-disable-next-line no-dupe-else-if
else if (formatRegexp.match(/EEEE/))
formatRegexp = formatRegexp.replace("EEE", "(?<dayofweek>\\w+)");
// Year
if (formatRegexp.match(/yyyy/))
formatRegexp = formatRegexp.replace("yyyy", "(?<year>\\d{4})");
else if (formatRegexp.match(/yy/))
formatRegexp = formatRegexp.replace("yy", "(?<year>\\d{2})");
// Month
if (formatRegexp.match(/MMMM/))
formatRegexp = formatRegexp.replace("MMMM", "(?<monthname>\\w+)");
else if (formatRegexp.match(/MMM/))
formatRegexp = formatRegexp.replace("MMM", "(?<monthnamesmall>\\w+)");
if (formatRegexp.match(/MM/))
formatRegexp = formatRegexp.replace("MM", "(?<month>\\d{2})");
else if (formatRegexp.match(/M/))
formatRegexp = formatRegexp.replace("M", "(?<month>\\d{1,2})");
// Milis and Am Pm
formatRegexp = formatRegexp
.replace("S", "(?<milis>\\d{1,3})")
.replace("aaa", "(?<ampm>\\w{2})");
const regexp = new RegExp(formatRegexp, "g");
const match = regexp.exec(date);
if (!match || !match.groups)
return new Date(date);
const safeParseInt = function (n) {
if (!n)
return 0;
const result = parseInt(n);
return isNaN(result) ? 0 : result;
};
const year = safeParseInt(match.groups.year);
const day = safeParseInt(match.groups.day);
const amPm = match.groups.ampm;
let hour = safeParseInt(match.groups.hour);
if (amPm)
hour = amPm === "PM" ? hour + 12 : hour;
const minutes = safeParseInt(match.groups.minutes);
const seconds = safeParseInt(match.groups.seconds);
const ms = safeParseInt(match.groups.milis);
const monthName = match.groups.monthname;
const monthNameSmall = match.groups.monthnamesmall;
let month = match.groups.month;
if (monthName)
month = MONTH_NAMES.indexOf(monthName);
else if (monthNameSmall) {
const m = MONTH_NAMES.find((m) => m.toLowerCase().startsWith(monthNameSmall.toLowerCase()));
if (!m)
return new Date(date);
month = MONTH_NAMES.indexOf(m);
}
else
month = safeParseInt(`${month}`);
return new Date(year, month - 1, day, hour, minutes, seconds, ms);
}
/**
* @description Binds a specific date format to a Date object's toString and toISOString methods
* @summary Modifies a Date object to return a formatted string when toString or toISOString is called.
* This function overrides the default toString and toISOString methods of the Date object to return
* the date formatted according to the specified format string.
* @param {Date} [date] The Date object to modify
* @param {string} [format] The format string to use for formatting the date
* @return {Date|undefined} The modified Date object or undefined if no date was provided
* @function bindDateToString
* @memberOf module:decorator-validation
* @category Model
*/
export function bindDateToString(date, format) {
if (!date)
return;
const func = () => formatDate(date, format);
Object.defineProperty(date, "toISOString", {
enumerable: false,
configurable: false,
value: func,
});
Object.defineProperty(date, "toString", {
enumerable: false,
configurable: false,
value: func,
});
// Object.setPrototypeOf(date, Date.prototype);
return date;
}
/**
* @description Safely checks if a value is a valid Date object
* @summary A utility function that determines if a value is a valid Date object.
* This function is more reliable than using instanceof Date as it also checks
* that the date is not NaN, which can happen with invalid date strings.
* @param {any} date The value to check
* @return {boolean} True if the value is a valid Date object, false otherwise
* @function isValidDate
* @memberOf module:decorator-validation
* @category Validation
*/
export function isValidDate(date) {
return (date &&
Object.prototype.toString.call(date) === "[object Date]" &&
!Number.isNaN(date));
}
/**
* @summary Util function to pad numbers
* @param {number} num
*
* @return {string}
*
* @function twoDigitPad
* @memberOf module:decorator-validation
* @category Model
*/
export function twoDigitPad(num) {
return num < 10 ? "0" + num : num.toString();
}
/**
* @summary Date Format Handling
* @description Code from {@link https://stackoverflow.com/questions/3552461/how-to-format-a-javascript-date}
*
* <pre>
* Using similar formatting as Moment.js, Class DateTimeFormatter (Java), and Class SimpleDateFormat (Java),
* I implemented a comprehensive solution formatDate(date, patternStr) where the code is easy to read and modify.
* You can display date, time, AM/PM, etc.
*
* Date and Time Patterns
* yy = 2-digit year; yyyy = full year
* M = digit month; MM = 2-digit month; MMM = short month name; MMMM = full month name
* EEEE = full weekday name; EEE = short weekday name
* d = digit day; dd = 2-digit day
* h = hours am/pm; hh = 2-digit hours am/pm; H = hours; HH = 2-digit hours
* m = minutes; mm = 2-digit minutes; aaa = AM/PM
* s = seconds; ss = 2-digit seconds
* S = miliseconds
* </pre>
*
* @param {Date} date
* @param {string} [patternStr] defaults to 'yyyy/MM/dd'
* @return {string} the formatted date
*
* @function formatDate
* @memberOf module:decorator-validation
* @category Model
*/
export function formatDate(date, patternStr = "yyyy/MM/dd") {
const day = date.getDate(), month = date.getMonth(), year = date.getFullYear(), hour = date.getHours(), minute = date.getMinutes(), second = date.getSeconds(), miliseconds = date.getMilliseconds(), h = hour % 12, hh = twoDigitPad(h), HH = twoDigitPad(hour), mm = twoDigitPad(minute), ss = twoDigitPad(second), aaa = hour < 12 ? "AM" : "PM", EEEE = DAYS_OF_WEEK_NAMES[date.getDay()], EEE = EEEE.substr(0, 3), dd = twoDigitPad(day), M = month + 1, MM = twoDigitPad(M), MMMM = MONTH_NAMES[month], MMM = MMMM.substr(0, 3), yyyy = year + "", yy = yyyy.substr(2, 2);
// checks to see if month name will be used
patternStr = patternStr
.replace("hh", hh)
.replace("h", h.toString())
.replace("HH", HH)
.replace("H", hour.toString())
.replace("mm", mm)
.replace("m", minute.toString())
.replace("ss", ss)
.replace("s", second.toString())
.replace("S", miliseconds.toString())
.replace("dd", dd)
.replace("d", day.toString())
.replace("EEEE", EEEE)
.replace("EEE", EEE)
.replace("yyyy", yyyy)
.replace("yy", yy)
.replace("aaa", aaa);
if (patternStr.indexOf("MMM") > -1) {
patternStr = patternStr.replace("MMMM", MMMM).replace("MMM", MMM);
}
else {
patternStr = patternStr.replace("MM", MM).replace("M", M.toString());
}
return patternStr;
}
/**
* @summary Parses a date from a specified format
* @param {string} format
* @param {string | Date | number} [v]
* @memberOf module:decorator-validation
* @category Model
*/
export function parseDate(format, v) {
let value = undefined;
if (!v)
return undefined;
if (v instanceof Date)
try {
value = dateFromFormat(formatDate(v, format), format);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
}
catch (e) {
throw new Error(sf("Could not convert date {0} to format: {1}", v.toString(), format));
}
else if (typeof v === "string") {
value = dateFromFormat(v, format);
}
else if (typeof v === "number") {
const d = new Date(v);
value = dateFromFormat(formatDate(d, format), format);
}
else if (isValidDate(v)) {
try {
const d = new Date(v);
value = dateFromFormat(formatDate(d, format), format);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
}
catch (e) {
throw new Error(sf("Could not convert date {0} to format: {1}", v, format));
}
}
else {
throw new Error(`Invalid value provided ${v}`);
}
return bindDateToString(value, format);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdXRpbHMvZGF0ZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxrQkFBa0IsQ0FBQztBQUMxQixPQUFPLEVBQ0wsa0JBQWtCLEVBQ2xCLFdBQVcsR0FDWixnREFBMkM7QUFDNUMsT0FBTyxFQUFFLEVBQUUsRUFBRSxxQkFBa0I7QUFFL0I7Ozs7Ozs7Ozs7R0FVRztBQUNILE1BQU0sVUFBVSxjQUFjLENBQUMsSUFBWSxFQUFFLE1BQWM7SUFDekQsSUFBSSxZQUFZLEdBQVcsTUFBTSxDQUFDO0lBRWxDLE9BQU87SUFDUCxJQUFJLFlBQVksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDO1FBQzFCLFlBQVksR0FBRyxZQUFZLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1NBQzFELElBQUksWUFBWSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUM7UUFDOUIsWUFBWSxHQUFHLFlBQVksQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLG1CQUFtQixDQUFDLENBQUM7U0FDM0QsSUFBSSxZQUFZLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQztRQUMvQixZQUFZLEdBQUcsWUFBWSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztTQUMxRCxJQUFJLFlBQVksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDO1FBQzlCLFlBQVksR0FBRyxZQUFZLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO0lBRWhFLFVBQVU7SUFDVixJQUFJLFlBQVksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDO1FBQzFCLFlBQVksR0FBRyxZQUFZLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxvQkFBb0IsQ0FBQyxDQUFDO1NBQzdELElBQUksWUFBWSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUM7UUFDOUIsWUFBWSxHQUFH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RUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUN0RSxDQUFDO1FBQ0osQ0FBQztTQUNFLElBQUksT0FBTyxDQUFDLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDL0IsS0FBSyxHQUFHLGNBQWMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDcEMsQ0FBQztTQUFNLElBQUksT0FBTyxDQUFDLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDakMsTUFBTSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdEIsS0FBSyxHQUFHLGNBQWMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ3hELENBQUM7U0FBTSxJQUFJLFdBQVcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQzFCLElBQUksQ0FBQztZQUNILE1BQU0sQ0FBQyxHQUFHLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3RCLEtBQUssR0FBRyxjQUFjLENBQUMsVUFBVSxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUN0RCw2REFBNkQ7UUFDL0QsQ0FBQztRQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDWCxNQUFNLElBQUksS0FBSyxDQUNiLEVBQUUsQ0FBQywyQ0FBMkMsRUFBRSxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQzNELENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztTQUFNLENBQUM7UUFDTixNQUFNLElBQUksS0FBSyxDQUFDLDBCQUEwQixDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFDRCxPQUFPLGdCQUFnQixDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQztBQUN6QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFwicmVmbGVjdC1tZXRhZGF0YVwiO1xuaW1wb3J0IHtcbiAgREFZU19PRl9XRUVLX05BTUVTLFxuICBNT05USF9OQU1FUyxcbn0gZnJvbSBcIi4uL3ZhbGlkYXRpb24vVmFsaWRhdG9ycy9jb25zdGFudHNcIjtcbmltcG9ydCB7IHNmIH0gZnJvbSBcIi4vc3RyaW5nc1wiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IFJldmVyc2VzIHRoZSBwcm9jZXNzIGZyb20ge0BsaW5rIGZvcm1hdERhdGV9XG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGUgdGhlIGRhdGUgc3RyaW5nIHRvIGJlIGNvbnZlcnRlZCBiYWNrIGludG8gZGF0ZVxuICogQHBhcmFtIHtzdHJpbmd9IGZvcm1hdCB0aGUgZGF0ZSBmb3JtYXRcbiAqIEByZXR1cm4ge0RhdGV9IHRoZSBkYXRlIGZyb20gdGhlIGZvcm1hdCBvciB0aGUgc3RhbmRhcmQgbmV3IERhdGUoe0Bwcm9wIGRhdGV9KSBpZiB0aGUgc3RyaW5nIGNvdWxkbid0IGJlIHBhcnNlZCAoYXJlIHlvdSBzdXJlIHRoZSBmb3JtYXQgbWF0Y2hlcyB0aGUgc3RyaW5nPylcbiAqXG4gKiBAZnVuY3Rpb24gZGF0ZUZyb21Gb3JtYXRcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb25cbiAqIEBjYXRlZ29yeSBNb2RlbFxuICovXG5leHBvcnQgZnVuY3Rpb24gZGF0ZUZyb21Gb3JtYXQoZGF0ZTogc3RyaW5nLCBmb3JtYXQ6IHN0cmluZykge1xuICBsZXQgZm9ybWF0UmVnZXhwOiBzdHJpbmcgPSBmb3JtYXQ7XG5cbiAgLy8gSG91clxuICBpZiAoZm9ybWF0UmVnZXhwLm1hdGNoKC9oaC8pKVxuICAgIGZvcm1hdFJlZ2V4cCA9IGZvcm1hdFJlZ2V4cC5yZXBsYWNlKFwiaGhcIiwgXCIoPzxob3VyPlxcXFxkezJ9KVwiKTtcbiAgZWxzZSBpZiAoZm9ybWF0UmVnZXhwLm1hdGNoKC9oLykpXG4gICAgZm9ybWF0UmVnZXhwID0gZm9ybWF0UmVnZXhwLnJlcGxhY2UoXCJoXCIsIFwiKD88aG91cj5cXFxcZHsxLDJ9KVwiKTtcbiAgZWxzZSBpZiAoZm9ybWF0UmVnZXhwLm1hdGNoKC9ISC8pKVxuICAgIGZvcm1hdFJlZ2V4cCA9IGZvcm1hdFJlZ2V4cC5yZXBsYWNlKFwiSEhcIiwgXCIoPzxob3VyPlxcXFxkezJ9KVwiKTtcbiAgZWxzZSBpZiAoZm9ybWF0UmVnZXhwLm1hdGNoKC9ILykpXG4gICAgZm9ybWF0UmVnZXhwID0gZm9ybWF0UmVnZXhwLnJlcGxhY2UoXCJIXCIsIFwiKD88aG91cj5cXFxcZHsxLDJ9KVwiKTtcblxuICAvLyBNaW51dGVzXG4gIGlmIChmb3JtYXRSZWdleHAubWF0Y2goL21tLykpXG4gICAgZm9ybWF0UmVnZXhwID0gZm9ybWF0UmVnZXhwLnJlcGxhY2UoXCJtbVwiLCBcIig/PG1pbnV0ZXM+XFxcXGR7Mn0pXCIpO1xuICBlbHNlIGlmIChmb3JtYXRSZWdleHAubWF0Y2goL20vKSlcbiAgICBmb3JtYXRSZWdleHAgPSBmb3JtYXRSZWdleHAucmVwbGFjZShcIm1cIiwgXCIoPzxtaW51dGVzPlxcXFxkezEsMn0pXCIpO1xuXG4gIC8vIFNlY29uZHNcbiAgaWYgKGZvcm1hdFJlZ2V4cC5tYXRjaCgvc3MvKSlcbiAgICBmb3JtYXRSZWdleHAgPSBmb3JtYXRSZWdleHAucmVwbGFjZShcInNzXCIsIFwiKD88c2Vjb25kcz5cXFxcZHsyfSlcIik7XG4gIGVsc2UgaWYgKGZvcm1hdFJlZ2V4cC5tYXRjaCgvcy8pKVxuICAgIGZvcm1hdFJlZ2V4cCA9IGZvcm1hdFJlZ2V4cC5yZXBsYWNlKFwic1wiLCBcIig/PHNlY29uZHM+XFxcXGR7MSwyfSlcIik7XG5cbiAgLy8gRGF5XG4gIGlmIChmb3JtYXRSZWdleHAubWF0Y2goL2RkLykpXG4gICAgZm9ybWF0UmVnZXhwID0gZm9ybWF0UmVnZXhwLnJlcGxhY2UoXCJkZFwiLCBcIig/PGRheT5cXFxcZHsyfSlcIik7XG4gIGVsc2UgaWYgKGZvcm1hdFJlZ2V4cC5tYXRjaCgvZC8pKVxuICAgIGZvcm1hdFJlZ2V4cCA9IGZvcm1hdFJlZ2V4cC5yZXBsYWNlKFwiZFwiLCBcIig/PGRheT5cXFxcZHsxLDJ9KVwiKTtcblxuICAvLyBEYXkgT2YgV2Vla1xuICBpZiAoZm9ybWF0UmVnZXhwLm1hdGNoKC9FRUVFLykpXG4gICAgZm9ybWF0UmVnZXhwID0gZm9ybWF0UmVnZXhwLnJlcGxhY2UoXCJFRUVFXCIsIFwiKD88ZGF5b2Z3ZWVrPlxcXFx3KylcIik7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1kdXBlLWVsc2UtaWZcbiAgZWxzZSBpZiAoZm9ybWF0UmVnZXhwLm1hdGNoKC9FRUVFLykpXG4gICAgZm9ybWF0UmVnZXhwID0gZm9ybWF0UmVnZXhwLnJlcGxhY2UoXCJFRUVcIiwgXCIoPzxkYXlvZndlZWs+XFxcXHcrKVwiKTtcblxuICAvLyBZZWFyXG4gIGlmIChmb3JtYXRSZWdleHAubWF0Y2goL3l5eXkvKSlcbiAgICBmb3JtYXRSZWdleHAgPSBmb3JtYXRSZWdleHAucmVwbGFjZShcInl5eXlcIiwgXCIoPzx5ZWFyPlxcXFxkezR9KVwiKTtcbiAgZWxzZSBpZiAoZm9ybWF0UmVnZXhwLm1hdGNoKC95eS8pKVxuICAgIGZvcm1hdFJlZ2V4cCA9IGZvcm1hdFJlZ2V4cC5yZXBsYWNlKFwieXlcIiwgXCIoPzx5ZWFyPlxcXFxkezJ9KVwiKTtcblxuICAvLyBNb250aFxuICBpZiAoZm9ybWF0UmVnZXhwLm1hdGNoKC9NTU1NLykpXG4gICAgZm9ybWF0UmVnZXhwID0gZm9ybWF0UmVnZXhwLnJlcGxhY2UoXCJNTU1NXCIsIFwiKD88bW9udGhuYW1lPlxcXFx3KylcIik7XG4gIGVsc2UgaWYgKGZvcm1hdFJlZ2V4cC5tYXRjaCgvTU1NLykpXG4gICAgZm9ybWF0UmVnZXhwID0gZm9ybWF0UmVnZXhwLnJlcGxhY2UoXCJNTU1cIiwgXCIoPzxtb250aG5hbWVzbWFsbD5cXFxcdyspXCIpO1xuICBpZiAoZm9ybWF0UmVnZXhwLm1hdGNoKC9NTS8pKVxuICAgIGZvcm1hdFJlZ2V4cCA9IGZvcm1hdFJlZ2V4cC5yZXBsYWNlKFwiTU1cIiwgXCIoPzxtb250aD5cXFxcZHsyfSlcIik7XG4gIGVsc2UgaWYgKGZvcm1hdFJlZ2V4cC5tYXRjaCgvTS8pKVxuICAgIGZvcm1hdFJlZ2V4cCA9IGZvcm1hdFJlZ2V4cC5yZXBsYWNlKFwiTVwiLCBcIig/PG1vbnRoPlxcXFxkezEsMn0pXCIpO1xuXG4gIC8vIE1pbGlzIGFuZCBBbSBQbVxuICBmb3JtYXRSZWdleHAgPSBmb3JtYXRSZWdleHBcbiAgICAucmVwbGFjZShcIlNcIiwgXCIoPzxtaWxpcz5cXFxcZHsxLDN9KVwiKVxuICAgIC5yZXBsYWNlKFwiYWFhXCIsIFwiKD88YW1wbT5cXFxcd3syfSlcIik7XG5cbiAgY29uc3QgcmVnZXhwID0gbmV3IFJlZ0V4cChmb3JtYXRSZWdleHAsIFwiZ1wiKTtcblxuICBjb25zdCBtYXRjaDoge1xuICAgIGdyb3Vwczoge1xuICAgICAgeWVhcj86IHN0cmluZztcbiAgICAgIGRheT86IHN0cmluZztcbiAgICAgIGFtcG0/OiBzdHJpbmc7XG4gICAgICBob3VyPzogc3RyaW5nO1xuICAgICAgbWludXRlcz86IHN0cmluZztcbiAgICAgIHNlY29uZHM/OiBzdHJpbmc7XG4gICAgICBtaWxpcz86IHN0cmluZztcbiAgICAgIG1vbnRobmFtZT86IHN0cmluZztcbiAgICAgIG1vbnRobmFtZXNtYWxsPzogc3RyaW5nO1xuICAgICAgbW9udGg/OiBzdHJpbmc7XG4gICAgfTtcbiAgfSA9IHJlZ2V4cC5leGVjKGRhdGUpIGFzIGFueTtcblxuICBpZiAoIW1hdGNoIHx8ICFtYXRjaC5ncm91cHMpIHJldHVybiBuZXcgRGF0ZShkYXRlKTtcblxuICBjb25zdCBzYWZlUGFyc2VJbnQgPSBmdW5jdGlvbiAobj86IHN0cmluZykge1xuICAgIGlmICghbikgcmV0dXJuIDA7XG4gICAgY29uc3QgcmVzdWx0ID0gcGFyc2VJbnQobik7XG5cbiAgICByZXR1cm4gaXNOYU4ocmVzdWx0KSA/IDAgOiByZXN1bHQ7XG4gIH07XG5cbiAgY29uc3QgeWVhciA9IHNhZmVQYXJzZUludChtYXRjaC5ncm91cHMueWVhcik7XG4gIGNvbnN0IGRheSA9IHNhZmVQYXJzZUludChtYXRjaC5ncm91cHMuZGF5KTtcblxuICBjb25zdCBhbVBtID0gbWF0Y2guZ3JvdXBzLmFtcG07XG4gIGxldCBob3VyID0gc2FmZVBhcnNlSW50KG1hdGNoLmdyb3Vwcy5ob3VyKTtcblxuICBpZiAoYW1QbSkgaG91ciA9IGFtUG0gPT09IFwiUE1cIiA/IGhvdXIgKyAxMiA6IGhvdXI7XG5cbiAgY29uc3QgbWludXRlcyA9IHNhZmVQYXJzZUludChtYXRjaC5ncm91cHMubWludXRlcyk7XG4gIGNvbnN0IHNlY29uZHMgPSBzYWZlUGFyc2VJbnQobWF0Y2guZ3JvdXBzLnNlY29uZHMpO1xuICBjb25zdCBtcyA9IHNhZmVQYXJzZUludChtYXRjaC5ncm91cHMubWlsaXMpO1xuXG4gIGNvbnN0IG1vbnRoTmFtZSA9IG1hdGNoLmdyb3Vwcy5tb250aG5hbWU7XG4gIGNvbnN0IG1vbnRoTmFtZVNtYWxsID0gbWF0Y2guZ3JvdXBzLm1vbnRobmFtZXNtYWxsO1xuICBsZXQgbW9udGg6IG51bWJlciB8IHN0cmluZyA9IG1hdGNoLmdyb3Vwcy5tb250aCBhcyBzdHJpbmc7XG4gIGlmIChtb250aE5hbWUpIG1vbnRoID0gTU9OVEhfTkFNRVMuaW5kZXhPZihtb250aE5hbWUpO1xuICBlbHNlIGlmIChtb250aE5hbWVTbWFsbCkge1xuICAgIGNvbnN0IG0gPSBNT05USF9OQU1FUy5maW5kKChtKSA9PlxuICAgICAgbS50b0xvd2VyQ2FzZSgpLnN0YXJ0c1dpdGgobW9udGhOYW1lU21hbGwudG9Mb3dlckNhc2UoKSlcbiAgICApO1xuICAgIGlmICghbSkgcmV0dXJuIG5ldyBEYXRlKGRhdGUpO1xuICAgIG1vbnRoID0gTU9OVEhfTkFNRVMuaW5kZXhPZihtKTtcbiAgfSBlbHNlIG1vbnRoID0gc2FmZVBhcnNlSW50KGAke21vbnRofWApO1xuXG4gIHJldHVybiBuZXcgRGF0ZSh5ZWFyLCBtb250aCAtIDEsIGRheSwgaG91ciwgbWludXRlcywgc2Vjb25kcywgbXMpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBCaW5kcyBhIHNwZWNpZmljIGRhdGUgZm9ybWF0IHRvIGEgRGF0ZSBvYmplY3QncyB0b1N0cmluZyBhbmQgdG9JU09TdHJpbmcgbWV0aG9kc1xuICogQHN1bW1hcnkgTW9kaWZpZXMgYSBEYXRlIG9iamVjdCB0byByZXR1cm4gYSBmb3JtYXR0ZWQgc3RyaW5nIHdoZW4gdG9TdHJpbmcgb3IgdG9JU09TdHJpbmcgaXMgY2FsbGVkLlxuICogVGhpcyBmdW5jdGlvbiBvdmVycmlkZXMgdGhlIGRlZmF1bHQgdG9TdHJpbmcgYW5kIHRvSVNPU3RyaW5nIG1ldGhvZHMgb2YgdGhlIERhdGUgb2JqZWN0IHRvIHJldHVyblxuICogdGhlIGRhdGUgZm9ybWF0dGVkIGFjY29yZGluZyB0byB0aGUgc3BlY2lmaWVkIGZvcm1hdCBzdHJpbmcuXG4gKiBAcGFyYW0ge0RhdGV9IFtkYXRlXSBUaGUgRGF0ZSBvYmplY3QgdG8gbW9kaWZ5XG4gKiBAcGFyYW0ge3N0cmluZ30gW2Zvcm1hdF0gVGhlIGZvcm1hdCBzdHJpbmcgdG8gdXNlIGZvciBmb3JtYXR0aW5nIHRoZSBkYXRlXG4gKiBAcmV0dXJuIHtEYXRlfHVuZGVmaW5lZH0gVGhlIG1vZGlmaWVkIERhdGUgb2JqZWN0IG9yIHVuZGVmaW5lZCBpZiBubyBkYXRlIHdhcyBwcm92aWRlZFxuICogQGZ1bmN0aW9uIGJpbmREYXRlVG9TdHJpbmdcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb25cbiAqIEBjYXRlZ29yeSBNb2RlbFxuICovXG5leHBvcnQgZnVuY3Rpb24gYmluZERhdGVUb1N0cmluZyhkYXRlOiBEYXRlIHwgdW5kZWZpbmVkLCBmb3JtYXQ6IHN0cmluZykge1xuICBpZiAoIWRhdGUpIHJldHVybjtcbiAgY29uc3QgZnVuYyA9ICgpID0+IGZvcm1hdERhdGUoZGF0ZSwgZm9ybWF0KTtcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGRhdGUsIFwidG9JU09TdHJpbmdcIiwge1xuICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gICAgdmFsdWU6IGZ1bmMsXG4gIH0pO1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZGF0ZSwgXCJ0b1N0cmluZ1wiLCB7XG4gICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgY29uZmlndXJhYmxlOiBmYWxzZSxcbiAgICB2YWx1ZTogZnVuYyxcbiAgfSk7XG4gIC8vIE9iamVjdC5zZXRQcm90b3R5cGVPZihkYXRlLCBEYXRlLnByb3RvdHlwZSk7XG4gIHJldHVybiBkYXRlO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTYWZlbHkgY2hlY2tzIGlmIGEgdmFsdWUgaXMgYSB2YWxpZCBEYXRlIG9iamVjdFxuICogQHN1bW1hcnkgQSB1dGlsaXR5IGZ1bmN0aW9uIHRoYXQgZGV0ZXJtaW5lcyBpZiBhIHZhbHVlIGlzIGEgdmFsaWQgRGF0ZSBvYmplY3QuXG4gKiBUaGlzIGZ1bmN0aW9uIGlzIG1vcmUgcmVsaWFibGUgdGhhbiB1c2luZyBpbnN0YW5jZW9mIERhdGUgYXMgaXQgYWxzbyBjaGVja3NcbiAqIHRoYXQgdGhlIGRhdGUgaXMgbm90IE5hTiwgd2hpY2ggY2FuIGhhcHBlbiB3aXRoIGludmFsaWQgZGF0ZSBzdHJpbmdzLlxuICogQHBhcmFtIHthbnl9IGRhdGUgVGhlIHZhbHVlIHRvIGNoZWNrXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIHRoZSB2YWx1ZSBpcyBhIHZhbGlkIERhdGUgb2JqZWN0LCBmYWxzZSBvdGhlcndpc2VcbiAqIEBmdW5jdGlvbiBpc1ZhbGlkRGF0ZVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0b3ItdmFsaWRhdGlvblxuICogQGNhdGVnb3J5IFZhbGlkYXRpb25cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWREYXRlKGRhdGU6IGFueSk6IGJvb2xlYW4ge1xuICByZXR1cm4gKFxuICAgIGRhdGUgJiZcbiAgICBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoZGF0ZSkgPT09IFwiW29iamVjdCBEYXRlXVwiICYmXG4gICAgIU51bWJlci5pc05hTihkYXRlKVxuICApO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IFV0aWwgZnVuY3Rpb24gdG8gcGFkIG51bWJlcnNcbiAqIEBwYXJhbSB7bnVtYmVyfSBudW1cbiAqXG4gKiBAcmV0dXJuIHtzdHJpbmd9XG4gKlxuICogQGZ1bmN0aW9uIHR3b0RpZ2l0UGFkXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uXG4gKiBAY2F0ZWdvcnkgTW9kZWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHR3b0RpZ2l0UGFkKG51bTogbnVtYmVyKTogc3RyaW5nIHtcbiAgcmV0dXJuIG51bSA8IDEwID8gXCIwXCIgKyBudW0gOiBudW0udG9TdHJpbmcoKTtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBEYXRlIEZvcm1hdCBIYW5kbGluZ1xuICogQGRlc2NyaXB0aW9uIENvZGUgZnJvbSB7QGxpbmsgaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMzU1MjQ2MS9ob3ctdG8tZm9ybWF0LWEtamF2YXNjcmlwdC1kYXRlfVxuICpcbiAqIDxwcmU+XG4gKiAgICAgIFVzaW5nIHNpbWlsYXIgZm9ybWF0dGluZyBhcyBNb21lbnQuanMsIENsYXNzIERhdGVUaW1lRm9ybWF0dGVyIChKYXZhKSwgYW5kIENsYXNzIFNpbXBsZURhdGVGb3JtYXQgKEphdmEpLFxuICogICAgICBJIGltcGxlbWVudGVkIGEgY29tcHJlaGVuc2l2ZSBzb2x1dGlvbiBmb3JtYXREYXRlKGRhdGUsIHBhdHRlcm5TdHIpIHdoZXJlIHRoZSBjb2RlIGlzIGVhc3kgdG8gcmVhZCBhbmQgbW9kaWZ5LlxuICogICAgICBZb3UgY2FuIGRpc3BsYXkgZGF0ZSwgdGltZSwgQU0vUE0sIGV0Yy5cbiAqXG4gKiAgICAgIERhdGUgYW5kIFRpbWUgUGF0dGVybnNcbiAqICAgICAgeXkgPSAyLWRpZ2l0IHllYXI7IHl5eXkgPSBmdWxsIHllYXJcbiAqICAgICAgTSA9IGRpZ2l0IG1vbnRoOyBNTSA9IDItZGlnaXQgbW9udGg7IE1NTSA9IHNob3J0IG1vbnRoIG5hbWU7IE1NTU0gPSBmdWxsIG1vbnRoIG5hbWVcbiAqICAgICAgRUVFRSA9IGZ1bGwgd2Vla2RheSBuYW1lOyBFRUUgPSBzaG9ydCB3ZWVrZGF5IG5hbWVcbiAqICAgICAgZCA9IGRpZ2l0IGRheTsgZGQgPSAyLWRpZ2l0IGRheVxuICogICAgICBoID0gaG91cnMgYW0vcG07IGhoID0gMi1kaWdpdCBob3VycyBhbS9wbTsgSCA9IGhvdXJzOyBISCA9IDItZGlnaXQgaG91cnNcbiAqICAgICAgbSA9IG1pbnV0ZXM7IG1tID0gMi1kaWdpdCBtaW51dGVzOyBhYWEgPSBBTS9QTVxuICogICAgICBzID0gc2Vjb25kczsgc3MgPSAyLWRpZ2l0IHNlY29uZHNcbiAqICAgICAgUyA9IG1pbGlzZWNvbmRzXG4gKiA8L3ByZT5cbiAqXG4gKiBAcGFyYW0ge0RhdGV9IGRhdGVcbiAqIEBwYXJhbSB7c3RyaW5nfSBbcGF0dGVyblN0cl0gZGVmYXVsdHMgdG8gJ3l5eXkvTU0vZGQnXG4gKiBAcmV0dXJuIHtzdHJpbmd9IHRoZSBmb3JtYXR0ZWQgZGF0ZVxuICpcbiAqIEBmdW5jdGlvbiBmb3JtYXREYXRlXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uXG4gKiBAY2F0ZWdvcnkgTW9kZWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdERhdGUoZGF0ZTogRGF0ZSwgcGF0dGVyblN0cjogc3RyaW5nID0gXCJ5eXl5L01NL2RkXCIpIHtcbiAgY29uc3QgZGF5OiBudW1iZXIgPSBkYXRlLmdldERhdGUoKSxcbiAgICBtb250aDogbnVtYmVyID0gZGF0ZS5nZXRNb250aCgpLFxuICAgIHllYXI6IG51bWJlciA9IGRhdGUuZ2V0RnVsbFllYXIoKSxcbiAgICBob3VyOiBudW1iZXIgPSBkYXRlLmdldEhvdXJzKCksXG4gICAgbWludXRlOiBudW1iZXIgPSBkYXRlLmdldE1pbnV0ZXMoKSxcbiAgICBzZWNvbmQ6IG51bWJlciA9IGRhdGUuZ2V0U2Vjb25kcygpLFxuICAgIG1pbGlzZWNvbmRzOiBudW1iZXIgPSBkYXRlLmdldE1pbGxpc2Vjb25kcygpLFxuICAgIGg6IG51bWJlciA9IGhvdXIgJSAxMixcbiAgICBoaDogc3RyaW5nID0gdHdvRGlnaXRQYWQoaCksXG4gICAgSEg6IHN0cmluZyA9IHR3b0RpZ2l0UGFkKGhvdXIpLFxuICAgIG1tOiBzdHJpbmcgPSB0d29EaWdpdFBhZChtaW51dGUpLFxuICAgIHNzOiBzdHJpbmcgPSB0d29EaWdpdFBhZChzZWNvbmQpLFxuICAgIGFhYTogc3RyaW5nID0gaG91ciA8IDEyID8gXCJBTVwiIDogXCJQTVwiLFxuICAgIEVFRUU6IHN0cmluZyA9IERBWVNfT0ZfV0VFS19OQU1FU1tkYXRlLmdldERheSgpXSxcbiAgICBFRUU6IHN0cmluZyA9IEVFRUUuc3Vic3RyKDAsIDMpLFxuICAgIGRkOiBzdHJpbmcgPSB0d29EaWdpdFBhZChkYXkpLFxuICAgIE06IG51bWJlciA9IG1vbnRoICsgMSxcbiAgICBNTTogc3RyaW5nID0gdHdvRGlnaXRQYWQoTSksXG4gICAgTU1NTTogc3RyaW5nID0gTU9OVEhfTkFNRVNbbW9udGhdLFxuICAgIE1NTTogc3RyaW5nID0gTU1NTS5zdWJzdHIoMCwgMyksXG4gICAgeXl5eTogc3RyaW5nID0geWVhciArIFwiXCIsXG4gICAgeXk6IHN0cmluZyA9IHl5eXkuc3Vic3RyKDIsIDIpO1xuICAvLyBjaGVja3MgdG8gc2VlIGlmIG1vbnRoIG5hbWUgd2lsbCBiZSB1c2VkXG4gIHBhdHRlcm5TdHIgPSBwYXR0ZXJuU3RyXG4gICAgLnJlcGxhY2UoXCJoaFwiLCBoaClcbiAgICAucmVwbGFjZShcImhcIiwgaC50b1N0cmluZygpKVxuICAgIC5yZXBsYWNlKFwiSEhcIiwgSEgpXG4gICAgLnJlcGxhY2UoXCJIXCIsIGhvdXIudG9TdHJpbmcoKSlcbiAgICAucmVwbGFjZShcIm1tXCIsIG1tKVxuICAgIC5yZXBsYWNlKFwibVwiLCBtaW51dGUudG9TdHJpbmcoKSlcbiAgICAucmVwbGFjZShcInNzXCIsIHNzKVxuICAgIC5yZXBsYWNlKFwic1wiLCBzZWNvbmQudG9TdHJpbmcoKSlcbiAgICAucmVwbGFjZShcIlNcIiwgbWlsaXNlY29uZHMudG9TdHJpbmcoKSlcbiAgICAucmVwbGFjZShcImRkXCIsIGRkKVxuICAgIC5yZXBsYWNlKFwiZFwiLCBkYXkudG9TdHJpbmcoKSlcblxuICAgIC5yZXBsYWNlKFwiRUVFRVwiLCBFRUVFKVxuICAgIC5yZXBsYWNlKFwiRUVFXCIsIEVFRSlcbiAgICAucmVwbGFjZShcInl5eXlcIiwgeXl5eSlcbiAgICAucmVwbGFjZShcInl5XCIsIHl5KVxuICAgIC5yZXBsYWNlKFwiYWFhXCIsIGFhYSk7XG4gIGlmIChwYXR0ZXJuU3RyLmluZGV4T2YoXCJNTU1cIikgPiAtMSkge1xuICAgIHBhdHRlcm5TdHIgPSBwYXR0ZXJuU3RyLnJlcGxhY2UoXCJNTU1NXCIsIE1NTU0pLnJlcGxhY2UoXCJNTU1cIiwgTU1NKTtcbiAgfSBlbHNlIHtcbiAgICBwYXR0ZXJuU3RyID0gcGF0dGVyblN0ci5yZXBsYWNlKFwiTU1cIiwgTU0pLnJlcGxhY2UoXCJNXCIsIE0udG9TdHJpbmcoKSk7XG4gIH1cbiAgcmV0dXJuIHBhdHRlcm5TdHI7XG59XG5cbi8qKlxuICogQHN1bW1hcnkgUGFyc2VzIGEgZGF0ZSBmcm9tIGEgc3BlY2lmaWVkIGZvcm1hdFxuICogQHBhcmFtIHtzdHJpbmd9IGZvcm1hdFxuICogQHBhcmFtIHtzdHJpbmcgfCBEYXRlIHwgbnVtYmVyfSBbdl1cbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb25cbiAqIEBjYXRlZ29yeSBNb2RlbFxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VEYXRlKGZvcm1hdDogc3RyaW5nLCB2Pzogc3RyaW5nIHwgRGF0ZSB8IG51bWJlcikge1xuICBsZXQgdmFsdWU6IERhdGUgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG5cbiAgaWYgKCF2KSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gIGlmICh2IGluc3RhbmNlb2YgRGF0ZSlcbiAgICB0cnkge1xuICAgICAgdmFsdWUgPSBkYXRlRnJvbUZvcm1hdChmb3JtYXREYXRlKHYgYXMgRGF0ZSwgZm9ybWF0KSwgZm9ybWF0KTtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgc2YoXCJDb3VsZCBub3QgY29udmVydCBkYXRlIHswfSB0byBmb3JtYXQ6IHsxfVwiLCB2LnRvU3RyaW5nKCksIGZvcm1hdClcbiAgICAgICk7XG4gICAgfVxuICBlbHNlIGlmICh0eXBlb2YgdiA9PT0gXCJzdHJpbmdcIikge1xuICAgIHZhbHVlID0gZGF0ZUZyb21Gb3JtYXQodiwgZm9ybWF0KTtcbiAgfSBlbHNlIGlmICh0eXBlb2YgdiA9PT0gXCJudW1iZXJcIikge1xuICAgIGNvbnN0IGQgPSBuZXcgRGF0ZSh2KTtcbiAgICB2YWx1ZSA9IGRhdGVGcm9tRm9ybWF0KGZvcm1hdERhdGUoZCwgZm9ybWF0KSwgZm9ybWF0KTtcbiAgfSBlbHNlIGlmIChpc1ZhbGlkRGF0ZSh2KSkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBkID0gbmV3IERhdGUodik7XG4gICAgICB2YWx1ZSA9IGRhdGVGcm9tRm9ybWF0KGZvcm1hdERhdGUoZCwgZm9ybWF0KSwgZm9ybWF0KTtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIHNmKFwiQ291bGQgbm90IGNvbnZlcnQgZGF0ZSB7MH0gdG8gZm9ybWF0OiB7MX1cIiwgdiwgZm9ybWF0KVxuICAgICAgKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHZhbHVlIHByb3ZpZGVkICR7dn1gKTtcbiAgfVxuICByZXR1cm4gYmluZERhdGVUb1N0cmluZyh2YWx1ZSwgZm9ybWF0KTtcbn1cbiJdfQ==