@loona/core
Version:
App State Management done with GraphQL (core package)
862 lines (830 loc) • 66.6 kB
JavaScript
import produce from 'immer';
import { __awaiter } from 'tslib';
import { ApolloLink } from 'apollo-link';
import { withClientState } from 'apollo-link-state';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @template T
*/
class Store {
/**
* @param {?=} data
*/
constructor(data = {}) {
this.store = new Map(Object.entries(data));
}
/**
* @param {?} key
* @return {?}
*/
get(key) {
return this.store.get(key);
}
/**
* @param {?} key
* @param {?} value
* @return {?}
*/
set(key, value) {
this.store.set(key, value);
}
/**
* @param {?} fn
* @return {?}
*/
forEach(fn) {
this.store.forEach(fn);
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @param {?} doc
* @return {?}
*/
function getMutationDefinition(doc) {
/** @type {?} */
const isMutation = (def) => def.kind === 'OperationDefinition' && def.operation === 'mutation';
/** @type {?} */
const defs = doc.definitions.filter(isMutation);
if (!defs || !defs[0]) {
throw new Error('Must contain a mutation definition.');
}
return defs[0];
}
/**
* @param {?} def
* @return {?}
*/
function getFirstField(def) {
return (/** @type {?} */ (def.selectionSet.selections[0]));
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @param {?} context
* @param {?} client
* @return {?}
*/
function buildContext(context, client) {
return Object.assign({}, context, { patchQuery: patchQuery(client), patchFragment: patchFragment(context, client), /**
* @param {?} options
* @return {?}
*/
writeData(options) {
return client.writeData(options);
} });
}
/**
* @param {?} cache
* @return {?}
*/
function buildGetCacheKey(cache) {
return (obj) => {
if (((/** @type {?} */ (cache))).config) {
return ((/** @type {?} */ (cache))).config.dataIdFromObject(obj);
}
else {
throw new Error('To use context.getCacheKey, you need to use a cache that has a configurable dataIdFromObject, like apollo-cache-inmemory.');
}
};
}
/**
* @param {?} fragment
* @return {?}
*/
function getFragmentTypename(fragment) {
/** @type {?} */
const def = (/** @type {?} */ (fragment.definitions.find(def => def.kind === 'FragmentDefinition')));
return def.typeCondition.name.value;
}
/**
* @param {?} client
* @return {?}
*/
function patchQuery(client) {
return (query, patchFn) => {
/** @type {?} */
const options = isDocument(query) ? { query } : query;
/** @type {?} */
const obj = client.readQuery(options);
/** @type {?} */
const data = produce(obj, patchFn);
client.writeQuery(Object.assign({}, options, { data }));
return data;
};
}
/**
* @param {?} context
* @param {?} client
* @return {?}
*/
function patchFragment(context, client) {
return (fragment, obj, patchFn) => {
/** @type {?} */
const __typename = getFragmentTypename(fragment);
/** @type {?} */
const id = context.getCacheKey(Object.assign({}, obj, { __typename }));
/** @type {?} */
const frgmt = client.readFragment({
fragment,
id,
});
/** @type {?} */
const data = produce(frgmt, patchFn);
client.writeFragment({
fragment,
id,
data: Object.assign({}, data, { __typename }),
});
return data;
};
}
/**
* @param {?} doc
* @return {?}
*/
function isDocument(doc) {
return doc && doc.kind === 'Document';
}
/**
* @param {?} action
* @return {?}
*/
function isMutationAsAction(action) {
return action.type === 'mutation';
}
/**
* @param {?} action
* @return {?}
*/
function getActionType(action) {
if (action.constructor && action.constructor.type) {
return action.constructor.type;
}
return action.type;
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
class MutationManager extends Store {
/**
* @param {?=} defs
*/
constructor(defs) {
super();
if (defs) {
defs.forEach(def => {
this.set(def.mutation, def);
});
}
}
/**
* @param {?} defs
* @return {?}
*/
add(defs) {
defs.forEach(def => {
this.set(def.mutation, def);
});
}
}
/**
* @param {?} action
* @return {?}
*/
function mutationToType(action) {
/** @type {?} */
const mutation = getMutation(action);
/** @type {?} */
const name = getNameOfMutation(mutation);
return name;
}
/**
* @param {?} action
* @return {?}
*/
function getMutation(action) {
if (action.constructor && action.constructor.mutation) {
return action.constructor.mutation;
}
return action.mutation;
}
/**
* @param {?} action
* @return {?}
*/
function isMutation(action) {
return typeof getMutation(action) !== 'undefined';
}
/**
* @param {?} mutation
* @return {?}
*/
function getNameOfMutation(mutation) {
/** @type {?} */
const def = getMutationDefinition(mutation);
/** @type {?} */
const field = getFirstField(def);
return field.name.value;
}
/**
* @template T, V
* @param {?} config
* @param {?} manager
* @return {?}
*/
function withUpdates(config, manager) {
/** @type {?} */
const orgUpdate = config.update;
return Object.assign({}, config, { update: (proxy, mutationResult) => {
/** @type {?} */
const name = getNameOfMutation(config.mutation);
/** @type {?} */
const result = mutationResult.data && mutationResult.data[name];
/** @type {?} */
const cache = manager.cache;
/** @type {?} */
const context = buildContext({
cache: proxy,
getCacheKey: buildGetCacheKey(cache),
}, manager.getClient());
/** @type {?} */
const updates = manager.updates.get(name);
if (updates) {
/** @type {?} */
const info = {
name,
variables: config.variables,
result,
};
updates.forEach(def => def.resolve(info, context));
}
if (orgUpdate) {
orgUpdate(proxy, mutationResult);
}
} });
}
/**
* @template T, V
* @param {?} config
* @param {?} result
* @return {?}
*/
function buildActionFromResult(config, result) {
return Object.assign({ type: 'mutation', options: config, ok: true }, result);
}
/**
* @template T, V
* @param {?} config
* @param {?} error
* @return {?}
*/
function buildActionFromError(config, error) {
return {
type: 'mutation',
options: config,
ok: false,
error,
};
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
class UpdateManager extends Store {
/**
* @param {?=} defs
*/
constructor(defs) {
super();
if (defs) {
this.add(defs);
}
}
/**
* @param {?} defs
* @return {?}
*/
add(defs) {
if (!Array.isArray(defs)) {
defs = [defs];
}
defs.forEach(def => {
/** @type {?} */
const all = this.get(def.mutation) || [];
all.push(def);
super.set(def.mutation, all);
});
}
/**
* @return {?}
*/
set() {
console.error('Use add() instead');
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
class ResolversManager extends Store {
/**
* @param {?=} defs
*/
constructor(defs) {
super();
if (defs) {
this.add(defs);
}
}
/**
* @param {?} defs
* @return {?}
*/
add(defs) {
defs.forEach(def => {
this.set(def.path, def);
});
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/** @type {?} */
const METADATA_KEY = '@@loona';
/**
* @param {?} target
* @return {?}
*/
function readMetadata(target) {
/** @type {?} */
const constructor = target.constructor;
return constructor[METADATA_KEY];
}
/**
* @param {?} target
* @return {?}
*/
function ensureMetadata(target) {
if (!target.hasOwnProperty(METADATA_KEY)) {
/** @type {?} */
const defaultValue = {
defaults: {},
mutations: [],
resolvers: [],
updates: [],
typeDefs: [],
effects: {},
};
Object.defineProperty(target, METADATA_KEY, {
value: defaultValue,
});
}
return target[METADATA_KEY];
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @param {?} proto
* @param {?} propName
* @param {?} mutation
* @return {?}
*/
function setMutationMetadata(proto, propName, mutation) {
/** @type {?} */
const constructor = proto.constructor;
/** @type {?} */
const meta = ensureMetadata(constructor);
meta.mutations.push({
propName,
mutation,
});
}
/**
* @param {?} target
* @param {?} propName
* @return {?}
*/
function hasMutation(target, propName) {
/** @type {?} */
const meta = readMetadata(target);
if (meta) {
return meta.mutations.some(def => {
return def.propName === propName;
});
}
return false;
}
/**
* @param {?} instance
* @param {?} meta
* @param {?=} transformFn
* @return {?}
*/
function transformMutations(instance, meta, transformFn = resolver => resolver) {
return meta.mutations.map(({ propName, mutation }) => ({
mutation: typeof mutation === 'string' ? mutation : getNameOfMutation(mutation),
resolve: transformFn(instance[propName].bind(instance)),
}));
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @param {?} proto
* @param {?} propName
* @param {?} mutation
* @return {?}
*/
function setUpdateMetadata(proto, propName, mutation) {
/** @type {?} */
const constructor = proto.constructor;
/** @type {?} */
const meta = ensureMetadata(constructor);
meta.updates.push({
propName,
mutation,
});
}
/**
* @param {?} instance
* @param {?} meta
* @param {?=} transformFn
* @return {?}
*/
function transformUpdates(instance, meta, transformFn = resolver => resolver) {
if (meta.updates) {
return meta.updates.map(({ propName, mutation }) => ({
mutation,
resolve: transformFn(instance[propName].bind(instance)),
}));
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @param {?} proto
* @param {?} propName
* @param {?} path
* @return {?}
*/
function setResolveMetadata(proto, propName, path) {
/** @type {?} */
const constructor = proto.constructor;
/** @type {?} */
const meta = ensureMetadata(constructor);
meta.resolvers.push({ propName, path });
}
/**
* @param {?} instance
* @param {?} meta
* @param {?=} transformFn
* @return {?}
*/
function transformResolvers(instance, meta, transformFn = resolver => resolver) {
return meta.resolvers.map(({ propName, path }) => ({
name: propName,
path,
resolve: transformFn(instance[propName].bind(instance)),
}));
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
class Manager {
/**
* @param {?} options
*/
constructor(options) {
this.getClient = () => {
throw new Error('Manager requires ApolloClient');
};
this.cache = options.cache;
this.defaults = options.defaults;
this.typeDefs = options.typeDefs;
this.resolvers = new ResolversManager(options.resolvers);
this.updates = new UpdateManager(options.updates);
this.mutations = new MutationManager(options.mutations);
if (options.getClient) {
this.getClient = options.getClient;
}
}
/**
* @param {?} instance
* @param {?} meta
* @param {?=} transformFn
* @return {?}
*/
addState(instance, meta, transformFn) {
this.mutations.add(transformMutations(instance, meta, transformFn));
this.updates.add(transformUpdates(instance, meta, transformFn) || []);
this.resolvers.add(transformResolvers(instance, meta, transformFn) || []);
if (meta.defaults) {
this.cache.writeData({
data: meta.defaults,
});
}
if (meta.typeDefs) {
if (!this.typeDefs) {
this.typeDefs = [];
}
if (typeof this.typeDefs === 'string') {
this.typeDefs = [this.typeDefs];
}
this.typeDefs.push(...(typeof meta.typeDefs === 'string'
? [meta.typeDefs]
: meta.typeDefs));
}
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @param {?} manager
* @return {?}
*/
function createMutationSchema(manager) {
/** @type {?} */
const schema = {};
manager.mutations.forEach((def, name) => {
schema[name] = createMutationResolver(def, manager);
});
return schema;
}
/**
* @param {?} def
* @param {?} manager
* @return {?}
*/
function createMutationResolver(def, manager) {
return (_, args, context) => __awaiter(this, void 0, void 0, function* () {
return def.resolve(args, buildContext(context, manager.getClient()));
});
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @param {?} manager
* @return {?}
*/
function createResolvers(manager) {
/** @type {?} */
const schema = {};
manager.resolvers.forEach(def => {
const [typeName, fieldName] = def.path.split('.');
if (!schema[typeName]) {
schema[typeName] = {};
}
schema[typeName][fieldName] = createResolver(def, manager);
});
return schema;
}
/**
* @param {?} def
* @param {?} manager
* @return {?}
*/
function createResolver(def, manager) {
return (parent, args, context) => def.resolve(parent, args, buildContext(context, manager.getClient()));
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @param {?} obj
* @return {?}
*/
function isManager(obj) {
return obj instanceof Manager;
}
class LoonaLink extends ApolloLink {
/**
* @param {?} optionsOrManager
*/
constructor(optionsOrManager) {
super();
if (isManager(optionsOrManager)) {
this.manager = optionsOrManager;
}
else {
this.manager = new Manager(optionsOrManager);
}
this.stateLink = withClientState({
cache: this.manager.cache,
resolvers: () => {
return Object.assign({ Mutation: createMutationSchema(this.manager) }, createResolvers(this.manager));
},
defaults: this.manager.defaults,
typeDefs: this.manager.typeDefs,
});
}
/**
* @param {?} operation
* @param {?} forward
* @return {?}
*/
request(operation, forward) {
return (/** @type {?} */ (this.stateLink.request(operation, forward)));
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @param {?} mutation
* @return {?}
*/
function Mutation(mutation) {
return function (target, name, _descriptor) {
setMutationMetadata(target, name, getMutation(mutation) || ((/** @type {?} */ (mutation))));
};
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @param {?} path
* @return {?}
*/
function Resolve(path) {
return function (target, name, _descriptor) {
setResolveMetadata(target, name, path);
};
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @param {?} target
* @param {?=} options
* @return {?}
*/
function setStateMetadata(target, options) {
/** @type {?} */
const meta = ensureMetadata(target);
if (typeof options !== 'undefined') {
meta.defaults = options.defaults;
meta.typeDefs = options.typeDefs;
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @template T
* @param {?=} options
* @return {?}
*/
function State(options) {
return (target) => {
setStateMetadata(target, options);
return target;
};
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @param {?} mutation
* @return {?}
*/
function Update(mutation) {
return function (target, name, _descriptor) {
/** @type {?} */
let mutationName;
if (isMutation(mutation)) {
/** @type {?} */
const document = getMutation(mutation);
if (!document) {
throw new Error(`Mutation ${((/** @type {?} */ (mutation))).name} is missing a static property 'mutation'`);
}
mutationName = getNameOfMutation(document);
}
else if (typeof mutation === 'string') {
mutationName = mutation;
}
else {
mutationName = getNameOfMutation(mutation);
}
setUpdateMetadata(target, name, mutationName);
};
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @param {?} proto
* @param {?} propName
* @param {?} effects
* @return {?}
*/
function setEffectMetadata(proto, propName, effects) {
/** @type {?} */
const constructor = proto.constructor;
/** @type {?} */
const meta = ensureMetadata(constructor);
for (const action of effects) {
/** @type {?} */
let type = undefined;
if (typeof action === 'string') {
type = action;
}
else if (isMutation(action)) {
type = mutationToType(action);
}
else if (isDocument(action)) {
type = getNameOfMutation(action);
}
else if (typeof action.type === 'string') {
type = action.type;
}
if (!type) {
throw new Error(`Loona couldn't figure out the type of the action`);
}
if (!meta.effects[type]) {
meta.effects[type] = [];
}
meta.effects[type].push({
propName,
type,
});
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @param {?} effects
* @return {?}
*/
function Effect(effects) {
return function (target, name, _descriptor) {
setEffectMetadata(target, name, Array.isArray(effects) ? effects : [effects]);
};
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
export { LoonaLink, Manager, Mutation, Resolve, State, Update, Effect, buildContext, buildGetCacheKey, getFragmentTypename, patchQuery, patchFragment, isDocument, isMutationAsAction, getActionType, readMetadata, ensureMetadata, METADATA_KEY, setMutationMetadata, hasMutation, transformMutations, setResolveMetadata, transformResolvers, setStateMetadata, setUpdateMetadata, transformUpdates, setEffectMetadata, mutationToType, getMutation, isMutation, getNameOfMutation, withUpdates, buildActionFromResult, buildActionFromError, MutationManager, Store as ɵb };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9vbmEuY29yZS5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vQGxvb25hL2NvcmUvaW50ZXJuYWwvc3RvcmUudHMiLCJuZzovL0Bsb29uYS9jb3JlL2ludGVybmFsL3V0aWxzLnRzIiwibmc6Ly9AbG9vbmEvY29yZS9oZWxwZXJzLnRzIiwibmc6Ly9AbG9vbmEvY29yZS9tdXRhdGlvbi50cyIsIm5nOi8vQGxvb25hL2NvcmUvdXBkYXRlLnRzIiwibmc6Ly9AbG9vbmEvY29yZS9yZXNvbHZlcnMudHMiLCJuZzovL0Bsb29uYS9jb3JlL21ldGFkYXRhL21ldGFkYXRhLnRzIiwibmc6Ly9AbG9vbmEvY29yZS9tZXRhZGF0YS9tdXRhdGlvbi50cyIsIm5nOi8vQGxvb25hL2NvcmUvbWV0YWRhdGEvdXBkYXRlLnRzIiwibmc6Ly9AbG9vbmEvY29yZS9tZXRhZGF0YS9yZXNvbHZlLnRzIiwibmc6Ly9AbG9vbmEvY29yZS9tYW5hZ2VyLnRzIiwibmc6Ly9AbG9vbmEvY29yZS9pbnRlcm5hbC9tdXRhdGlvbi50cyIsIm5nOi8vQGxvb25hL2NvcmUvaW50ZXJuYWwvcmVzb2x2ZXJzLnRzIiwibmc6Ly9AbG9vbmEvY29yZS9saW5rLnRzIiwibmc6Ly9AbG9vbmEvY29yZS9kZWNvcmF0b3JzL211dGF0aW9uLnRzIiwibmc6Ly9AbG9vbmEvY29yZS9kZWNvcmF0b3JzL3Jlc29sdmUudHMiLCJuZzovL0Bsb29uYS9jb3JlL21ldGFkYXRhL3N0YXRlLnRzIiwibmc6Ly9AbG9vbmEvY29yZS9kZWNvcmF0b3JzL3N0YXRlLnRzIiwibmc6Ly9AbG9vbmEvY29yZS9kZWNvcmF0b3JzL3VwZGF0ZS50cyIsIm5nOi8vQGxvb25hL2NvcmUvbWV0YWRhdGEvZWZmZWN0LnRzIiwibmc6Ly9AbG9vbmEvY29yZS9kZWNvcmF0b3JzL2VmZmVjdC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgY2xhc3MgU3RvcmU8VD4ge1xuICBzdG9yZTogTWFwPHN0cmluZywgVD47XG5cbiAgY29uc3RydWN0b3IoZGF0YTogUmVjb3JkPHN0cmluZywgVD4gPSB7fSkge1xuICAgIHRoaXMuc3RvcmUgPSBuZXcgTWFwKE9iamVjdC5lbnRyaWVzKGRhdGEpKTtcbiAgfVxuXG4gIGdldChrZXk6IHN0cmluZyk6IFQgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLnN0b3JlLmdldChrZXkpO1xuICB9XG5cbiAgc2V0KGtleTogc3RyaW5nLCB2YWx1ZTogVCk6IHZvaWQge1xuICAgIHRoaXMuc3RvcmUuc2V0KGtleSwgdmFsdWUpO1xuICB9XG5cbiAgZm9yRWFjaChmbjogKHZhbHVlOiBULCBrZXk6IHN0cmluZykgPT4gdm9pZCkge1xuICAgIHRoaXMuc3RvcmUuZm9yRWFjaChmbik7XG4gIH1cbn1cbiIsImltcG9ydCB7RG9jdW1lbnROb2RlLCBPcGVyYXRpb25EZWZpbml0aW9uTm9kZSwgRmllbGROb2RlfSBmcm9tICdncmFwaHFsJztcblxuZXhwb3J0IGZ1bmN0aW9uIGdldE11dGF0aW9uRGVmaW5pdGlvbihcbiAgZG9jOiBEb2N1bWVudE5vZGUsXG4pOiBPcGVyYXRpb25EZWZpbml0aW9uTm9kZSB7XG4gIGNvbnN0IGlzTXV0YXRpb24gPSAoZGVmOiBhbnkpOiBkZWYgaXMgT3BlcmF0aW9uRGVmaW5pdGlvbk5vZGUgPT5cbiAgICBkZWYua2luZCA9PT0gJ09wZXJhdGlvbkRlZmluaXRpb24nICYmIGRlZi5vcGVyYXRpb24gPT09ICdtdXRhdGlvbic7XG4gIGNvbnN0IGRlZnMgPSBkb2MuZGVmaW5pdGlvbnMuZmlsdGVyKGlzTXV0YXRpb24pO1xuXG4gIGlmICghZGVmcyB8fCAhZGVmc1swXSkge1xuICAgIHRocm93IG5ldyBFcnJvcignTXVzdCBjb250YWluIGEgbXV0YXRpb24gZGVmaW5pdGlvbi4nKTtcbiAgfVxuXG4gIHJldHVybiBkZWZzWzBdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0Rmlyc3RGaWVsZChkZWY6IE9wZXJhdGlvbkRlZmluaXRpb25Ob2RlKTogRmllbGROb2RlIHtcbiAgcmV0dXJuIGRlZi5zZWxlY3Rpb25TZXQuc2VsZWN0aW9uc1swXSBhcyBGaWVsZE5vZGU7XG59XG4iLCJpbXBvcnQge0RvY3VtZW50Tm9kZSwgRnJhZ21lbnREZWZpbml0aW9uTm9kZX0gZnJvbSAnZ3JhcGhxbCc7XG5pbXBvcnQge0Fwb2xsb0NsaWVudH0gZnJvbSAnYXBvbGxvLWNsaWVudCc7XG5pbXBvcnQge0RhdGFQcm94eX0gZnJvbSAnYXBvbGxvLWNhY2hlJztcbmltcG9ydCBwcm9kdWNlIGZyb20gJ2ltbWVyJztcblxuaW1wb3J0IHtSZWNlaXZlZENvbnRleHQsIENvbnRleHR9IGZyb20gJy4vdHlwZXMvY29tbW9uJztcbmltcG9ydCB7QWN0aW9uLCBNdXRhdGlvbkFzQWN0aW9ufSBmcm9tICcuL3R5cGVzL2VmZmVjdCc7XG5cbmV4cG9ydCBmdW5jdGlvbiBidWlsZENvbnRleHQoXG4gIGNvbnRleHQ6IFJlY2VpdmVkQ29udGV4dCxcbiAgY2xpZW50OiBBcG9sbG9DbGllbnQ8YW55Pixcbik6IENvbnRleHQge1xuICByZXR1cm4ge1xuICAgIC4uLmNvbnRleHQsXG4gICAgcGF0Y2hRdWVyeTogcGF0Y2hRdWVyeShjbGllbnQpLFxuICAgIHBhdGNoRnJhZ21lbnQ6IHBhdGNoRnJhZ21lbnQoY29udGV4dCwgY2xpZW50KSxcbiAgICB3cml0ZURhdGEob3B0aW9uczogRGF0YVByb3h5LldyaXRlRGF0YU9wdGlvbnM8YW55Pikge1xuICAgICAgcmV0dXJuIGNsaWVudC53cml0ZURhdGEob3B0aW9ucyk7XG4gICAgfSxcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkR2V0Q2FjaGVLZXkoY2FjaGU6IGFueSkge1xuICByZXR1cm4gKG9iajoge19fdHlwZW5hbWU6IHN0cmluZzsgaWQ6IHN0cmluZyB8IG51bWJlcn0pID0+IHtcbiAgICBpZiAoKGNhY2hlIGFzIGFueSkuY29uZmlnKSB7XG4gICAgICByZXR1cm4gKGNhY2hlIGFzIGFueSkuY29uZmlnLmRhdGFJZEZyb21PYmplY3Qob2JqKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnVG8gdXNlIGNvbnRleHQuZ2V0Q2FjaGVLZXksIHlvdSBuZWVkIHRvIHVzZSBhIGNhY2hlIHRoYXQgaGFzIGEgY29uZmlndXJhYmxlIGRhdGFJZEZyb21PYmplY3QsIGxpa2UgYXBvbGxvLWNhY2hlLWlubWVtb3J5LicsXG4gICAgICApO1xuICAgIH1cbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEZyYWdtZW50VHlwZW5hbWUoZnJhZ21lbnQ6IERvY3VtZW50Tm9kZSk6IHN0cmluZyB7XG4gIGNvbnN0IGRlZiA9IGZyYWdtZW50LmRlZmluaXRpb25zLmZpbmQoXG4gICAgZGVmID0+IGRlZi5raW5kID09PSAnRnJhZ21lbnREZWZpbml0aW9uJyxcbiAgKSBhcyBGcmFnbWVudERlZmluaXRpb25Ob2RlO1xuXG4gIHJldHVybiBkZWYudHlwZUNvbmRpdGlvbi5uYW1lLnZhbHVlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGF0Y2hRdWVyeShjbGllbnQ6IEFwb2xsb0NsaWVudDxhbnk+KSB7XG4gIHJldHVybiA8UiA9IGFueT4oXG4gICAgcXVlcnk6XG4gICAgICB8IERvY3VtZW50Tm9kZVxuICAgICAgfCB7XG4gICAgICAgICAgcXVlcnk6IERvY3VtZW50Tm9kZTtcbiAgICAgICAgICB2YXJpYWJsZXM6IHtcbiAgICAgICAgICAgIFtrZXk6IHN0cmluZ106IGFueTtcbiAgICAgICAgICB9O1xuICAgICAgICB9LFxuICAgIHBhdGNoRm46IChkYXRhOiBSKSA9PiBhbnksXG4gICk6IFIgPT4ge1xuICAgIGNvbnN0IG9wdGlvbnMgPSBpc0RvY3VtZW50KHF1ZXJ5KSA/IHtxdWVyeX0gOiBxdWVyeTtcbiAgICBjb25zdCBvYmo6IGFueSA9IGNsaWVudC5yZWFkUXVlcnkob3B0aW9ucyk7XG4gICAgY29uc3QgZGF0YSA9IHByb2R1Y2Uob2JqLCBwYXRjaEZuKTtcblxuICAgIGNsaWVudC53cml0ZVF1ZXJ5KHtcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgICBkYXRhLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIGRhdGE7XG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXRjaEZyYWdtZW50KFxuICBjb250ZXh0OiBSZWNlaXZlZENvbnRleHQsXG4gIGNsaWVudDogQXBvbGxvQ2xpZW50PGFueT4sXG4pIHtcbiAgcmV0dXJuIDxSID0gYW55PihcbiAgICBmcmFnbWVudDogRG9jdW1lbnROb2RlLFxuICAgIG9iajogYW55LFxuICAgIHBhdGNoRm46IChkYXRhOiBSKSA9PiBhbnksXG4gICk6IFIgPT4ge1xuICAgIGNvbnN0IF9fdHlwZW5hbWUgPSBnZXRGcmFnbWVudFR5cGVuYW1lKGZyYWdtZW50KTtcbiAgICBjb25zdCBpZCA9IGNvbnRleHQuZ2V0Q2FjaGVLZXkoe1xuICAgICAgLi4ub2JqLFxuICAgICAgX190eXBlbmFtZSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGZyZ210OiBhbnkgPSBjbGllbnQucmVhZEZyYWdtZW50KHtcbiAgICAgIGZyYWdtZW50LFxuICAgICAgaWQsXG4gICAgfSk7XG4gICAgY29uc3QgZGF0YSA9IHByb2R1Y2UoZnJnbXQsIHBhdGNoRm4pO1xuXG4gICAgY2xpZW50LndyaXRlRnJhZ21lbnQoe1xuICAgICAgZnJhZ21lbnQsXG4gICAgICBpZCxcbiAgICAgIGRhdGE6IHtcbiAgICAgICAgLi4uZGF0YSxcbiAgICAgICAgX190eXBlbmFtZSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICByZXR1cm4gZGF0YTtcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzRG9jdW1lbnQoZG9jOiBhbnkpOiBkb2MgaXMgRG9jdW1lbnROb2RlIHtcbiAgcmV0dXJuIGRvYyAmJiBkb2Mua2luZCA9PT0gJ0RvY3VtZW50Jztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzTXV0YXRpb25Bc0FjdGlvbihhY3Rpb246IEFjdGlvbik6IGFjdGlvbiBpcyBNdXRhdGlvbkFzQWN0aW9uIHtcbiAgcmV0dXJuIGFjdGlvbi50eXBlID09PSAnbXV0YXRpb24nO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0QWN0aW9uVHlwZShhY3Rpb246IGFueSk6IHN0cmluZyB7XG4gIGlmIChhY3Rpb24uY29uc3RydWN0b3IgJiYgYWN0aW9uLmNvbnN0cnVjdG9yLnR5cGUpIHtcbiAgICByZXR1cm4gYWN0aW9uLmNvbnN0cnVjdG9yLnR5cGU7XG4gIH1cblxuICByZXR1cm4gYWN0aW9uLnR5cGU7XG59XG4iLCJpbXBvcnQge0RvY3VtZW50Tm9kZSwgR3JhcGhRTEVycm9yfSBmcm9tICdncmFwaHFsJztcbmltcG9ydCB7TXV0YXRpb25PcHRpb25zfSBmcm9tICdhcG9sbG8tY2xpZW50JztcbmltcG9ydCB7RmV0Y2hSZXN1bHR9IGZyb20gJ2Fwb2xsby1saW5rJztcblxuaW1wb3J0IHtNdXRhdGlvbkRlZiwgTXV0YXRpb25PYmplY3R9IGZyb20gJy4vdHlwZXMvbXV0YXRpb24nO1xuaW1wb3J0IHtTdG9yZX0gZnJvbSAnLi9pbnRlcm5hbC9zdG9yZSc7XG5pbXBvcnQge2dldE11dGF0aW9uRGVmaW5pdGlvbiwgZ2V0Rmlyc3RGaWVsZH0gZnJvbSAnLi9pbnRlcm5hbC91dGlscyc7XG5pbXBvcnQge01hbmFnZXJ9IGZyb20gJy4vbWFuYWdlcic7XG5pbXBvcnQge2J1aWxkQ29udGV4dCwgYnVpbGRHZXRDYWNoZUtleX0gZnJvbSAnLi9oZWxwZXJzJztcblxuZXhwb3J0IGNsYXNzIE11dGF0aW9uTWFuYWdlciBleHRlbmRzIFN0b3JlPE11dGF0aW9uRGVmPiB7XG4gIGNvbnN0cnVjdG9yKGRlZnM/OiBNdXRhdGlvbkRlZltdKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGlmIChkZWZzKSB7XG4gICAgICBkZWZzLmZvckVhY2goZGVmID0+IHtcbiAgICAgICAgdGhpcy5zZXQoZGVmLm11dGF0aW9uLCBkZWYpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgYWRkKGRlZnM6IE11dGF0aW9uRGVmW10pOiB2b2lkIHtcbiAgICBkZWZzLmZvckVhY2goZGVmID0+IHtcbiAgICAgIHRoaXMuc2V0KGRlZi5tdXRhdGlvbiwgZGVmKTtcbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbXV0YXRpb25Ub1R5cGUoYWN0aW9uOiBNdXRhdGlvbk9iamVjdCk6IHN0cmluZyB7XG4gIGNvbnN0IG11dGF0aW9uID0gZ2V0TXV0YXRpb24oYWN0aW9uKTtcbiAgY29uc3QgbmFtZSA9IGdldE5hbWVPZk11dGF0aW9uKG11dGF0aW9uKTtcblxuICByZXR1cm4gbmFtZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldE11dGF0aW9uKGFjdGlvbjogYW55KTogRG9jdW1lbnROb2RlIHtcbiAgaWYgKGFjdGlvbi5jb25zdHJ1Y3RvciAmJiBhY3Rpb24uY29uc3RydWN0b3IubXV0YXRpb24pIHtcbiAgICByZXR1cm4gYWN0aW9uLmNvbnN0cnVjdG9yLm11dGF0aW9uO1xuICB9XG5cbiAgcmV0dXJuIGFjdGlvbi5tdXRhdGlvbjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzTXV0YXRpb24oYWN0aW9uOiBhbnkpOiBhY3Rpb24gaXMgTXV0YXRpb25PYmplY3Qge1xuICByZXR1cm4gdHlwZW9mIGdldE11dGF0aW9uKGFjdGlvbikgIT09ICd1bmRlZmluZWQnO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TmFtZU9mTXV0YXRpb24obXV0YXRpb246IERvY3VtZW50Tm9kZSk6IHN0cmluZyB7XG4gIGNvbnN0IGRlZiA9IGdldE11dGF0aW9uRGVmaW5pdGlvbihtdXRhdGlvbik7XG4gIGNvbnN0IGZpZWxkID0gZ2V0Rmlyc3RGaWVsZChkZWYpO1xuXG4gIHJldHVybiBmaWVsZC5uYW1lLnZhbHVlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gd2l0aFVwZGF0ZXM8VCwgVj4oXG4gIGNvbmZpZzogTXV0YXRpb25PcHRpb25zPGFueSwgVj4sXG4gIG1hbmFnZXI6IE1hbmFnZXIsXG4pOiBNdXRhdGlvbk9wdGlvbnM8YW55LCBWPiB7XG4gIGNvbnN0IG9yZ1VwZGF0ZSA9IGNvbmZpZy51cGRhdGU7XG5cbiAgcmV0dXJuIHtcbiAgICAuLi5jb25maWcsXG4gICAgdXBkYXRlOiAocHJveHksIG11dGF0aW9uUmVzdWx0OiBGZXRjaFJlc3VsdDxUPikgPT4ge1xuICAgICAgY29uc3QgbmFtZSA9IGdldE5hbWVPZk11dGF0aW9uKGNvbmZpZy5tdXRhdGlvbik7XG4gICAgICBjb25zdCByZXN1bHQ6IFQgPSBtdXRhdGlvblJlc3VsdC5kYXRhICYmIG11dGF0aW9uUmVzdWx0LmRhdGFbbmFtZV07XG4gICAgICBjb25zdCBjYWNoZSA9IG1hbmFnZXIuY2FjaGU7XG5cbiAgICAgIGNvbnN0IGNvbnRleHQgPSBidWlsZENvbnRleHQoXG4gICAgICAgIHtcbiAgICAgICAgICBjYWNoZTogcHJveHksXG4gICAgICAgICAgZ2V0Q2FjaGVLZXk6IGJ1aWxkR2V0Q2FjaGVLZXkoY2FjaGUpLFxuICAgICAgICB9LFxuICAgICAgICBtYW5hZ2VyLmdldENsaWVudCgpLFxuICAgICAgKTtcblxuICAgICAgY29uc3QgdXBkYXRlcyA9IG1hbmFnZXIudXBkYXRlcy5nZXQobmFtZSk7XG5cbiAgICAgIGlmICh1cGRhdGVzKSB7XG4gICAgICAgIGNvbnN0IGluZm8gPSB7XG4gICAgICAgICAgbmFtZSxcbiAgICAgICAgICB2YXJpYWJsZXM6IGNvbmZpZy52YXJpYWJsZXMsXG4gICAgICAgICAgcmVzdWx0LFxuICAgICAgICB9O1xuXG4gICAgICAgIHVwZGF0ZXMuZm9yRWFjaChkZWYgPT4gZGVmLnJlc29sdmUoaW5mbywgY29udGV4dCkpO1xuICAgICAgfVxuXG4gICAgICBpZiAob3JnVXBkYXRlKSB7XG4gICAgICAgIG9yZ1VwZGF0ZShwcm94eSwgbXV0YXRpb25SZXN1bHQpO1xuICAgICAgfVxuICAgIH0sXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBidWlsZEFjdGlvbkZyb21SZXN1bHQ8VCwgVj4oXG4gIGNvbmZpZzogTXV0YXRpb25PcHRpb25zPFQsIFY+LFxuICByZXN1bHQ6IEZldGNoUmVzdWx0PFQ+LFxuKToge1xuICB0eXBlOiBzdHJpbmc7XG4gIG9wdGlvbnM6IE11dGF0aW9uT3B0aW9uczxULCBWPjtcbiAgb2s6IGJvb2xlYW47XG4gIGVycm9ycz86IFJlYWRvbmx5QXJyYXk8R3JhcGhRTEVycm9yPjtcbiAgZGF0YT86IFQgfCB7W2tleTogc3RyaW5nXTogYW55fTtcbiAgZXh0ZW5zaW9ucz86IFJlY29yZDxzdHJpbmcsIGFueT47XG4gIGNvbnRleHQ/OiBhbnk7XG59IHtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiAnbXV0YXRpb24nLFxuICAgIG9wdGlvbnM6IGNvbmZpZyxcbiAgICBvazogdHJ1ZSxcbiAgICAuLi5yZXN1bHQsXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBidWlsZEFjdGlvbkZyb21FcnJvcjxULCBWPihcbiAgY29uZmlnOiBNdXRhdGlvbk9wdGlvbnM8VCwgVj4sXG4gIGVycm9yOiBhbnksXG4pIHtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiAnbXV0YXRpb24nLFxuICAgIG9wdGlvbnM6IGNvbmZpZyxcbiAgICBvazogZmFsc2UsXG4gICAgZXJyb3IsXG4gIH07XG59XG4iLCJpbXBvcnQge1N0b3JlfSBmcm9tICcuL2ludGVybmFsL3N0b3JlJztcbmltcG9ydCB7VXBkYXRlRGVmfSBmcm9tICcuL3R5cGVzL3VwZGF0ZSc7XG5cbmV4cG9ydCBjbGFzcyBVcGRhdGVNYW5hZ2VyIGV4dGVuZHMgU3RvcmU8VXBkYXRlRGVmW10+IHtcbiAgY29uc3RydWN0b3IoZGVmcz86IFVwZGF0ZURlZltdKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGlmIChkZWZzKSB7XG4gICAgICB0aGlzLmFkZChkZWZzKTtcbiAgICB9XG4gIH1cblxuICBhZGQoZGVmczogVXBkYXRlRGVmW10gfCBVcGRhdGVEZWYpOiB2b2lkIHtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoZGVmcykpIHtcbiAgICAgIGRlZnMgPSBbZGVmc107XG4gICAgfVxuXG4gICAgZGVmcy5mb3JFYWNoKGRlZiA9PiB7XG4gICAgICBjb25zdCBhbGwgPSB0aGlzLmdldChkZWYubXV0YXRpb24pIHx8IFtdO1xuXG4gICAgICBhbGwucHVzaChkZWYpO1xuXG4gICAgICBzdXBlci5zZXQoZGVmLm11dGF0aW9uLCBhbGwpO1xuICAgIH0pO1xuICB9XG5cbiAgc2V0KCkge1xuICAgIGNvbnNvbGUuZXJyb3IoJ1VzZSBhZGQoKSBpbnN0ZWFkJyk7XG4gIH1cbn1cbiIsImltcG9ydCB7U3RvcmV9IGZyb20gJy4vaW50ZXJuYWwvc3RvcmUnO1xuaW1wb3J0IHtSZXNvbHZlckRlZn0gZnJvbSAnLi90eXBlcy9yZXNvbHZlcic7XG5cbmV4cG9ydCBjbGFzcyBSZXNvbHZlcnNNYW5hZ2VyIGV4dGVuZHMgU3RvcmU8UmVzb2x2ZXJEZWY+IHtcbiAgY29uc3RydWN0b3IoZGVmcz86IFJlc29sdmVyRGVmW10pIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKGRlZnMpIHtcbiAgICAgIHRoaXMuYWRkKGRlZnMpO1xuICAgIH1cbiAgfVxuXG4gIGFkZChkZWZzOiBSZXNvbHZlckRlZltdKTogdm9pZCB7XG4gICAgZGVmcy5mb3JFYWNoKGRlZiA9PiB7XG4gICAgICB0aGlzLnNldChkZWYucGF0aCwgZGVmKTtcbiAgICB9KTtcbiAgfVxufVxuIiwiaW1wb3J0IHtNZXRhZGF0YX0gZnJvbSAnLi4vdHlwZXMvbWV0YWRhdGEnO1xuXG5leHBvcnQgY29uc3QgTUVUQURBVEFfS0VZID0gJ0BAbG9vbmEnO1xuXG5leHBvcnQgZnVuY3Rpb24gcmVhZE1ldGFkYXRhKHRhcmdldDogYW55KTogTWV0YWRhdGEge1xuICBjb25zdCBjb25zdHJ1Y3RvciA9IHRhcmdldC5jb25zdHJ1Y3RvcjtcblxuICByZXR1cm4gY29uc3RydWN0b3JbTUVUQURBVEFfS0VZXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGVuc3VyZU1ldGFkYXRhKHRhcmdldDogYW55KTogTWV0YWRhdGEge1xuICBpZiAoIXRhcmdldC5oYXNPd25Qcm9wZXJ0eShNRVRBREFUQV9LRVkpKSB7XG4gICAgY29uc3QgZGVmYXVsdFZhbHVlOiBNZXRhZGF0YSA9IHtcbiAgICAgIGRlZmF1bHRzOiB7fSxcbiAgICAgIG11dGF0aW9uczogW10sXG4gICAgICByZXNvbHZlcnM6IFtdLFxuICAgICAgdXBkYXRlczogW10sXG4gICAgICB0eXBlRGVmczogW10sXG4gICAgICBlZmZlY3RzOiB7fSxcbiAgICB9O1xuXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgTUVUQURBVEFfS0VZLCB7XG4gICAgICB2YWx1ZTogZGVmYXVsdFZhbHVlLFxuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHRhcmdldFtNRVRBREFUQV9LRVldO1xufVxuIiwiaW1wb3J0IHtEb2N1bWVudE5vZGV9IGZyb20gJ2dyYXBocWwnO1xuXG5pbXBvcnQge2Vuc3VyZU1ldGFkYXRhLCByZWFkTWV0YWRhdGF9IGZyb20gJy4vbWV0YWRhdGEnO1xuaW1wb3J0IHtNZXRhZGF0YX0gZnJvbSAnLi4vdHlwZXMvbWV0YWRhdGEnO1xuaW1wb3J0IHtNdXRhdGlvbkRlZiwgTXV0YXRpb25SZXNvbHZlRm59IGZyb20gJy4uL3R5cGVzL211dGF0aW9uJztcbmltcG9ydCB7Z2V0TmFtZU9mTXV0YXRpb259IGZyb20gJy4uL211dGF0aW9uJztcblxuZXhwb3J0IGZ1bmN0aW9uIHNldE11dGF0aW9uTWV0YWRhdGEoXG4gIHByb3RvOiBhbnksXG4gIHByb3BOYW1lOiBzdHJpbmcsXG4gIG11dGF0aW9uOiBEb2N1bWVudE5vZGUgfCBzdHJpbmcsXG4pIHtcbiAgY29uc3QgY29uc3RydWN0b3IgPSBwcm90by5jb25zdHJ1Y3RvcjtcbiAgY29uc3QgbWV0YSA9IGVuc3VyZU1ldGFkYXRhKGNvbnN0cnVjdG9yKTtcblxuICBtZXRhLm11dGF0aW9ucy5wdXNoKHtcbiAgICBwcm9wTmFtZSxcbiAgICBtdXRhdGlvbixcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBoYXNNdXRhdGlvbih0YXJnZXQ6IGFueSwgcHJvcE5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBjb25zdCBtZXRhID0gcmVhZE1ldGFkYXRhKHRhcmdldCk7XG5cbiAgaWYgKG1ldGEpIHtcbiAgICByZXR1cm4gbWV0YS5tdXRhdGlvbnMuc29tZShkZWYgPT4ge1xuICAgICAgcmV0dXJuIGRlZi5wcm9wTmFtZSA9PT0gcHJvcE5hbWU7XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2Zvcm1NdXRhdGlvbnMoXG4gIGluc3RhbmNlOiBhbnksXG4gIG1ldGE6IE1ldGFkYXRhLFxuICB0cmFuc2Zvcm1GbjogKChyZXNvbHZlcjogYW55KSA9PiBNdXRhdGlvblJlc29sdmVGbikgPSByZXNvbHZlciA9PiByZXNvbHZlcixcbik6IE11dGF0aW9uRGVmW10ge1xuICByZXR1cm4gbWV0YS5tdXRhdGlvbnMubWFwKCh7cHJvcE5hbWUsIG11dGF0aW9ufSkgPT4gKHtcbiAgICBtdXRhdGlvbjpcbiAgICAgIHR5cGVvZiBtdXRhdGlvbiA9PT0gJ3N0cmluZycgPyBtdXRhdGlvbiA6IGdldE5hbWVPZk11dGF0aW9uKG11dGF0aW9uKSxcbiAgICByZXNvbHZlOiB0cmFuc2Zvcm1GbihpbnN0YW5jZVtwcm9wTmFtZV0uYmluZChpbnN0YW5jZSkpLFxuICB9KSk7XG59XG4iLCJpbXBvcnQge1VwZGF0ZURlZiwgVXBkYXRlUmVzb2x2ZUZufSBmcm9tICcuLi90eXBlcy91cGRhdGUnO1xuaW1wb3J0IHtNZXRhZGF0YX0gZnJvbSAnLi4vdHlwZXMvbWV0YWRhdGEnO1xuaW1wb3J0IHtlbnN1cmVNZXRhZGF0YX0gZnJvbSAnLi9tZXRhZGF0YSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRVcGRhdGVNZXRhZGF0YShcbiAgcHJvdG86IGFueSxcbiAgcHJvcE5hbWU6IHN0cmluZyxcbiAgbXV0YXRpb246IHN0cmluZyxcbikge1xuICBjb25zdCBjb25zdHJ1Y3RvciA9IHByb3RvLmNvbnN0cnVjdG9yO1xuICBjb25zdCBtZXRhID0gZW5zdXJlTWV0YWRhdGEoY29uc3RydWN0b3IpO1xuXG4gIG1ldGEudXBkYXRlcy5wdXNoKHtcbiAgICBwcm9wTmFtZSxcbiAgICBtdXRhdGlvbixcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2Zvcm1VcGRhdGVzKFxuICBpbnN0YW5jZTogYW55LFxuICBtZXRhOiBNZXRhZGF0YSxcbiAgdHJhbnNmb3JtRm46ICgocmVzb2x2ZXI6IGFueSkgPT4gVXBkYXRlUmVzb2x2ZUZuKSA9IHJlc29sdmVyID0+IHJlc29sdmVyLFxuKTogVXBkYXRlRGVmW10gfCB1bmRlZmluZWQge1xuICBpZiAobWV0YS51cGRhdGVzKSB7XG4gICAgcmV0dXJuIG1ldGEudXBkYXRlcy5tYXAoKHtwcm9wTmFtZSwgbXV0YXRpb259KSA9PiAoe1xuICAgICAgbXV0YXRpb24sXG4gICAgICByZXNvbHZlOiB0cmFuc2Zvcm1GbihpbnN0YW5jZVtwcm9wTmFtZV0uYmluZChpbnN0YW5jZSkpLFxuICAgIH0pKTtcbiAgfVxufVxuIiwiaW1wb3J0IHtlbnN1cmVNZXRhZGF0YX0gZnJvbSAnLi9tZXRhZGF0YSc7XG5pbXBvcnQge01ldGFkYXRhfSBmcm9tICcuLi90eXBlcy9tZXRhZGF0YSc7XG5pbXBvcnQge1Jlc29sdmVyRGVmfSBmcm9tICcuLi90eXBlcy9yZXNvbHZlcic7XG5pbXBvcnQge1Jlc29sdmVGbn0gZnJvbSAnLi4vdHlwZXMvY29tbW9uJztcblxuZXhwb3J0IGZ1bmN0aW9uIHNldFJlc29sdmVNZXRhZGF0YShwcm90bzogYW55LCBwcm9wTmFtZTogc3RyaW5nLCBwYXRoOiBzdHJpbmcpIHtcbiAgY29uc3QgY29uc3RydWN0b3IgPSBwcm90by5jb25zdHJ1Y3RvcjtcbiAgY29uc3QgbWV0YSA9IGVuc3VyZU1ldGFkYXRhKGNvbnN0cnVjdG9yKTtcblxuICBtZXRhLnJlc29sdmVycy5wdXNoKHtwcm9wTmFtZSwgcGF0aH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdHJhbnNmb3JtUmVzb2x2ZXJzKFxuICBpbnN0YW5jZTogYW55LFxuICBtZXRhOiBNZXRhZGF0YSxcbiAgdHJhbnNmb3JtRm46ICgocmVzb2x2ZXI6IGFueSkgPT4gUmVzb2x2ZUZuKSA9IHJlc29sdmVyID0+IHJlc29sdmVyLFxuKTogUmVzb2x2ZXJEZWZbXSB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiBtZXRhLnJlc29sdmVycy5tYXAoKHtwcm9wTmFtZSwgcGF0aH0pID0+ICh7XG4gICAgbmFtZTogcHJvcE5hbWUsXG4gICAgcGF0aCxcbiAgICByZXNvbHZlOiB0cmFuc2Zvcm1GbihpbnN0YW5jZVtwcm9wTmFtZV0uYmluZChpbnN0YW5jZSkpLFxuICB9KSk7XG59XG4iLCJpbXBvcnQge0Fwb2xsb0NsaWVudH0gZnJvbSAnYXBvbGxvLWNsaWVudCc7XG5pbXBvcnQge0Fwb2xsb0NhY2hlfSBmcm9tICdhcG9sbG8tY2FjaGUnO1xuXG5pbXBvcnQge011dGF0aW9uTWFuYWdlcn0gZnJvbSAnLi9tdXRhdGlvbic7XG5pbXBvcnQge1VwZGF0ZU1hbmFnZXJ9IGZyb20gJy4vdXBkYXRlJztcbmltcG9ydCB7UmVzb2x2ZXJzTWFuYWdlcn0gZnJvbSAnLi9yZXNvbHZlcnMnO1xuaW1wb3J0IHtPcHRpb25zfSBmcm9tICcuL3R5cGVzL29wdGlvbnMnO1xuaW1wb3J0IHtNZXRhZGF0YX0gZnJvbSAnLi90eXBlcy9tZXRhZGF0YSc7XG5pbXBvcnQge3RyYW5zZm9ybU11dGF0aW9uc30gZnJvbSAnLi9tZXRhZGF0YS9tdXRhdGlvbic7XG5pbXBvcnQge3RyYW5zZm9ybVVwZGF0ZXN9IGZyb20gJy4vbWV0YWRhdGEvdXBkYXRlJztcbmltcG9ydCB7dHJhbnNmb3JtUmVzb2x2ZXJzfSBmcm9tICcuL21ldGFkYXRhL3Jlc29sdmUnO1xuXG5leHBvcnQgY2xhc3MgTWFuYWdlciB7XG4gIGNhY2hlOiBBcG9sbG9DYWNoZTxhbnk+O1xuICBtdXRhdGlvbnM6IE11dGF0aW9uTWFuYWdlcjtcbiAgdXBkYXRlczogVXBkYXRlTWFuYWdlcjtcbiAgcmVzb2x2ZXJzOiBSZXNvbHZlcnNNYW5hZ2VyO1xuICBkZWZhdWx0czogYW55O1xuICB0eXBlRGVmczogc3RyaW5nIHwgc3RyaW5nW10gfCB1bmRlZmluZWQ7XG4gIGdldENsaWVudDogKCkgPT4gQXBvbGxvQ2xpZW50PGFueT4gfCBuZXZlciA9ICgpID0+IHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01hbmFnZXIgcmVxdWlyZXMgQXBvbGxvQ2xpZW50Jyk7XG4gIH07XG5cbiAgY29uc3RydWN0b3Iob3B0aW9uczogT3B0aW9ucykge1xuICAgIHRoaXMuY2FjaGUgPSBvcHRpb25zLmNhY2hlO1xuICAgIHRoaXMuZGVmYXVsdHMgPSBvcHRpb25zLmRlZmF1bHRzO1xuICAgIHRoaXMudHlwZURlZnMgPSBvcHRpb25zLnR5cGVEZWZzO1xuICAgIHRoaXMucmVzb2x2ZXJzID0gbmV3IFJlc29sdmVyc01hbmFnZXIob3B0aW9ucy5yZXNvbHZlcnMpO1xuICAgIHRoaXMudXBkYXRlcyA9IG5ldyBVcGRhdGVNYW5hZ2VyKG9wdGlvbnMudXBkYXRlcyk7XG4gICAgdGhpcy5tdXRhdGlvbnMgPSBuZXcgTXV0YXRpb25NYW5hZ2VyKG9wdGlvbnMubXV0YXRpb25zKTtcblxuICAgIGlmIChvcHRpb25zLmdldENsaWVudCkge1xuICAgICAgdGhpcy5nZXRDbGllbnQgPSBvcHRpb25zLmdldENsaWVudDtcbiAgICB9XG4gIH1cblxuICBhZGRTdGF0ZShcbiAgICBpbnN0YW5jZTogYW55LFxuICAgIG1ldGE6IE1ldGFkYXRhLFxuICAgIHRyYW5zZm9ybUZuPzogKChyZXNvbHZlcjogYW55KSA9PiBhbnkpLFxuICApIHtcbiAgICB0aGlzLm11dGF0aW9ucy5hZGQodHJhbnNmb3JtTXV0YXRpb25zKGluc3RhbmNlLCBtZXRhLCB0cmFuc2Zvcm1GbikpO1xuICAgIHRoaXMudXBkYXRlcy5hZGQodHJhbnNmb3JtVXBkYXRlcyhpbnN0YW5jZSwgbWV0YSwgdHJhbnNmb3JtRm4pIHx8IFtdKTtcbiAgICB0aGlzLnJlc29sdmVycy5hZGQodHJhbnNmb3JtUmVzb2x2ZXJzKGluc3RhbmNlLCBtZXRhLCB0cmFuc2Zvcm1GbikgfHwgW10pO1xuXG4gICAgaWYgKG1ldGEuZGVmYXVsdHMpIHtcbiAgICAgIHRoaXMuY2FjaGUud3JpdGVEYXRhKHtcbiAgICAgICAgZGF0YTogbWV0YS5kZWZhdWx0cyxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmIChtZXRhLnR5cGVEZWZzKSB7XG4gICAgICBpZiAoIXRoaXMudHlwZURlZnMpIHtcbiAgICAgICAgdGhpcy50eXBlRGVmcyA9IFtdO1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIHRoaXMudHlwZURlZnMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRoaXMudHlwZURlZnMgPSBbdGhpcy50eXBlRGVmc107XG4gICAgICB9XG5cbiAgICAgIHRoaXMudHlwZURlZnMucHVzaChcbiAgICAgICAgLi4uKHR5cGVvZiBtZXRhLnR5cGVEZWZzID09PSAnc3RyaW5nJ1xuICAgICAgICAgID8gW21ldGEudHlwZURlZnNdXG4gICAgICAgICAgOiBtZXRhLnR5cGVEZWZzKSxcbiAgICAgICk7XG4gICAgfVxuICB9XG59XG4iLCJpbXBvcnQge011dGF0aW9uU2NoZW1hLCBNdXRhdGlvbkRlZn0gZnJvbSAnLi4vdHlwZXMvbXV0YXRpb24nO1xuaW1wb3J0IHtSZXNvbHZlRm59IGZyb20gJy4uL3R5cGVzL2NvbW1vbic7XG5pbXBvcnQge01hbmFnZXJ9IGZyb20gJy4uL21hbmFnZXInO1xuaW1wb3J0IHtidWlsZENvbnRleHR9IGZyb20gJy4uL2hlbHBlcnMnO1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlTXV0YXRpb25TY2hlbWEobWFuYWdlcjogTWFuYWdlcik6IE11dGF0aW9uU2NoZW1hIHtcbiAgY29uc3Qgc2NoZW1hOiBNdXRhdGlvblNjaGVtYSA9IHt9O1xuXG4gIG1hbmFnZXIubXV0YXRpb25zLmZvckVhY2goKGRlZiwgbmFtZSkgPT4ge1xuICAgIHNjaGVtYVtuYW1lXSA9IGNyZWF0ZU11dGF0aW9uUmVzb2x2ZXIoZGVmLCBtYW5hZ2VyKTtcbiAgfSk7XG5cbiAgcmV0dXJuIHNjaGVtYTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlTXV0YXRpb25SZXNvbHZlcihkZWY6IE11dGF0aW9uRGVmLCBtYW5hZ2VyOiBNYW5hZ2VyKTogUmVzb2x2ZUZuIHtcbiAgcmV0dXJuIGFzeW5jIChfLCBhcmdzLCBjb250ZXh0KSA9PiB7XG4gICAgcmV0dXJuIGRlZi5yZXNvbHZlKGFyZ3MsIGJ1aWxkQ29udGV4dChjb250ZXh0LCBtYW5hZ2VyLmdldENsaWVudCgpKSk7XG4gIH07XG59XG4iLCJpbXBvcnQge1Jlc29sdmVycywgUmVzb2x2ZXJEZWZ9IGZyb20gJy4uL3R5cGVzL3Jlc29sdmVyJztcbmltcG9ydCB7TWFuYWdlcn0gZnJvbSAnLi4vbWFuYWdlcic7XG5pbXBvcnQge1Jlc29sdmVGbn0gZnJvbSAnLi4vdHlwZXMvY29tbW9uJztcbmltcG9ydCB7YnVpbGRDb250ZXh0fSBmcm9tICcuLi9oZWxwZXJzJztcblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVJlc29sdmVycyhtYW5hZ2VyOiBNYW5hZ2VyKTogUmVzb2x2ZXJzIHtcbiAgY29uc3Qgc2NoZW1hOiBSZXNvbHZlcnMgPSB7fTtcblxuICBtYW5hZ2VyLnJlc29sdmVycy5mb3JFYWNoKGRlZiA9PiB7XG4gICAgY29uc3QgW3R5cGVOYW1lLCBmaWVsZE5hbWVdID0gZGVmLnBhdGguc3BsaXQoJy4nKTtcblxuICAgIGlmICghc2NoZW1hW3R5cGVOYW1lXSkge1xuICAgICAgc2NoZW1hW3R5cGVOYW1lXSA9IHt9O1xuICAgIH1cblxuICAgIHNjaGVtYVt0eXBlTmFtZV1bZmllbGROYW1lXSA9IGNyZWF0ZVJlc29sdmVyKGRlZiwgbWFuYWdlcik7XG4gIH0pO1xuXG4gIHJldHVybiBzY2hlbWE7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVJlc29sdmVyKGRlZjogUmVzb2x2ZXJEZWYsIG1hbmFnZXI6IE1hbmFnZXIpOiBSZXNvbHZlRm4ge1xuICByZXR1cm4gKHBhcmVudCwgYXJncywgY29udGV4dCkgPT5cbiAgICBkZWYucmVzb2x2ZShwYXJlbnQsIGFyZ3MsIGJ1aWxkQ29udGV4dChjb250ZXh0LCBtYW5hZ2VyLmdldENsaWVudCgpKSk7XG59XG4iLCJpbXBvcnQge1xuICBBcG9sbG9MaW5rLFxuICBPcGVyYXRpb24sXG4gIE5leHRMaW5rLFxuICBPYnNlcnZhYmxlLFxuICBGZXRjaFJlc3VsdCxcbn0gZnJvbSAnYXBvbGxvLWxpbmsnO1xuaW1wb3J0IHt3aXRoQ2xpZW50U3RhdGV9IGZyb20gJ2Fwb2xsby1saW5rLXN0YXRlJztcblxuaW1wb3J0IHtNYW5hZ2VyfSBmcm9tICcuL21hbmFnZXInO1xuaW1wb3J0IHtjcmVhdGVNdXRhdGlvblNjaGVtYX0gZnJvbSAnLi9pbnRlcm5hbC9tdXRhdGlvbic7XG5pbXBvcnQge2NyZWF0ZVJlc29sdmVyc30gZnJvbSAnLi9pbnRlcm5hbC9yZXNvbHZlcnMnO1xuaW1wb3J0IHtPcHRpb25zfSBmcm9tICcuL3R5cGVzL29wdGlvbnMnO1xuXG5mdW5jdGlvbiBpc01hbmFnZXIob2JqOiBhbnkpOiBvYmogaXMgTWFuYWdlciB7XG4gIHJldHVybiBvYmogaW5zdGFuY2VvZiBNYW5hZ2VyO1xufVxuXG5leHBvcnQgY2xhc3MgTG9vbmFMaW5rIGV4dGVuZHMgQXBvbGxvTGluayB7XG4gIHB1YmxpYyBtYW5hZ2VyOiBNYW5hZ2VyO1xuICBwcml2YXRlIHN0YXRlTGluazogQXBvbGxvTGluaztcblxuICBjb25zdHJ1Y3RvcihvcHRpb25zT3JNYW5hZ2VyOiBPcHRpb25zIHwgTWFuYWdlcikge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAoaXNNYW5hZ2VyKG9wdGlvbnNPck1hbmFnZXIpKSB7XG4gICAgICB0aGlzLm1hbmFnZXIgPSBvcHRpb25zT3JNYW5hZ2VyO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm1hbmFnZXIgPSBuZXcgTWFuYWdlcihvcHRpb25zT3JNYW5hZ2VyKTtcbiAgICB9XG5cbiAgICB0aGlzLnN0YXRlTGluayA9IHdpdGhDbGllbnRTdGF0ZSh7XG4gICAgICBjYWNoZTogdGhpcy5tYW5hZ2VyLmNhY2hlLFxuICAgICAgcmVzb2x2ZXJzOiAoKSA9PiB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgTXV0YXRpb246IGNyZWF0ZU11dGF0aW9uU2NoZW1hKHRoaXMubWFuYWdlciksXG4gICAgICAgICAgLi4uY3JlYXRlUmVzb2x2ZXJzKHRoaXMubWFuYWdlciksXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgICAgZGVmYXVsdHM6IHRoaXMubWFuYWdlci5kZWZhdWx0cyxcbiAgICAgIHR5cGVEZWZzOiB0aGlzLm1hbmFnZXIudHlwZURlZnMsXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgcmVxdWVzdChcbiAgICBvcGVyYXRpb246IE9wZXJhdGlvbixcbiAgICBmb3J3YXJkOiBOZXh0TGluayxcbiAgKTogT2JzZXJ2YWJsZTxGZXRjaFJlc3VsdD4ge1xuICAgIHJldHVybiB0aGlzLnN0YXRlTGluay5yZXF1ZXN0KG9wZXJhdGlvbiwgZm9yd2FyZCkgYXMgT2JzZXJ2YWJsZTxcbiAgICAgIEZldGNoUmVzdWx0XG4gICAgPjtcbiAgfVxufVxuIiwiaW1wb3J0IHtEb2N1bWVudE5vZGV9IGZyb20gJ2dyYXBocWwnO1xuXG5pbXBvcnQge3NldE11dGF0aW9uTWV0YWRhdGF9IGZyb20gJy4uL21ldGFkYXRhL211dGF0aW9uJztcbmltcG9ydCB7Z2V0TXV0YXRpb259IGZyb20gJy4uL211dGF0aW9uJztcbmltcG9ydCB7TXV0YXRpb25NZXRob2QsIE11dGF0aW9uT2JqZWN0fSBmcm9tICcuLi90eXBlcy9tdXRhdGlvbic7XG5cbmV4cG9ydCBmdW5jdGlvbiBNdXRhdGlvbihtdXRhdGlvbjogTXV0YXRpb25PYmplY3QgfCBEb2N1bWVudE5vZGUgfCBzdHJpbmcpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKFxuICAgIHRhcmdldDogYW55LFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBfZGVzY3JpcHRvcjogVHlwZWRQcm9wZXJ0eURlc2NyaXB0b3I8TXV0YXRpb25NZXRob2Q+LFxuICApIHtcbiAgICBzZXRNdXRhdGlvbk1ldGFkYXRhKFxuICAgICAgdGFyZ2V0LFxuICAgICAgbmFtZSxcbiAgICAgIGdldE11dGF0aW9uKG11dGF0aW9uKSB8fCAobXV0YXRpb24gYXMgc3RyaW5nKSxcbiAgICApO1xuICB9O1xufVxuIiwiaW1wb3J0IHtzZXRSZXNvbHZlTWV0YWRhdGF9IGZyb20gJy4uL21ldGFkYXRhL3Jlc29sdmUnO1xuaW1wb3J0IHtSZXNvbHZlTWV0aG9kfSBmcm9tICcuLi90eXBlcy9yZXNvbHZlcic7XG5cbmV4cG9ydCBmdW5jdGlvbiBSZXNvbHZlKHBhdGg6IHN0cmluZykge1xuICByZXR1cm4gZnVuY3Rpb24oXG4gICAgdGFyZ2V0OiBhbnksXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIF9kZXNjcmlwdG9yOiBUeXBlZFByb3BlcnR5RGVzY3JpcHRvcjxSZXNvbHZlTWV0aG9kPixcbiAgKSB7XG4gICAgc2V0UmVzb2x2ZU1ldGFkYXRhKHRhcmdldCwgbmFtZSwgcGF0aCk7XG4gIH07XG59XG4iLCJpbXBvcnQge2Vuc3VyZU1ldGFkYXRhfSBmcm9tICcuL21ldGFkYXRhJztcbmltcG9ydCB7U3RhdGVPcHRpb25zfSBmcm9tICcuLi90eXBlcy9zdGF0ZSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRTdGF0ZU1ldGFkYXRhKHRhcmdldDogYW55LCBvcHRpb25zPzogU3RhdGVPcHRpb25zPGFueT4pIHtcbiAgY29uc3QgbWV0YSA9IGVuc3VyZU1ldGFkYXRhKHRhcmdldCk7XG5cbiAgaWYgKHR5cGVvZiBvcHRpb25zICE9PSAndW5kZWZpbmVkJykge1xuICAgIG1ldGEuZGVmYXVsdHMgPSBvcHRpb25zLmRlZmF1bHRzO1xuICAgIG1ldGEudHlwZURlZnMgPSBvcHRpb25zLnR5cGVEZWZzO1xuICB9XG59XG4iLCJpbXBvcnQge3NldFN0YXRlTWV0YWRhdGF9IGZyb20gJy4uL21ldGFkYXRhL3N0YXRlJztcbmltcG9ydCB7U3RhdGVPcHRpb25zfSBmcm9tICcuLi90eXBlcy9zdGF0ZSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBTdGF0ZTxUPihvcHRpb25zPzogU3RhdGVPcHRpb25zPFQ+KSB7XG4gIHJldHVybiAodGFyZ2V0OiBhbnkpID0+IHtcbiAgICBzZXRTdGF0ZU1ldGFkYXRhKHRhcmdldCwgb3B0aW9ucyk7XG5cbiAgICByZXR1cm4gdGFyZ2V0O1xuICB9O1xufVxuIiwiaW1wb3J0IHtEb2N1bWVudE5vZGV9IGZyb20gJ2dyYXBocWwnO1xuaW1wb3J0IHtzZXRVcGRhdGVNZXRhZGF0YX0gZnJvbSAnLi4vbWV0YWRhdGEvdXBkYXRlJztcbmltcG9ydCB7Z2V0TmFtZU9mTXV0YXRpb24sIGdldE11dGF0aW9uLCBpc011dGF0aW9ufSBmcm9tICcuLi9tdXRhdGlvbic7XG5pbXBvcnQge1VwZGF0ZU1ldGhvZH0gZnJvbSAnLi4vdHlwZXMvdXBkYXRlJztcbmltcG9ydCB7TXV0YXRpb25PYmplY3R9IGZyb20gJy4uL3R5cGVzL211dGF0aW9uJztcblxuZXhwb3J0IGZ1bmN0aW9uIFVwZGF0ZShtdXRhdGlvbjogTXV0YXRpb25PYmplY3QgfCBEb2N1bWVudE5vZGUgfCBzdHJpbmcpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKFxuICAgIHRhcmdldDogYW55LFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBfZGVzY3JpcHRvcjogVHlwZWRQcm9wZXJ0eURlc2NyaXB0b3I8VXBkYXRlTWV0aG9kPixcbiAgKSB7XG4gICAgbGV0IG11dGF0aW9uTmFtZTogc3RyaW5nO1xuXG4gICAgaWYgKGlzTXV0YXRpb24obXV0YXRpb24pKSB7XG4gICAgICBjb25zdCBkb2N1bWVudCA9IGdldE11dGF0aW9uKG11dGF0aW9uKTtcblxuICAgICAgaWYgKCFkb2N1bWVudCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYE11dGF0aW9uICR7XG4gICAgICAgICAgICAobXV0YXRpb24gYXMgYW55KS5uYW1lXG4gICAgICAgICAgfSBpcyBtaXNzaW5nIGEgc3RhdGljIHByb3BlcnR5ICdtdXRhdGlvbidgLFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBtdXRhdGlvbk5hbWUgPSBnZXROYW1lT2ZNdXRhdGlvbihkb2N1bWVudCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgbXV0YXRpb24gPT09ICdzdHJpbmcnKSB7XG4gICAgICBtdXRhdGlvbk5hbWUgPSBtdXRhdGlvbjtcbiAgICB9IGVsc2Uge1xuICAgICAgbXV0YXRpb25OYW1lID0gZ2V0TmFtZU9mTXV0YXRpb24obXV0YXRpb24pO1xuICAgIH1cblxuICAgIHNldFVwZGF0ZU1ldGFkYXRhKHRhcmdldCwgbmFtZSwgbXV0YXRpb25OYW1lKTtcbiAgfTtcbn1cbiIsImltcG9ydCB7ZW5zdXJlTWV0YWRhdGF9IGZyb20gJy4vbWV0YWRhdGEnO1xuaW1wb3J0IHtFZmZlY3REZWZ9IGZyb20gJy4uL3R5cGVzL2VmZmVjdCc7XG5pbXBvcnQge2dldE5hbWVPZk11dGF0aW9uLCBpc011dGF0aW9uLCBtdXRhdGlvblRvVHlwZX0gZnJvbSAnLi4vbXV0YXRpb24nO1xuaW1wb3J0IHtpc0RvY3VtZW50fSBmcm9tICcuLi9oZWxwZXJzJztcblxuZXhwb3J0IGZ1bmN0aW9uIHNldEVmZmVjdE1ldGFkYXRhKFxuICBwcm90bzogYW55LFxuICBwcm9wTmFtZTogc3RyaW5nLFxuICBlZmZlY3RzOiBFZmZlY3REZWZbXSxcbikge1xuICBjb25zdCBjb25zdHJ1Y3RvciA9IHByb3RvLmNvbnN0cnVjdG9yO1xuICBjb25zdCBtZXRhID0gZW5zdXJlTWV0YWRhdGEoY29uc3RydWN0b3IpO1xuXG4gIGZvciAoY29uc3QgYWN0aW9uIG9mIGVmZmVjdHMpIHtcbiAgICBsZXQgdHlwZTogc3RyaW5nIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuXG4gICAgaWYgKHR5cGVvZiBhY3Rpb24gPT09ICdzdHJpbmcnKSB7XG4gICAgICB0eXBlID0gYWN0aW9uO1xuICAgIH0gZWxzZSBpZiAoaXNNdXRhdGlvbihhY3Rpb24pKSB7XG4gICAgICB0eXBlID0gbXV0YXRpb25Ub1R5cGUoYWN0aW9uKTtcbiAgICB9IGVsc2UgaWYgKGlzRG9jdW1lbnQoYWN0aW9uKSkge1xuICAgICAgdHlwZSA9IGdldE5hbWVPZk11dGF0aW9uKGFjdGlvbik7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgYWN0aW9uLnR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICB0eXBlID0gYWN0aW9uLnR5cGU7XG4gICAgfVxuXG4gICAgaWYgKCF0eXBlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYExvb25hIGNvdWxkbid0IGZpZ3VyZSBvdXQgdGhlIHR5cGUgb2YgdGhlIGFjdGlvbmApO1xuICAgIH1cblxuICAgIGlmICghbWV0YS5lZmZlY3RzW3R5cGVdKSB7XG4gICAgICBtZXRhLmVmZmVjdHNbdHlwZV0gPSBbXTtcbiAgICB9XG5cbiAgICBtZXRhLmVmZmVjdHNbdHlwZV0ucHVzaCh7XG4gICAgICBwcm9wTmFtZSxcbiAgICAgIHR5cGUsXG4gICAgfSk7XG4gIH1cbn1cbiIsImltcG9ydCB7RWZmZWN0RGVmLCBFZmZlY3RNZXRob2R9IGZyb20gJy4uL3R5cGVzL2VmZmVjdCc7XG5pbXBvcnQge3NldEVmZmVjdE1ldGFkYXRhfSBmcm9tICcuLi9tZXRhZGF0YS9lZmZlY3QnO1xuXG5leHBvcnQgZnVuY3Rpb24gRWZmZWN0KGVmZmVjdHM6IEVmZmVjdERlZiB8IEVmZmVjdERlZltdKSB7XG4gIHJldHVybiBmdW5jdGlvbihcbiAgICB0YXJnZXQ6IGFueSxcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgX2Rlc2NyaXB0b3I6IFR5cGVkUHJvcGVydHlEZXNjcmlwdG9yPEVmZmVjdE1ldGhvZD4sXG4gICkge1xuICAgIHNldEVmZmVjdE1ldGFkYXRhKFxuICAgICAgdGFyZ2V0LFxuICAgICAgbmFtZSxcbiAgICAgIEFycmF5LmlzQXJyYXkoZWZmZWN0cykgPyBlZmZlY3RzIDogW2VmZmVjdHNdLFxuICAgICk7XG4gIH07XG59XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBQUEsTUFBYSxLQUFLOzs7O0lBR2hCLFlBQVksT0FBMEIsRUFBRTtRQUN0QyxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztLQUM1Qzs7Ozs7SUFFRCxHQUFHLENBQUMsR0FBVztRQUNiLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7S0FDNUI7Ozs7OztJQUVELEdBQUcsQ0FBQyxHQUFXLEVBQUUsS0FBUTtRQUN2QixJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7S0FDNUI7Ozs7O0lBRUQsT0FBTyxDQUFDLEVBQW1DO1FBQ3pDLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0tBQ3hCO0NBQ0Y7Ozs7Ozs7Ozs7QUNoQkQsU0FBZ0IscUJBQXFCLENBQ25DLEd