@simplux/core
Version:
The core package of simplux. Contains everything to manage your application state in a simple way.
142 lines (141 loc) • 23.1 kB
JavaScript
/**
* Helper symbol used for identifying simplux mutation objects.
*
* @public
*/
// should really be a symbol, but as of TypeScript 4.1 there is a bug
// that causes the symbol to not be properly re-exported in type
// definitions when spreading a mutation object onto an export, which can
// cause issues with composite builds
export const SIMPLUX_MUTATION = '[SIMPLUX_MUTATION]';
/**
* Create new mutations for the module. A mutation is a function
* that takes the module state and optionally additional parameters
* and updates the state.
*
* @param simpluxModule - the module to create mutations for
* @param mutationDefinitions - the mutations to create
*
* @returns an object that contains a function for each provided
* mutation which when called will execute the mutation on the module
*
* @public
*/
export function createMutations(simpluxModule, mutationDefinitions) {
const module = simpluxModule;
const { name: moduleName, dispatch, getReducer, mutations } = module.$simplux;
if (process.env.NODE_ENV !== 'production') {
for (const mutationName of Object.keys(mutationDefinitions)) {
if (mutations[mutationName]) {
throw new Error(`mutation '${mutationName}' is already defined for module '${moduleName}'`);
}
}
}
Object.assign(mutations, mutationDefinitions);
let currentlyDispatchingMutationName;
const resolvedMutations = Object.keys(mutationDefinitions).reduce((acc, mutationName) => {
const type = `@simplux/${moduleName}/mutation/${mutationName}`;
function createAction(...allArgs) {
const args = filterEventArgs(allArgs);
if (process.env.NODE_ENV !== 'production') {
if (args.some((arg) => typeof arg === 'function')) {
throw new Error(
// tslint:disable-next-line: max-line-length
`mutation '${mutationName}' was called with a function argument; mutation arguments must be serializable, therefore functions are not supported`);
}
}
return { type, mutationName, args };
}
const mutation = nameFunction(mutationName, (...args) => {
var _a;
const mock = (_a = module.$simplux.mutationMocks) === null || _a === void 0 ? void 0 : _a[mutationName];
if (mock) {
return mock(...args);
}
if (process.env.NODE_ENV !== 'production') {
if (currentlyDispatchingMutationName) {
throw new Error(
// tslint:disable-next-line: max-line-length
`mutation '${mutationName}' was attempted to be dispatched from within mutation '${currentlyDispatchingMutationName}' which is not allowed; instead use '${mutationName}.withState(...)' to call the mutation without a dispatch`);
}
}
currentlyDispatchingMutationName = mutationName;
dispatch(createAction(...args));
currentlyDispatchingMutationName = undefined;
return module.state();
});
acc[mutationName] = mutation;
const extras = mutation;
extras.withState = (state, ...args) => {
return getReducer()(state, createAction(...args));
};
extras.asAction = createAction;
extras.type = type;
extras.mutationName = mutationName;
extras.owningModule = module;
extras[SIMPLUX_MUTATION] = '';
return acc;
}, {});
return resolvedMutations;
// this helper function allows creating a function with a dynamic name (only works with ES6+)
function nameFunction(name, body) {
return {
[name](...args) {
return body(...args);
},
}[name];
}
}
// a very common use case for mutations in frontend applications is to
// use them as event handlers for HTML elements like buttons; if the
// mutation has no arguments and is passed directly as an event handler
// (e.g. in React applications: onClick={myMutation}) it will get the
// HTML event passed as an argument; we believe that in 99.99999% of
// all cases where this happens we do not want that arg; therefore, we
// filter any argument here that looks like an HTML event; if someone
// needs an event as an arg, they can just wrap it in an object or
// tuple as a workaround; we are not mentioning this in the docs, since
// it is such an edge case and we can just tell people about the work-
// around when they create a bug report
function filterEventArgs(args) {
if (args.length === 0) {
return args;
}
if (isEvent(args[0])) {
return args.slice(1);
}
return args;
}
function isEvent(arg) {
// tslint:disable-next-line: strict-type-predicates
if (typeof Event !== 'undefined' && arg instanceof Event) {
return true;
}
if (arg === null || arg === undefined) {
return false;
}
// check if it looks like an event
if (hasProp(arg, 'target') &&
hasProp(arg, 'currentTarget') &&
hasProp(arg, 'defaultPrevented')) {
return true;
}
return false;
function hasProp(arg, name) {
return Object.prototype.hasOwnProperty.call(arg, name);
}
}
/**
* Checks if an object is a simplux mutation.
*
* @param object - the object to check
*
* @returns true if the object is a simplux mutation
*
* @internal
*/
export function _isSimpluxMutation(object) {
var _a;
return ((_a = object) === null || _a === void 0 ? void 0 : _a[SIMPLUX_MUTATION]) === '';
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXV0YXRpb25zLmpzIiwic291cmNlcyI6WyJAc2ltcGx1eC9jb3JlL3NyYy9tdXRhdGlvbnMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBTaW1wbHV4TW9kdWxlLCBTaW1wbHV4TW9kdWxlTWFya2VyIH0gZnJvbSAnLi9tb2R1bGUuanMnXG5cbi8qKlxuICogSGVscGVyIHN5bWJvbCB1c2VkIGZvciBpZGVudGlmeWluZyBzaW1wbHV4IG11dGF0aW9uIG9iamVjdHMuXG4gKlxuICogQHB1YmxpY1xuICovXG4vLyBzaG91bGQgcmVhbGx5IGJlIGEgc3ltYm9sLCBidXQgYXMgb2YgVHlwZVNjcmlwdCA0LjEgdGhlcmUgaXMgYSBidWdcbi8vIHRoYXQgY2F1c2VzIHRoZSBzeW1ib2wgdG8gbm90IGJlIHByb3Blcmx5IHJlLWV4cG9ydGVkIGluIHR5cGVcbi8vIGRlZmluaXRpb25zIHdoZW4gc3ByZWFkaW5nIGEgbXV0YXRpb24gb2JqZWN0IG9udG8gYW4gZXhwb3J0LCB3aGljaCBjYW5cbi8vIGNhdXNlIGlzc3VlcyB3aXRoIGNvbXBvc2l0ZSBidWlsZHNcbmV4cG9ydCBjb25zdCBTSU1QTFVYX01VVEFUSU9OID0gJ1tTSU1QTFVYX01VVEFUSU9OXSdcblxuLyoqXG4gKiBBIGZ1bmN0aW9uIHRvIHR1cm4gaW50byBhIG11dGF0aW9uLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IHR5cGUgTXV0YXRpb25EZWZpbml0aW9uPFRTdGF0ZT4gPSAoXG4gIHN0YXRlOiBUU3RhdGUsXG4gIC4uLmFyZ3M6IGFueVxuKSA9PiBUU3RhdGUgfCB2b2lkXG5cbi8qKlxuICogVGhlIGZ1bmN0aW9ucyB0byB0dXJuIGludG8gbXV0YXRpb25zLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBNdXRhdGlvbkRlZmluaXRpb25zPFRTdGF0ZT4ge1xuICBbbmFtZTogc3RyaW5nXTogTXV0YXRpb25EZWZpbml0aW9uPFRTdGF0ZT5cbn1cblxuLyoqXG4gKiBJbnRlcmZhY2UgZm9yIGVmZmljaWVudGx5IGlkZW50aWZ5aW5nIHNpbXBsdXggbXV0YXRpb24gb2JqZWN0cyBhdCBjb21waWxlIHRpbWUuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgaW50ZXJmYWNlIFNpbXBsdXhNdXRhdGlvbk1hcmtlcjxUU3RhdGUsIFRBcmdzIGV4dGVuZHMgYW55W10+IHtcbiAgLyoqXG4gICAqIEEgc3ltYm9sIHRoYXQgYWxsb3dzIGVmZmljaWVudCBjb21waWxlLXRpbWUgYW5kIHJ1bi10aW1lIGlkZW50aWZpY2F0aW9uXG4gICAqIG9mIHNpbXBsdXggbXV0YXRpb24gb2JqZWN0cy5cbiAgICpcbiAgICogVGhpcyBwcm9wZXJ0eSB3aWxsIGhhdmUgYW4gYHVuZGVmaW5lZGAgdmFsdWUgYXQgcnVudGltZS5cbiAgICpcbiAgICogQHB1YmxpY1xuICAgKi9cbiAgcmVhZG9ubHkgW1NJTVBMVVhfTVVUQVRJT05dOiBbVFN0YXRlLCBUQXJnc11cbn1cblxuLyoqXG4gKiBBIHNpbXBsdXggbXV0YXRpb24gaXMgYSBmdW5jdGlvbiB0aGF0IHVwZGF0ZXMgYSBtb2R1bGUncyBzdGF0ZS5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2ltcGx1eE11dGF0aW9uPFRTdGF0ZSwgVEFyZ3MgZXh0ZW5kcyBhbnlbXT5cbiAgZXh0ZW5kcyBTaW1wbHV4TXV0YXRpb25NYXJrZXI8VFN0YXRlLCBUQXJncz4ge1xuICAvLyB0aGlzIHNpZ25hdHVyZSBkb2VzIG5vdCBoYXZlIGEgVFNEb2MgY29tbWVudCBvbiBwdXJwb3NlIHRvIGFsbG93XG4gIC8vIGNvbnN1bWVycyB0byBkZWZpbmUgdGhlaXIgb3duIGRvY3MgZm9yIHRoZWlyIG11dGF0aW9ucyAod2hpY2ggd291bGRcbiAgLy8gYmUgb3ZlcndyaXR0ZW4gaWYgdGhpcyBzaWduYXR1cmUgaGFkIGEgVFNEb2MgY29tbWVudClcbiAgKC4uLmFyZ3M6IFRBcmdzKTogVFN0YXRlXG5cbiAgLyoqXG4gICAqIEEgdW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoaXMgdHlwZSBvZiBtdXRhdGlvbi5cbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICByZWFkb25seSB0eXBlOiBzdHJpbmdcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhpcyBtdXRhdGlvbi5cbiAgICovXG4gIHJlYWRvbmx5IG11dGF0aW9uTmFtZTogc3RyaW5nXG5cbiAgLyoqXG4gICAqIFdoZW4gYSBtdXRhdGlvbiBpcyBjYWxsZWQgZGlyZWN0bHkgaXQgdXBkYXRlcyB0aGUgbW9kdWxlJ3Mgc3RhdGUuXG4gICAqIFNvbWV0aW1lcyAoZS5nLiBmb3IgdGVzdGluZykgaXQgaXMgdXNlZnVsIHRvIGNhbGwgdGhlIG11dGF0aW9uXG4gICAqIHdpdGggYSBnaXZlbiBzdGF0ZS4gSW4gdGhpcyBjYXNlIG5vIGNoYW5nZXMgYXJlIG1hZGUgdG8gdGhlIG1vZHVsZS5cbiAgICpcbiAgICogQHBhcmFtIHN0YXRlIC0gdGhlIHN0YXRlIHRvIHVzZSB3aGVuIGV4ZWN1dGluZyB0aGUgbXV0YXRpb25cbiAgICogQHBhcmFtIGFyZ3MgLSB0aGUgYXJndW1lbnRzIGZvciB0aGUgbXV0YXRpb25cbiAgICpcbiAgICogQHJldHVybnMgdGhlIHVwZGF0ZWQgc3RhdGVcbiAgICovXG4gIHJlYWRvbmx5IHdpdGhTdGF0ZTogKHN0YXRlOiBUU3RhdGUsIC4uLmFyZ3M6IFRBcmdzKSA9PiBUU3RhdGVcblxuICAvKipcbiAgICogV2hlbiBhIG11dGF0aW9uIGlzIGNhbGxlZCBkaXJlY3RseSBpdCB1cGRhdGVzIHRoZSBtb2R1bGUncyBzdGF0ZSBieVxuICAgKiBkaXNwYXRjaGluZyBhIHJlZHV4IGFjdGlvbiB0byB0aGUgc3RvcmUuIFNvbWV0aW1lcyBpdCBpcyB1c2VmdWwgdG9cbiAgICogaW5zdGVhZCBoYW5kbGUgdGhlIGFjdGlvbiB5b3Vyc2VsZiBpbnN0ZWFkIG9mIGhhdmluZyBzaW1wbHV4IGRpc3BhdGNoXG4gICAqIGl0IGF1dG9tYXRpY2FsbHkuIFRoaXMgZnVuY3Rpb24gcmV0dXJucyB0aGUgcmVkdXggYWN0aW9uIGluc3RlYWQgb2ZcbiAgICogZGlzcGF0Y2hpbmcgaXQuXG4gICAqXG4gICAqIEBwYXJhbSBhcmdzIC0gdGhlIGFyZ3VtZW50cyBmb3IgdGhlIG11dGF0aW9uXG4gICAqXG4gICAqIEByZXR1cm5zIGEgcmVkdXggYWN0aW9uIG9iamVjdFxuICAgKi9cbiAgcmVhZG9ubHkgYXNBY3Rpb246ICguLi5hcmdzOiBUQXJncykgPT4geyB0eXBlOiBzdHJpbmc7IGFyZ3M6IFRBcmdzIH1cblxuICAvKipcbiAgICogVGhlIG1vZHVsZSB0aGlzIG11dGF0aW9uIGJlbG9uZ3MgdG8uXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcmVhZG9ubHkgb3duaW5nTW9kdWxlOiBTaW1wbHV4TW9kdWxlPFRTdGF0ZT5cbn1cblxudHlwZSBTaGFsbG93TXV0YWJsZTxUPiA9IHsgLXJlYWRvbmx5IFtwcm9wIGluIGtleW9mIFRdOiBUW3Byb3BdIH1cblxuLyoqXG4gKiBBIHNpbXBsdXggbXV0YXRpb24gaXMgYSBmdW5jdGlvbiB0aGF0IHVwZGF0ZXMgYSBtb2R1bGUncyBzdGF0ZS5cbiAqIHtAbGluayBTaW1wbHV4TXV0YXRpb259XG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgdHlwZSBSZXNvbHZlZE11dGF0aW9uPFxuICBUU3RhdGUsXG4gIFRNdXRhdGlvbiBleHRlbmRzIE11dGF0aW9uRGVmaW5pdGlvbjxUU3RhdGU+XG4+ID0gVE11dGF0aW9uIGV4dGVuZHMgKHN0YXRlOiBUU3RhdGUsIC4uLmFyZ3M6IGluZmVyIFRBcmdzKSA9PiBUU3RhdGUgfCB2b2lkXG4gID8gU2ltcGx1eE11dGF0aW9uPFRTdGF0ZSwgVEFyZ3M+XG4gIDogbmV2ZXJcblxuLyoqXG4gKiBBIGNvbGxlY3Rpb24gb2Ygc2ltcGx1eCBtdXRhdGlvbnMuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgdHlwZSBTaW1wbHV4TXV0YXRpb25zPFxuICBUU3RhdGUsXG4gIFRNdXRhdGlvbnMgZXh0ZW5kcyBNdXRhdGlvbkRlZmluaXRpb25zPFRTdGF0ZT5cbj4gPSB7XG4gIHJlYWRvbmx5IFtuYW1lIGluIGtleW9mIFRNdXRhdGlvbnNdOiBSZXNvbHZlZE11dGF0aW9uPFxuICAgIFRTdGF0ZSxcbiAgICBUTXV0YXRpb25zW25hbWVdXG4gID5cbn1cblxuLyoqXG4gKiBDcmVhdGUgbmV3IG11dGF0aW9ucyBmb3IgdGhlIG1vZHVsZS4gQSBtdXRhdGlvbiBpcyBhIGZ1bmN0aW9uXG4gKiB0aGF0IHRha2VzIHRoZSBtb2R1bGUgc3RhdGUgYW5kIG9wdGlvbmFsbHkgYWRkaXRpb25hbCBwYXJhbWV0ZXJzXG4gKiBhbmQgdXBkYXRlcyB0aGUgc3RhdGUuXG4gKlxuICogQHBhcmFtIHNpbXBsdXhNb2R1bGUgLSB0aGUgbW9kdWxlIHRvIGNyZWF0ZSBtdXRhdGlvbnMgZm9yXG4gKiBAcGFyYW0gbXV0YXRpb25EZWZpbml0aW9ucyAtIHRoZSBtdXRhdGlvbnMgdG8gY3JlYXRlXG4gKlxuICogQHJldHVybnMgYW4gb2JqZWN0IHRoYXQgY29udGFpbnMgYSBmdW5jdGlvbiBmb3IgZWFjaCBwcm92aWRlZFxuICogbXV0YXRpb24gd2hpY2ggd2hlbiBjYWxsZWQgd2lsbCBleGVjdXRlIHRoZSBtdXRhdGlvbiBvbiB0aGUgbW9kdWxlXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlTXV0YXRpb25zPFxuICBUU3RhdGUsXG4gIFRNdXRhdGlvbnMgZXh0ZW5kcyBNdXRhdGlvbkRlZmluaXRpb25zPFRTdGF0ZT5cbj4oXG4gIHNpbXBsdXhNb2R1bGU6IFNpbXBsdXhNb2R1bGVNYXJrZXI8VFN0YXRlPixcbiAgbXV0YXRpb25EZWZpbml0aW9uczogVE11dGF0aW9ucyxcbik6IFNpbXBsdXhNdXRhdGlvbnM8VFN0YXRlLCBUTXV0YXRpb25zPiB7XG4gIGNvbnN0IG1vZHVsZSA9IHNpbXBsdXhNb2R1bGUgYXMgU2ltcGx1eE1vZHVsZTxUU3RhdGU+XG5cbiAgY29uc3QgeyBuYW1lOiBtb2R1bGVOYW1lLCBkaXNwYXRjaCwgZ2V0UmVkdWNlciwgbXV0YXRpb25zIH0gPSBtb2R1bGUuJHNpbXBsdXhcblxuICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgIT09ICdwcm9kdWN0aW9uJykge1xuICAgIGZvciAoY29uc3QgbXV0YXRpb25OYW1lIG9mIE9iamVjdC5rZXlzKG11dGF0aW9uRGVmaW5pdGlvbnMpKSB7XG4gICAgICBpZiAobXV0YXRpb25zW211dGF0aW9uTmFtZV0pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBtdXRhdGlvbiAnJHttdXRhdGlvbk5hbWV9JyBpcyBhbHJlYWR5IGRlZmluZWQgZm9yIG1vZHVsZSAnJHttb2R1bGVOYW1lfSdgLFxuICAgICAgICApXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgT2JqZWN0LmFzc2lnbihtdXRhdGlvbnMsIG11dGF0aW9uRGVmaW5pdGlvbnMpXG5cbiAgbGV0IGN1cnJlbnRseURpc3BhdGNoaW5nTXV0YXRpb25OYW1lOiBzdHJpbmcgfCB1bmRlZmluZWRcblxuICBjb25zdCByZXNvbHZlZE11dGF0aW9ucyA9IE9iamVjdC5rZXlzKG11dGF0aW9uRGVmaW5pdGlvbnMpLnJlZHVjZShcbiAgICAoYWNjLCBtdXRhdGlvbk5hbWU6IGtleW9mIFRNdXRhdGlvbnMpID0+IHtcbiAgICAgIGNvbnN0IHR5cGUgPSBgQHNpbXBsdXgvJHttb2R1bGVOYW1lfS9tdXRhdGlvbi8ke211dGF0aW9uTmFtZX1gXG5cbiAgICAgIGZ1bmN0aW9uIGNyZWF0ZUFjdGlvbiguLi5hbGxBcmdzOiBhbnlbXSkge1xuICAgICAgICBjb25zdCBhcmdzID0gZmlsdGVyRXZlbnRBcmdzKGFsbEFyZ3MpXG5cbiAgICAgICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicpIHtcbiAgICAgICAgICBpZiAoYXJncy5zb21lKChhcmcpID0+IHR5cGVvZiBhcmcgPT09ICdmdW5jdGlvbicpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTogbWF4LWxpbmUtbGVuZ3RoXG4gICAgICAgICAgICAgIGBtdXRhdGlvbiAnJHttdXRhdGlvbk5hbWV9JyB3YXMgY2FsbGVkIHdpdGggYSBmdW5jdGlvbiBhcmd1bWVudDsgbXV0YXRpb24gYXJndW1lbnRzIG11c3QgYmUgc2VyaWFsaXphYmxlLCB0aGVyZWZvcmUgZnVuY3Rpb25zIGFyZSBub3Qgc3VwcG9ydGVkYCxcbiAgICAgICAgICAgIClcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4geyB0eXBlLCBtdXRhdGlvbk5hbWUsIGFyZ3MgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBtdXRhdGlvbiA9IG5hbWVGdW5jdGlvbihcbiAgICAgICAgbXV0YXRpb25OYW1lIGFzIHN0cmluZyxcbiAgICAgICAgKC4uLmFyZ3M6IGFueVtdKSA9PiB7XG4gICAgICAgICAgY29uc3QgbW9jayA9IG1vZHVsZS4kc2ltcGx1eC5tdXRhdGlvbk1vY2tzPy5bbXV0YXRpb25OYW1lIGFzIHN0cmluZ11cblxuICAgICAgICAgIGlmIChtb2NrKSB7XG4gICAgICAgICAgICByZXR1cm4gbW9jayguLi5hcmdzKVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nKSB7XG4gICAgICAgICAgICBpZiAoY3VycmVudGx5RGlzcGF0Y2hpbmdNdXRhdGlvbk5hbWUpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTogbWF4LWxpbmUtbGVuZ3RoXG4gICAgICAgICAgICAgICAgYG11dGF0aW9uICcke211dGF0aW9uTmFtZX0nIHdhcyBhdHRlbXB0ZWQgdG8gYmUgZGlzcGF0Y2hlZCBmcm9tIHdpdGhpbiBtdXRhdGlvbiAnJHtjdXJyZW50bHlEaXNwYXRjaGluZ011dGF0aW9uTmFtZX0nIHdoaWNoIGlzIG5vdCBhbGxvd2VkOyBpbnN0ZWFkIHVzZSAnJHttdXRhdGlvbk5hbWV9LndpdGhTdGF0ZSguLi4pJyB0byBjYWxsIHRoZSBtdXRhdGlvbiB3aXRob3V0IGEgZGlzcGF0Y2hgLFxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY3VycmVudGx5RGlzcGF0Y2hpbmdNdXRhdGlvbk5hbWUgPSBtdXRhdGlvbk5hbWUgYXMgc3RyaW5nXG4gICAgICAgICAgZGlzcGF0Y2goY3JlYXRlQWN0aW9uKC4uLmFyZ3MpKVxuICAgICAgICAgIGN1cnJlbnRseURpc3BhdGNoaW5nTXV0YXRpb25OYW1lID0gdW5kZWZpbmVkXG4gICAgICAgICAgcmV0dXJuIG1vZHVsZS5zdGF0ZSgpXG4gICAgICAgIH0sXG4gICAgICApIGFzIFJlc29sdmVkTXV0YXRpb248VFN0YXRlLCBUTXV0YXRpb25zW3R5cGVvZiBtdXRhdGlvbk5hbWVdPlxuXG4gICAgICBhY2NbbXV0YXRpb25OYW1lXSA9IG11dGF0aW9uXG5cbiAgICAgIGNvbnN0IGV4dHJhcyA9IG11dGF0aW9uIGFzIFNoYWxsb3dNdXRhYmxlPHR5cGVvZiBtdXRhdGlvbj5cblxuICAgICAgZXh0cmFzLndpdGhTdGF0ZSA9IChzdGF0ZTogVFN0YXRlLCAuLi5hcmdzOiBhbnlbXSkgPT4ge1xuICAgICAgICByZXR1cm4gZ2V0UmVkdWNlcigpKHN0YXRlLCBjcmVhdGVBY3Rpb24oLi4uYXJncykpXG4gICAgICB9XG5cbiAgICAgIGV4dHJhcy5hc0FjdGlvbiA9IGNyZWF0ZUFjdGlvbiBhcyBhbnlcblxuICAgICAgZXh0cmFzLnR5cGUgPSB0eXBlXG5cbiAgICAgIGV4dHJhcy5tdXRhdGlvbk5hbWUgPSBtdXRhdGlvbk5hbWUgYXMgc3RyaW5nXG4gICAgICBleHRyYXMub3duaW5nTW9kdWxlID0gbW9kdWxlXG4gICAgICBleHRyYXNbU0lNUExVWF9NVVRBVElPTl0gPSAnJyBhcyBhbnlcblxuICAgICAgcmV0dXJuIGFjY1xuICAgIH0sXG4gICAge30gYXMgU2hhbGxvd011dGFibGU8U2ltcGx1eE11dGF0aW9uczxUU3RhdGUsIFRNdXRhdGlvbnM+PixcbiAgKVxuXG4gIHJldHVybiByZXNvbHZlZE11dGF0aW9uc1xuXG4gIC8vIHRoaXMgaGVscGVyIGZ1bmN0aW9uIGFsbG93cyBjcmVhdGluZyBhIGZ1bmN0aW9uIHdpdGggYSBkeW5hbWljIG5hbWUgKG9ubHkgd29ya3Mgd2l0aCBFUzYrKVxuICBmdW5jdGlvbiBuYW1lRnVuY3Rpb248VCBleHRlbmRzICguLi5hcmdzOiBhbnlbXSkgPT4gYW55PihcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgYm9keTogVCxcbiAgKTogVCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIFtuYW1lXSguLi5hcmdzOiBhbnlbXSkge1xuICAgICAgICByZXR1cm4gYm9keSguLi5hcmdzKVxuICAgICAgfSxcbiAgICB9W25hbWVdIGFzIFRcbiAgfVxufVxuXG4vLyBhIHZlcnkgY29tbW9uIHVzZSBjYXNlIGZvciBtdXRhdGlvbnMgaW4gZnJvbnRlbmQgYXBwbGljYXRpb25zIGlzIHRvXG4vLyB1c2UgdGhlbSBhcyBldmVudCBoYW5kbGVycyBmb3IgSFRNTCBlbGVtZW50cyBsaWtlIGJ1dHRvbnM7IGlmIHRoZVxuLy8gbXV0YXRpb24gaGFzIG5vIGFyZ3VtZW50cyBhbmQgaXMgcGFzc2VkIGRpcmVjdGx5IGFzIGFuIGV2ZW50IGhhbmRsZXJcbi8vIChlLmcuIGluIFJlYWN0IGFwcGxpY2F0aW9uczogb25DbGljaz17bXlNdXRhdGlvbn0pIGl0IHdpbGwgZ2V0IHRoZVxuLy8gSFRNTCBldmVudCBwYXNzZWQgYXMgYW4gYXJndW1lbnQ7IHdlIGJlbGlldmUgdGhhdCBpbiA5OS45OTk5OSUgb2Zcbi8vIGFsbCBjYXNlcyB3aGVyZSB0aGlzIGhhcHBlbnMgd2UgZG8gbm90IHdhbnQgdGhhdCBhcmc7IHRoZXJlZm9yZSwgd2Vcbi8vIGZpbHRlciBhbnkgYXJndW1lbnQgaGVyZSB0aGF0IGxvb2tzIGxpa2UgYW4gSFRNTCBldmVudDsgaWYgc29tZW9uZVxuLy8gbmVlZHMgYW4gZXZlbnQgYXMgYW4gYXJnLCB0aGV5IGNhbiBqdXN0IHdyYXAgaXQgaW4gYW4gb2JqZWN0IG9yXG4vLyB0dXBsZSBhcyBhIHdvcmthcm91bmQ7IHdlIGFyZSBub3QgbWVudGlvbmluZyB0aGlzIGluIHRoZSBkb2NzLCBzaW5jZVxuLy8gaXQgaXMgc3VjaCBhbiBlZGdlIGNhc2UgYW5kIHdlIGNhbiBqdXN0IHRlbGwgcGVvcGxlIGFib3V0IHRoZSB3b3JrLVxuLy8gYXJvdW5kIHdoZW4gdGhleSBjcmVhdGUgYSBidWcgcmVwb3J0XG5mdW5jdGlvbiBmaWx0ZXJFdmVudEFyZ3MoYXJnczogYW55W10pIHtcbiAgaWYgKGFyZ3MubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIGFyZ3NcbiAgfVxuXG4gIGlmIChpc0V2ZW50KGFyZ3NbMF0pKSB7XG4gICAgcmV0dXJuIGFyZ3Muc2xpY2UoMSlcbiAgfVxuXG4gIHJldHVybiBhcmdzXG59XG5cbmRlY2xhcmUgY2xhc3MgRXZlbnQge31cblxuZnVuY3Rpb24gaXNFdmVudChhcmc6IGFueSkge1xuICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6IHN0cmljdC10eXBlLXByZWRpY2F0ZXNcbiAgaWYgKHR5cGVvZiBFdmVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgYXJnIGluc3RhbmNlb2YgRXZlbnQpIHtcbiAgICByZXR1cm4gdHJ1ZVxuICB9XG5cbiAgaWYgKGFyZyA9PT0gbnVsbCB8fCBhcmcgPT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgLy8gY2hlY2sgaWYgaXQgbG9va3MgbGlrZSBhbiBldmVudFxuICBpZiAoXG4gICAgaGFzUHJvcChhcmcsICd0YXJnZXQnKSAmJlxuICAgIGhhc1Byb3AoYXJnLCAnY3VycmVudFRhcmdldCcpICYmXG4gICAgaGFzUHJvcChhcmcsICdkZWZhdWx0UHJldmVudGVkJylcbiAgKSB7XG4gICAgcmV0dXJuIHRydWVcbiAgfVxuXG4gIHJldHVybiBmYWxzZVxuXG4gIGZ1bmN0aW9uIGhhc1Byb3AoYXJnOiBhbnksIG5hbWU6IHN0cmluZykge1xuICAgIHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYXJnLCBuYW1lKVxuICB9XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGFuIG9iamVjdCBpcyBhIHNpbXBsdXggbXV0YXRpb24uXG4gKlxuICogQHBhcmFtIG9iamVjdCAtIHRoZSBvYmplY3QgdG8gY2hlY2tcbiAqXG4gKiBAcmV0dXJucyB0cnVlIGlmIHRoZSBvYmplY3QgaXMgYSBzaW1wbHV4IG11dGF0aW9uXG4gKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBfaXNTaW1wbHV4TXV0YXRpb248VFN0YXRlLCBUQXJncyBleHRlbmRzIGFueVtdLCBUT3RoZXI+KFxuICBvYmplY3Q6IFNpbXBsdXhNdXRhdGlvbk1hcmtlcjxUU3RhdGUsIFRBcmdzPiB8IFRPdGhlcixcbik6IG9iamVjdCBpcyBTaW1wbHV4TXV0YXRpb248VFN0YXRlLCBUQXJncz4ge1xuICByZXR1cm4gKG9iamVjdCBhcyBhbnkpPy5bU0lNUExVWF9NVVRBVElPTl0gPT09ICcnXG59XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUE7Ozs7R0FJRztBQUNILHFFQUFxRTtBQUNyRSxnRUFBZ0U7QUFDaEUseUVBQXlFO0FBQ3pFLHFDQUFxQztBQUNyQyxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBRyxvQkFBb0IsQ0FBQTtBQTZIcEQ7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0gsTUFBTSxVQUFVLGVBQWUsQ0FJN0IsYUFBMEMsRUFDMUMsbUJBQStCO0lBRS9CLE1BQU0sTUFBTSxHQUFHLGFBQXNDLENBQUE7SUFFckQsTUFBTSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxTQUFTLEVB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