@decaf-ts/decorator-validation
Version:
simple decorator based validation engine
137 lines • 14.8 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { Validator } from "./Validator.js";
import { DEFAULT_ERROR_MESSAGES, ValidationKeys } from "./constants.js";
import { validator } from "./decorators.js";
/**
* @description Regular expression for parsing string patterns with flags
* @summary This regular expression is used to parse string patterns in the format "/pattern/flags".
* It captures the pattern and flags separately, allowing the creation of a RegExp object
* with the appropriate flags.
*
* @const {RegExp}
* @memberOf module:decorator-validation
* @category Validation
*/
export const regexpParser = new RegExp("^/(.+)/([gimus]*)$");
/**
* @description Validator for checking if a string matches a regular expression pattern
* @summary The PatternValidator checks if a string value matches a specified regular expression pattern.
* It supports both RegExp objects and string representations of patterns, including those with flags.
* This validator is the foundation for specialized validators like EmailValidator and URLValidator,
* and is typically used with the @pattern decorator.
*
* @param {string} [message] - Custom error message to display when validation fails, defaults to {@link DEFAULT_ERROR_MESSAGES#PATTERN}
*
* @class PatternValidator
* @extends Validator
*
* @example
* ```typescript
* // Create a pattern validator with default error message
* const patternValidator = new PatternValidator();
*
* // Create a pattern validator with custom error message
* const customPatternValidator = new PatternValidator("Value must match the required format");
*
* // Validate using a RegExp object
* const regexOptions = { pattern: /^[A-Z][a-z]+$/ };
* patternValidator.hasErrors("Hello", regexOptions); // undefined (valid)
* patternValidator.hasErrors("hello", regexOptions); // Returns error message (invalid)
*
* // Validate using a string pattern
* const stringOptions = { pattern: "^\\d{3}-\\d{2}-\\d{4}$" };
* patternValidator.hasErrors("123-45-6789", stringOptions); // undefined (valid)
*
* // Validate using a string pattern with flags
* const flagOptions = { pattern: "/^hello$/i" };
* patternValidator.hasErrors("Hello", flagOptions); // undefined (valid)
* ```
*
* @mermaid
* sequenceDiagram
* participant C as Client
* participant V as PatternValidator
*
* C->>V: new PatternValidator(message)
* C->>V: hasErrors(value, options)
* alt value is empty
* V-->>C: undefined (valid)
* else pattern is missing
* V-->>C: Error: Missing Pattern
* else pattern is string
* V->>V: getPattern(pattern)
* end
* V->>V: Reset pattern.lastIndex
* V->>V: Test value against pattern
* alt pattern test passes
* V-->>C: undefined (valid)
* else pattern test fails
* V-->>C: Error message
* end
*
* @category Validators
*/
let PatternValidator = class PatternValidator extends Validator {
constructor(message = DEFAULT_ERROR_MESSAGES.PATTERN) {
super(message, "string");
}
/**
* @description Converts a string pattern to a RegExp object
* @summary Parses a string representation of a regular expression and converts it to a RegExp object.
* It handles both simple string patterns and patterns with flags in the format "/pattern/flags".
*
* @param {string} pattern - The string pattern to convert
* @return {RegExp} A RegExp object created from the string pattern
* @private
*/
getPattern(pattern) {
if (!regexpParser.test(pattern))
return new RegExp(pattern);
const match = pattern.match(regexpParser);
return new RegExp(match[1], match[2]);
}
/**
* @description Checks if a string matches a regular expression pattern
* @summary Validates that the provided string matches the pattern specified in the options.
* If the pattern is provided as a string, it's converted to a RegExp object using the getPattern method.
* The method resets the pattern's lastIndex property to ensure consistent validation results
* for patterns with the global flag.
*
* @param {string} value - The string to validate against the pattern
* @param {PatternValidatorOptions} options - Configuration options containing the pattern
*
* @return {string | undefined} Error message if validation fails, undefined if validation passes
*
* @throws {Error} If no pattern is provided in the options
*
* @override
*
* @see Validator#hasErrors
*/
hasErrors(value, options) {
if (!value)
return;
let { pattern } = options;
if (!pattern)
throw new Error("Missing Pattern");
pattern = typeof pattern === "string" ? this.getPattern(pattern) : pattern;
pattern.lastIndex = 0; // resets pattern position for repeat validation requests
return !pattern.test(value)
? this.getMessage(options.message || this.message)
: undefined;
}
};
PatternValidator = __decorate([
validator(ValidationKeys.PATTERN),
__metadata("design:paramtypes", [String])
], PatternValidator);
export { PatternValidator };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGF0dGVyblZhbGlkYXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy92YWxpZGF0aW9uL1ZhbGlkYXRvcnMvUGF0dGVyblZhbGlkYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLHVCQUFvQjtBQUN4QyxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsY0FBYyxFQUFFLHVCQUFvQjtBQUNyRSxPQUFPLEVBQUUsU0FBUyxFQUFFLHdCQUFxQjtBQUd6Qzs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLENBQUMsTUFBTSxZQUFZLEdBQVcsSUFBSSxNQUFNLENBQUMsb0JBQW9CLENBQUMsQ0FBQztBQUVyRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBeURHO0FBRUksSUFBTSxnQkFBZ0IsR0FBdEIsTUFBTSxnQkFBaUIsU0FBUSxTQUFrQztJQUN0RSxZQUFZLFVBQWtCLHNCQUFzQixDQUFDLE9BQU87UUFDMUQsS0FBSyxDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQztJQUMzQixDQUFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSyxVQUFVLENBQUMsT0FBZTtRQUNoQyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7WUFBRSxPQUFPLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzVELE1BQU0sS0FBSyxHQUFRLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDL0MsT0FBTyxJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7Ozs7OztPQWlCRztJQUNJLFNBQVMsQ0FDZCxLQUFhLEVBQ2IsT0FBZ0M7UUFFaEMsSUFBSSxDQUFDLEtBQUs7WUFBRSxPQUFPO1FBRW5CLElBQUksRUFBRSxPQUFPLEVBQUUsR0FBRyxPQUFPLENBQUM7UUFDMUIsSUFBSSxDQUFDLE9BQU87WUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDakQsT0FBTyxHQUFHLE9BQU8sT0FBTyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO1FBQzNFLE9BQU8sQ0FBQyxTQUFTLEdBQUcsQ0FBQyxDQUFDLENBQUMseURBQXlEO1FBQ2hGLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztZQUN6QixDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUM7WUFDbEQsQ0FBQyxDQUFDLFNBQVMsQ0FBQztJQUNoQixDQUFDO0NBQ0YsQ0FBQTtBQXBEWSxnQkFBZ0I7SUFENUIsU0FBUyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUM7O0dBQ3JCLGdCQUFnQixDQW9ENUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBWYWxpZGF0b3IgfSBmcm9tIFwiLi9WYWxpZGF0b3JcIjtcbmltcG9ydCB7IERFRkFVTFRfRVJST1JfTUVTU0FHRVMsIFZhbGlkYXRpb25LZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyB2YWxpZGF0b3IgfSBmcm9tIFwiLi9kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBQYXR0ZXJuVmFsaWRhdG9yT3B0aW9ucyB9IGZyb20gXCIuLi90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZWd1bGFyIGV4cHJlc3Npb24gZm9yIHBhcnNpbmcgc3RyaW5nIHBhdHRlcm5zIHdpdGggZmxhZ3NcbiAqIEBzdW1tYXJ5IFRoaXMgcmVndWxhciBleHByZXNzaW9uIGlzIHVzZWQgdG8gcGFyc2Ugc3RyaW5nIHBhdHRlcm5zIGluIHRoZSBmb3JtYXQgXCIvcGF0dGVybi9mbGFnc1wiLlxuICogSXQgY2FwdHVyZXMgdGhlIHBhdHRlcm4gYW5kIGZsYWdzIHNlcGFyYXRlbHksIGFsbG93aW5nIHRoZSBjcmVhdGlvbiBvZiBhIFJlZ0V4cCBvYmplY3RcbiAqIHdpdGggdGhlIGFwcHJvcHJpYXRlIGZsYWdzLlxuICpcbiAqIEBjb25zdCB7UmVnRXhwfVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0b3ItdmFsaWRhdGlvblxuICogQGNhdGVnb3J5IFZhbGlkYXRpb25cbiAqL1xuZXhwb3J0IGNvbnN0IHJlZ2V4cFBhcnNlcjogUmVnRXhwID0gbmV3IFJlZ0V4cChcIl4vKC4rKS8oW2dpbXVzXSopJFwiKTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gVmFsaWRhdG9yIGZvciBjaGVja2luZyBpZiBhIHN0cmluZyBtYXRjaGVzIGEgcmVndWxhciBleHByZXNzaW9uIHBhdHRlcm5cbiAqIEBzdW1tYXJ5IFRoZSBQYXR0ZXJuVmFsaWRhdG9yIGNoZWNrcyBpZiBhIHN0cmluZyB2YWx1ZSBtYXRjaGVzIGEgc3BlY2lmaWVkIHJlZ3VsYXIgZXhwcmVzc2lvbiBwYXR0ZXJuLlxuICogSXQgc3VwcG9ydHMgYm90aCBSZWdFeHAgb2JqZWN0cyBhbmQgc3RyaW5nIHJlcHJlc2VudGF0aW9ucyBvZiBwYXR0ZXJucywgaW5jbHVkaW5nIHRob3NlIHdpdGggZmxhZ3MuXG4gKiBUaGlzIHZhbGlkYXRvciBpcyB0aGUgZm91bmRhdGlvbiBmb3Igc3BlY2lhbGl6ZWQgdmFsaWRhdG9ycyBsaWtlIEVtYWlsVmFsaWRhdG9yIGFuZCBVUkxWYWxpZGF0b3IsXG4gKiBhbmQgaXMgdHlwaWNhbGx5IHVzZWQgd2l0aCB0aGUgQHBhdHRlcm4gZGVjb3JhdG9yLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBbbWVzc2FnZV0gLSBDdXN0b20gZXJyb3IgbWVzc2FnZSB0byBkaXNwbGF5IHdoZW4gdmFsaWRhdGlvbiBmYWlscywgZGVmYXVsdHMgdG8ge0BsaW5rIERFRkFVTFRfRVJST1JfTUVTU0FHRVMjUEFUVEVSTn1cbiAqXG4gKiBAY2xhc3MgUGF0dGVyblZhbGlkYXRvclxuICogQGV4dGVuZHMgVmFsaWRhdG9yXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIENyZWF0ZSBhIHBhdHRlcm4gdmFsaWRhdG9yIHdpdGggZGVmYXVsdCBlcnJvciBtZXNzYWdlXG4gKiBjb25zdCBwYXR0ZXJuVmFsaWRhdG9yID0gbmV3IFBhdHRlcm5WYWxpZGF0b3IoKTtcbiAqXG4gKiAvLyBDcmVhdGUgYSBwYXR0ZXJuIHZhbGlkYXRvciB3aXRoIGN1c3RvbSBlcnJvciBtZXNzYWdlXG4gKiBjb25zdCBjdXN0b21QYXR0ZXJuVmFsaWRhdG9yID0gbmV3IFBhdHRlcm5WYWxpZGF0b3IoXCJWYWx1ZSBtdXN0IG1hdGNoIHRoZSByZXF1aXJlZCBmb3JtYXRcIik7XG4gKlxuICogLy8gVmFsaWRhdGUgdXNpbmcgYSBSZWdFeHAgb2JqZWN0XG4gKiBjb25zdCByZWdleE9wdGlvbnMgPSB7IHBhdHRlcm46IC9eW0EtWl1bYS16XSskLyB9O1xuICogcGF0dGVyblZhbGlkYXRvci5oYXNFcnJvcnMoXCJIZWxsb1wiLCByZWdleE9wdGlvbnMpOyAvLyB1bmRlZmluZWQgKHZhbGlkKVxuICogcGF0dGVyblZhbGlkYXRvci5oYXNFcnJvcnMoXCJoZWxsb1wiLCByZWdleE9wdGlvbnMpOyAvLyBSZXR1cm5zIGVycm9yIG1lc3NhZ2UgKGludmFsaWQpXG4gKlxuICogLy8gVmFsaWRhdGUgdXNpbmcgYSBzdHJpbmcgcGF0dGVyblxuICogY29uc3Qgc3RyaW5nT3B0aW9ucyA9IHsgcGF0dGVybjogXCJeXFxcXGR7M30tXFxcXGR7Mn0tXFxcXGR7NH0kXCIgfTtcbiAqIHBhdHRlcm5WYWxpZGF0b3IuaGFzRXJyb3JzKFwiMTIzLTQ1LTY3ODlcIiwgc3RyaW5nT3B0aW9ucyk7IC8vIHVuZGVmaW5lZCAodmFsaWQpXG4gKlxuICogLy8gVmFsaWRhdGUgdXNpbmcgYSBzdHJpbmcgcGF0dGVybiB3aXRoIGZsYWdzXG4gKiBjb25zdCBmbGFnT3B0aW9ucyA9IHsgcGF0dGVybjogXCIvXmhlbGxvJC9pXCIgfTtcbiAqIHBhdHRlcm5WYWxpZGF0b3IuaGFzRXJyb3JzKFwiSGVsbG9cIiwgZmxhZ09wdGlvbnMpOyAvLyB1bmRlZmluZWQgKHZhbGlkKVxuICogYGBgXG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDIGFzIENsaWVudFxuICogICBwYXJ0aWNpcGFudCBWIGFzIFBhdHRlcm5WYWxpZGF0b3JcbiAqXG4gKiAgIEMtPj5WOiBuZXcgUGF0dGVyblZhbGlkYXRvcihtZXNzYWdlKVxuICogICBDLT4+VjogaGFzRXJyb3JzKHZhbHVlLCBvcHRpb25zKVxuICogICBhbHQgdmFsdWUgaXMgZW1wdHlcbiAqICAgICBWLS0+PkM6IHVuZGVmaW5lZCAodmFsaWQpXG4gKiAgIGVsc2UgcGF0dGVybiBpcyBtaXNzaW5nXG4gKiAgICAgVi0tPj5DOiBFcnJvcjogTWlzc2luZyBQYXR0ZXJuXG4gKiAgIGVsc2UgcGF0dGVybiBpcyBzdHJpbmdcbiAqICAgICBWLT4+VjogZ2V0UGF0dGVybihwYXR0ZXJuKVxuICogICBlbmRcbiAqICAgVi0+PlY6IFJlc2V0IHBhdHRlcm4ubGFzdEluZGV4XG4gKiAgIFYtPj5WOiBUZXN0IHZhbHVlIGFnYWluc3QgcGF0dGVyblxuICogICBhbHQgcGF0dGVybiB0ZXN0IHBhc3Nlc1xuICogICAgIFYtLT4+QzogdW5kZWZpbmVkICh2YWxpZClcbiAqICAgZWxzZSBwYXR0ZXJuIHRlc3QgZmFpbHNcbiAqICAgICBWLS0+PkM6IEVycm9yIG1lc3NhZ2VcbiAqICAgZW5kXG4gKlxuICogQGNhdGVnb3J5IFZhbGlkYXRvcnNcbiAqL1xuQHZhbGlkYXRvcihWYWxpZGF0aW9uS2V5cy5QQVRURVJOKVxuZXhwb3J0IGNsYXNzIFBhdHRlcm5WYWxpZGF0b3IgZXh0ZW5kcyBWYWxpZGF0b3I8UGF0dGVyblZhbGlkYXRvck9wdGlvbnM+IHtcbiAgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nID0gREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5QQVRURVJOKSB7XG4gICAgc3VwZXIobWVzc2FnZSwgXCJzdHJpbmdcIik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENvbnZlcnRzIGEgc3RyaW5nIHBhdHRlcm4gdG8gYSBSZWdFeHAgb2JqZWN0XG4gICAqIEBzdW1tYXJ5IFBhcnNlcyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhIHJlZ3VsYXIgZXhwcmVzc2lvbiBhbmQgY29udmVydHMgaXQgdG8gYSBSZWdFeHAgb2JqZWN0LlxuICAgKiBJdCBoYW5kbGVzIGJvdGggc2ltcGxlIHN0cmluZyBwYXR0ZXJucyBhbmQgcGF0dGVybnMgd2l0aCBmbGFncyBpbiB0aGUgZm9ybWF0IFwiL3BhdHRlcm4vZmxhZ3NcIi5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHBhdHRlcm4gLSBUaGUgc3RyaW5nIHBhdHRlcm4gdG8gY29udmVydFxuICAgKiBAcmV0dXJuIHtSZWdFeHB9IEEgUmVnRXhwIG9iamVjdCBjcmVhdGVkIGZyb20gdGhlIHN0cmluZyBwYXR0ZXJuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIGdldFBhdHRlcm4ocGF0dGVybjogc3RyaW5nKTogUmVnRXhwIHtcbiAgICBpZiAoIXJlZ2V4cFBhcnNlci50ZXN0KHBhdHRlcm4pKSByZXR1cm4gbmV3IFJlZ0V4cChwYXR0ZXJuKTtcbiAgICBjb25zdCBtYXRjaDogYW55ID0gcGF0dGVybi5tYXRjaChyZWdleHBQYXJzZXIpO1xuICAgIHJldHVybiBuZXcgUmVnRXhwKG1hdGNoWzFdLCBtYXRjaFsyXSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENoZWNrcyBpZiBhIHN0cmluZyBtYXRjaGVzIGEgcmVndWxhciBleHByZXNzaW9uIHBhdHRlcm5cbiAgICogQHN1bW1hcnkgVmFsaWRhdGVzIHRoYXQgdGhlIHByb3ZpZGVkIHN0cmluZyBtYXRjaGVzIHRoZSBwYXR0ZXJuIHNwZWNpZmllZCBpbiB0aGUgb3B0aW9ucy5cbiAgICogSWYgdGhlIHBhdHRlcm4gaXMgcHJvdmlkZWQgYXMgYSBzdHJpbmcsIGl0J3MgY29udmVydGVkIHRvIGEgUmVnRXhwIG9iamVjdCB1c2luZyB0aGUgZ2V0UGF0dGVybiBtZXRob2QuXG4gICAqIFRoZSBtZXRob2QgcmVzZXRzIHRoZSBwYXR0ZXJuJ3MgbGFzdEluZGV4IHByb3BlcnR5IHRvIGVuc3VyZSBjb25zaXN0ZW50IHZhbGlkYXRpb24gcmVzdWx0c1xuICAgKiBmb3IgcGF0dGVybnMgd2l0aCB0aGUgZ2xvYmFsIGZsYWcuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSAtIFRoZSBzdHJpbmcgdG8gdmFsaWRhdGUgYWdhaW5zdCB0aGUgcGF0dGVyblxuICAgKiBAcGFyYW0ge1BhdHRlcm5WYWxpZGF0b3JPcHRpb25zfSBvcHRpb25zIC0gQ29uZmlndXJhdGlvbiBvcHRpb25zIGNvbnRhaW5pbmcgdGhlIHBhdHRlcm5cbiAgICpcbiAgICogQHJldHVybiB7c3RyaW5nIHwgdW5kZWZpbmVkfSBFcnJvciBtZXNzYWdlIGlmIHZhbGlkYXRpb24gZmFpbHMsIHVuZGVmaW5lZCBpZiB2YWxpZGF0aW9uIHBhc3Nlc1xuICAgKlxuICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgbm8gcGF0dGVybiBpcyBwcm92aWRlZCBpbiB0aGUgb3B0aW9uc1xuICAgKlxuICAgKiBAb3ZlcnJpZGVcbiAgICpcbiAgICogQHNlZSBWYWxpZGF0b3IjaGFzRXJyb3JzXG4gICAqL1xuICBwdWJsaWMgaGFzRXJyb3JzKFxuICAgIHZhbHVlOiBzdHJpbmcsXG4gICAgb3B0aW9uczogUGF0dGVyblZhbGlkYXRvck9wdGlvbnNcbiAgKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIXZhbHVlKSByZXR1cm47XG5cbiAgICBsZXQgeyBwYXR0ZXJuIH0gPSBvcHRpb25zO1xuICAgIGlmICghcGF0dGVybikgdGhyb3cgbmV3IEVycm9yKFwiTWlzc2luZyBQYXR0ZXJuXCIpO1xuICAgIHBhdHRlcm4gPSB0eXBlb2YgcGF0dGVybiA9PT0gXCJzdHJpbmdcIiA/IHRoaXMuZ2V0UGF0dGVybihwYXR0ZXJuKSA6IHBhdHRlcm47XG4gICAgcGF0dGVybi5sYXN0SW5kZXggPSAwOyAvLyByZXNldHMgcGF0dGVybiBwb3NpdGlvbiBmb3IgcmVwZWF0IHZhbGlkYXRpb24gcmVxdWVzdHNcbiAgICByZXR1cm4gIXBhdHRlcm4udGVzdCh2YWx1ZSlcbiAgICAgID8gdGhpcy5nZXRNZXNzYWdlKG9wdGlvbnMubWVzc2FnZSB8fCB0aGlzLm1lc3NhZ2UpXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgfVxufVxuIl19