@data-client/core
Version:
Async State Management without the Management. REST, GraphQL, SSE, Websockets, Fetch
110 lines (109 loc) • 16.8 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import { normalize } from '@data-client/normalizr';
import { OPTIMISTIC } from '../../actionTypes.js';
import AbortOptimistic from '../../controller/AbortOptimistic.js';
export function setResponseReducer(state, action, controller) {
if (action.error) {
return reduceError(state, action, action.response);
}
try {
var _state$meta$action$ke;
let response;
// for true set's response is contained in action
if (action.type === OPTIMISTIC) {
// this should never happen
/* istanbul ignore if */
if (!action.endpoint.getOptimisticResponse) return state;
try {
// compute optimistic response based on current state
response = action.endpoint.getOptimisticResponse.call(action.endpoint, controller.snapshot(state, action.meta.fetchedAt), ...action.args);
} catch (e) {
// AbortOptimistic means 'do nothing', otherwise we count the exception as endpoint failure
if (e.constructor === AbortOptimistic) {
return state;
}
throw e;
}
} else {
response = action.response;
}
const {
result,
entities,
indexes,
entityMeta
} = normalize(action.endpoint.schema, response, action.args, state, action.meta);
const endpoints = _extends({}, state.endpoints, {
[action.key]: result
});
try {
if (action.endpoint.update) {
const updaters = action.endpoint.update(result, ...action.args);
Object.keys(updaters).forEach(key => {
endpoints[key] = updaters[key](endpoints[key]);
});
}
// no reason to completely fail because of user-code error
// integrity of this state update is still guaranteed
} catch (error) {
console.error(`The following error occured during Endpoint.update() for ${action.key}`);
console.error(error);
}
return {
entities,
endpoints,
indexes,
meta: _extends({}, state.meta, {
[action.key]: {
date: action.meta.date,
fetchedAt: action.meta.fetchedAt,
expiresAt: action.meta.expiresAt,
prevExpiresAt: (_state$meta$action$ke = state.meta[action.key]) == null ? void 0 : _state$meta$action$ke.expiresAt
}
}),
entityMeta,
optimistic: filterOptimistic(state, action),
lastReset: state.lastReset
};
// reducer must update the state, so in case of processing errors we simply compute the endpoints inline
} catch (error) {
if (typeof error === 'object') {
error.message = `Error processing ${action.key}\n\nFull Schema: ${JSON.stringify(action.endpoint.schema, undefined, 2)}\n\nError:\n${error.message}`;
if ('response' in action) error.response = action.response;
error.status = 400;
}
// this is not always bubbled up, so let's double sure this doesn't fail silently
/* istanbul ignore else */
if (process.env.NODE_ENV !== 'production') {
console.error(error);
}
return reduceError(state, action, error);
}
}
function reduceError(state, action, error) {
if (error.name === 'AbortError') {
// In case we abort simply undo the optimistic update and act like no fetch even occured
// We still want those watching promises from fetch directly to observed the abort, but we don't want to
// Trigger errors in this case. This means theoretically improperly built abortes useResource() could suspend forever.
return _extends({}, state, {
optimistic: filterOptimistic(state, action)
});
}
return _extends({}, state, {
meta: _extends({}, state.meta, {
[action.key]: {
date: action.meta.date,
fetchedAt: action.meta.fetchedAt,
expiresAt: action.meta.expiresAt,
error,
errorPolicy: action.endpoint.errorPolicy == null ? void 0 : action.endpoint.errorPolicy(error)
}
}),
optimistic: filterOptimistic(state, action)
});
}
/** Filter all requests with same serialization that did not start after the resolving request */
function filterOptimistic(state, resolvingAction) {
return state.optimistic.filter(optimisticAction => optimisticAction.key !== resolvingAction.key || (optimisticAction.type === OPTIMISTIC ? optimisticAction.meta.fetchedAt !== resolvingAction.meta.fetchedAt : optimisticAction.meta.date > resolvingAction.meta.date));
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJub3JtYWxpemUiLCJPUFRJTUlTVElDIiwiQWJvcnRPcHRpbWlzdGljIiwic2V0UmVzcG9uc2VSZWR1Y2VyIiwic3RhdGUiLCJhY3Rpb24iLCJjb250cm9sbGVyIiwiZXJyb3IiLCJyZWR1Y2VFcnJvciIsInJlc3BvbnNlIiwiX3N0YXRlJG1ldGEkYWN0aW9uJGtlIiwidHlwZSIsImVuZHBvaW50IiwiZ2V0T3B0aW1pc3RpY1Jlc3BvbnNlIiwiY2FsbCIsInNuYXBzaG90IiwibWV0YSIsImZldGNoZWRBdCIsImFyZ3MiLCJlIiwiY29uc3RydWN0b3IiLCJyZXN1bHQiLCJlbnRpdGllcyIsImluZGV4ZXMiLCJlbnRpdHlNZXRhIiwic2NoZW1hIiwiZW5kcG9pbnRzIiwiX2V4dGVuZHMiLCJrZXkiLCJ1cGRhdGUiLCJ1cGRhdGVycyIsIk9iamVjdCIsImtleXMiLCJmb3JFYWNoIiwiY29uc29sZSIsImRhdGUiLCJleHBpcmVzQXQiLCJwcmV2RXhwaXJlc0F0Iiwib3B0aW1pc3RpYyIsImZpbHRlck9wdGltaXN0aWMiLCJsYXN0UmVzZXQiLCJtZXNzYWdlIiwiSlNPTiIsInN0cmluZ2lmeSIsInVuZGVmaW5lZCIsInN0YXR1cyIsInByb2Nlc3MiLCJlbnYiLCJOT0RFX0VOViIsIm5hbWUiLCJlcnJvclBvbGljeSIsInJlc29sdmluZ0FjdGlvbiIsImZpbHRlciIsIm9wdGltaXN0aWNBY3Rpb24iXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc3RhdGUvcmVkdWNlci9zZXRSZXNwb25zZVJlZHVjZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgbm9ybWFsaXplIH0gZnJvbSAnQGRhdGEtY2xpZW50L25vcm1hbGl6cic7XG5cbmltcG9ydCB7IE9QVElNSVNUSUMgfSBmcm9tICcuLi8uLi9hY3Rpb25UeXBlcy5qcyc7XG5pbXBvcnQgQWJvcnRPcHRpbWlzdGljIGZyb20gJy4uLy4uL2NvbnRyb2xsZXIvQWJvcnRPcHRpbWlzdGljLmpzJztcbmltcG9ydCB0eXBlIENvbnRyb2xsZXIgZnJvbSAnLi4vLi4vY29udHJvbGxlci9Db250cm9sbGVyLmpzJztcbmltcG9ydCB0eXBlIHtcbiAgU3RhdGUsXG4gIFNldFJlc3BvbnNlQWN0aW9uLFxuICBPcHRpbWlzdGljQWN0aW9uLFxufSBmcm9tICcuLi8uLi90eXBlcy5qcyc7XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRSZXNwb25zZVJlZHVjZXIoXG4gIHN0YXRlOiBTdGF0ZTx1bmtub3duPixcbiAgYWN0aW9uOiBPcHRpbWlzdGljQWN0aW9uIHwgU2V0UmVzcG9uc2VBY3Rpb24sXG4gIGNvbnRyb2xsZXI6IENvbnRyb2xsZXIsXG4pIHtcbiAgaWYgKGFjdGlvbi5lcnJvcikge1xuICAgIHJldHVybiByZWR1Y2VFcnJvcihzdGF0ZSwgYWN0aW9uLCBhY3Rpb24ucmVzcG9uc2UpO1xuICB9XG4gIHRyeSB7XG4gICAgbGV0IHJlc3BvbnNlOiBhbnk7XG4gICAgLy8gZm9yIHRydWUgc2V0J3MgcmVzcG9uc2UgaXMgY29udGFpbmVkIGluIGFjdGlvblxuICAgIGlmIChhY3Rpb24udHlwZSA9PT0gT1BUSU1JU1RJQykge1xuICAgICAgLy8gdGhpcyBzaG91bGQgbmV2ZXIgaGFwcGVuXG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICAgIGlmICghYWN0aW9uLmVuZHBvaW50LmdldE9wdGltaXN0aWNSZXNwb25zZSkgcmV0dXJuIHN0YXRlO1xuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gY29tcHV0ZSBvcHRpbWlzdGljIHJlc3BvbnNlIGJhc2VkIG9uIGN1cnJlbnQgc3RhdGVcbiAgICAgICAgcmVzcG9uc2UgPSBhY3Rpb24uZW5kcG9pbnQuZ2V0T3B0aW1pc3RpY1Jlc3BvbnNlLmNhbGwoXG4gICAgICAgICAgYWN0aW9uLmVuZHBvaW50LFxuICAgICAgICAgIGNvbnRyb2xsZXIuc25hcHNob3Qoc3RhdGUsIGFjdGlvbi5tZXRhLmZldGNoZWRBdCksXG4gICAgICAgICAgLi4uYWN0aW9uLmFyZ3MsXG4gICAgICAgICk7XG4gICAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgICAgLy8gQWJvcnRPcHRpbWlzdGljIG1lYW5zICdkbyBub3RoaW5nJywgb3RoZXJ3aXNlIHdlIGNvdW50IHRoZSBleGNlcHRpb24gYXMgZW5kcG9pbnQgZmFpbHVyZVxuICAgICAgICBpZiAoZS5jb25zdHJ1Y3RvciA9PT0gQWJvcnRPcHRpbWlzdGljKSB7XG4gICAgICAgICAgcmV0dXJuIHN0YXRlO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3BvbnNlID0gYWN0aW9uLnJlc3BvbnNlO1xuICAgIH1cbiAgICBjb25zdCB7IHJlc3VsdCwgZW50aXRpZXMsIGluZGV4ZXMsIGVudGl0eU1ldGEgfSA9IG5vcm1hbGl6ZShcbiAgICAgIGFjdGlvbi5lbmRwb2ludC5zY2hlbWEsXG4gICAgICByZXNwb25zZSxcbiAgICAgIGFjdGlvbi5hcmdzLFxuICAgICAgc3RhdGUsXG4gICAgICBhY3Rpb24ubWV0YSxcbiAgICApO1xuICAgIGNvbnN0IGVuZHBvaW50czogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7XG4gICAgICAuLi5zdGF0ZS5lbmRwb2ludHMsXG4gICAgICBbYWN0aW9uLmtleV06IHJlc3VsdCxcbiAgICB9O1xuICAgIHRyeSB7XG4gICAgICBpZiAoYWN0aW9uLmVuZHBvaW50LnVwZGF0ZSkge1xuICAgICAgICBjb25zdCB1cGRhdGVycyA9IGFjdGlvbi5lbmRwb2ludC51cGRhdGUocmVzdWx0LCAuLi5hY3Rpb24uYXJncyk7XG4gICAgICAgIE9iamVjdC5rZXlzKHVwZGF0ZXJzKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgZW5kcG9pbnRzW2tleV0gPSB1cGRhdGVyc1trZXldKGVuZHBvaW50c1trZXldKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICAvLyBubyByZWFzb24gdG8gY29tcGxldGVseSBmYWlsIGJlY2F1c2Ugb2YgdXNlci1jb2RlIGVycm9yXG4gICAgICAvLyBpbnRlZ3JpdHkgb2YgdGhpcyBzdGF0ZSB1cGRhdGUgaXMgc3RpbGwgZ3VhcmFudGVlZFxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICBgVGhlIGZvbGxvd2luZyBlcnJvciBvY2N1cmVkIGR1cmluZyBFbmRwb2ludC51cGRhdGUoKSBmb3IgJHthY3Rpb24ua2V5fWAsXG4gICAgICApO1xuICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBlbnRpdGllcyxcbiAgICAgIGVuZHBvaW50cyxcbiAgICAgIGluZGV4ZXMsXG4gICAgICBtZXRhOiB7XG4gICAgICAgIC4uLnN0YXRlLm1ldGEsXG4gICAgICAgIFthY3Rpb24ua2V5XToge1xuICAgICAgICAgIGRhdGU6IGFjdGlvbi5tZXRhLmRhdGUsXG4gICAgICAgICAgZmV0Y2hlZEF0OiBhY3Rpb24ubWV0YS5mZXRjaGVkQXQsXG4gICAgICAgICAgZXhwaXJlc0F0OiBhY3Rpb24ubWV0YS5leHBpcmVzQXQsXG4gICAgICAgICAgcHJldkV4cGlyZXNBdDogc3RhdGUubWV0YVthY3Rpb24ua2V5XT8uZXhwaXJlc0F0LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGVudGl0eU1ldGEsXG4gICAgICBvcHRpbWlzdGljOiBmaWx0ZXJPcHRpbWlzdGljKHN0YXRlLCBhY3Rpb24pLFxuICAgICAgbGFzdFJlc2V0OiBzdGF0ZS5sYXN0UmVzZXQsXG4gICAgfTtcbiAgICAvLyByZWR1Y2VyIG11c3QgdXBkYXRlIHRoZSBzdGF0ZSwgc28gaW4gY2FzZSBvZiBwcm9jZXNzaW5nIGVycm9ycyB3ZSBzaW1wbHkgY29tcHV0ZSB0aGUgZW5kcG9pbnRzIGlubGluZVxuICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgaWYgKHR5cGVvZiBlcnJvciA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGVycm9yLm1lc3NhZ2UgPSBgRXJyb3IgcHJvY2Vzc2luZyAke1xuICAgICAgICBhY3Rpb24ua2V5XG4gICAgICB9XFxuXFxuRnVsbCBTY2hlbWE6ICR7SlNPTi5zdHJpbmdpZnkoXG4gICAgICAgIGFjdGlvbi5lbmRwb2ludC5zY2hlbWEsXG4gICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgMixcbiAgICAgICl9XFxuXFxuRXJyb3I6XFxuJHtlcnJvci5tZXNzYWdlfWA7XG4gICAgICBpZiAoJ3Jlc3BvbnNlJyBpbiBhY3Rpb24pIGVycm9yLnJlc3BvbnNlID0gYWN0aW9uLnJlc3BvbnNlO1xuICAgICAgZXJyb3Iuc3RhdHVzID0gNDAwO1xuICAgIH1cblxuICAgIC8vIHRoaXMgaXMgbm90IGFsd2F5cyBidWJibGVkIHVwLCBzbyBsZXQncyBkb3VibGUgc3VyZSB0aGlzIGRvZXNuJ3QgZmFpbCBzaWxlbnRseVxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgIH1cbiAgICByZXR1cm4gcmVkdWNlRXJyb3Ioc3RhdGUsIGFjdGlvbiwgZXJyb3IpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlZHVjZUVycm9yKFxuICBzdGF0ZTogU3RhdGU8dW5rbm93bj4sXG4gIGFjdGlvbjogU2V0UmVzcG9uc2VBY3Rpb24gfCBPcHRpbWlzdGljQWN0aW9uLFxuICBlcnJvcjogYW55LFxuKTogU3RhdGU8dW5rbm93bj4ge1xuICBpZiAoZXJyb3IubmFtZSA9PT0gJ0Fib3J0RXJyb3InKSB7XG4gICAgLy8gSW4gY2FzZSB3ZSBhYm9ydCBzaW1wbHkgdW5kbyB0aGUgb3B0aW1pc3RpYyB1cGRhdGUgYW5kIGFjdCBsaWtlIG5vIGZldGNoIGV2ZW4gb2NjdXJlZFxuICAgIC8vIFdlIHN0aWxsIHdhbnQgdGhvc2Ugd2F0Y2hpbmcgcHJvbWlzZXMgZnJvbSBmZXRjaCBkaXJlY3RseSB0byBvYnNlcnZlZCB0aGUgYWJvcnQsIGJ1dCB3ZSBkb24ndCB3YW50IHRvXG4gICAgLy8gVHJpZ2dlciBlcnJvcnMgaW4gdGhpcyBjYXNlLiBUaGlzIG1lYW5zIHRoZW9yZXRpY2FsbHkgaW1wcm9wZXJseSBidWlsdCBhYm9ydGVzIHVzZVJlc291cmNlKCkgY291bGQgc3VzcGVuZCBmb3JldmVyLlxuICAgIHJldHVybiB7XG4gICAgICAuLi5zdGF0ZSxcbiAgICAgIG9wdGltaXN0aWM6IGZpbHRlck9wdGltaXN0aWMoc3RhdGUsIGFjdGlvbiksXG4gICAgfTtcbiAgfVxuICByZXR1cm4ge1xuICAgIC4uLnN0YXRlLFxuICAgIG1ldGE6IHtcbiAgICAgIC4uLnN0YXRlLm1ldGEsXG4gICAgICBbYWN0aW9uLmtleV06IHtcbiAgICAgICAgZGF0ZTogYWN0aW9uLm1ldGEuZGF0ZSxcbiAgICAgICAgZmV0Y2hlZEF0OiBhY3Rpb24ubWV0YS5mZXRjaGVkQXQsXG4gICAgICAgIGV4cGlyZXNBdDogYWN0aW9uLm1ldGEuZXhwaXJlc0F0LFxuICAgICAgICBlcnJvcixcbiAgICAgICAgZXJyb3JQb2xpY3k6IGFjdGlvbi5lbmRwb2ludC5lcnJvclBvbGljeT8uKGVycm9yKSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBvcHRpbWlzdGljOiBmaWx0ZXJPcHRpbWlzdGljKHN0YXRlLCBhY3Rpb24pLFxuICB9O1xufVxuLyoqIEZpbHRlciBhbGwgcmVxdWVzdHMgd2l0aCBzYW1lIHNlcmlhbGl6YXRpb24gdGhhdCBkaWQgbm90IHN0YXJ0IGFmdGVyIHRoZSByZXNvbHZpbmcgcmVxdWVzdCAqL1xuZnVuY3Rpb24gZmlsdGVyT3B0aW1pc3RpYyhcbiAgc3RhdGU6IFN0YXRlPHVua25vd24+LFxuICByZXNvbHZpbmdBY3Rpb246IFNldFJlc3BvbnNlQWN0aW9uIHwgT3B0aW1pc3RpY0FjdGlvbixcbikge1xuICByZXR1cm4gc3RhdGUub3B0aW1pc3RpYy5maWx0ZXIoXG4gICAgb3B0aW1pc3RpY0FjdGlvbiA9PlxuICAgICAgb3B0aW1pc3RpY0FjdGlvbi5rZXkgIT09IHJlc29sdmluZ0FjdGlvbi5rZXkgfHxcbiAgICAgIChvcHRpbWlzdGljQWN0aW9uLnR5cGUgPT09IE9QVElNSVNUSUMgP1xuICAgICAgICBvcHRpbWlzdGljQWN0aW9uLm1ldGEuZmV0Y2hlZEF0ICE9PSByZXNvbHZpbmdBY3Rpb24ubWV0YS5mZXRjaGVkQXRcbiAgICAgIDogb3B0aW1pc3RpY0FjdGlvbi5tZXRhLmRhdGUgPiByZXNvbHZpbmdBY3Rpb24ubWV0YS5kYXRlKSxcbiAgKTtcbn1cbiJdLCJtYXBwaW5ncyI6IjtBQUFBLFNBQVNBLFNBQVMsUUFBUSx3QkFBd0I7QUFFbEQsU0FBU0MsVUFBVSxRQUFRLHNCQUFzQjtBQUNqRCxPQUFPQyxlQUFlLE1BQU0scUNBQXFDO0FBUWpFLE9BQU8sU0FBU0Msa0JBQWtCQSxDQUNoQ0MsS0FBcUIsRUFDckJDLE1BQTRDLEVBQzVDQyxVQUFzQixFQUN0QjtFQUNBLElBQUlELE1BQU0sQ0FBQ0UsS0FBSyxFQUFFO0lBQ2hCLE9BQU9DLFdBQVcsQ0FBQ0osS0FBSyxFQUFFQyxNQUFNLEVBQUVBLE1BQU0sQ0FBQ0ksUUFBUSxDQUFDO0VBQ3BEO0VBQ0EsSUFBSTtJQUFBLElBQUFDLHFCQUFBO0lBQ0YsSUFBSUQsUUFBYTtJQUNqQjtJQUNBLElBQUlKLE1BQU0sQ0FBQ00sSUFBSSxLQUFLVixVQUFVLEVBQUU7TUFDOUI7TUFDQTtNQUNBLElBQUksQ0FBQ0ksTUFBTSxDQUFDTyxRQUFRLENBQUNDLHFCQUFxQixFQUFFLE9BQU9ULEtBQUs7TUFDeEQsSUFBSTtRQUNGO1FBQ0FLLFFBQVEsR0FBR0osTUFBTSxDQUFDTyxRQUFRLENBQUNDLHFCQUFxQixDQUFDQyxJQUFJLENBQ25EVCxNQUFNLENBQUNPLFFBQVEsRUFDZk4sVUFBVSxDQUFDUyxRQUFRLENBQUNYLEtBQUssRUFBRUMsTUFBTSxDQUFDVyxJQUFJLENBQUNDLFNBQVMsQ0FBQyxFQUNqRCxHQUFHWixNQUFNLENBQUNhLElBQ1osQ0FBQztNQUNILENBQUMsQ0FBQyxPQUFPQyxDQUFNLEVBQUU7UUFDZjtRQUNBLElBQUlBLENBQUMsQ0FBQ0MsV0FBVyxLQUFLbEIsZUFBZSxFQUFFO1VBQ3JDLE9BQU9FLEtBQUs7UUFDZDtRQUNBLE1BQU1lLENBQUM7TUFDVDtJQUNGLENBQUMsTUFBTTtNQUNMVixRQUFRLEdBQUdKLE1BQU0sQ0FBQ0ksUUFBUTtJQUM1QjtJQUNBLE1BQU07TUFBRVksTUFBTTtNQUFFQyxRQUFRO01BQUVDLE9BQU87TUFBRUM7SUFBVyxDQUFDLEdBQUd4QixTQUFTLENBQ3pESyxNQUFNLENBQUNPLFFBQVEsQ0FBQ2EsTUFBTSxFQUN0QmhCLFFBQVEsRUFDUkosTUFBTSxDQUFDYSxJQUFJLEVBQ1hkLEtBQUssRUFDTEMsTUFBTSxDQUFDVyxJQUNULENBQUM7SUFDRCxNQUFNVSxTQUFrQyxHQUFBQyxRQUFBLEtBQ25DdkIsS0FBSyxDQUFDc0IsU0FBUztNQUNsQixDQUFDckIsTUFBTSxDQUFDdUIsR0FBRyxHQUFHUDtJQUFNLEVBQ3JCO0lBQ0QsSUFBSTtNQUNGLElBQUloQixNQUFNLENBQUNPLFFBQVEsQ0FBQ2lCLE1BQU0sRUFBRTtRQUMxQixNQUFNQyxRQUFRLEdBQUd6QixNQUFNLENBQUNPLFFBQVEsQ0FBQ2lCLE1BQU0sQ0FBQ1IsTUFBTSxFQUFFLEdBQUdoQixNQUFNLENBQUNhLElBQUksQ0FBQztRQUMvRGEsTUFBTSxDQUFDQyxJQUFJLENBQUNGLFFBQVEsQ0FBQyxDQUFDRyxPQUFPLENBQUNMLEdBQUcsSUFBSTtVQUNuQ0YsU0FBUyxDQUFDRSxHQUFHLENBQUMsR0FBR0UsUUFBUSxDQUFDRixHQUFHLENBQUMsQ0FBQ0YsU0FBUyxDQUFDRSxHQUFHLENBQUMsQ0FBQztRQUNoRCxDQUFDLENBQUM7TUFDSjtNQUNBO01BQ0E7SUFDRixDQUFDLENBQUMsT0FBT3JCLEtBQUssRUFBRTtNQUNkMkIsT0FBTyxDQUFDM0IsS0FBSyxDQUNYLDREQUE0REYsTUFBTSxDQUFDdUIsR0FBRyxFQUN4RSxDQUFDO01BQ0RNLE9BQU8sQ0FBQzNCLEtBQUssQ0FBQ0EsS0FBSyxDQUFDO0lBQ3RCO0lBQ0EsT0FBTztNQUNMZSxRQUFRO01BQ1JJLFNBQVM7TUFDVEgsT0FBTztNQUNQUCxJQUFJLEVBQUFXLFFBQUEsS0FDQ3ZCLEtBQUssQ0FBQ1ksSUFBSTtRQUNiLENBQUNYLE1BQU0sQ0FBQ3VCLEdBQUcsR0FBRztVQUNaTyxJQUFJLEVBQUU5QixNQUFNLENBQUNXLElBQUksQ0FBQ21CLElBQUk7VUFDdEJsQixTQUFTLEVBQUVaLE1BQU0sQ0FBQ1csSUFBSSxDQUFDQyxTQUFTO1VBQ2hDbUIsU0FBUyxFQUFFL0IsTUFBTSxDQUFDVyxJQUFJLENBQUNvQixTQUFTO1VBQ2hDQyxhQUFhLEdBQUEzQixxQkFBQSxHQUFFTixLQUFLLENBQUNZLElBQUksQ0FBQ1gsTUFBTSxDQUFDdUIsR0FBRyxDQUFDLHFCQUF0QmxCLHFCQUFBLENBQXdCMEI7UUFDekM7TUFBQyxFQUNGO01BQ0RaLFVBQVU7TUFDVmMsVUFBVSxFQUFFQyxnQkFBZ0IsQ0FBQ25DLEtBQUssRUFBRUMsTUFBTSxDQUFDO01BQzNDbUMsU0FBUyxFQUFFcEMsS0FBSyxDQUFDb0M7SUFDbkIsQ0FBQztJQUNEO0VBQ0YsQ0FBQyxDQUFDLE9BQU9qQyxLQUFVLEVBQUU7SUFDbkIsSUFBSSxPQUFPQSxLQUFLLEtBQUssUUFBUSxFQUFFO01BQzdCQSxLQUFLLENBQUNrQyxPQUFPLEdBQUcsb0JBQ2RwQyxNQUFNLENBQUN1QixHQUFHLG9CQUNRYyxJQUFJLENBQUNDLFNBQVMsQ0FDaEN0QyxNQUFNLENBQUNPLFFBQVEsQ0FBQ2EsTUFBTSxFQUN0Qm1CLFNBQVMsRUFDVCxDQUNGLENBQUMsZUFBZXJDLEtBQUssQ0FBQ2tDLE9BQU8sRUFBRTtNQUMvQixJQUFJLFVBQVUsSUFBSXBDLE1BQU0sRUFBRUUsS0FBSyxDQUFDRSxRQUFRLEdBQUdKLE1BQU0sQ0FBQ0ksUUFBUTtNQUMxREYsS0FBSyxDQUFDc0MsTUFBTSxHQUFHLEdBQUc7SUFDcEI7O0lBRUE7SUFDQTtJQUNBLElBQUlDLE9BQU8sQ0FBQ0MsR0FBRyxDQUFDQyxRQUFRLEtBQUssWUFBWSxFQUFFO01BQ3pDZCxPQUFPLENBQUMzQixLQUFLLENBQUNBLEtBQUssQ0FBQztJQUN0QjtJQUNBLE9BQU9DLFdBQVcsQ0FBQ0osS0FBSyxFQUFFQyxNQUFNLEVBQUVFLEtBQUssQ0FBQztFQUMxQztBQUNGO0FBRUEsU0FBU0MsV0FBV0EsQ0FDbEJKLEtBQXFCLEVBQ3JCQyxNQUE0QyxFQUM1Q0UsS0FBVSxFQUNNO0VBQ2hCLElBQUlBLEtBQUssQ0FBQzBDLElBQUksS0FBSyxZQUFZLEVBQUU7SUFDL0I7SUFDQTtJQUNBO0lBQ0EsT0FBQXRCLFFBQUEsS0FDS3ZCLEtBQUs7TUFDUmtDLFVBQVUsRUFBRUMsZ0JBQWdCLENBQUNuQyxLQUFLLEVBQUVDLE1BQU07SUFBQztFQUUvQztFQUNBLE9BQUFzQixRQUFBLEtBQ0t2QixLQUFLO0lBQ1JZLElBQUksRUFBQVcsUUFBQSxLQUNDdkIsS0FBSyxDQUFDWSxJQUFJO01BQ2IsQ0FBQ1gsTUFBTSxDQUFDdUIsR0FBRyxHQUFHO1FBQ1pPLElBQUksRUFBRTlCLE1BQU0sQ0FBQ1csSUFBSSxDQUFDbUIsSUFBSTtRQUN0QmxCLFNBQVMsRUFBRVosTUFBTSxDQUFDVyxJQUFJLENBQUNDLFNBQVM7UUFDaENtQixTQUFTLEVBQUUvQixNQUFNLENBQUNXLElBQUksQ0FBQ29CLFNBQVM7UUFDaEM3QixLQUFLO1FBQ0wyQyxXQUFXLEVBQUU3QyxNQUFNLENBQUNPLFFBQVEsQ0FBQ3NDLFdBQVcsb0JBQTNCN0MsTUFBTSxDQUFDTyxRQUFRLENBQUNzQyxXQUFXLENBQUczQyxLQUFLO01BQ2xEO0lBQUMsRUFDRjtJQUNEK0IsVUFBVSxFQUFFQyxnQkFBZ0IsQ0FBQ25DLEtBQUssRUFBRUMsTUFBTTtFQUFDO0FBRS9DO0FBQ0E7QUFDQSxTQUFTa0MsZ0JBQWdCQSxDQUN2Qm5DLEtBQXFCLEVBQ3JCK0MsZUFBcUQsRUFDckQ7RUFDQSxPQUFPL0MsS0FBSyxDQUFDa0MsVUFBVSxDQUFDYyxNQUFNLENBQzVCQyxnQkFBZ0IsSUFDZEEsZ0JBQWdCLENBQUN6QixHQUFHLEtBQUt1QixlQUFlLENBQUN2QixHQUFHLEtBQzNDeUIsZ0JBQWdCLENBQUMxQyxJQUFJLEtBQUtWLFVBQVUsR0FDbkNvRCxnQkFBZ0IsQ0FBQ3JDLElBQUksQ0FBQ0MsU0FBUyxLQUFLa0MsZUFBZSxDQUFDbkMsSUFBSSxDQUFDQyxTQUFTLEdBQ2xFb0MsZ0JBQWdCLENBQUNyQyxJQUFJLENBQUNtQixJQUFJLEdBQUdnQixlQUFlLENBQUNuQyxJQUFJLENBQUNtQixJQUFJLENBQzVELENBQUM7QUFDSCIsImlnbm9yZUxpc3QiOltdfQ==