ngrx-forms
Version:
Proper integration of forms in Angular 4 applications using ngrx
122 lines (120 loc) • 18 kB
JavaScript
import { ALL_NGRX_FORMS_ACTION_TYPES } from './actions';
import { formArrayReducer } from './array/reducer';
import { formControlReducer } from './control/reducer';
import { formGroupReducer } from './group/reducer';
import { isArrayState, isFormState, isGroupState } from './state';
export function formStateReducer(state, action) {
if (!state) {
throw new Error('The form state must be defined!');
}
if (!isFormState(state)) {
throw new Error(`state must be a form state, got ${state}`);
}
if (isGroupState(state)) {
return formGroupReducer(state, action);
}
if (isArrayState(state)) {
return formArrayReducer(state, action);
}
return formControlReducer(state, action);
}
/**
* This function creates a reducer function that first applies an action to the state
* and afterwards applies all given update functions one after another to the resulting
* form state. However, the update functions are only applied if the form state changed
* as result of applying the action. If you need the update functions to be applied
* regardless of whether the state changed (e.g. because the update function closes
* over variables that may change independently of the form state) you can simply apply
* the update manually (e.g. `updateFunction(formStateReducer(state, action))`).
*
* The following (contrived) example uses this function to create a reducer that after
* each action validates the child control `name` to be required and sets the child
* control `email`'s value to be `''` if the name is invalid.
*
```typescript
interface FormValue {
name: string;
email: string;
}
const updateFormState = updateGroup<FormValue>(
{
name: validate(required),
},
{
email: (email, parentGroup) =>
parentGroup.controls.name.isInvalid
? setValue('', email)
: email,
},
);
const reducer = createFormStateReducerWithUpdate<FormValue>(updateFormState);
```
*/
export function createFormStateReducerWithUpdate(updateFnOrUpdateFnArr, ...updateFnArr) {
updateFnArr = [...(Array.isArray(updateFnOrUpdateFnArr) ? updateFnOrUpdateFnArr : [updateFnOrUpdateFnArr]), ...updateFnArr];
return (state, action) => {
const newState = formStateReducer(state, action);
return newState === state ? state : updateFnArr.reduce((s, f) => f(s), newState);
};
}
function reduceNestedFormState(state, key, action) {
const value = state[key];
if (!isFormState(value)) {
return state;
}
return Object.assign(Object.assign({}, state), { [key]: formStateReducer(value, action) });
}
function reduceNestedFormStates(state, action) {
return Object.keys(state).reduce((s, key) => reduceNestedFormState(s, key, action), state);
}
/**
* This function returns an object that can be passed to ngrx's `createReducer`
* function (available starting with ngrx version 8). By doing this all form
* state properties on the state will be updated whenever necessary (i.e.
* whenever an ngrx-forms action is dispatched).
*
* To manually update a form state (e.g. to validate it) use
* `wrapReducerWithFormStateUpdate`.
*/
export function onNgrxForms() {
return {
reducer: (state, action) => isFormState(state) ? formStateReducer(state, action) : reduceNestedFormStates(state, action),
types: ALL_NGRX_FORMS_ACTION_TYPES,
};
}
/**
* Define a reducer for a ngrx-forms action. This functions works the same as
* ngrx's `on` except that you provide the ngrx-forms action class instead of
* your action creator as a parameter.
*/
export function onNgrxFormsAction(actionCons, reducer) {
return {
reducer: (state, action) => reducer(reduceNestedFormStates(state, action), action),
types: [actionCons.TYPE],
};
}
/**
* This function wraps a reducer and returns another reducer that first calls
* the given reducer and then calls the given update function for the form state
* that is specified by the form state locator function.
*
* The update function is passed the form state and the updated containing state
* as parameters.
*/
export function wrapReducerWithFormStateUpdate(reducer, formStateLocator, updateFn) {
return (state, action) => {
const updatedState = reducer(state, action);
const formState = formStateLocator(updatedState);
// if the state itself is the form state, update it directly
if (formState === updatedState) {
return updateFn(formState, updatedState);
}
const formStateKey = Object.keys(updatedState).find(key => updatedState[key] === formState);
const updatedFormState = updateFn(formState, updatedState);
if (updatedFormState === formState) {
return updatedState;
}
return Object.assign(Object.assign({}, updatedState), { [formStateKey]: updatedFormState });
};
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkdWNlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9yZWR1Y2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFBVywyQkFBMkIsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNqRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNuRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNuRCxPQUFPLEVBQXFFLFlBQVksRUFBRSxXQUFXLEVBQUUsWUFBWSxFQUFZLE1BQU0sU0FBUyxDQUFDO0FBRy9JLE1BQU0sVUFBVSxnQkFBZ0IsQ0FDOUIsS0FBbUUsRUFDbkUsTUFBYztJQUVkLElBQUksQ0FBQyxLQUFLLEVBQUU7UUFDVixNQUFNLElBQUksS0FBSyxDQUFDLGlDQUFpQyxDQUFDLENBQUM7S0FDcEQ7SUFFRCxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxFQUFFO1FBQ3ZCLE1BQU0sSUFBSSxLQUFLLENBQUMsbUNBQW1DLEtBQUssRUFBRSxDQUFDLENBQUM7S0FDN0Q7SUFFRCxJQUFJLFlBQVksQ0FBQyxLQUFLLENBQUMsRUFBRTtRQUN2QixPQUFPLGdCQUFnQixDQUFDLEtBQUssRUFBRSxNQUFNLENBQVEsQ0FBQztLQUMvQztJQUVELElBQUksWUFBWSxDQUFDLEtBQUssQ0FBQyxFQUFFO1FBQ3ZCLE9BQU8sZ0JBQWdCLENBQUMsS0FBNEIsRUFBRSxNQUFNLENBQVEsQ0FBQztLQUN0RTtJQUVELE9BQU8sa0JBQWtCLENBQUMsS0FBOEIsRUFBRSxNQUFNLENBQVEsQ0FBQztBQUMzRSxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWlDRztBQUNILE1BQU0sVUFBVSxnQ0FBZ0MsQ0FDOUMscUJBQW9GLEVBQ3BGLEdBQUcsV0FBMkM7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QUFRLEtBQUssU0FBUyxDQUFFLENBQUM7UUFFcEgsTUFBTSxnQkFBZ0IsR0FBRyxRQUFRLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBRTNELElBQUksZ0JBQWdCLEtBQUssU0FBUyxFQUFFO1lBQ2xDLE9BQU8sWUFBWSxDQUFDO1NBQ3JCO1FBRUQsdUNBQ0ssWUFBWSxLQUNmLENBQUMsWUFBWSxDQUFDLEVBQUUsZ0JBQWdCLElBQ2hDO0lBQ0osQ0FBQyxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFjdGlvbiwgQWN0aW9uUmVkdWNlciB9IGZyb20gJ0BuZ3J4L3N0b3JlJztcclxuXHJcbmltcG9ydCB7IEFjdGlvbnMsIEFMTF9OR1JYX0ZPUk1TX0FDVElPTl9UWVBFUyB9IGZyb20gJy4vYWN0aW9ucyc7XHJcbmltcG9ydCB7IGZvcm1BcnJheVJlZHVjZXIgfSBmcm9tICcuL2FycmF5L3JlZHVjZXInO1xyXG5pbXBvcnQgeyBmb3JtQ29udHJvbFJlZHVjZXIgfSBmcm9tICcuL2NvbnRyb2wvcmVkdWNlcic7XHJcbmltcG9ydCB7IGZvcm1Hcm91cFJlZHVjZXIgfSBmcm9tICcuL2dyb3VwL3JlZHVjZXInO1xyXG5pbXBvcnQgeyBBYnN0cmFjdENvbnRyb2xTdGF0ZSwgRm9ybUFycmF5U3RhdGUsIEZvcm1Db250cm9sU3RhdGUsIEZvcm1TdGF0ZSwgaXNBcnJheVN0YXRlLCBpc0Zvcm1TdGF0ZSwgaXNHcm91cFN0YXRlLCBLZXlWYWx1ZSB9IGZyb20gJy4vc3RhdGUnO1xyXG5pbXBvcnQgeyBQcm9qZWN0Rm4gfSBmcm9tICcuL3VwZGF0ZS1mdW5jdGlvbi91dGlsJztcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBmb3JtU3RhdGVSZWR1Y2VyPFRWYWx1ZT4oXHJcbiAgc3RhdGU6IEZvcm1TdGF0ZTxUVmFsdWU+IHwgQWJzdHJhY3RDb250cm9sU3RhdGU8VFZhbHVlPiB8IHVuZGVmaW5lZCxcclxuICBhY3Rpb246IEFjdGlvbixcclxuKTogRm9ybVN0YXRlPFRWYWx1ZT4ge1xyXG4gIGlmICghc3RhdGUpIHtcclxuICAgIHRocm93IG5ldyBFcnJvcignVGhlIGZvcm0gc3RhdGUgbXVzdCBiZSBkZWZpbmVkIScpO1xyXG4gIH1cclxuXHJcbiAgaWYgKCFpc0Zvcm1TdGF0ZShzdGF0ZSkpIHtcclxuICAgIHRocm93IG5ldyBFcnJvcihgc3RhdGUgbXVzdCBiZSBhIGZvcm0gc3RhdGUsIGdvdCAke3N0YXRlfWApO1xyXG4gIH1cclxuXHJcbiAgaWYgKGlzR3JvdXBTdGF0ZShzdGF0ZSkpIHtcclxuICAgIHJldHVybiBmb3JtR3JvdXBSZWR1Y2VyKHN0YXRlLCBhY3Rpb24pIGFzIGFueTtcclxuICB9XHJcblxyXG4gIGlmIChpc0FycmF5U3RhdGUoc3RhdGUpKSB7XHJcbiAgICByZXR1cm4gZm9ybUFycmF5UmVkdWNlcihzdGF0ZSBhcyBGb3JtQXJyYXlTdGF0ZTxhbnk+LCBhY3Rpb24pIGFzIGFueTtcclxuICB9XHJcblxyXG4gIHJldHVybiBmb3JtQ29udHJvbFJlZHVjZXIoc3RhdGUgYXMgRm9ybUNvbnRyb2xTdGF0ZTxhbnk+LCBhY3Rpb24pIGFzIGFueTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFRoaXMgZnVuY3Rpb24gY3JlYXRlcyBhIHJlZHVjZXIgZnVuY3Rpb24gdGhhdCBmaXJzdCBhcHBsaWVzIGFuIGFjdGlvbiB0byB0aGUgc3RhdGVcclxuICogYW5kIGFmdGVyd2FyZHMgYXBwbGllcyBhbGwgZ2l2ZW4gdXBkYXRlIGZ1bmN0aW9ucyBvbmUgYWZ0ZXIgYW5vdGhlciB0byB0aGUgcmVzdWx0aW5nXHJcbiAqIGZvcm0gc3RhdGUuIEhvd2V2ZXIsIHRoZSB1cGRhdGUgZnVuY3Rpb25zIGFyZSBvbmx5IGFwcGxpZWQgaWYgdGhlIGZvcm0gc3RhdGUgY2hhbmdlZFxyXG4gKiBhcyByZXN1bHQgb2YgYXBwbHlpbmcgdGhlIGFjdGlvbi4gSWYgeW91IG5lZWQgdGhlIHVwZGF0ZSBmdW5jdGlvbnMgdG8gYmUgYXBwbGllZFxyXG4gKiByZWdhcmRsZXNzIG9mIHdoZXRoZXIgdGhlIHN0YXRlIGNoYW5nZWQgKGUuZy4gYmVjYXVzZSB0aGUgdXBkYXRlIGZ1bmN0aW9uIGNsb3Nlc1xyXG4gKiBvdmVyIHZhcmlhYmxlcyB0aGF0IG1heSBjaGFuZ2UgaW5kZXBlbmRlbnRseSBvZiB0aGUgZm9ybSBzdGF0ZSkgeW91IGNhbiBzaW1wbHkgYXBwbHlcclxuICogdGhlIHVwZGF0ZSBtYW51YWxseSAoZS5nLiBgdXBkYXRlRnVuY3Rpb24oZm9ybVN0YXRlUmVkdWNlcihzdGF0ZSwgYWN0aW9uKSlgKS5cclxuICpcclxuICogVGhlIGZvbGxvd2luZyAoY29udHJpdmVkKSBleGFtcGxlIHVzZXMgdGhpcyBmdW5jdGlvbiB0byBjcmVhdGUgYSByZWR1Y2VyIHRoYXQgYWZ0ZXJcclxuICogZWFjaCBhY3Rpb24gdmFsaWRhdGVzIHRoZSBjaGlsZCBjb250cm9sIGBuYW1lYCB0byBiZSByZXF1aXJlZCBhbmQgc2V0cyB0aGUgY2hpbGRcclxuICogY29udHJvbCBgZW1haWxgJ3MgdmFsdWUgdG8gYmUgYCcnYCBpZiB0aGUgbmFtZSBpcyBpbnZhbGlkLlxyXG4gKlxyXG5gYGB0eXBlc2NyaXB0XHJcbmludGVyZmFjZSBGb3JtVmFsdWUge1xyXG4gIG5hbWU6IHN0cmluZztcclxuICBlbWFpbDogc3RyaW5nO1xyXG59XHJcblxyXG5jb25zdCB1cGRhdGVGb3JtU3RhdGUgPSB1cGRhdGVHcm91cDxGb3JtVmFsdWU+KFxyXG4gIHtcclxuICAgIG5hbWU6IHZhbGlkYXRlKHJlcXVpcmVkKSxcclxuICB9LFxyXG4gIHtcclxuICAgIGVtYWlsOiAoZW1haWwsIHBhcmVudEdyb3VwKSA9PlxyXG4gICAgICBwYXJlbnRHcm91cC5jb250cm9scy5uYW1lLmlzSW52YWxpZFxyXG4gICAgICAgID8gc2V0VmFsdWUoJycsIGVtYWlsKVxyXG4gICAgICAgIDogZW1haWwsXHJcbiAgfSxcclxuKTtcclxuXHJcbmNvbnN0IHJlZHVjZXIgPSBjcmVhdGVGb3JtU3RhdGVSZWR1Y2VyV2l0aFVwZGF0ZTxGb3JtVmFsdWU+KHVwZGF0ZUZvcm1TdGF0ZSk7XHJcbmBgYFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUZvcm1TdGF0ZVJlZHVjZXJXaXRoVXBkYXRlPFRWYWx1ZT4oXHJcbiAgdXBkYXRlRm5PclVwZGF0ZUZuQXJyOiBQcm9qZWN0Rm48Rm9ybVN0YXRlPFRWYWx1ZT4+IHwgUHJvamVjdEZuPEZvcm1TdGF0ZTxUVmFsdWU+PltdLFxyXG4gIC4uLnVwZGF0ZUZuQXJyOiBQcm9qZWN0Rm48Rm9ybVN0YXRlPFRWYWx1ZT4+W11cclxuKTogQWN0aW9uUmVkdWNlcjxGb3JtU3RhdGU8VFZhbHVlPj4ge1xyXG4gIHVwZGF0ZUZuQXJyID0gWy4uLihBcnJheS5pc0FycmF5KHVwZGF0ZUZuT3JVcGRhdGVGbkFycikgPyB1cGRhdGVGbk9yVXBkYXRlRm5BcnIgOiBbdXBkYXRlRm5PclVwZGF0ZUZuQXJyXSksIC4uLnVwZGF0ZUZuQXJyXTtcclxuICByZXR1cm4gKHN0YXRlOiBGb3JtU3RhdGU8VFZhbHVlPiB8IHVuZGVmaW5lZCwgYWN0aW9uOiBBY3Rpb24pOiBGb3JtU3RhdGU8VFZhbHVlPiA9PiB7XHJcbiAgICBjb25zdCBuZXdTdGF0ZSA9IGZvcm1TdGF0ZVJlZHVjZXIoc3RhdGUgYXMgQWJzdHJhY3RDb250cm9sU3RhdGU8VFZhbHVlPiwgYWN0aW9uKTtcclxuICAgIHJldHVybiBuZXdTdGF0ZSA9PT0gc3RhdGUgPyBzdGF0ZSA6IHVwZGF0ZUZuQXJyLnJlZHVjZSgocywgZikgPT4gZihzKSwgbmV3U3RhdGUpO1xyXG4gIH07XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHJlZHVjZU5lc3RlZEZvcm1TdGF0ZTxUU3RhdGU+KHN0YXRlOiBUU3RhdGUsIGtleToga2V5b2YgVFN0YXRlLCBhY3Rpb246IEFjdGlvbik6IFRTdGF0ZSB7XHJcbiAgY29uc3QgdmFsdWUgPSBzdGF0ZVtrZXldO1xyXG5cclxuICBpZiAoIWlzRm9ybVN0YXRlKHZhbHVlKSkge1xyXG4gICAgcmV0dXJuIHN0YXRlO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHtcclxuICAgIC4uLnN0YXRlLFxyXG4gICAgW2tleV06IGZvcm1TdGF0ZVJlZHVjZXIodmFsdWUsIGFjdGlvbiksXHJcbiAgfTtcclxufVxyXG5cclxuZnVuY3Rpb24gcmVkdWNlTmVzdGVkRm9ybVN0YXRlczxUU3RhdGUgZXh0ZW5kcyBLZXlWYWx1ZT4oc3RhdGU6IFRTdGF0ZSwgYWN0aW9uOiBBY3Rpb24pOiBUU3RhdGUge1xyXG4gIHJldHVybiBPYmplY3Qua2V5cyhzdGF0ZSkucmVkdWNlKChzLCBrZXkpID0+IHJlZHVjZU5lc3RlZEZvcm1TdGF0ZShzLCBrZXkgYXMga2V5b2YgVFN0YXRlLCBhY3Rpb24pLCBzdGF0ZSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBUaGlzIGZ1bmN0aW9uIHJldHVybnMgYW4gb2JqZWN0IHRoYXQgY2FuIGJlIHBhc3NlZCB0byBuZ3J4J3MgYGNyZWF0ZVJlZHVjZXJgXHJcbiAqIGZ1bmN0aW9uIChhdmFpbGFibGUgc3RhcnRpbmcgd2l0aCBuZ3J4IHZlcnNpb24gOCkuIEJ5IGRvaW5nIHRoaXMgYWxsIGZvcm1cclxuICogc3RhdGUgcHJvcGVydGllcyBvbiB0aGUgc3RhdGUgd2lsbCBiZSB1cGRhdGVkIHdoZW5ldmVyIG5lY2Vzc2FyeSAoaS5lLlxyXG4gKiB3aGVuZXZlciBhbiBuZ3J4LWZvcm1zIGFjdGlvbiBpcyBkaXNwYXRjaGVkKS5cclxuICpcclxuICogVG8gbWFudWFsbHkgdXBkYXRlIGEgZm9ybSBzdGF0ZSAoZS5nLiB0byB2YWxpZGF0ZSBpdCkgdXNlXHJcbiAqIGB3cmFwUmVkdWNlcldpdGhGb3JtU3RhdGVVcGRhdGVgLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIG9uTmdyeEZvcm1zPFRTdGF0ZSA9IGFueT4oKTogeyByZWR1Y2VyOiBBY3Rpb25SZWR1Y2VyPFRTdGF0ZT47IHR5cGVzOiBzdHJpbmdbXSB9IHtcclxuICByZXR1cm4ge1xyXG4gICAgcmVkdWNlcjogKHN0YXRlLCBhY3Rpb24pID0+IGlzRm9ybVN0YXRlKHN0YXRlKSA/IGZvcm1TdGF0ZVJlZHVjZXIoc3RhdGUhLCBhY3Rpb24pIGFzIHVua25vd24gYXMgVFN0YXRlIDogcmVkdWNlTmVzdGVkRm9ybVN0YXRlcyhzdGF0ZSEsIGFjdGlvbiksXHJcbiAgICB0eXBlczogQUxMX05HUlhfRk9STVNfQUNUSU9OX1RZUEVTLFxyXG4gIH07XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgQWN0aW9uQ29uc3RydWN0b3Ige1xyXG4gIG5ldyguLi5hcmdzOiBhbnlbXSk6IEFjdGlvbnM8YW55PjtcclxuICByZWFkb25seSBUWVBFOiBzdHJpbmc7XHJcbn1cclxuXHJcbmV4cG9ydCB0eXBlIENyZWF0ZWRBY3Rpb248VEFjdGlvbkNvbnM+ID0gVEFjdGlvbkNvbnMgZXh0ZW5kcyBuZXcgKC4uLmFyZ3M6IGFueVtdKSA9PiBpbmZlciBUQWN0aW9uID8gVEFjdGlvbiA6IG5ldmVyO1xyXG5cclxuLyoqXHJcbiAqIERlZmluZSBhIHJlZHVjZXIgZm9yIGEgbmdyeC1mb3JtcyBhY3Rpb24uIFRoaXMgZnVuY3Rpb25zIHdvcmtzIHRoZSBzYW1lIGFzXHJcbiAqIG5ncngncyBgb25gIGV4Y2VwdCB0aGF0IHlvdSBwcm92aWRlIHRoZSBuZ3J4LWZvcm1zIGFjdGlvbiBjbGFzcyBpbnN0ZWFkIG9mXHJcbiAqIHlvdXIgYWN0aW9uIGNyZWF0b3IgYXMgYSBwYXJhbWV0ZXIuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gb25OZ3J4Rm9ybXNBY3Rpb248XHJcbiAgVEFjdGlvbkNvbnMgZXh0ZW5kcyBBY3Rpb25Db25zdHJ1Y3RvcixcclxuICBUU3RhdGVcclxuPihcclxuICBhY3Rpb25Db25zOiBUQWN0aW9uQ29ucyxcclxuICByZWR1Y2VyOiAoc3RhdGU6IFRTdGF0ZSwgYWN0aW9uOiBDcmVhdGVkQWN0aW9uPFRBY3Rpb25Db25zPikgPT4gVFN0YXRlLFxyXG4pOiB7IHJlZHVjZXI6IEFjdGlvblJlZHVjZXI8VFN0YXRlPjsgdHlwZXM6IHN0cmluZ1tdIH0ge1xyXG4gIHJldHVybiB7XHJcbiAgICByZWR1Y2VyOiAoc3RhdGUsIGFjdGlvbikgPT4gcmVkdWNlcihyZWR1Y2VOZXN0ZWRGb3JtU3RhdGVzKHN0YXRlISwgYWN0aW9uKSwgYWN0aW9uIGFzIGFueSksXHJcbiAgICB0eXBlczogW2FjdGlvbkNvbnMuVFlQRV0sXHJcbiAgfTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFRoaXMgZnVuY3Rpb24gd3JhcHMgYSByZWR1Y2VyIGFuZCByZXR1cm5zIGFub3RoZXIgcmVkdWNlciB0aGF0IGZpcnN0IGNhbGxzXHJcbiAqIHRoZSBnaXZlbiByZWR1Y2VyIGFuZCB0aGVuIGNhbGxzIHRoZSBnaXZlbiB1cGRhdGUgZnVuY3Rpb24gZm9yIHRoZSBmb3JtIHN0YXRlXHJcbiAqIHRoYXQgaXMgc3BlY2lmaWVkIGJ5IHRoZSBmb3JtIHN0YXRlIGxvY2F0b3IgZnVuY3Rpb24uXHJcbiAqXHJcbiAqIFRoZSB1cGRhdGUgZnVuY3Rpb24gaXMgcGFzc2VkIHRoZSBmb3JtIHN0YXRlIGFuZCB0aGUgdXBkYXRlZCBjb250YWluaW5nIHN0YXRlXHJcbiAqIGFzIHBhcmFtZXRlcnMuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gd3JhcFJlZHVjZXJXaXRoRm9ybVN0YXRlVXBkYXRlPFRTdGF0ZSBleHRlbmRzIEtleVZhbHVlLCBURm9ybVN0YXRlIGV4dGVuZHMgQWJzdHJhY3RDb250cm9sU3RhdGU8YW55Pj4oXHJcbiAgcmVkdWNlcjogQWN0aW9uUmVkdWNlcjxUU3RhdGU+LFxyXG4gIGZvcm1TdGF0ZUxvY2F0b3I6IChzdGF0ZTogVFN0YXRlKSA9PiBURm9ybVN0YXRlLFxyXG4gIHVwZGF0ZUZuOiAoZm9ybVN0YXRlOiBURm9ybVN0YXRlLCBzdGF0ZTogVFN0YXRlKSA9PiBURm9ybVN0YXRlLFxyXG4pOiBBY3Rpb25SZWR1Y2VyPFRTdGF0ZT4ge1xyXG4gIHJldHVybiAoc3RhdGUsIGFjdGlvbikgPT4ge1xyXG4gICAgY29uc3QgdXBkYXRlZFN0YXRlID0gcmVkdWNlcihzdGF0ZSwgYWN0aW9uKTtcclxuXHJcbiAgICBjb25zdCBmb3JtU3RhdGUgPSBmb3JtU3RhdGVMb2NhdG9yKHVwZGF0ZWRTdGF0ZSk7XHJcblxyXG4gICAgLy8gaWYgdGhlIHN0YXRlIGl0c2VsZiBpcyB0aGUgZm9ybSBzdGF0ZSwgdXBkYXRlIGl0IGRpcmVjdGx5XHJcbiAgICBpZiAoZm9ybVN0YXRlID09PSB1cGRhdGVkU3RhdGUgYXMgdW5rbm93bikge1xyXG4gICAgICByZXR1cm4gdXBkYXRlRm4oZm9ybVN0YXRlLCB1cGRhdGVkU3RhdGUpIGFzIHVua25vd24gYXMgVFN0YXRlO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGZvcm1TdGF0ZUtleSA9IE9iamVjdC5rZXlzKHVwZGF0ZWRTdGF0ZSkuZmluZChrZXkgPT4gdXBkYXRlZFN0YXRlW2tleSBhcyBrZXlvZiBUU3RhdGVdIGFzIGFueSA9PT0gZm9ybVN0YXRlKSE7XHJcblxyXG4gICAgY29uc3QgdXBkYXRlZEZvcm1TdGF0ZSA9IHVwZGF0ZUZuKGZvcm1TdGF0ZSwgdXBkYXRlZFN0YXRlKTtcclxuXHJcbiAgICBpZiAodXBkYXRlZEZvcm1TdGF0ZSA9PT0gZm9ybVN0YXRlKSB7XHJcbiAgICAgIHJldHVybiB1cGRhdGVkU3RhdGU7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHtcclxuICAgICAgLi4udXBkYXRlZFN0YXRlLFxyXG4gICAgICBbZm9ybVN0YXRlS2V5XTogdXBkYXRlZEZvcm1TdGF0ZSxcclxuICAgIH07XHJcbiAgfTtcclxufVxyXG4iXX0=