UNPKG

chain-able

Version:

interfaces that describe their intentions.

276 lines (255 loc) 23.1 kB
/** * @since 4.0.0 <- moved out of the store, into scoped * @since 1.0.0 * @desc library of validators to use by name * @modifies this.validators * @param {Object} validators */ var ChainedMap = require('../../ChainedMapBase') var ENV_DEBUG = require('../env/debug') var is = require('../is') var isArray = require('../is/array') var isReal = require('../is/real') var isString = require('../is/string') var isFunction = require('../is/function') var dopemerge = require('../dopemerge') var camelCase = require('../camel-case') var not = require('../conditional/not') var and = require('../conditional/and') var or = require('../conditional/or') var all = require('../conditional/all') var validators = new ChainedMap() // eslint-disable-next-line var stripArithmeticSymbols = function (x) { return x.replace(/[?\[\]!\|]/g, ''); } var escapedKey = function (x) { return camelCase('is-' + x); } var enummy = function (enums) { return function (x) { return enums === x || enums.includes(x); }; } // @TODO: .remap!!! // @TODO: can use these to return noops with error logging on development var get = function (key) { return validators.get(key) || validators.get(escapedKey(key)) || enummy(key); } var has = function (key) { return validators.has(key) || validators.get(escapedKey(key)); } var set = function (key, value) { return validators.set(key, value); } var doesNotHave = not(has) /** * @desc add custom types for validation * @category types * @category schema * @types schema * * @since 4.0.0 <- used with schema, used in method chain * @since 3.0.0 <- took out * @since 1.0.0 * * @param {Object} types custom Types * * @see deps/validators/validatorFactory * * @example * * addTypes({yaya: x => typeof x === 'string'}) * * const chain = new Chain().methods('eh').type('yaya').build() * * chain.eh('good') * //=> chain * * chain.eh(!!'throws') * //=> TypeError(false != {yaya: x => typeof x === 'string'}) * * @example * * const custom = {} * custom.enums = enums => x => enums.includes(x) * custom['*'] = x => true * addTypes(custom) * //-> void * * new Chain().methods('eh').type('*').build().eh * //=> validateType(custom['*']) * */ var addTypes = function (types) { return validators.from(dopemerge(validators.entries(), types)); } addTypes(is) // ---- // @NOTE: putting these as functions increased size 20 bytes: worth it // ---- // @SIZE: another 10bytes for these fns var isNotRealOrIsEmptyString = and(not(isReal), function (x) { return x === ''; }) // const isArrayOf = predicate => x => isArray(x) && x.every(predicate) var isArrayOf = function (predicate) { return and(isArray, all(predicate)); } var includesAndOr = function (x) { return x.includes('|') || x.includes('&'); } /** * @memberOf schema * @category types * * @param {string} fullKey a key with `|` and/or '&' * @return {Function} validator * * @example * * const isStringOrNumber = typeListFactory('string|number') * * isStringOrNumber(1) * //=> true * isStringOrNumber('one') * //=> true * isStringOrNumber(Object) * //=> false * */ function typeListFactory(fullKey) { // already have it if (has(fullKey)) { return get(fullKey) } // get all types var orTypes = fullKey.split('|') var andTypes = fullKey.split('&') // ensure we have all validators - sets up conditionals for (var v = 0; v < orTypes.length; v++) { builder(orTypes[v]) } // go through all valid options, if any are true, good to go set(fullKey, function (x) { for (var v = 0; v < orTypes.length; v++) { if (get(orTypes[v])(x)) { return true } } return false }) return get(fullKey) } // @TODO how to iterate properly with the bitwise fn + AND // add another param? ignore overly complex |& things? just allow 1? // just show how to use these shorthand fn builders /** * @desc transform arithmetic strings into types * @since 4.0.0-alpha.1 * @category types * * @param {Matchable} fullKey arithmetic type key * @return {Matchable} function to match with, with .inspect for easy debugging * * @types schema * @test typed * @test schema * @see is * @todo coercing values to certain types: arithmeticTypeFactory('<value>') * * @example * * arithmeticTypeFactory('?string') * //=> x => !isReal(x) || isString(x) * * @example * * arithmeticTypeFactory('?string|string[]') * //=> x => isString(x) || isArrayOf(isString)(x) * * @example * * arithmeticTypeFactory('!string') * //=> x => not(isString)(x) * * @example * * types.addTypes({star: x => true}) * arithmeticTypeFactory('object|function|star') * //=> x => isObj(x) || isFunction(x) || isStar(x) * * @example * * arithmeticTypeFactory('===') * //=> x => (['===']).includes(x) */ function arithmeticTypeFactory(fullKey) { var key = stripArithmeticSymbols(fullKey) var fn = get(key) var optionalType = "?" + key var typeOrArrayOrType = key + "[]" var notType = "!" + key var isValidOrNotRealOrEmptyStr = or(fn, isNotRealOrIsEmptyString) var isValidOrArrayOfValid = or(fn, isArrayOf(fn)) if (doesNotHave(optionalType)) { set(optionalType, isValidOrNotRealOrEmptyStr) } if (doesNotHave(typeOrArrayOrType)) { set(typeOrArrayOrType, isValidOrArrayOfValid) } if (doesNotHave(notType)) { set(notType, not(fn)) } return get(fullKey) } // ---- // ; function split // ---- // v- annoying on comments with ifs /* prettier-ignore */ /** * @desc @pattern @builder -> builds using multiple factories depending on conditons * or abstractFactory whatever * opinionated: if it's a function, it's a validator... * * @category types * @since 4.0.0 * @param {string | Function | Primitive} fullKey arithmetic key to the validator * @return {Function} validator * * @see https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Default_parameters * @NOTE if/else is for uglifying ternaries, even though else if is not needed * @NOTE if key is number, iterating the array * * @example * * // functionType * const isString = x => typeof x === 'string' * builder(isString) * // => isString * * @example * * // stringType (built in, or custom-keyed validator, or eqeqeq) * builder('string') * // => isString * * const enummy = builder('enum') * // => x => ['enum'].includes(x) * * @example * * // arithmeticType * builder('string|string[]') * // => isString || isArrayOf(isString) * */ function builder(fullKey) { if (isFunction(fullKey)) { /* istanbul ignore next: dev */ if (ENV_DEBUG) { console.log('functionType', {fullKey: fullKey}) } return fullKey } else if (isString(fullKey) && includesAndOr(fullKey)) { /* istanbul ignore next: dev */ if (ENV_DEBUG) { console.log('andOrType', {fullKey: fullKey}) } return typeListFactory(fullKey) } else { /* istanbul ignore next: dev */ if (ENV_DEBUG) { console.log('arithmeticType', {fullKey: fullKey}, arithmeticTypeFactory(fullKey)) } return arithmeticTypeFactory(fullKey) } } builder.has = has builder.get = get builder.set = set builder.addTypes = addTypes // was merge builder.map = validators module.exports = builder //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdG9yQnVpbGRlci5qcyIsInNvdXJjZXMiOlsidmFsaWRhdG9yQnVpbGRlci5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBzaW5jZSA0LjAuMCA8LSBtb3ZlZCBvdXQgb2YgdGhlIHN0b3JlLCBpbnRvIHNjb3BlZFxuICogQHNpbmNlIDEuMC4wXG4gKiBAZGVzYyBsaWJyYXJ5IG9mIHZhbGlkYXRvcnMgdG8gdXNlIGJ5IG5hbWVcbiAqICAgICAgIEBtb2RpZmllcyB0aGlzLnZhbGlkYXRvcnNcbiAqIEBwYXJhbSAge09iamVjdH0gdmFsaWRhdG9yc1xuICovXG5jb25zdCBDaGFpbmVkTWFwID0gcmVxdWlyZSgnLi4vLi4vQ2hhaW5lZE1hcEJhc2UnKVxuY29uc3QgRU5WX0RFQlVHID0gcmVxdWlyZSgnLi4vZW52L2RlYnVnJylcbmNvbnN0IGlzID0gcmVxdWlyZSgnLi4vaXMnKVxuY29uc3QgaXNBcnJheSA9IHJlcXVpcmUoJy4uL2lzL2FycmF5JylcbmNvbnN0IGlzUmVhbCA9IHJlcXVpcmUoJy4uL2lzL3JlYWwnKVxuY29uc3QgaXNTdHJpbmcgPSByZXF1aXJlKCcuLi9pcy9zdHJpbmcnKVxuY29uc3QgaXNGdW5jdGlvbiA9IHJlcXVpcmUoJy4uL2lzL2Z1bmN0aW9uJylcbmNvbnN0IGRvcGVtZXJnZSA9IHJlcXVpcmUoJy4uL2RvcGVtZXJnZScpXG5jb25zdCBjYW1lbENhc2UgPSByZXF1aXJlKCcuLi9jYW1lbC1jYXNlJylcbmNvbnN0IG5vdCA9IHJlcXVpcmUoJy4uL2NvbmRpdGlvbmFsL25vdCcpXG5jb25zdCBhbmQgPSByZXF1aXJlKCcuLi9jb25kaXRpb25hbC9hbmQnKVxuY29uc3Qgb3IgPSByZXF1aXJlKCcuLi9jb25kaXRpb25hbC9vcicpXG5jb25zdCBhbGwgPSByZXF1aXJlKCcuLi9jb25kaXRpb25hbC9hbGwnKVxuXG5sZXQgdmFsaWRhdG9ycyA9IG5ldyBDaGFpbmVkTWFwKClcblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG5jb25zdCBzdHJpcEFyaXRobWV0aWNTeW1ib2xzID0geCA9PiB4LnJlcGxhY2UoL1s/XFxbXFxdIVxcfF0vZywgJycpXG5jb25zdCBlc2NhcGVkS2V5ID0geCA9PiBjYW1lbENhc2UoJ2lzLScgKyB4KVxuY29uc3QgZW51bW15ID0gZW51bXMgPT4geCA9PiBlbnVtcyA9PT0geCB8fCBlbnVtcy5pbmNsdWRlcyh4KVxuXG4vLyBAVE9ETzogLnJlbWFwISEhXG4vLyBAVE9ETzogY2FuIHVzZSB0aGVzZSB0byByZXR1cm4gbm9vcHMgd2l0aCBlcnJvciBsb2dnaW5nIG9uIGRldmVsb3BtZW50XG5jb25zdCBnZXQgPSBrZXkgPT5cbiAgdmFsaWRhdG9ycy5nZXQoa2V5KSB8fCB2YWxpZGF0b3JzLmdldChlc2NhcGVkS2V5KGtleSkpIHx8IGVudW1teShrZXkpXG5jb25zdCBoYXMgPSBrZXkgPT4gdmFsaWRhdG9ycy5oYXMoa2V5KSB8fCB2YWxpZGF0b3JzLmdldChlc2NhcGVkS2V5KGtleSkpXG5jb25zdCBzZXQgPSAoa2V5LCB2YWx1ZSkgPT4gdmFsaWRhdG9ycy5zZXQoa2V5LCB2YWx1ZSlcbmNvbnN0IGRvZXNOb3RIYXZlID0gbm90KGhhcylcblxuLyoqXG4gKiBAZGVzYyBhZGQgY3VzdG9tIHR5cGVzIGZvciB2YWxpZGF0aW9uXG4gKiBAY2F0ZWdvcnkgdHlwZXNcbiAqIEBjYXRlZ29yeSBzY2hlbWFcbiAqIEB0eXBlcyBzY2hlbWFcbiAqXG4gKiBAc2luY2UgNC4wLjAgPC0gdXNlZCB3aXRoIHNjaGVtYSwgdXNlZCBpbiBtZXRob2QgY2hhaW5cbiAqIEBzaW5jZSAzLjAuMCA8LSB0b29rIG91dFxuICogQHNpbmNlIDEuMC4wXG4gKlxuICogQHBhcmFtICB7T2JqZWN0fSB0eXBlcyBjdXN0b20gVHlwZXNcbiAqXG4gKiBAc2VlIGRlcHMvdmFsaWRhdG9ycy92YWxpZGF0b3JGYWN0b3J5XG4gKlxuICogQGV4YW1wbGVcbiAqXG4gKiAgIGFkZFR5cGVzKHt5YXlhOiB4ID0+IHR5cGVvZiB4ID09PSAnc3RyaW5nJ30pXG4gKlxuICogICBjb25zdCBjaGFpbiA9IG5ldyBDaGFpbigpLm1ldGhvZHMoJ2VoJykudHlwZSgneWF5YScpLmJ1aWxkKClcbiAqXG4gKiAgIGNoYWluLmVoKCdnb29kJylcbiAqICAgLy89PiBjaGFpblxuICpcbiAqICAgY2hhaW4uZWgoISEndGhyb3dzJylcbiAqICAgLy89PiBUeXBlRXJyb3IoZmFsc2UgIT0ge3lheWE6IHggPT4gdHlwZW9mIHggPT09ICdzdHJpbmcnfSlcbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqICAgY29uc3QgY3VzdG9tID0ge31cbiAqICAgY3VzdG9tLmVudW1zID0gZW51bXMgPT4geCA9PiBlbnVtcy5pbmNsdWRlcyh4KVxuICogICBjdXN0b21bJyonXSA9IHggPT4gdHJ1ZVxuICogICBhZGRUeXBlcyhjdXN0b20pXG4gKiAgIC8vLT4gdm9pZFxuICpcbiAqICAgbmV3IENoYWluKCkubWV0aG9kcygnZWgnKS50eXBlKCcqJykuYnVpbGQoKS5laFxuICogICAvLz0+IHZhbGlkYXRlVHlwZShjdXN0b21bJyonXSlcbiAqXG4gKi9cbmNvbnN0IGFkZFR5cGVzID0gdHlwZXMgPT5cbiAgdmFsaWRhdG9ycy5mcm9tKGRvcGVtZXJnZSh2YWxpZGF0b3JzLmVudHJpZXMoKSwgdHlwZXMpKVxuXG5hZGRUeXBlcyhpcylcblxuLy8gLS0tLVxuLy8gQE5PVEU6IHB1dHRpbmcgdGhlc2UgYXMgZnVuY3Rpb25zIGluY3JlYXNlZCBzaXplIDIwIGJ5dGVzOiB3b3J0aCBpdFxuLy8gLS0tLVxuXG4vLyBAU0laRTogYW5vdGhlciAxMGJ5dGVzIGZvciB0aGVzZSBmbnNcbmNvbnN0IGlzTm90UmVhbE9ySXNFbXB0eVN0cmluZyA9IGFuZChub3QoaXNSZWFsKSwgeCA9PiB4ID09PSAnJylcblxuLy8gY29uc3QgaXNBcnJheU9mID0gcHJlZGljYXRlID0+IHggPT4gaXNBcnJheSh4KSAmJiB4LmV2ZXJ5KHByZWRpY2F0ZSlcbmNvbnN0IGlzQXJyYXlPZiA9IHByZWRpY2F0ZSA9PiBhbmQoaXNBcnJheSwgYWxsKHByZWRpY2F0ZSkpXG5jb25zdCBpbmNsdWRlc0FuZE9yID0geCA9PiB4LmluY2x1ZGVzKCd8JykgfHwgeC5pbmNsdWRlcygnJicpXG5cbi8qKlxuICogQG1lbWJlck9mIHNjaGVtYVxuICogQGNhdGVnb3J5IHR5cGVzXG4gKlxuICogQHBhcmFtICB7c3RyaW5nfSBmdWxsS2V5IGEga2V5IHdpdGggYHxgIGFuZC9vciAnJidcbiAqIEByZXR1cm4ge0Z1bmN0aW9ufSB2YWxpZGF0b3JcbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqICAgIGNvbnN0IGlzU3RyaW5nT3JOdW1iZXIgPSB0eXBlTGlzdEZhY3RvcnkoJ3N0cmluZ3xudW1iZXInKVxuICpcbiAqICAgIGlzU3RyaW5nT3JOdW1iZXIoMSlcbiAqICAgIC8vPT4gdHJ1ZVxuICogICAgaXNTdHJpbmdPck51bWJlcignb25lJylcbiAqICAgIC8vPT4gdHJ1ZVxuICogICAgaXNTdHJpbmdPck51bWJlcihPYmplY3QpXG4gKiAgICAvLz0+IGZhbHNlXG4gKlxuICovXG5mdW5jdGlvbiB0eXBlTGlzdEZhY3RvcnkoZnVsbEtleSkge1xuICAvLyBhbHJlYWR5IGhhdmUgaXRcbiAgaWYgKGhhcyhmdWxsS2V5KSkge1xuICAgIHJldHVybiBnZXQoZnVsbEtleSlcbiAgfVxuXG4gIC8vIGdldCBhbGwgdHlwZXNcbiAgbGV0IG9yVHlwZXMgPSBmdWxsS2V5LnNwbGl0KCd8JylcbiAgbGV0IGFuZFR5cGVzID0gZnVsbEtleS5zcGxpdCgnJicpXG5cbiAgLy8gZW5zdXJlIHdlIGhhdmUgYWxsIHZhbGlkYXRvcnMgLSBzZXRzIHVwIGNvbmRpdGlvbmFsc1xuICBmb3IgKGxldCB2ID0gMDsgdiA8IG9yVHlwZXMubGVuZ3RoOyB2KyspIHtcbiAgICBidWlsZGVyKG9yVHlwZXNbdl0pXG4gIH1cblxuICAvLyBnbyB0aHJvdWdoIGFsbCB2YWxpZCBvcHRpb25zLCBpZiBhbnkgYXJlIHRydWUsIGdvb2QgdG8gZ29cbiAgc2V0KGZ1bGxLZXksIHggPT4ge1xuICAgIGZvciAobGV0IHYgPSAwOyB2IDwgb3JUeXBlcy5sZW5ndGg7IHYrKykge1xuICAgICAgaWYgKGdldChvclR5cGVzW3ZdKSh4KSkge1xuICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2VcbiAgfSlcblxuICByZXR1cm4gZ2V0KGZ1bGxLZXkpXG59XG5cbi8vIEBUT0RPIGhvdyB0byBpdGVyYXRlIHByb3Blcmx5IHdpdGggdGhlIGJpdHdpc2UgZm4gKyBBTkRcbi8vICAgICAgIGFkZCBhbm90aGVyIHBhcmFtPyBpZ25vcmUgb3Zlcmx5IGNvbXBsZXggfCYgdGhpbmdzPyBqdXN0IGFsbG93IDE/XG4vLyAgICAgICBqdXN0IHNob3cgaG93IHRvIHVzZSB0aGVzZSBzaG9ydGhhbmQgZm4gYnVpbGRlcnNcblxuLyoqXG4gKiBAZGVzYyB0cmFuc2Zvcm0gYXJpdGhtZXRpYyBzdHJpbmdzIGludG8gdHlwZXNcbiAqIEBzaW5jZSA0LjAuMC1hbHBoYS4xXG4gKiBAY2F0ZWdvcnkgdHlwZXNcbiAqXG4gKiBAcGFyYW0gIHtNYXRjaGFibGV9IGZ1bGxLZXkgYXJpdGhtZXRpYyB0eXBlIGtleVxuICogQHJldHVybiB7TWF0Y2hhYmxlfSBmdW5jdGlvbiB0byBtYXRjaCB3aXRoLCB3aXRoIC5pbnNwZWN0IGZvciBlYXN5IGRlYnVnZ2luZ1xuICpcbiAqIEB0eXBlcyBzY2hlbWFcbiAqIEB0ZXN0IHR5cGVkXG4gKiBAdGVzdCBzY2hlbWFcbiAqIEBzZWUgaXNcbiAqIEB0b2RvIGNvZXJjaW5nIHZhbHVlcyB0byBjZXJ0YWluIHR5cGVzOiBhcml0aG1ldGljVHlwZUZhY3RvcnkoJzx2YWx1ZT4nKVxuICpcbiAqIEBleGFtcGxlXG4gKlxuICogICBhcml0aG1ldGljVHlwZUZhY3RvcnkoJz9zdHJpbmcnKVxuICogICAvLz0+IHggPT4gIWlzUmVhbCh4KSB8fCBpc1N0cmluZyh4KVxuICpcbiAqIEBleGFtcGxlXG4gKlxuICogICBhcml0aG1ldGljVHlwZUZhY3RvcnkoJz9zdHJpbmd8c3RyaW5nW10nKVxuICogICAvLz0+IHggPT4gaXNTdHJpbmcoeCkgfHwgaXNBcnJheU9mKGlzU3RyaW5nKSh4KVxuICpcbiAqIEBleGFtcGxlXG4gKlxuICogICBhcml0aG1ldGljVHlwZUZhY3RvcnkoJyFzdHJpbmcnKVxuICogICAvLz0+IHggPT4gbm90KGlzU3RyaW5nKSh4KVxuICpcbiAqIEBleGFtcGxlXG4gKlxuICogICB0eXBlcy5hZGRUeXBlcyh7c3RhcjogeCA9PiB0cnVlfSlcbiAqICAgYXJpdGhtZXRpY1R5cGVGYWN0b3J5KCdvYmplY3R8ZnVuY3Rpb258c3RhcicpXG4gKiAgIC8vPT4geCA9PiBpc09iaih4KSB8fCBpc0Z1bmN0aW9uKHgpIHx8IGlzU3Rhcih4KVxuICpcbiAqIEBleGFtcGxlXG4gKlxuICogICBhcml0aG1ldGljVHlwZUZhY3RvcnkoJz09PScpXG4gKiAgIC8vPT4geCA9PiAoWyc9PT0nXSkuaW5jbHVkZXMoeClcbiAqL1xuZnVuY3Rpb24gYXJpdGhtZXRpY1R5cGVGYWN0b3J5KGZ1bGxLZXkpIHtcbiAgY29uc3Qga2V5ID0gc3RyaXBBcml0aG1ldGljU3ltYm9scyhmdWxsS2V5KVxuICBsZXQgZm4gPSBnZXQoa2V5KVxuICBjb25zdCBvcHRpb25hbFR5cGUgPSBgPyR7a2V5fWBcbiAgY29uc3QgdHlwZU9yQXJyYXlPclR5cGUgPSBgJHtrZXl9W11gXG4gIGNvbnN0IG5vdFR5cGUgPSBgISR7a2V5fWBcblxuICBjb25zdCBpc1ZhbGlkT3JOb3RSZWFsT3JFbXB0eVN0ciA9IG9yKGZuLCBpc05vdFJlYWxPcklzRW1wdHlTdHJpbmcpXG4gIGNvbnN0IGlzVmFsaWRPckFycmF5T2ZWYWxpZCA9IG9yKGZuLCBpc0FycmF5T2YoZm4pKVxuICBpZiAoZG9lc05vdEhhdmUob3B0aW9uYWxUeXBlKSkge1xuICAgIHNldChvcHRpb25hbFR5cGUsIGlzVmFsaWRPck5vdFJlYWxPckVtcHR5U3RyKVxuICB9XG4gIGlmIChkb2VzTm90SGF2ZSh0eXBlT3JBcnJheU9yVHlwZSkpIHtcbiAgICBzZXQodHlwZU9yQXJyYXlPclR5cGUsIGlzVmFsaWRPckFycmF5T2ZWYWxpZClcbiAgfVxuICBpZiAoZG9lc05vdEhhdmUobm90VHlwZSkpIHtcbiAgICBzZXQobm90VHlwZSwgbm90KGZuKSlcbiAgfVxuXG4gIHJldHVybiBnZXQoZnVsbEtleSlcbn1cblxuLy8gLS0tLVxuLy8gOyBmdW5jdGlvbiBzcGxpdFxuLy8gLS0tLVxuXG4vLyB2LSBhbm5veWluZyBvbiBjb21tZW50cyB3aXRoIGlmc1xuLyogcHJldHRpZXItaWdub3JlICovXG4vKipcbiAqIEBkZXNjIEBwYXR0ZXJuIEBidWlsZGVyIC0+IGJ1aWxkcyB1c2luZyBtdWx0aXBsZSBmYWN0b3JpZXMgZGVwZW5kaW5nIG9uIGNvbmRpdG9uc1xuICogICAgICAgb3IgYWJzdHJhY3RGYWN0b3J5IHdoYXRldmVyXG4gKiAgICAgICBvcGluaW9uYXRlZDogaWYgaXQncyBhIGZ1bmN0aW9uLCBpdCdzIGEgdmFsaWRhdG9yLi4uXG4gKlxuICogQGNhdGVnb3J5IHR5cGVzXG4gKiBAc2luY2UgNC4wLjBcbiAqIEBwYXJhbSAge3N0cmluZyB8IEZ1bmN0aW9uIHwgUHJpbWl0aXZlfSBmdWxsS2V5IGFyaXRobWV0aWMga2V5IHRvIHRoZSB2YWxpZGF0b3JcbiAqIEByZXR1cm4ge0Z1bmN0aW9ufSB2YWxpZGF0b3JcbiAqXG4gKiBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0Z1bmN0aW9ucy9EZWZhdWx0X3BhcmFtZXRlcnNcbiAqIEBOT1RFIGlmL2Vsc2UgaXMgZm9yIHVnbGlmeWluZyB0ZXJuYXJpZXMsIGV2ZW4gdGhvdWdoIGVsc2UgaWYgaXMgbm90IG5lZWRlZFxuICogQE5PVEUgaWYga2V5IGlzIG51bWJlciwgaXRlcmF0aW5nIHRoZSBhcnJheVxuICpcbiAqIEBleGFtcGxlXG4gKlxuICogICAgLy8gZnVuY3Rpb25UeXBlXG4gKiAgICBjb25zdCBpc1N0cmluZyA9IHggPT4gdHlwZW9mIHggPT09ICdzdHJpbmcnXG4gKiAgICBidWlsZGVyKGlzU3RyaW5nKVxuICogICAgLy8gPT4gaXNTdHJpbmdcbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqICAgIC8vIHN0cmluZ1R5cGUgKGJ1aWx0IGluLCBvciBjdXN0b20ta2V5ZWQgdmFsaWRhdG9yLCBvciBlcWVxZXEpXG4gKiAgICBidWlsZGVyKCdzdHJpbmcnKVxuICogICAgLy8gPT4gaXNTdHJpbmdcbiAqXG4gKiAgICBjb25zdCBlbnVtbXkgPSBidWlsZGVyKCdlbnVtJylcbiAqICAgIC8vID0+IHggPT4gWydlbnVtJ10uaW5jbHVkZXMoeClcbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqICAgIC8vIGFyaXRobWV0aWNUeXBlXG4gKiAgICBidWlsZGVyKCdzdHJpbmd8c3RyaW5nW10nKVxuICogICAgLy8gPT4gaXNTdHJpbmcgfHwgaXNBcnJheU9mKGlzU3RyaW5nKVxuICpcbiAqL1xuZnVuY3Rpb24gYnVpbGRlcihmdWxsS2V5KSB7XG4gIGlmIChpc0Z1bmN0aW9uKGZ1bGxLZXkpKSB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQ6IGRldiAqL1xuICAgIGlmIChFTlZfREVCVUcpIHtcbiAgICAgIGNvbnNvbGUubG9nKCdmdW5jdGlvblR5cGUnLCB7ZnVsbEtleX0pXG4gICAgfVxuICAgIHJldHVybiBmdWxsS2V5XG4gIH1cbiAgZWxzZSBpZiAoaXNTdHJpbmcoZnVsbEtleSkgJiYgaW5jbHVkZXNBbmRPcihmdWxsS2V5KSkge1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBkZXYgKi9cbiAgICBpZiAoRU5WX0RFQlVHKSB7XG4gICAgICBjb25zb2xlLmxvZygnYW5kT3JUeXBlJywge2Z1bGxLZXl9KVxuICAgIH1cbiAgICByZXR1cm4gdHlwZUxpc3RGYWN0b3J5KGZ1bGxLZXkpXG4gIH1cbiAgZWxzZSB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQ6IGRldiAqL1xuICAgIGlmIChFTlZfREVCVUcpIHtcbiAgICAgIGNvbnNvbGUubG9nKCdhcml0aG1ldGljVHlwZScsIHtmdWxsS2V5fSwgYXJpdGhtZXRpY1R5cGVGYWN0b3J5KGZ1bGxLZXkpKVxuICAgIH1cbiAgICByZXR1cm4gYXJpdGhtZXRpY1R5cGVGYWN0b3J5KGZ1bGxLZXkpXG4gIH1cbn1cblxuYnVpbGRlci5oYXMgPSBoYXNcbmJ1aWxkZXIuZ2V0ID0gZ2V0XG5idWlsZGVyLnNldCA9IHNldFxuYnVpbGRlci5hZGRUeXBlcyA9IGFkZFR5cGVzIC8vIHdhcyBtZXJnZVxuYnVpbGRlci5tYXAgPSB2YWxpZGF0b3JzXG5tb2R1bGUuZXhwb3J0cyA9IGJ1aWxkZXJcbiJdLCJuYW1lcyI6WyJjb25zdCIsImxldCJdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7QUFPQUEsR0FBSyxDQUFDLFVBQVUsR0FBRyxPQUFPLENBQUMsc0JBQXNCLENBQUM7QUFDbERBLEdBQUssQ0FBQyxTQUFTLEdBQUcsT0FBTyxDQUFDLGNBQWMsQ0FBQztBQUN6Q0EsR0FBSyxDQUFDLEVBQUUsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDO0FBQzNCQSxHQUFLLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUM7QUFDdENBLEdBQUssQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQztBQUNwQ0EsR0FBSyxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDO0FBQ3hDQSxHQUFLLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQztBQUM1Q0EsR0FBSyxDQUFDLFNBQVMsR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDO0FBQ3pDQSxHQUFLLENBQUMsU0FBUyxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUM7QUFDMUNBLEdBQUssQ0FBQyxHQUFHLEdBQUcsT0FBTyxDQUFDLG9CQUFvQixDQUFDO0FBQ3pDQSxHQUFLLENBQUMsR0FBRyxHQUFHLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQztBQUN6Q0Es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