Polishing

This commit is contained in:
Kai Moseley 2016-12-04 09:25:21 +00:00
parent b04936697f
commit 71cef6dee8
5 changed files with 25 additions and 18 deletions

View File

@ -5,8 +5,8 @@ import { Types } from './redux-arg/structure';
const exampleReducer = {
example: Types.reducer({
form2: Types.reducer(Types.shape({
lowerLevel: Types.number(),
lowerLevel2: Types.string(),
lowerLevel: Types.number(5),
lowerLevel2: Types.string('Blargle'),
})),
form3: Types.reducer({
example2: Types.reducer(Types.shape({
@ -33,7 +33,7 @@ const store = createStore(
compose(window.devToolsExtension ? window.devToolsExtension() : f => f)
);
store.dispatch(test.actionsObject.example.form2.update({ lowerLevel: 'nom' }));
store.dispatch(test.actionsObject.example.form2.update({ lowerLevel: 2, lowerLevel2: 'Rawrg' }));
store.dispatch(test.actionsObject.example.form2.reset());
store.dispatch(test.actionsObject.example.form2.replace({ toast: 'nommyNom' }));
store.dispatch(test.actionsObject.example.form2.reset());

View File

@ -2,7 +2,7 @@
//==============================
// Flow imports
//==============================
import type { StructureType, PrimitiveType, ShapeStructure } from './structure';
import type { StructureType, PrimitiveType } from './structure';
import type { PartialReducer, Selectors } from './reducers';
import { combineReducers } from 'redux';
@ -10,7 +10,7 @@ import { reduce, find } from 'lodash';
import { createReducer } from './reducers';
import { PROP_TYPES } from './structure';
export function buildReducers(name: string, structure: ShapeStructure, {
export function buildReducers(name: string, structure: any, {
baseSelector = state => state,
locationString = '',
}: {
@ -18,6 +18,7 @@ export function buildReducers(name: string, structure: ShapeStructure, {
locationString: string,
} = {}): PartialReducer {
if (structure === undefined) throw new Error(`The structure must be defined for a reducer! LocationString: ${ locationString }`);
//Build up the reducers, actions, and selectors for this level. Due to recursion,
//these objects will be assigned to a property in the parent object, or simply
//returned to the call site for use in the rest of the application.
@ -37,7 +38,7 @@ export function buildReducers(name: string, structure: ShapeStructure, {
//will be some form of shape (or primitives in the case of arrays). At this point we
//are only interested in whether or not the structure contains reducers, as that
//has an impact on how we proceed with regards to calls.
const { structure: propStructure} = propValue();
const { structure: propStructure } = propValue();
const containsReducers = !!find(propStructure, v => v().type === PROP_TYPES._reducer);
//Create the child reducer. Depending on whether or not the current structure level contains

View File

@ -64,10 +64,11 @@ export function createObjectReducer(reducerShape: StructureType, {
}: ObjectReducerOptions = {}) {
return {
reducers: createReducer(reducerShape, createReducerBehaviors(DEFAULT_OBJECT_BEHAVIORS, locationString)),
actionsObject: createActions(DEFAULT_OBJECT_BEHAVIORS, locationString),
actionsObject: createActions(DEFAULT_OBJECT_BEHAVIORS, locationString, {}),
};
}
function calculateDefaults(reducerStructure) {
return reduce(reducerStructure, (memo, propValue, propName) => ({
...memo,
@ -75,29 +76,32 @@ function calculateDefaults(reducerStructure) {
}), {});
}
function createReducer(objectStructure: StructureType, behaviors: ObjectReducerBehaviors): ObjectReducer {
const initialState = calculateDefaults(objectStructure().structure);
return (state = initialState, { type, payload }: ObjectReducerAction) => {
//If the action type does not match any of the specified behaviors, just return the current state.
if (!behaviors[type]) return state;
//Sanitize the payload using the reducer shape, then
//apply the sanitized payload to the state using the behavior linked to this action type.
//TODO: Add validation to payload
//Sanitize the payload using the reducer shape, then apply the sanitized
//payload to the state using the behavior linked to this action type.
return behaviors[type](state, validateObject(objectStructure, payload), initialState);
}
}
function createActions(behaviorsConfig: ObjectReducerBehaviorsConfig, locationString: string): ObjectActions {
function createActions(behaviorsConfig: ObjectReducerBehaviorsConfig, locationString: string, defaultPayload: any): ObjectActions {
//Take a reducer behavior config object, and create actions using the location string
return reduce(behaviorsConfig, (memo, behavior, name) => ({
...memo,
[name]: (value: Object) => ({
type: `${locationString}.${name}`,
payload: (behavior.action || (() => {}))(value) || {}
payload: (behavior.action || (() => defaultPayload))(value) || {}
})
}), {});
}
function createReducerBehaviors(behaviorsConfig: ObjectReducerBehaviorsConfig, locationString: string): ObjectReducerBehaviors {
//Take a reducer behavior config object, and create the reducer behaviors using the location string
return reduce(behaviorsConfig, (memo, behavior, name) => ({

View File

@ -11,12 +11,13 @@ export type StructureType = () => {
structure: ShapeStructure | StructureType | PrimitiveType
};
export type PrimitiveType = () => {
type: string,
type: $Keys<typeof PROP_TYPES>,
defaultValue?: any,
typeofValue: string,
structure?: PrimitiveType,
};
export type TypesObject = {
[key: string]: CreateArrayType | CreateStringType | CreateNumberType | CreateObjectType;
[key: string]: CreateArrayType | CreateStringType | CreateNumberType | CreateObjectType | CreateBooleanType;
}
export type TypesObjectDefaults = {
@ -26,6 +27,7 @@ export type TypesArrayDefaults = Array<mixed> | Array<TypesObjectDefaults>;
type CreateStringType = (defaultValue: string) => PrimitiveType;
type CreateNumberType = (defaultValue: number) => PrimitiveType;
type CreateBooleanType = (defaultValue: boolean) => PrimitiveType;
type CreateArrayType = (structure: StructureType | PrimitiveType, defaultValue: TypesArrayDefaults | TypesObjectDefaults) => StructureType;
type CreateObjectType = (structure: ShapeStructure, defaultValue: TypesArrayDefaults | TypesObjectDefaults) => StructureType;
@ -45,12 +47,12 @@ export const Types: TypesObject = {
string: (defaultValue: string = '') => () => ({
type: PROP_TYPES._string,
defaultValue,
typeofValue: 'string'
typeofValue: 'string',
}),
number: (defaultValue: number = 0) => () => ({
type: PROP_TYPES._number,
defaultValue,
typeofValue: 'number'
typeofValue: 'number',
}),
boolean: (defaultValue: boolean = false) => () => ({
type: PROP_TYPES._boolean,

View File

@ -21,14 +21,14 @@ export function validateObject(objectStructure: any, value: mixed): Object {
//If the value type does not exist in the reducer structure, we don't want to include it in the payload.
//Display a console error for the developer, and skip the inclusion of this property in the payload.
if (!valueType) {
console.error(`The property, ${name}, was not specified in the structure` +
console.warn(`The property, ${name}, was not specified in the structure` +
' and was stripped out of the payload. Structure: ', objectStructure().structure);
return memo;
}
const validatedValue = getTypeValidation(valueType().type)(valueType, value);
if (validatedValue === undefined) {
console.error(`The property, ${name}, was populated with a type ${ typeof value } which does not` +
console.warn(`The property, ${name}, was populated with a type ${ typeof value } which does not` +
' match that specified in the reducer configuration. It has been stripped from' +
' the payload');
return memo;