UNPKG

@data-client/core

Version:

Async State Management without the Management. REST, GraphQL, SSE, Websockets, Fetch

114 lines (113 loc) 16.7 kB
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 = { ...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: { ...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 { ...state, optimistic: filterOptimistic(state, action) }; } return { ...state, meta: { ...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,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJub3JtYWxpemUiLCJPUFRJTUlTVElDIiwiQWJvcnRPcHRpbWlzdGljIiwic2V0UmVzcG9uc2VSZWR1Y2VyIiwic3RhdGUiLCJhY3Rpb24iLCJjb250cm9sbGVyIiwiZXJyb3IiLCJyZWR1Y2VFcnJvciIsInJlc3BvbnNlIiwiX3N0YXRlJG1ldGEkYWN0aW9uJGtlIiwidHlwZSIsImVuZHBvaW50IiwiZ2V0T3B0aW1pc3RpY1Jlc3BvbnNlIiwiY2FsbCIsInNuYXBzaG90IiwibWV0YSIsImZldGNoZWRBdCIsImFyZ3MiLCJlIiwiY29uc3RydWN0b3IiLCJyZXN1bHQiLCJlbnRpdGllcyIsImluZGV4ZXMiLCJlbnRpdHlNZXRhIiwic2NoZW1hIiwiZW5kcG9pbnRzIiwia2V5IiwidXBkYXRlIiwidXBkYXRlcnMiLCJPYmplY3QiLCJrZXlzIiwiZm9yRWFjaCIsImNvbnNvbGUiLCJkYXRlIiwiZXhwaXJlc0F0IiwicHJldkV4cGlyZXNBdCIsIm9wdGltaXN0aWMiLCJmaWx0ZXJPcHRpbWlzdGljIiwibGFzdFJlc2V0IiwibWVzc2FnZSIsIkpTT04iLCJzdHJpbmdpZnkiLCJ1bmRlZmluZWQiLCJzdGF0dXMiLCJwcm9jZXNzIiwiZW52IiwiTk9ERV9FTlYiLCJuYW1lIiwiZXJyb3JQb2xpY3kiLCJyZXNvbHZpbmdBY3Rpb24iLCJmaWx0ZXIiLCJvcHRpbWlzdGljQWN0aW9uIl0sInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3N0YXRlL3JlZHVjZXIvc2V0UmVzcG9uc2VSZWR1Y2VyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IG5vcm1hbGl6ZSB9IGZyb20gJ0BkYXRhLWNsaWVudC9ub3JtYWxpenInO1xuXG5pbXBvcnQgeyBPUFRJTUlTVElDIH0gZnJvbSAnLi4vLi4vYWN0aW9uVHlwZXMuanMnO1xuaW1wb3J0IEFib3J0T3B0aW1pc3RpYyBmcm9tICcuLi8uLi9jb250cm9sbGVyL0Fib3J0T3B0aW1pc3RpYy5qcyc7XG5pbXBvcnQgdHlwZSBDb250cm9sbGVyIGZyb20gJy4uLy4uL2NvbnRyb2xsZXIvQ29udHJvbGxlci5qcyc7XG5pbXBvcnQgdHlwZSB7XG4gIFN0YXRlLFxuICBTZXRSZXNwb25zZUFjdGlvbixcbiAgT3B0aW1pc3RpY0FjdGlvbixcbn0gZnJvbSAnLi4vLi4vdHlwZXMuanMnO1xuXG5leHBvcnQgZnVuY3Rpb24gc2V0UmVzcG9uc2VSZWR1Y2VyKFxuICBzdGF0ZTogU3RhdGU8dW5rbm93bj4sXG4gIGFjdGlvbjogT3B0aW1pc3RpY0FjdGlvbiB8IFNldFJlc3BvbnNlQWN0aW9uLFxuICBjb250cm9sbGVyOiBDb250cm9sbGVyLFxuKSB7XG4gIGlmIChhY3Rpb24uZXJyb3IpIHtcbiAgICByZXR1cm4gcmVkdWNlRXJyb3Ioc3RhdGUsIGFjdGlvbiwgYWN0aW9uLnJlc3BvbnNlKTtcbiAgfVxuICB0cnkge1xuICAgIGxldCByZXNwb25zZTogYW55O1xuICAgIC8vIGZvciB0cnVlIHNldCdzIHJlc3BvbnNlIGlzIGNvbnRhaW5lZCBpbiBhY3Rpb25cbiAgICBpZiAoYWN0aW9uLnR5cGUgPT09IE9QVElNSVNUSUMpIHtcbiAgICAgIC8vIHRoaXMgc2hvdWxkIG5ldmVyIGhhcHBlblxuICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgICBpZiAoIWFjdGlvbi5lbmRwb2ludC5nZXRPcHRpbWlzdGljUmVzcG9uc2UpIHJldHVybiBzdGF0ZTtcbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIGNvbXB1dGUgb3B0aW1pc3RpYyByZXNwb25zZSBiYXNlZCBvbiBjdXJyZW50IHN0YXRlXG4gICAgICAgIHJlc3BvbnNlID0gYWN0aW9uLmVuZHBvaW50LmdldE9wdGltaXN0aWNSZXNwb25zZS5jYWxsKFxuICAgICAgICAgIGFjdGlvbi5lbmRwb2ludCxcbiAgICAgICAgICBjb250cm9sbGVyLnNuYXBzaG90KHN0YXRlLCBhY3Rpb24ubWV0YS5mZXRjaGVkQXQpLFxuICAgICAgICAgIC4uLmFjdGlvbi5hcmdzLFxuICAgICAgICApO1xuICAgICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICAgIC8vIEFib3J0T3B0aW1pc3RpYyBtZWFucyAnZG8gbm90aGluZycsIG90aGVyd2lzZSB3ZSBjb3VudCB0aGUgZXhjZXB0aW9uIGFzIGVuZHBvaW50IGZhaWx1cmVcbiAgICAgICAgaWYgKGUuY29uc3RydWN0b3IgPT09IEFib3J0T3B0aW1pc3RpYykge1xuICAgICAgICAgIHJldHVybiBzdGF0ZTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXNwb25zZSA9IGFjdGlvbi5yZXNwb25zZTtcbiAgICB9XG4gICAgY29uc3QgeyByZXN1bHQsIGVudGl0aWVzLCBpbmRleGVzLCBlbnRpdHlNZXRhIH0gPSBub3JtYWxpemUoXG4gICAgICBhY3Rpb24uZW5kcG9pbnQuc2NoZW1hLFxuICAgICAgcmVzcG9uc2UsXG4gICAgICBhY3Rpb24uYXJncyxcbiAgICAgIHN0YXRlLFxuICAgICAgYWN0aW9uLm1ldGEsXG4gICAgKTtcbiAgICBjb25zdCBlbmRwb2ludHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge1xuICAgICAgLi4uc3RhdGUuZW5kcG9pbnRzLFxuICAgICAgW2FjdGlvbi5rZXldOiByZXN1bHQsXG4gICAgfTtcbiAgICB0cnkge1xuICAgICAgaWYgKGFjdGlvbi5lbmRwb2ludC51cGRhdGUpIHtcbiAgICAgICAgY29uc3QgdXBkYXRlcnMgPSBhY3Rpb24uZW5kcG9pbnQudXBkYXRlKHJlc3VsdCwgLi4uYWN0aW9uLmFyZ3MpO1xuICAgICAgICBPYmplY3Qua2V5cyh1cGRhdGVycykuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICAgIGVuZHBvaW50c1trZXldID0gdXBkYXRlcnNba2V5XShlbmRwb2ludHNba2V5XSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgLy8gbm8gcmVhc29uIHRvIGNvbXBsZXRlbHkgZmFpbCBiZWNhdXNlIG9mIHVzZXItY29kZSBlcnJvclxuICAgICAgLy8gaW50ZWdyaXR5IG9mIHRoaXMgc3RhdGUgdXBkYXRlIGlzIHN0aWxsIGd1YXJhbnRlZWRcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc29sZS5lcnJvcihcbiAgICAgICAgYFRoZSBmb2xsb3dpbmcgZXJyb3Igb2NjdXJlZCBkdXJpbmcgRW5kcG9pbnQudXBkYXRlKCkgZm9yICR7YWN0aW9uLmtleX1gLFxuICAgICAgKTtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgZW50aXRpZXMsXG4gICAgICBlbmRwb2ludHMsXG4gICAgICBpbmRleGVzLFxuICAgICAgbWV0YToge1xuICAgICAgICAuLi5zdGF0ZS5tZXRhLFxuICAgICAgICBbYWN0aW9uLmtleV06IHtcbiAgICAgICAgICBkYXRlOiBhY3Rpb24ubWV0YS5kYXRlLFxuICAgICAgICAgIGZldGNoZWRBdDogYWN0aW9uLm1ldGEuZmV0Y2hlZEF0LFxuICAgICAgICAgIGV4cGlyZXNBdDogYWN0aW9uLm1ldGEuZXhwaXJlc0F0LFxuICAgICAgICAgIHByZXZFeHBpcmVzQXQ6IHN0YXRlLm1ldGFbYWN0aW9uLmtleV0/LmV4cGlyZXNBdCxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBlbnRpdHlNZXRhLFxuICAgICAgb3B0aW1pc3RpYzogZmlsdGVyT3B0aW1pc3RpYyhzdGF0ZSwgYWN0aW9uKSxcbiAgICAgIGxhc3RSZXNldDogc3RhdGUubGFzdFJlc2V0LFxuICAgIH07XG4gICAgLy8gcmVkdWNlciBtdXN0IHVwZGF0ZSB0aGUgc3RhdGUsIHNvIGluIGNhc2Ugb2YgcHJvY2Vzc2luZyBlcnJvcnMgd2Ugc2ltcGx5IGNvbXB1dGUgdGhlIGVuZHBvaW50cyBpbmxpbmVcbiAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgIGlmICh0eXBlb2YgZXJyb3IgPT09ICdvYmplY3QnKSB7XG4gICAgICBlcnJvci5tZXNzYWdlID0gYEVycm9yIHByb2Nlc3NpbmcgJHtcbiAgICAgICAgYWN0aW9uLmtleVxuICAgICAgfVxcblxcbkZ1bGwgU2NoZW1hOiAke0pTT04uc3RyaW5naWZ5KFxuICAgICAgICBhY3Rpb24uZW5kcG9pbnQuc2NoZW1hLFxuICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgIDIsXG4gICAgICApfVxcblxcbkVycm9yOlxcbiR7ZXJyb3IubWVzc2FnZX1gO1xuICAgICAgaWYgKCdyZXNwb25zZScgaW4gYWN0aW9uKSBlcnJvci5yZXNwb25zZSA9IGFjdGlvbi5yZXNwb25zZTtcbiAgICAgIGVycm9yLnN0YXR1cyA9IDQwMDtcbiAgICB9XG5cbiAgICAvLyB0aGlzIGlzIG5vdCBhbHdheXMgYnViYmxlZCB1cCwgc28gbGV0J3MgZG91YmxlIHN1cmUgdGhpcyBkb2Vzbid0IGZhaWwgc2lsZW50bHlcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nKSB7XG4gICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlZHVjZUVycm9yKHN0YXRlLCBhY3Rpb24sIGVycm9yKTtcbiAgfVxufVxuXG5mdW5jdGlvbiByZWR1Y2VFcnJvcihcbiAgc3RhdGU6IFN0YXRlPHVua25vd24+LFxuICBhY3Rpb246IFNldFJlc3BvbnNlQWN0aW9uIHwgT3B0aW1pc3RpY0FjdGlvbixcbiAgZXJyb3I6IGFueSxcbik6IFN0YXRlPHVua25vd24+IHtcbiAgaWYgKGVycm9yLm5hbWUgPT09ICdBYm9ydEVycm9yJykge1xuICAgIC8vIEluIGNhc2Ugd2UgYWJvcnQgc2ltcGx5IHVuZG8gdGhlIG9wdGltaXN0aWMgdXBkYXRlIGFuZCBhY3QgbGlrZSBubyBmZXRjaCBldmVuIG9jY3VyZWRcbiAgICAvLyBXZSBzdGlsbCB3YW50IHRob3NlIHdhdGNoaW5nIHByb21pc2VzIGZyb20gZmV0Y2ggZGlyZWN0bHkgdG8gb2JzZXJ2ZWQgdGhlIGFib3J0LCBidXQgd2UgZG9uJ3Qgd2FudCB0b1xuICAgIC8vIFRyaWdnZXIgZXJyb3JzIGluIHRoaXMgY2FzZS4gVGhpcyBtZWFucyB0aGVvcmV0aWNhbGx5IGltcHJvcGVybHkgYnVpbHQgYWJvcnRlcyB1c2VSZXNvdXJjZSgpIGNvdWxkIHN1c3BlbmQgZm9yZXZlci5cbiAgICByZXR1cm4ge1xuICAgICAgLi4uc3RhdGUsXG4gICAgICBvcHRpbWlzdGljOiBmaWx0ZXJPcHRpbWlzdGljKHN0YXRlLCBhY3Rpb24pLFxuICAgIH07XG4gIH1cbiAgcmV0dXJuIHtcbiAgICAuLi5zdGF0ZSxcbiAgICBtZXRhOiB7XG4gICAgICAuLi5zdGF0ZS5tZXRhLFxuICAgICAgW2FjdGlvbi5rZXldOiB7XG4gICAgICAgIGRhdGU6IGFjdGlvbi5tZXRhLmRhdGUsXG4gICAgICAgIGZldGNoZWRBdDogYWN0aW9uLm1ldGEuZmV0Y2hlZEF0LFxuICAgICAgICBleHBpcmVzQXQ6IGFjdGlvbi5tZXRhLmV4cGlyZXNBdCxcbiAgICAgICAgZXJyb3IsXG4gICAgICAgIGVycm9yUG9saWN5OiBhY3Rpb24uZW5kcG9pbnQuZXJyb3JQb2xpY3k/LihlcnJvciksXG4gICAgICB9LFxuICAgIH0sXG4gICAgb3B0aW1pc3RpYzogZmlsdGVyT3B0aW1pc3RpYyhzdGF0ZSwgYWN0aW9uKSxcbiAgfTtcbn1cbi8qKiBGaWx0ZXIgYWxsIHJlcXVlc3RzIHdpdGggc2FtZSBzZXJpYWxpemF0aW9uIHRoYXQgZGlkIG5vdCBzdGFydCBhZnRlciB0aGUgcmVzb2x2aW5nIHJlcXVlc3QgKi9cbmZ1bmN0aW9uIGZpbHRlck9wdGltaXN0aWMoXG4gIHN0YXRlOiBTdGF0ZTx1bmtub3duPixcbiAgcmVzb2x2aW5nQWN0aW9uOiBTZXRSZXNwb25zZUFjdGlvbiB8IE9wdGltaXN0aWNBY3Rpb24sXG4pIHtcbiAgcmV0dXJuIHN0YXRlLm9wdGltaXN0aWMuZmlsdGVyKFxuICAgIG9wdGltaXN0aWNBY3Rpb24gPT5cbiAgICAgIG9wdGltaXN0aWNBY3Rpb24ua2V5ICE9PSByZXNvbHZpbmdBY3Rpb24ua2V5IHx8XG4gICAgICAob3B0aW1pc3RpY0FjdGlvbi50eXBlID09PSBPUFRJTUlTVElDID9cbiAgICAgICAgb3B0aW1pc3RpY0FjdGlvbi5tZXRhLmZldGNoZWRBdCAhPT0gcmVzb2x2aW5nQWN0aW9uLm1ldGEuZmV0Y2hlZEF0XG4gICAgICA6IG9wdGltaXN0aWNBY3Rpb24ubWV0YS5kYXRlID4gcmVzb2x2aW5nQWN0aW9uLm1ldGEuZGF0ZSksXG4gICk7XG59XG4iXSwibWFwcGluZ3MiOiJBQUFBLFNBQVNBLFNBQVMsUUFBUSx3QkFBd0I7QUFFbEQsU0FBU0MsVUFBVSxRQUFRLHNCQUFzQjtBQUNqRCxPQUFPQyxlQUFlLE1BQU0scUNBQXFDO0FBUWpFLE9BQU8sU0FBU0Msa0JBQWtCQSxDQUNoQ0MsS0FBcUIsRUFDckJDLE1BQTRDLEVBQzVDQyxVQUFzQixFQUN0QjtFQUNBLElBQUlELE1BQU0sQ0FBQ0UsS0FBSyxFQUFFO0lBQ2hCLE9BQU9DLFdBQVcsQ0FBQ0osS0FBSyxFQUFFQyxNQUFNLEVBQUVBLE1BQU0sQ0FBQ0ksUUFBUSxDQUFDO0VBQ3BEO0VBQ0EsSUFBSTtJQUFBLElBQUFDLHFCQUFBO0lBQ0YsSUFBSUQsUUFBYTtJQUNqQjtJQUNBLElBQUlKLE1BQU0sQ0FBQ00sSUFBSSxLQUFLVixVQUFVLEVBQUU7TUFDOUI7TUFDQTtNQUNBLElBQUksQ0FBQ0ksTUFBTSxDQUFDTyxRQUFRLENBQUNDLHFCQUFxQixFQUFFLE9BQU9ULEtBQUs7TUFDeEQsSUFBSTtRQUNGO1FBQ0FLLFFBQVEsR0FBR0osTUFBTSxDQUFDTyxRQUFRLENBQUNDLHFCQUFxQixDQUFDQyxJQUFJLENBQ25EVCxNQUFNLENBQUNPLFFBQVEsRUFDZk4sVUFBVSxDQUFDUyxRQUFRLENBQUNYLEtBQUssRUFBRUMsTUFBTSxDQUFDVyxJQUFJLENBQUNDLFNBQVMsQ0FBQyxFQUNqRCxHQUFHWixNQUFNLENBQUNhLElBQ1osQ0FBQztNQUNILENBQUMsQ0FBQyxPQUFPQyxDQUFNLEVBQUU7UUFD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ZCxPQUFPLENBQUMxQixLQUFLLENBQUNBLEtBQUssQ0FBQztJQUN0QjtJQUNBLE9BQU9DLFdBQVcsQ0FBQ0osS0FBSyxFQUFFQyxNQUFNLEVBQUVFLEtBQUssQ0FBQztFQUMxQztBQUNGO0FBRUEsU0FBU0MsV0FBV0EsQ0FDbEJKLEtBQXFCLEVBQ3JCQyxNQUE0QyxFQUM1Q0UsS0FBVSxFQUNNO0VBQ2hCLElBQUlBLEtBQUssQ0FBQ3lDLElBQUksS0FBSyxZQUFZLEVBQUU7SUFDL0I7SUFDQTtJQUNBO0lBQ0EsT0FBTztNQUNMLEdBQUc1QyxLQUFLO01BQ1JpQyxVQUFVLEVBQUVDLGdCQUFnQixDQUFDbEMsS0FBSyxFQUFFQyxNQUFNO0lBQzVDLENBQUM7RUFDSDtFQUNBLE9BQU87SUFDTCxHQUFHRCxLQUFLO0lBQ1JZLElBQUksRUFBRTtNQUNKLEdBQUdaLEtBQUssQ0FBQ1ksSUFBSTtNQUNiLENBQUNYLE1BQU0sQ0FBQ3NCLEdBQUcsR0FBRztRQUNaTyxJQUFJLEVBQUU3QixNQUFNLENBQUNXLElBQUksQ0FBQ2tCLElBQUk7UUFDdEJqQixTQUFTLEVBQUVaLE1BQU0sQ0FBQ1csSUFBSSxDQUFDQyxTQUFTO1FBQ2hDa0IsU0FBUyxFQUFFOUIsTUFBTSxDQUFDVyxJQUFJLENBQUNtQixTQUFTO1FBQ2hDNUIsS0FBSztRQUNMMEMsV0FBVyxFQUFFNUMsTUFBTSxDQUFDTyxRQUFRLENBQUNxQyxXQUFXLG9CQUEzQjVDLE1BQU0sQ0FBQ08sUUFBUSxDQUFDcUMsV0FBVyxDQUFHMUMsS0FBSztNQUNsRDtJQUNGLENBQUM7SUFDRDhCLFVBQVUsRUFBRUMsZ0JBQWdCLENBQUNsQyxLQUFLLEVBQUVDLE1BQU07RUFDNUMsQ0FBQztBQUNIO0FBQ0E7QUFDQSxTQUFTaUMsZ0JBQWdCQSxDQUN2QmxDLEtBQXFCLEVBQ3JCOEMsZUFBcUQsRUFDckQ7RUFDQSxPQUFPOUMsS0FBSyxDQUFDaUMsVUFBVSxDQUFDYyxNQUFNLENBQzVCQyxnQkFBZ0IsSUFDZEEsZ0JBQWdCLENBQUN6QixHQUFHLEtBQUt1QixlQUFlLENBQUN2QixHQUFHLEtBQzNDeUIsZ0JBQWdCLENBQUN6QyxJQUFJLEtBQUtWLFVBQVUsR0FDbkNtRCxnQkFBZ0IsQ0FBQ3BDLElBQUksQ0FBQ0MsU0FBUyxLQUFLaUMsZUFBZSxDQUFDbEMsSUFBSSxDQUFDQyxTQUFTLEdBQ2xFbUMsZ0JBQWdCLENBQUNwQyxJQUFJLENBQUNrQixJQUFJLEdBQUdnQixlQUFlLENBQUNsQyxJQUFJLENBQUNrQixJQUFJLENBQzVELENBQUM7QUFDSCIsImlnbm9yZUxpc3QiOltdfQ==