diff --git a/src/buildActions/index.ts b/src/buildActions/index.ts index 0feaa10..0455716 100644 --- a/src/buildActions/index.ts +++ b/src/buildActions/index.ts @@ -1,5 +1,5 @@ import fp from 'lodash/fp'; -import { Action } from '../types'; +import { Action, ActionPayloadGenerator, Dictionary } from '../types'; interface ActionCreator { ( ...args: any[] ): Action; @@ -16,27 +16,25 @@ function actionFor(type:string) { return creator; } -export default function buildActions( - creators : { [action: string]: Function } = {}, - mutations = {}, - effects = {}, - subActions = [], -) { +type ActionPair = [ string, ActionCreator ]; + +function buildActions( + generators : Dictionary = {}, + actionNames: string[] = [], + subActions : ActionPair[] = [], +):Dictionary { // priority => generics => generic subs => craft subs => creators const [ crafted, generic ] = fp.partition( ([type,f]) => !f._genericAction - )( fp.flatten( subActions.map( x => Object.entries(x) ) ).filter( - ([_,f]) => f - ) ) + )( subActions ); const actions = [ - ...([ ...Object.keys(mutations), ...Object.keys(effects) ] - .map( type => [ type, actionFor(type) ] )), + ...(actionNames.map( type => [ type, actionFor(type) ] )), ...generic, ...crafted, - ...Object.entries(creators).map( + ...Object.entries(generators).map( ([type, payload]: [ string, Function ]) => [type, (...args: any) => ({ type, payload: payload(...args) })] ), ]; @@ -44,3 +42,5 @@ export default function buildActions( return fp.fromPairs(actions); } + +export default buildActions; diff --git a/src/buildInitial/index.ts b/src/buildInitial/index.ts index 96e2878..a32431d 100644 --- a/src/buildInitial/index.ts +++ b/src/buildInitial/index.ts @@ -1,9 +1,11 @@ import fp from 'lodash/fp'; +import { Dictionary } from '../types'; -function buildInitial( initial?: Partial, subduxes?: Partial ): S; +function buildInitial( initial: S, subduxes?: Dictionary ): S; +function buildInitial( initial?: Partial, subduxes?: Partial ): S extends object ? S : never; function buildInitial( - initial = {}, - subduxes = {} , + initial : any = {}, + subduxes : any = {} , ) { return fp.isPlainObject(initial) ? fp.mergeAll([subduxes, initial]) : initial; } diff --git a/src/buildMiddleware/index.ts b/src/buildMiddleware/index.ts index 519c62d..bb5d61d 100644 --- a/src/buildMiddleware/index.ts +++ b/src/buildMiddleware/index.ts @@ -12,14 +12,9 @@ const MiddlewareFor = (type: any, mw: Middleware ): Middleware => api => next => type Next = (action: Action) => any; function buildMiddleware( - effects: Dictionary, - actions: Dictionary, - subMiddlewares: Middleware[], -): Middleware -function buildMiddleware( - effects = {}, - actions = {}, - subduxes = {}, + effects : Dictionary= {}, + actions : Dictionary= {}, + subMiddlewares :Middleware[] = [], ) { return (api: any) => { for (let type in actions) { @@ -31,7 +26,7 @@ function buildMiddleware( ...fp.toPairs(effects).map(([type, effect]) => MiddlewareFor(type,effect as Middleware) ), - ...fp.map('middleware', subduxes), + ...subMiddlewares ] .filter(x => x) .reduceRight((next, mw) => mw(api)(next), original_next); diff --git a/src/buildUpreducer/index.ts b/src/buildUpreducer/index.ts index 5209d76..98fac0e 100644 --- a/src/buildUpreducer/index.ts +++ b/src/buildUpreducer/index.ts @@ -1,8 +1,8 @@ import fp from 'lodash/fp'; -import { Dictionary, Mutation, Action } from '../types'; +import { Dictionary, Mutation, Action, Upreducer } from '../types'; -function buildUpreducer(initial: S, mutations: Dictionary> ) { +function buildUpreducer(initial: S, mutations: Dictionary> ): Upreducer { return (action :Action) => (state: S) => { if (state === null) state = initial; diff --git a/src/types.ts b/src/types.ts index b1df809..a303474 100644 --- a/src/types.ts +++ b/src/types.ts @@ -9,11 +9,12 @@ export type Dictionary = { [key: string]: T }; export type Mutation = (payload: any, action: Action) => (state: S) => S ; -type ActionPayloadGenerator = (...args:any[]) => any; +export type ActionPayloadGenerator = (...args:any[]) => any; export type ActionCreator = (...args: any[] ) => Action; -export type UpduxConfig = Partial<{ +export type UpduxConfig = Partial<{ + initial: S, subduxes: {}, actions: { [ type: string ]: ActionPayloadGenerator @@ -21,3 +22,5 @@ export type UpduxConfig = Partial<{ mutations: any, effects: any, }>; + +export type Upreducer = (action:Action) => (state:S) => S; diff --git a/src/updux.ts b/src/updux.ts index cbe237b..f734082 100644 --- a/src/updux.ts +++ b/src/updux.ts @@ -6,15 +6,28 @@ import buildMutations from './buildMutations'; import buildCreateStore from './buildCreateStore'; import buildMiddleware from './buildMiddleware'; import buildUpreducer from './buildUpreducer'; -import { UpduxConfig, Dictionary, Action, ActionCreator } from './types'; +import { UpduxConfig, Dictionary, Action, ActionCreator, Mutation, Upreducer } from './types'; +import { Middleware } from 'redux'; -export class Updux { +export class Updux { subduxes: Dictionary; actions: Dictionary + initial: S; + + mutations: Dictionary; + + upreducer: Upreducer; + + reducer: (state:S|undefined,action:Action) => S; + + middleware: Middleware; + + createStore: Function; + constructor(config: UpduxConfig) { this.subduxes = fp.mapValues( @@ -24,12 +37,11 @@ export class Updux { this.actions = buildActions( config.actions, - config.mutations, - config.effects, - Object.values( this.subduxes ).map( ({actions}) => actions ), + [ ...Object.keys(config.mutations||{}), ...Object.keys(config.effects||{} ) ], + fp.flatten( Object.values( this.subduxes ).map( ({actions}:Updux) => Object.entries(actions) ) ), ) - this.initial = buildInitial( + this.initial = buildInitial( config.initial, fp.mapValues( ({initial}) => initial )(this.subduxes) ); @@ -42,16 +54,16 @@ export class Updux { ); this.reducer = (state,action) => { - return this.upreducer(action)(state); + return this.upreducer(action)(state as S); } this.middleware = buildMiddleware( config.effects, this.actions, - config.subduxes, + Object.values(this.subduxes).map( sd => sd.middleware ) ); - this.createStore = buildCreateStore(this.reducer,this.initial,this.middleware,this.actions); + this.createStore = buildCreateStore(this.reducer,this.initial,this.middleware,this.actions); } }