reducer-class
Version:
Boilerplate free class-based reducer creator. Built with TypeScript. Works with Redux and NGRX. Has integration with immer.
55 lines (54 loc) • 2.21 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const immer_1 = require("immer");
const constants_1 = require("./constants");
const errors_1 = require("./errors");
const reducer_class_1 = require("./reducer-class");
class ReducerClassHelpers {
typeGuardReducerPure(method) {
return method.length !== 3;
}
addImmerIfNeeded(method) {
if (this.typeGuardReducerPure(method)) {
return method;
}
return (state, action) => immer_1.produce(state, (draft) => method(state, draft, action));
}
getReducerClassMethodsWthActionTypes(instance, keys) {
return keys.reduce((accum, methodName) => {
const actionTypes = Reflect.getMetadata(constants_1.METADATA_KEY_ACTION, instance, methodName);
if (!actionTypes) {
throw new errors_1.MetadataActionMissingError(methodName);
}
const methodBound = instance[methodName].bind(instance);
const method = this.addImmerIfNeeded(methodBound);
actionTypes.forEach((actionType) => accum.push({
actionType,
method,
}));
return accum;
}, []);
}
mergeReducers(...reducers) {
return (state, action) => reducers.reduce((resState, reducer) => reducer(resState, action), state);
}
getReducerMap(data) {
return data.reduce((accum, { method, actionType }) => {
let methodToAdd = method;
if (accum[actionType]) {
methodToAdd = this.mergeReducers(accum[actionType], method);
}
accum[actionType] = methodToAdd;
return accum;
}, {});
}
getClassInstanceMethodNames(obj) {
const proto = Object.getPrototypeOf(obj);
if (!(proto instanceof reducer_class_1.ReducerClass)) {
return [];
}
const protoMethodNames = Object.getOwnPropertyNames(proto).filter((name) => name !== 'constructor' && !name.startsWith(constants_1.PREFIX_OMIT_METHOD));
return [...this.getClassInstanceMethodNames(proto), ...protoMethodNames];
}
}
exports.ReducerClassHelpers = ReducerClassHelpers;