astx
Version:
super powerful structural search and replace for JavaScript and TypeScript to automate your refactoring
424 lines (377 loc) • 45.6 kB
JavaScript
import find, { convertWithCaptures, createMatch } from './find.mjs'
import replace from './replace.mjs'
import compileMatcher from './compileMatcher/index.mjs'
import CodeFrameError from './util/CodeFrameError.mjs'
import ensureArray from './util/ensureArray.mjs'
import {
isPlaceholder,
getPlaceholder,
getArrayPlaceholder,
getRestPlaceholder,
} from './compileMatcher/Placeholder.mjs'
function isNode(x) {
return x instanceof Object && typeof x.type === 'string'
}
function isNodeArray(x) {
return Array.isArray(x) && !Array.isArray(x.raw)
}
function isPlaceholdersHash(item) {
if (!(item instanceof Object)) return false
for (const [key, value] of Object.entries(item)) {
if (!isPlaceholder(key)) return false
if (!(value instanceof Astx)) return false
}
return true
}
class ExtendableProxy {
constructor(handler) {
return new Proxy(this, handler)
}
}
export default class Astx extends ExtendableProxy {
backend
_matches
_withCaptures
_placeholder
_lazyPaths
_lazyNodes
_lazyInitialMatch
constructor(backend, paths, { withCaptures = [], placeholder } = {}) {
super({
get(target, prop) {
if (typeof prop === 'symbol' || !prop.startsWith('$'))
return target[prop]
const matches = []
for (const {
arrayPathCaptures,
pathCaptures,
stringCaptures,
} of target._matches) {
const path =
pathCaptures === null || pathCaptures === void 0
? void 0
: pathCaptures[prop]
const stringValue =
stringCaptures === null || stringCaptures === void 0
? void 0
: stringCaptures[prop]
const arrayPaths =
arrayPathCaptures === null || arrayPathCaptures === void 0
? void 0
: arrayPathCaptures[prop]
if (path)
matches.push(
createMatch(path, {
stringCaptures: stringValue
? {
[prop]: stringValue,
}
: undefined,
})
)
if (arrayPaths) matches.push(createMatch(arrayPaths, {}))
}
return new Astx(target.backend, matches, {
placeholder: prop,
})
},
})
this.backend = backend
this._placeholder = placeholder
const { NodePath } = backend.t
this._matches =
paths[0] instanceof NodePath
? paths.map((path) => createMatch(path, {}))
: paths
this._withCaptures = withCaptures
}
get placeholder() {
return this._placeholder
}
get size() {
return this._matches.length
}
get matches() {
return this._matches
}
*[Symbol.iterator]() {
if (this._placeholder) {
for (const path of this.paths) {
yield new Astx(this.backend, [path])
}
} else {
for (const match of this._matches) {
yield new Astx(this.backend, [match])
}
}
}
get match() {
const [match] = this._matches
if (!match) {
throw new Error(`you can't call match() when there are no matches`)
}
return match
}
get node() {
return this.match.node
}
get path() {
return this.match.path
}
get code() {
return this.backend.generate(this.node).code
}
get stringValue() {
var _this$match$stringCap
const result =
(_this$match$stringCap = this.match.stringCaptures) === null ||
_this$match$stringCap === void 0
? void 0
: _this$match$stringCap[this._placeholder || '']
if (!result) throw new Error(`not a string capture`)
return result
}
get paths() {
return (
this._lazyPaths ||
(this._lazyPaths = this.matches.map((m) => m.paths).flat())
)
}
get nodes() {
return (
this._lazyNodes ||
(this._lazyNodes = this.matches.map((m) => m.nodes).flat())
)
}
filter(iteratee) {
const filtered = []
let index = 0
for (const astx of this) {
if (iteratee(astx, index++, this)) {
filtered.push(astx.match)
}
}
return new Astx(this.backend, filtered)
}
map(iteratee) {
const result = []
let index = 0
for (const astx of this) {
result.push(iteratee(astx, index++, this))
}
return result
}
at(index) {
return new Astx(this.backend, [this._matches[index]])
}
withCaptures(...captures) {
const withCaptures = [...this._withCaptures]
for (const item of captures) {
if (item instanceof Astx) {
if (item._placeholder) {
const placeholder = item._placeholder
for (const { path, paths, stringCaptures } of item._matches) {
withCaptures.push(
createMatch(paths, {
captures: getPlaceholder(placeholder)
? {
[placeholder]: path,
}
: undefined,
arrayCaptures:
getArrayPlaceholder(placeholder) ||
getRestPlaceholder(placeholder)
? {
[placeholder]: paths,
}
: undefined,
stringCaptures:
getPlaceholder(placeholder) &&
stringCaptures !== null &&
stringCaptures !== void 0 &&
stringCaptures[placeholder]
? {
[placeholder]: stringCaptures[placeholder],
}
: undefined,
})
)
}
} else {
for (const match of item._withCaptures) withCaptures.push(match)
for (const match of item._matches) withCaptures.push(match)
}
} else if (isPlaceholdersHash(item)) {
for (const [placeholder, astx] of Object.entries(item)) {
const { _placeholder } = astx
for (const { path, paths, stringCaptures } of astx._matches) {
withCaptures.push(
createMatch(paths, {
captures: getPlaceholder(placeholder)
? {
[placeholder]: path,
}
: undefined,
arrayCaptures:
getArrayPlaceholder(placeholder) ||
getRestPlaceholder(placeholder)
? {
[placeholder]: paths,
}
: undefined,
stringCaptures:
getPlaceholder(placeholder) &&
_placeholder &&
stringCaptures !== null &&
stringCaptures !== void 0 &&
stringCaptures[_placeholder]
? {
[placeholder]: stringCaptures[_placeholder],
}
: undefined,
})
)
}
}
} else {
withCaptures.push(item)
}
}
return new Astx(this.backend, this._matches, {
withCaptures,
})
}
get initialMatch() {
return (
this._lazyInitialMatch ||
(this._lazyInitialMatch = convertWithCaptures([
...this._matches,
...this._withCaptures,
]))
)
}
_execPattern(name, exec, arg0, ...rest) {
const { backend } = this
const { parsePattern } = backend
const { NodePath } = backend.t
try {
let pattern, options
if (typeof arg0 === 'string') {
pattern = parsePattern(arg0)
options = rest[0]
} else if (
Array.isArray(arg0)
? arg0[0] instanceof NodePath
: arg0 instanceof NodePath
) {
pattern = ensureArray(arg0)
options = rest[0]
} else if (isNode(arg0) || isNodeArray(arg0)) {
pattern = ensureArray(arg0).map((node) => new NodePath(node))
options = rest[0]
} else {
pattern = parsePattern(arg0, ...rest)
return (options) => exec(pattern, options)
}
return exec(pattern, options)
} catch (error) {
if (error instanceof Error) {
CodeFrameError.rethrow(error, {
filename: `${name} pattern`,
source: typeof arg0 === 'string' ? arg0 : undefined,
})
}
throw error
}
}
closest(arg0, ...rest) {
const { backend } = this
return this._execPattern(
'closest',
(pattern, options) => {
pattern = ensureArray(pattern)
if (pattern.length !== 1) {
throw new Error(`must be a single node`)
}
const matcher = compileMatcher(pattern[0], { ...options, backend })
const matchedParents = new Set()
const matches = []
this.paths.forEach((path) => {
for (let p = path.parentPath; p; p = p.parentPath) {
if (matchedParents.has(p)) return
const match = matcher.match(p, this.initialMatch)
if (match) {
matchedParents.add(p)
matches.push(createMatch(p, match))
return
}
}
})
return new Astx(backend, matches)
},
arg0,
...rest
)
}
find(arg0, ...rest) {
const { backend } = this
return this._execPattern(
'find',
(pattern, options) =>
new Astx(
backend,
find(this.paths, pattern, {
...options,
backend,
matchSoFar: this.initialMatch,
})
),
arg0,
...rest
)
}
replace(arg0, ...quasis) {
const { backend } = this
const { parsePatternToNodes } = backend
try {
if (typeof arg0 === 'function') {
for (const astx of this) {
const replacement = arg0(astx, parsePatternToNodes)
replace(
astx.match,
typeof replacement === 'string'
? parsePatternToNodes(replacement)
: replacement,
{
backend,
}
)
}
} else if (typeof arg0 === 'string') {
const replacement = parsePatternToNodes(arg0)
for (const match of this._matches) {
replace(match, replacement, {
backend,
})
}
} else if (isNode(arg0) || isNodeArray(arg0)) {
for (const match of this._matches) {
replace(match, arg0, {
backend,
})
}
} else {
const finalPaths = parsePatternToNodes(arg0, ...quasis)
return () => this.replace(finalPaths)
}
} catch (error) {
if (error instanceof Error) {
CodeFrameError.rethrow(error, {
filename: 'replace pattern',
source: typeof arg0 === 'string' ? arg0 : undefined,
})
}
throw error
}
}
} //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJmaW5kIiwiY29udmVydFdpdGhDYXB0dXJlcyIsImNyZWF0ZU1hdGNoIiwicmVwbGFjZSIsImNvbXBpbGVNYXRjaGVyIiwiQ29kZUZyYW1lRXJyb3IiLCJlbnN1cmVBcnJheSIsImlzUGxhY2Vob2xkZXIiLCJnZXRQbGFjZWhvbGRlciIsImdldEFycmF5UGxhY2Vob2xkZXIiLCJnZXRSZXN0UGxhY2Vob2xkZXIiLCJpc05vZGUiLCJ4IiwiT2JqZWN0IiwidHlwZSIsImlzTm9kZUFycmF5IiwiQXJyYXkiLCJpc0FycmF5IiwicmF3IiwiaXNQbGFjZWhvbGRlcnNIYXNoIiwiaXRlbSIsImtleSIsInZhbHVlIiwiZW50cmllcyIsIkFzdHgiLCJFeHRlbmRhYmxlUHJveHkiLCJjb25zdHJ1Y3RvciIsImhhbmRsZXIiLCJQcm94eSIsImJhY2tlbmQiLCJfbWF0Y2hlcyIsIl93aXRoQ2FwdHVyZXMiLCJfcGxhY2Vob2xkZXIiLCJfbGF6eVBhdGhzIiwiX2xhenlOb2RlcyIsIl9sYXp5SW5pdGlhbE1hdGNoIiwicGF0aHMiLCJ3aXRoQ2FwdHVyZXMiLCJwbGFjZWhvbGRlciIsImdldCIsInRhcmdldCIsInByb3AiLCJzdGFydHNXaXRoIiwibWF0Y2hlcyIsImFycmF5UGF0aENhcHR1cmVzIiwicGF0aENhcHR1cmVzIiwic3RyaW5nQ2FwdHVyZXMiLCJwYXRoIiwic3RyaW5nVmFsdWUiLCJhcnJheVBhdGhzIiwicHVzaCIsInVuZGVmaW5lZCIsIk5vZGVQYXRoIiwidCIsIm1hcCIsInNpemUiLCJsZW5ndGgiLCJTeW1ib2wiLCJpdGVyYXRvciIsIm1hdGNoIiwiRXJyb3IiLCJub2RlIiwiY29kZSIsImdlbmVyYXRlIiwicmVzdWx0IiwibSIsImZsYXQiLCJub2RlcyIsImZpbHRlciIsIml0ZXJhdGVlIiwiZmlsdGVyZWQiLCJpbmRleCIsImFzdHgiLCJhdCIsImNhcHR1cmVzIiwiYXJyYXlDYXB0dXJlcyIsImluaXRpYWxNYXRjaCIsIl9leGVjUGF0dGVybiIsIm5hbWUiLCJleGVjIiwiYXJnMCIsInJlc3QiLCJwYXJzZVBhdHRlcm4iLCJwYXR0ZXJuIiwib3B0aW9ucyIsImVycm9yIiwicmV0aHJvdyIsImZpbGVuYW1lIiwic291cmNlIiwiY2xvc2VzdCIsIm1hdGNoZXIiLCJtYXRjaGVkUGFyZW50cyIsIlNldCIsImZvckVhY2giLCJwIiwicGFyZW50UGF0aCIsImhhcyIsImFkZCIsIm1hdGNoU29GYXIiLCJxdWFzaXMiLCJwYXJzZVBhdHRlcm5Ub05vZGVzIiwicmVwbGFjZW1lbnQiLCJmaW5hbFBhdGhzIl0sInNvdXJjZXMiOlsiLi4vc3JjL0FzdHgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRXhwcmVzc2lvbiwgU3RhdGVtZW50LCBOb2RlLCBOb2RlUGF0aCB9IGZyb20gJy4vdHlwZXMnXG5pbXBvcnQgeyBCYWNrZW5kIH0gZnJvbSAnLi9iYWNrZW5kL0JhY2tlbmQnXG5pbXBvcnQgZmluZCwgeyBNYXRjaCwgY29udmVydFdpdGhDYXB0dXJlcywgY3JlYXRlTWF0Y2ggfSBmcm9tICcuL2ZpbmQnXG5pbXBvcnQgcmVwbGFjZSBmcm9tICcuL3JlcGxhY2UnXG5pbXBvcnQgY29tcGlsZU1hdGNoZXIsIHsgTWF0Y2hSZXN1bHQgfSBmcm9tICcuL2NvbXBpbGVNYXRjaGVyJ1xuaW1wb3J0IENvZGVGcmFtZUVycm9yIGZyb20gJy4vdXRpbC9Db2RlRnJhbWVFcnJvcidcbmltcG9ydCBlbnN1cmVBcnJheSBmcm9tICcuL3V0aWwvZW5zdXJlQXJyYXknXG5pbXBvcnQgKiBhcyBBc3RUeXBlcyBmcm9tICdhc3QtdHlwZXMnXG5pbXBvcnQge1xuICBpc1BsYWNlaG9sZGVyLFxuICBnZXRQbGFjZWhvbGRlcixcbiAgZ2V0QXJyYXlQbGFjZWhvbGRlcixcbiAgZ2V0UmVzdFBsYWNlaG9sZGVyLFxufSBmcm9tICcuL2NvbXBpbGVNYXRjaGVyL1BsYWNlaG9sZGVyJ1xuXG5leHBvcnQgdHlwZSBUcmFuc2Zvcm1PcHRpb25zID0ge1xuICAvKiogVGhlIGFic29sdXRlIHBhdGggdG8gdGhlIGN1cnJlbnQgZmlsZS4gKi9cbiAgZmlsZTogc3RyaW5nXG4gIC8qKiBUaGUgc291cmNlIGNvZGUgb2YgdGhlIGN1cnJlbnQgZmlsZS4gKi9cbiAgc291cmNlOiBzdHJpbmdcbiAgYXN0eDogQXN0eFxuICBleHByZXNzaW9uKHN0cmluZ3M6IFRlbXBsYXRlU3RyaW5nc0FycmF5LCAuLi5xdWFzaXM6IGFueVtdKTogRXhwcmVzc2lvblxuICBzdGF0ZW1lbnQoc3RyaW5nczogVGVtcGxhdGVTdHJpbmdzQXJyYXksIC4uLnF1YXNpczogYW55W10pOiBTdGF0ZW1lbnRcbiAgc3RhdGVtZW50cyhzdHJpbmdzOiBUZW1wbGF0ZVN0cmluZ3NBcnJheSwgLi4ucXVhc2lzOiBhbnlbXSk6IFN0YXRlbWVudFtdXG4gIHQ6IHR5cGVvZiBBc3RUeXBlc1xuICByZXBvcnQ6IChtc2c6IHVua25vd24pID0+IHZvaWRcbn1cblxuZXhwb3J0IHR5cGUgVHJhbnNmb3JtRnVuY3Rpb24gPSAoXG4gIG9wdGlvbnM6IFRyYW5zZm9ybU9wdGlvbnNcbikgPT4gc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCB8IHZvaWRcblxuZXhwb3J0IHR5cGUgVHJhbnNmb3JtID0ge1xuICBhc3R4PzogVHJhbnNmb3JtRnVuY3Rpb25cbiAgZmluZD86IHN0cmluZyB8IE5vZGUgfCBOb2RlW11cbiAgcmVwbGFjZT86IHN0cmluZyB8IE5vZGUgfCBOb2RlW10gfCBHZXRSZXBsYWNlbWVudFxuICB3aGVyZT86IEZpbmRPcHRpb25zWyd3aGVyZSddXG4gIG9uUmVwb3J0PzogKG9wdGlvbnM6IHsgZmlsZTogc3RyaW5nOyByZXBvcnQ6IHVua25vd24gfSkgPT4gdm9pZFxuICBmaW5pc2g/OiAoKSA9PiBhbnlcbn1cblxuZXhwb3J0IHR5cGUgVHJhbnNmb3JtUmVzdWx0ID0ge1xuICBmaWxlOiBzdHJpbmdcbiAgc291cmNlPzogc3RyaW5nXG4gIHRyYW5zZm9ybWVkPzogc3RyaW5nXG4gIHJlcG9ydHM/OiB1bmtub3duW11cbiAgZXJyb3I/OiBFcnJvclxuICBtYXRjaGVzPzogcmVhZG9ubHkgTWF0Y2hbXVxuICBiYWNrZW5kOiBCYWNrZW5kXG59XG5cbmV4cG9ydCB0eXBlIFBhcnNlUGF0dGVybiA9IChcbiAgc3RyaW5nczogc3RyaW5nIHwgc3RyaW5nW10gfCBUZW1wbGF0ZVN0cmluZ3NBcnJheSxcbiAgLi4ucXVhc2lzOiBhbnlbXVxuKSA9PiBOb2RlIHwgTm9kZVtdXG5cbmV4cG9ydCB0eXBlIEdldFJlcGxhY2VtZW50ID0gKFxuICBhc3R4OiBBc3R4LFxuICBwYXJzZTogUGFyc2VQYXR0ZXJuXG4pID0+IHN0cmluZyB8IE5vZGUgfCBOb2RlW11cblxuZnVuY3Rpb24gaXNOb2RlKHg6IHVua25vd24pOiB4IGlzIE5vZGUge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIE9iamVjdCAmJiB0eXBlb2YgKHggYXMgYW55KS50eXBlID09PSAnc3RyaW5nJ1xufVxuZnVuY3Rpb24gaXNOb2RlQXJyYXkoeDogdW5rbm93bik6IHggaXMgTm9kZVtdIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkoeCkgJiYgIUFycmF5LmlzQXJyYXkoKHggYXMgYW55KS5yYXcpXG59XG5mdW5jdGlvbiBpc1BsYWNlaG9sZGVyc0hhc2goXG4gIGl0ZW06IHVua25vd25cbik6IGl0ZW0gaXMgeyBbbmFtZTogYCQke3N0cmluZ31gIHwgYCQkJHtzdHJpbmd9YCB8IGAkJCQke3N0cmluZ31gXTogQXN0eCB9IHtcbiAgaWYgKCEoaXRlbSBpbnN0YW5jZW9mIE9iamVjdCkpIHJldHVybiBmYWxzZVxuICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhpdGVtKSkge1xuICAgIGlmICghaXNQbGFjZWhvbGRlcihrZXkpKSByZXR1cm4gZmFsc2VcbiAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIEFzdHgpKSByZXR1cm4gZmFsc2VcbiAgfVxuICByZXR1cm4gdHJ1ZVxufVxuXG5leHBvcnQgdHlwZSBGaW5kT3B0aW9ucyA9IHtcbiAgd2hlcmU/OiB7IFtjYXB0dXJlTmFtZTogc3RyaW5nXTogKHBhdGg6IE5vZGVQYXRoKSA9PiBib29sZWFuIH1cbn1cblxuY2xhc3MgRXh0ZW5kYWJsZVByb3h5IHtcbiAgY29uc3RydWN0b3IoaGFuZGxlcjogUHJveHlIYW5kbGVyPGFueT4pIHtcbiAgICByZXR1cm4gbmV3IFByb3h5KHRoaXMsIGhhbmRsZXIpXG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQXN0eCBleHRlbmRzIEV4dGVuZGFibGVQcm94eSBpbXBsZW1lbnRzIEl0ZXJhYmxlPEFzdHg+IHtcbiAgW25hbWU6IGAkJHtzdHJpbmd9YCB8IGAkJCR7c3RyaW5nfWAgfCBgJCQkJHtzdHJpbmd9YF06IEFzdHhcbiAgcHVibGljIHJlYWRvbmx5IGJhY2tlbmQ6IEJhY2tlbmRcbiAgcHJpdmF0ZSByZWFkb25seSBfbWF0Y2hlczogTWF0Y2hbXVxuICBwcml2YXRlIHJlYWRvbmx5IF93aXRoQ2FwdHVyZXM6IE1hdGNoW11cbiAgcHJpdmF0ZSByZWFkb25seSBfcGxhY2Vob2xkZXI6IHN0cmluZyB8IHVuZGVmaW5lZFxuICBwcml2YXRlIF9sYXp5UGF0aHM6IE5vZGVQYXRoPE5vZGUsIGFueT5bXSB8IHVuZGVmaW5lZFxuICBwcml2YXRlIF9sYXp5Tm9kZXM6IE5vZGVbXSB8IHVuZGVmaW5lZFxuICBwcml2YXRlIF9sYXp5SW5pdGlhbE1hdGNoOiBNYXRjaFJlc3VsdCB8IHVuZGVmaW5lZFxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGJhY2tlbmQ6IEJhY2tlbmQsXG4gICAgcGF0aHM6IE5vZGVQYXRoPGFueT5bXSB8IE1hdGNoW10sXG4gICAge1xuICAgICAgd2l0aENhcHR1cmVzID0gW10sXG4gICAgICBwbGFjZWhvbGRlcixcbiAgICB9OiB7IHdpdGhDYXB0dXJlcz86IE1hdGNoW107IHBsYWNlaG9sZGVyPzogc3RyaW5nIH0gPSB7fVxuICApIHtcbiAgICBzdXBlcih7XG4gICAgICBnZXQodGFyZ2V0OiBBc3R4LCBwcm9wOiBzdHJpbmcpOiBBc3R4IHtcbiAgICAgICAgaWYgKHR5cGVvZiBwcm9wID09PSAnc3ltYm9sJyB8fCAhcHJvcC5zdGFydHNXaXRoKCckJykpXG4gICAgICAgICAgcmV0dXJuICh0YXJnZXQgYXMgYW55KVtwcm9wXVxuICAgICAgICBjb25zdCBtYXRjaGVzOiBNYXRjaFtdID0gW11cbiAgICAgICAgZm9yIChjb25zdCB7XG4gICAgICAgICAgYXJyYXlQYXRoQ2FwdHVyZXMsXG4gICAgICAgICAgcGF0aENhcHR1cmVzLFxuICAgICAgICAgIHN0cmluZ0NhcHR1cmVzLFxuICAgICAgICB9IG9mIHRhcmdldC5fbWF0Y2hlcykge1xuICAgICAgICAgIGNvbnN0IHBhdGggPSBwYXRoQ2FwdHVyZXM/Lltwcm9wXVxuICAgICAgICAgIGNvbnN0IHN0cmluZ1ZhbHVlID0gc3RyaW5nQ2FwdHVyZXM/Lltwcm9wXVxuICAgICAgICAgIGNvbnN0IGFycmF5UGF0aHMgPSBhcnJheVBhdGhDYXB0dXJlcz8uW3Byb3BdXG4gICAgICAgICAgaWYgKHBhdGgpXG4gICAgICAgICAgICBtYXRjaGVzLnB1c2goXG4gICAgICAgICAgICAgIGNyZWF0ZU1hdGNoKHBhdGgsIHtcbiAgICAgICAgICAgICAgICBzdHJpbmdDYXB0dXJlczogc3RyaW5nVmFsdWVcbiAgICAgICAgICAgICAgICAgID8geyBbcHJvcF06IHN0cmluZ1ZhbHVlIH1cbiAgICAgICAgICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKVxuICAgICAgICAgIGlmIChhcnJheVBhdGhzKSBtYXRjaGVzLnB1c2goY3JlYXRlTWF0Y2goYXJyYXlQYXRocywge30pKVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgQXN0eCh0YXJnZXQuYmFja2VuZCwgbWF0Y2hlcywgeyBwbGFjZWhvbGRlcjogcHJvcCB9KVxuICAgICAgfSxcbiAgICB9KVxuICAgIHRoaXMuYmFja2VuZCA9IGJhY2tlbmRcbiAgICB0aGlzLl9wbGFjZWhvbGRlciA9IHBsYWNlaG9sZGVyXG4gICAgY29uc3QgeyBOb2RlUGF0aCB9ID0gYmFja2VuZC50XG4gICAgdGhpcy5fbWF0Y2hlcyA9XG4gICAgICBwYXRoc1swXSBpbnN0YW5jZW9mIE5vZGVQYXRoXG4gICAgICAgID8gKHBhdGhzIGFzIE5vZGVQYXRoW10pLm1hcCgocGF0aCkgPT4gY3JlYXRlTWF0Y2gocGF0aCwge30pKVxuICAgICAgICA6IChwYXRocyBhcyBNYXRjaFtdKVxuICAgIHRoaXMuX3dpdGhDYXB0dXJlcyA9IHdpdGhDYXB0dXJlc1xuICB9XG5cbiAgZ2V0IHBsYWNlaG9sZGVyKCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuX3BsYWNlaG9sZGVyXG4gIH1cblxuICBnZXQgc2l6ZSgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLl9tYXRjaGVzLmxlbmd0aFxuICB9XG5cbiAgZ2V0IG1hdGNoZXMoKTogcmVhZG9ubHkgTWF0Y2hbXSB7XG4gICAgcmV0dXJuIHRoaXMuX21hdGNoZXNcbiAgfVxuXG4gICpbU3ltYm9sLml0ZXJhdG9yXSgpOiBJdGVyYXRvcjxBc3R4PiB7XG4gICAgaWYgKHRoaXMuX3BsYWNlaG9sZGVyKSB7XG4gICAgICBmb3IgKGNvbnN0IHBhdGggb2YgdGhpcy5wYXRocykge1xuICAgICAgICB5aWVsZCBuZXcgQXN0eCh0aGlzLmJhY2tlbmQsIFtwYXRoXSlcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZm9yIChjb25zdCBtYXRjaCBvZiB0aGlzLl9tYXRjaGVzKSB7XG4gICAgICAgIHlpZWxkIG5ldyBBc3R4KHRoaXMuYmFja2VuZCwgW21hdGNoXSlcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBnZXQgbWF0Y2goKTogTWF0Y2gge1xuICAgIGNvbnN0IFttYXRjaF0gPSB0aGlzLl9tYXRjaGVzXG4gICAgaWYgKCFtYXRjaCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGB5b3UgY2FuJ3QgY2FsbCBtYXRjaCgpIHdoZW4gdGhlcmUgYXJlIG5vIG1hdGNoZXNgKVxuICAgIH1cbiAgICByZXR1cm4gbWF0Y2hcbiAgfVxuXG4gIGdldCBub2RlKCk6IE5vZGUge1xuICAgIHJldHVybiB0aGlzLm1hdGNoLm5vZGVcbiAgfVxuXG4gIGdldCBwYXRoKCk6IE5vZGVQYXRoIHtcbiAgICByZXR1cm4gdGhpcy5tYXRjaC5wYXRoXG4gIH1cblxuICBnZXQgY29kZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmJhY2tlbmQuZ2VuZXJhdGUodGhpcy5ub2RlKS5jb2RlXG4gIH1cblxuICBnZXQgc3RyaW5nVmFsdWUoKTogc3RyaW5nIHtcbiAgICBjb25zdCByZXN1bHQgPSB0aGlzLm1hdGNoLnN0cmluZ0NhcHR1cmVzPy5bdGhpcy5fcGxhY2Vob2xkZXIgfHwgJyddXG4gICAgaWYgKCFyZXN1bHQpIHRocm93IG5ldyBFcnJvcihgbm90IGEgc3RyaW5nIGNhcHR1cmVgKVxuICAgIHJldHVybiByZXN1bHRcbiAgfVxuXG4gIGdldCBwYXRocygpOiByZWFkb25seSBOb2RlUGF0aFtdIHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5fbGF6eVBhdGhzIHx8XG4gICAgICAodGhpcy5fbGF6eVBhdGhzID0gdGhpcy5tYXRjaGVzLm1hcCgobSkgPT4gbS5wYXRocykuZmxhdCgpKVxuICAgIClcbiAgfVxuXG4gIGdldCBub2RlcygpOiByZWFkb25seSBOb2RlW10ge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLl9sYXp5Tm9kZXMgfHxcbiAgICAgICh0aGlzLl9sYXp5Tm9kZXMgPSB0aGlzLm1hdGNoZXMubWFwKChtKSA9PiBtLm5vZGVzKS5mbGF0KCkpXG4gICAgKVxuICB9XG5cbiAgZmlsdGVyKGl0ZXJhdGVlOiAoYXN0eDogQXN0eCwgaW5kZXg6IG51bWJlciwgcGFyZW50OiBBc3R4KSA9PiBib29sZWFuKTogQXN0eCB7XG4gICAgY29uc3QgZmlsdGVyZWQgPSBbXVxuICAgIGxldCBpbmRleCA9IDBcbiAgICBmb3IgKGNvbnN0IGFzdHggb2YgdGhpcykge1xuICAgICAgaWYgKGl0ZXJhdGVlKGFzdHgsIGluZGV4KyssIHRoaXMpKSB7XG4gICAgICAgIGZpbHRlcmVkLnB1c2goYXN0eC5tYXRjaClcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG5ldyBBc3R4KHRoaXMuYmFja2VuZCwgZmlsdGVyZWQpXG4gIH1cblxuICBtYXA8VD4oaXRlcmF0ZWU6IChhc3R4OiBBc3R4LCBpbmRleDogbnVtYmVyLCBwYXJlbnQ6IEFzdHgpID0+IFQpOiBUW10ge1xuICAgIGNvbnN0IHJlc3VsdCA9IFtdXG4gICAgbGV0IGluZGV4ID0gMFxuICAgIGZvciAoY29uc3QgYXN0eCBvZiB0aGlzKSB7XG4gICAgICByZXN1bHQucHVzaChpdGVyYXRlZShhc3R4LCBpbmRleCsrLCB0aGlzKSlcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG5cbiAgYXQoaW5kZXg6IG51bWJlcik6IEFzdHgge1xuICAgIHJldHVybiBuZXcgQXN0eCh0aGlzLmJhY2tlbmQsIFt0aGlzLl9tYXRjaGVzW2luZGV4XV0pXG4gIH1cblxuICB3aXRoQ2FwdHVyZXMoXG4gICAgLi4uY2FwdHVyZXM6IChcbiAgICAgIHwgTWF0Y2hcbiAgICAgIHwgQXN0eFxuICAgICAgfCB7IFtuYW1lOiBgJCR7c3RyaW5nfWAgfCBgJCQke3N0cmluZ31gIHwgYCQkJCR7c3RyaW5nfWBdOiBBc3R4IH1cbiAgICApW11cbiAgKTogQXN0eCB7XG4gICAgY29uc3Qgd2l0aENhcHR1cmVzOiBNYXRjaFtdID0gWy4uLnRoaXMuX3dpdGhDYXB0dXJlc11cbiAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgY2FwdHVyZXMpIHtcbiAgICAgIGlmIChpdGVtIGluc3RhbmNlb2YgQXN0eCkge1xuICAgICAgICBpZiAoaXRlbS5fcGxhY2Vob2xkZXIpIHtcbiAgICAgICAgICBjb25zdCBwbGFjZWhvbGRlciA9IGl0ZW0uX3BsYWNlaG9sZGVyXG4gICAgICAgICAgZm9yIChjb25zdCB7IHBhdGgsIHBhdGhzLCBzdHJpbmdDYXB0dXJlcyB9IG9mIGl0ZW0uX21hdGNoZXMpIHtcbiAgICAgICAgICAgIHdpdGhDYXB0dXJlcy5wdXNoKFxuICAgICAgICAgICAgICBjcmVhdGVNYXRjaChwYXRocywge1xuICAgICAgICAgICAgICAgIGNhcHR1cmVzOiBnZXRQbGFjZWhvbGRlcihwbGFjZWhvbGRlcilcbiAgICAgICAgICAgICAgICAgID8geyBbcGxhY2Vob2xkZXJdOiBwYXRoIH1cbiAgICAgICAgICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgIGFycmF5Q2FwdHVyZXM6XG4gICAgICAgICAgICAgICAgICBnZXRBcnJheVBsYWNlaG9sZGVyKHBsYWNlaG9sZGVyKSB8fFxuICAgICAgICAgICAgICAgICAgZ2V0UmVzdFBsYWNlaG9sZGVyKHBsYWNlaG9sZGVyKVxuICAgICAgICAgICAgICAgICAgICA/IHsgW3BsYWNlaG9sZGVyXTogcGF0aHMgfVxuICAgICAgICAgICAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICBzdHJpbmdDYXB0dXJlczpcbiAgICAgICAgICAgICAgICAgIGdldFBsYWNlaG9sZGVyKHBsYWNlaG9sZGVyKSAmJiBzdHJpbmdDYXB0dXJlcz8uW3BsYWNlaG9sZGVyXVxuICAgICAgICAgICAgICAgICAgICA/IHsgW3BsYWNlaG9sZGVyXTogc3RyaW5nQ2FwdHVyZXNbcGxhY2Vob2xkZXJdIH1cbiAgICAgICAgICAgICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICApXG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGZvciAoY29uc3QgbWF0Y2ggb2YgaXRlbS5fd2l0aENhcHR1cmVzKSB3aXRoQ2FwdHVyZXMucHVzaChtYXRjaClcbiAgICAgICAgICBmb3IgKGNvbnN0IG1hdGNoIG9mIGl0ZW0uX21hdGNoZXMpIHdpdGhDYXB0dXJlcy5wdXNoKG1hdGNoKVxuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGlzUGxhY2Vob2xkZXJzSGFzaChpdGVtKSkge1xuICAgICAgICBmb3IgKGNvbnN0IFtwbGFjZWhvbGRlciwgYXN0eF0gb2YgT2JqZWN0LmVudHJpZXMoaXRlbSkpIHtcbiAgICAgICAgICBjb25zdCB7IF9wbGFjZWhvbGRlciB9ID0gYXN0eFxuICAgICAgICAgIGZvciAoY29uc3QgeyBwYXRoLCBwYXRocywgc3RyaW5nQ2FwdHVyZXMgfSBvZiBhc3R4Ll9tYXRjaGVzKSB7XG4gICAgICAgICAgICB3aXRoQ2FwdHVyZXMucHVzaChcbiAgICAgICAgICAgICAgY3JlYXRlTWF0Y2gocGF0aHMsIHtcbiAgICAgICAgICAgICAgICBjYXB0dXJlczogZ2V0UGxhY2Vob2xkZXIocGxhY2Vob2xkZXIpXG4gICAgICAgICAgICAgICAgICA/IHsgW3BsYWNlaG9sZGVyXTogcGF0aCB9XG4gICAgICAgICAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICBhcnJheUNhcHR1cmVzOlxuICAgICAgICAgICAgICAgICAgZ2V0QXJyYXlQbGFjZWhvbGRlcihwbGFjZWhvbGRlcikgfHxcbiAgICAgICAgICAgICAgICAgIGdldFJlc3RQbGFjZWhvbGRlcihwbGFjZWhvbGRlcilcbiAgICAgICAgICAgICAgICAgICAgPyB7IFtwbGFjZWhvbGRlcl06IHBhdGhzIH1cbiAgICAgICAgICAgICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgc3RyaW5nQ2FwdHVyZXM6XG4gICAgICAgICAgICAgICAgICBnZXRQbGFjZWhvbGRlcihwbGFjZWhvbGRlcikgJiZcbiAgICAgICAgICAgICAgICAgIF9wbGFjZWhvbGRlciAmJlxuICAgICAgICAgICAgICAgICAgc3RyaW5nQ2FwdHVyZXM/LltfcGxhY2Vob2xkZXJdXG4gICAgICAgICAgICAgICAgICAgID8geyBbcGxhY2Vob2xkZXJdOiBzdHJpbmdDYXB0dXJlc1tfcGxhY2Vob2xkZXJdIH1cbiAgICAgICAgICAgICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICApXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB3aXRoQ2FwdHVyZXMucHVzaChpdGVtKVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBuZXcgQXN0eCh0aGlzLmJhY2tlbmQsIHRoaXMuX21hdGNoZXMsIHtcbiAgICAgIHdpdGhDYXB0dXJlcyxcbiAgICB9KVxuICB9XG5cbiAgcHJpdmF0ZSBnZXQgaW5pdGlhbE1hdGNoKCk6IE1hdGNoUmVzdWx0IHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5fbGF6eUluaXRpYWxNYXRjaCB8fFxuICAgICAgKHRoaXMuX2xhenlJbml0aWFsTWF0Y2ggPSBjb252ZXJ0V2l0aENhcHR1cmVzKFtcbiAgICAgICAgLi4udGhpcy5fbWF0Y2hlcyxcbiAgICAgICAgLi4udGhpcy5fd2l0aENhcHR1cmVzLFxuICAgICAgXSkpXG4gICAgKVxuICB9XG5cbiAgcHJpdmF0ZSBfZXhlY1BhdHRlcm48T3B0aW9ucz4oXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIGV4ZWM6IChcbiAgICAgIHBhdHRlcm46IE5vZGVQYXRoPE5vZGUsIGFueT4gfCByZWFkb25seSBOb2RlUGF0aDxOb2RlLCBhbnk+W10sXG4gICAgICBvcHRpb25zPzogT3B0aW9uc1xuICAgICkgPT4gQXN0eCxcbiAgICBhcmcwOlxuICAgICAgfCBzdHJpbmdcbiAgICAgIHwgTm9kZVxuICAgICAgfCBOb2RlW11cbiAgICAgIHwgTm9kZVBhdGg8YW55PlxuICAgICAgfCBOb2RlUGF0aDxhbnk+W11cbiAgICAgIHwgc3RyaW5nW11cbiAgICAgIHwgVGVtcGxhdGVTdHJpbmdzQXJyYXksXG4gICAgLi4ucmVzdDogYW55W11cbiAgKTogQXN0eCB8ICgob3B0aW9ucz86IE9wdGlvbnMpID0+IEFzdHgpIHtcbiAgICBjb25zdCB7IGJhY2tlbmQgfSA9IHRoaXNcbiAgICBjb25zdCB7IHBhcnNlUGF0dGVybiB9ID0gYmFja2VuZFxuICAgIGNvbnN0IHsgTm9kZVBhdGggfSA9IGJhY2tlbmQudFxuICAgIHRyeSB7XG4gICAgICBsZXQgcGF0dGVybjogTm9kZVBhdGg8Tm9kZSwgYW55PiB8IHJlYWRvbmx5IE5vZGVQYXRoPE5vZGUsIGFueT5bXSxcbiAgICAgICAgb3B0aW9uczogT3B0aW9ucyB8IHVuZGVmaW5lZFxuICAgICAgaWYgKHR5cGVvZiBhcmcwID09PSAnc3RyaW5nJykge1xuICAgICAgICBwYXR0ZXJuID0gcGFyc2VQYXR0ZXJuKGFyZzApXG4gICAgICAgIG9wdGlvbnMgPSByZXN0WzBdXG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBBcnJheS5pc0FycmF5KGFyZzApXG4gICAgICAgICAgPyBhcmcwWzBdIGluc3RhbmNlb2YgTm9kZVBhdGhcbiAgICAgICAgICA6IGFyZzAgaW5zdGFuY2VvZiBOb2RlUGF0aFxuICAgICAgKSB7XG4gICAgICAgIHBhdHRlcm4gPSBlbnN1cmVBcnJheShhcmcwIGFzIE5vZGVQYXRoIHwgTm9kZVBhdGhbXSlcbiAgICAgICAgb3B0aW9ucyA9IHJlc3RbMF1cbiAgICAgIH0gZWxzZSBpZiAoaXNOb2RlKGFyZzApIHx8IGlzTm9kZUFycmF5KGFyZzApKSB7XG4gICAgICAgIHBhdHRlcm4gPSBlbnN1cmVBcnJheShhcmcwKS5tYXAoKG5vZGUpID0+IG5ldyBOb2RlUGF0aChub2RlKSlcbiAgICAgICAgb3B0aW9ucyA9IHJlc3RbMF1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhdHRlcm4gPSBwYXJzZVBhdHRlcm4oYXJnMCBhcyBhbnksIC4uLnJlc3QpXG4gICAgICAgIHJldHVybiAob3B0aW9ucz86IE9wdGlvbnMpID0+IGV4ZWMocGF0dGVybiwgb3B0aW9ucylcbiAgICAgIH1cbiAgICAgIHJldHVybiBleGVjKHBhdHRlcm4sIG9wdGlvbnMpXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIENvZGVGcmFtZUVycm9yLnJldGhyb3coZXJyb3IsIHtcbiAgICAgICAgICBmaWxlbmFtZTogYCR7bmFtZX0gcGF0dGVybmAsXG4gICAgICAgICAgc291cmNlOiB0eXBlb2YgYXJnMCA9PT0gJ3N0cmluZycgPyBhcmcwIDogdW5kZWZpbmVkLFxuICAgICAgICB9KVxuICAgICAgfVxuICAgICAgdGhyb3cgZXJyb3JcbiAgICB9XG4gIH1cblxuICBjbG9zZXN0KFxuICAgIHN0cmluZ3M6IFRlbXBsYXRlU3RyaW5nc0FycmF5LFxuICAgIC4uLnF1YXNpczogYW55W11cbiAgKTogKG9wdGlvbnM/OiBGaW5kT3B0aW9ucykgPT4gQXN0eFxuICBjbG9zZXN0KFxuICAgIHBhdHRlcm46IHN0cmluZyB8IE5vZGUgfCBOb2RlW10gfCBOb2RlUGF0aDxhbnk+IHwgTm9kZVBhdGg8YW55PltdLFxuICAgIG9wdGlvbnM/OiBGaW5kT3B0aW9uc1xuICApOiBBc3R4XG4gIGNsb3Nlc3QoXG4gICAgYXJnMDpcbiAgICAgIHwgc3RyaW5nXG4gICAgICB8IE5vZGVcbiAgICAgIHwgTm9kZVtdXG4gICAgICB8IE5vZGVQYXRoPGFueT5cbiAgICAgIHwgTm9kZVBhdGg8YW55PltdXG4gICAgICB8IFRlbXBsYXRlU3RyaW5nc0FycmF5LFxuICAgIC4uLnJlc3Q6IGFueVtdXG4gICk6IEFzdHggfCAoKG9wdGlvbnM/OiBGaW5kT3B0aW9ucykgPT4gQXN0eCkge1xuICAgIGNvbnN0IHsgYmFja2VuZCB9ID0gdGhpc1xuICAgIHJldHVybiB0aGlzLl9leGVjUGF0dGVybihcbiAgICAgICdjbG9zZXN0JyxcbiAgICAgIChcbiAgICAgICAgcGF0dGVybjogTm9kZVBhdGg8Tm9kZSwgYW55PiB8IHJlYWRvbmx5IE5vZGVQYXRoPE5vZGUsIGFueT5bXSxcbiAgICAgICAgb3B0aW9ucz86IEZpbmRPcHRpb25zXG4gICAgICApOiBBc3R4ID0+IHtcbiAgICAgICAgcGF0dGVybiA9IGVuc3VyZUFycmF5KHBhdHRlcm4pXG4gICAgICAgIGlmIChwYXR0ZXJuLmxlbmd0aCAhPT0gMSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgbXVzdCBiZSBhIHNpbmdsZSBub2RlYClcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBtYXRjaGVyID0gY29tcGlsZU1hdGNoZXIocGF0dGVyblswXSwge1xuICAgICAgICAgIC4uLm9wdGlvbnMsXG4gICAgICAgICAgYmFja2VuZCxcbiAgICAgICAgfSlcblxuICAgICAgICBjb25zdCBtYXRjaGVkUGFyZW50czogU2V0PE5vZGVQYXRoPiA9IG5ldyBTZXQoKVxuICAgICAgICBjb25zdCBtYXRjaGVzOiBNYXRjaFtdID0gW11cbiAgICAgICAgdGhpcy5wYXRocy5mb3JFYWNoKChwYXRoKSA9PiB7XG4gICAgICAgICAgZm9yIChsZXQgcCA9IHBhdGgucGFyZW50UGF0aDsgcDsgcCA9IHAucGFyZW50UGF0aCkge1xuICAgICAgICAgICAgaWYgKG1hdGNoZWRQYXJlbnRzLmhhcyhwKSkgcmV0dXJuXG4gICAgICAgICAgICBjb25zdCBtYXRjaCA9IG1hdGNoZXIubWF0Y2gocCwgdGhpcy5pbml0aWFsTWF0Y2gpXG4gICAgICAgICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgbWF0Y2hlZFBhcmVudHMuYWRkKHApXG4gICAgICAgICAgICAgIG1hdGNoZXMucHVzaChjcmVhdGVNYXRjaChwLCBtYXRjaCkpXG4gICAgICAgICAgICAgIHJldHVyblxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSlcblxuICAgICAgICByZXR1cm4gbmV3IEFzdHgoYmFja2VuZCwgbWF0Y2hlcylcbiAgICAgIH0sXG4gICAgICBhcmcwLFxuICAgICAgLi4ucmVzdFxuICAgIClcbiAgfVxuXG4gIGZpbmQoXG4gICAgc3RyaW5nczogc3RyaW5nW10gfCBUZW1wbGF0ZVN0cmluZ3NBcnJheSxcbiAgICAuLi5xdWFzaXM6IGFueVtdXG4gICk6IChvcHRpb25zPzogRmluZE9wdGlvbnMpID0+IEFzdHhcbiAgZmluZChcbiAgICBwYXR0ZXJuOiBzdHJpbmcgfCBOb2RlIHwgTm9kZVtdIHwgTm9kZVBhdGg8YW55PiB8IE5vZGVQYXRoPGFueT5bXSxcbiAgICBvcHRpb25zPzogRmluZE9wdGlvbnNcbiAgKTogQXN0eFxuICBmaW5kKFxuICAgIGFyZzA6XG4gICAgICB8IHN0cmluZ1xuICAgICAgfCBOb2RlXG4gICAgICB8IE5vZGVbXVxuICAgICAgfCBOb2RlUGF0aDxhbnk+XG4gICAgICB8IE5vZGVQYXRoPGFueT5bXVxuICAgICAgfCBzdHJpbmdbXVxuICAgICAgfCBUZW1wbGF0ZVN0cmluZ3NBcnJheSxcbiAgICAuLi5yZXN0OiBhbnlbXVxuICApOiBBc3R4IHwgKChvcHRpb25zPzogRmluZE9wdGlvbnMpID0+IEFzdHgpIHtcbiAgICBjb25zdCB7IGJhY2tlbmQgfSA9IHRoaXNcbiAgICByZXR1cm4gdGhpcy5fZXhlY1BhdHRlcm4oXG4gICAgICAnZmluZCcsXG4gICAgICAoXG4gICAgICAgIHBhdHRlcm46IE5vZGVQYXRoPE5vZGUsIGFueT4gfCByZWFkb25seSBOb2RlUGF0aDxOb2RlLCBhbnk+W10sXG4gICAgICAgIG9wdGlvbnM/OiBGaW5kT3B0aW9uc1xuICAgICAgKTogQXN0eCA9PlxuICAgICAgICBuZXcgQXN0eChcbiAgICAgICAgICBiYWNrZW5kLFxuICAgICAgICAgIGZpbmQodGhpcy5wYXRocywgcGF0dGVybiwge1xuICAgICAgICAgICAgLi4ub3B0aW9ucyxcbiAgICAgICAgICAgIGJhY2tlbmQsXG4gICAgICAgICAgICBtYXRjaFNvRmFyOiB0aGlzLmluaXRpYWxNYXRjaCxcbiAgICAgICAgICB9KVxuICAgICAgICApLFxuICAgICAgYXJnMCxcbiAgICAgIC4uLnJlc3RcbiAgICApXG4gIH1cblxuICByZXBsYWNlKFxuICAgIHN0cmluZ3M6IHN0cmluZ1tdIHwgVGVtcGxhdGVTdHJpbmdzQXJyYXksXG4gICAgLi4ucXVhc2lzOiBhbnlbXVxuICApOiAoKSA9PiB2b2lkXG4gIHJlcGxhY2UocmVwbGFjZW1lbnQ6IHN0cmluZyB8IE5vZGUgfCBOb2RlW10gfCBHZXRSZXBsYWNlbWVudCk6IHZvaWRcbiAgcmVwbGFjZShcbiAgICBhcmcwOlxuICAgICAgfCBzdHJpbmdcbiAgICAgIHwgTm9kZVxuICAgICAgfCBOb2RlW11cbiAgICAgIHwgR2V0UmVwbGFjZW1lbnRcbiAgICAgIHwgc3RyaW5nW11cbiAgICAgIHwgVGVtcGxhdGVTdHJpbmdzQXJyYXksXG4gICAgLi4ucXVhc2lzOiBhbnlbXVxuICApOiB2b2lkIHwgKCgpID0+IHZvaWQpIHtcbiAgICBjb25zdCB7IGJhY2tlbmQgfSA9IHRoaXNcbiAgICBjb25zdCB7IHBhcnNlUGF0dGVyblRvTm9kZXMgfSA9IGJhY2tlbmRcbiAgICB0cnkge1xuICAgICAgaWYgKHR5cGVvZiBhcmcwID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGZvciAoY29uc3QgYXN0eCBvZiB0aGlzKSB7XG4gICAgICAgICAgY29uc3QgcmVwbGFjZW1lbnQgPSBhcmcwKGFzdHgsIHBhcnNlUGF0dGVyblRvTm9kZXMpXG4gICAgICAgICAgcmVwbGFjZShcbiAgICAgICAgICAgIGFzdHgubWF0Y2gsXG4gICAgICAgICAgICB0eXBlb2YgcmVwbGFjZW1lbnQgPT09ICdzdHJpbmcnXG4gICAgICAgICAgICAgID8gcGFyc2VQYXR0ZXJuVG9Ob2RlcyhyZXBsYWNlbWVudClcbiAgICAgICAgICAgICAgOiByZXBsYWNlbWVudCxcbiAgICAgICAgICAgIHsgYmFja2VuZCB9XG4gICAgICAgICAgKVxuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcmcwID09PSAnc3RyaW5nJykge1xuICAgICAgICBjb25zdCByZXBsYWNlbWVudCA9IHBhcnNlUGF0dGVyblRvTm9kZXMoYXJnMClcbiAgICAgICAgZm9yIChjb25zdCBtYXRjaCBvZiB0aGlzLl9tYXRjaGVzKSB7XG4gICAgICAgICAgcmVwbGFjZShtYXRjaCwgcmVwbGFjZW1lbnQsIHsgYmFja2VuZCB9KVxuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGlzTm9kZShhcmcwKSB8fCBpc05vZGVBcnJheShhcmcwKSkge1xuICAgICAgICBmb3IgKGNvbnN0IG1hdGNoIG9mIHRoaXMuX21hdGNoZXMpIHtcbiAgICAgICAgICByZXBsYWNlKG1hdGNoLCBhcmcwLCB7IGJhY2tlbmQgfSlcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgZmluYWxQYXRocyA9IHBhcnNlUGF0dGVyblRvTm9kZXMoYXJnMCwgLi4ucXVhc2lzKVxuICAgICAgICByZXR1cm4gKCkgPT4gdGhpcy5yZXBsYWNlKGZpbmFsUGF0aHMpXG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIENvZGVGcmFtZUVycm9yLnJldGhyb3coZXJyb3IsIHtcbiAgICAgICAgICBmaWxlbmFtZTogJ3JlcGxhY2UgcGF0dGVybicsXG4gICAgICAgICAgc291cmNlOiB0eXBlb2YgYXJnMCA9PT0gJ3N0cmluZycgPyBhcmcwIDogdW5kZWZpbmVkLFxuICAgICAgICB9KVxuICAgICAgfVxuICAgICAgdGhyb3cgZXJyb3JcbiAgICB9XG4gIH1cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7QUFFQSxPQUFPQSxJQUFQLElBQXNCQyxtQkFBdEIsRUFBMkNDLFdBQTNDLFFBQThELFFBQTlEO0FBQ0EsT0FBT0MsT0FBUCxNQUFvQixXQUFwQjtBQUNBLE9BQU9DLGNBQVAsTUFBNEMsa0JBQTVDO0FBQ0EsT0FBT0MsY0FBUCxNQUEyQix1QkFBM0I7QUFDQSxPQUFPQyxXQUFQLE1BQXdCLG9CQUF4Qjs7QUFFQTtBQUNFQyxhQURGO0FBRUVDLGNBRkY7QUFHRUMsbUJBSEY7QUFJRUMsa0JBSkY7QUFLTyw4QkFMUDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBcURBLFNBQVNDLE1BQVQsQ0FBZ0JDLENBQWhCLEVBQXVD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