all is converted!

This commit is contained in:
Yanick Champoux 2019-10-24 11:17:57 -04:00
parent 366bd91cf6
commit 44a897ac5a
6 changed files with 40 additions and 31 deletions

View File

@ -1,7 +1,7 @@
import fp from 'lodash/fp'; import fp from 'lodash/fp';
import { Middleware } from 'redux'; import { Middleware, MiddlewareAPI, Dispatch } from 'redux';
import { Dictionary, ActionCreator, Action } from '../types'; import { Dictionary, ActionCreator, Action, UpduxDispatch } from '../types';
const MiddlewareFor = (type: any, mw: Middleware ): Middleware => api => next => action => { const MiddlewareFor = (type: any, mw: Middleware ): Middleware => api => next => action => {
if (type !== '*' && action.type !== type) return next(action); if (type !== '*' && action.type !== type) return next(action);
@ -11,12 +11,13 @@ const MiddlewareFor = (type: any, mw: Middleware ): Middleware => api => next =>
type Next = (action: Action) => any; type Next = (action: Action) => any;
function buildMiddleware( function buildMiddleware<S=any>(
effects : Dictionary<Middleware>= {}, effects : Dictionary<Middleware<{},S,UpduxDispatch>>= {},
actions : Dictionary<ActionCreator>= {}, actions : Dictionary<ActionCreator>= {},
subMiddlewares :Middleware[] = [], subMiddlewares :Middleware<{},S,UpduxDispatch>[] = [],
) { ): Middleware<{},S,UpduxDispatch>
return (api: any) => { {
return (api: MiddlewareAPI<UpduxDispatch,S>) => {
for (let type in actions) { for (let type in actions) {
api.dispatch[type] = (...args:any[]) => api.dispatch(((actions as any)[type] as any)(...args)); api.dispatch[type] = (...args:any[]) => api.dispatch(((actions as any)[type] as any)(...args));
} }

View File

@ -5,7 +5,7 @@ test('actions from mutations', () => {
actions: {foo, bar}, actions: {foo, bar},
} = updux({ } = updux({
mutations: { mutations: {
foo: () => x => x, foo: () => (x:any) => x,
}, },
}); });
@ -24,11 +24,11 @@ test('reducer', () => {
const {actions, reducer} = updux({ const {actions, reducer} = updux({
initial: {counter: 1}, initial: {counter: 1},
mutations: { mutations: {
inc: () => ({counter}) => ({counter: counter + 1}), inc: () => ({counter}:{counter:number}) => ({counter: counter + 1}),
}, },
}); });
let state = reducer(null, {}); let state = reducer(null, {type:'noop'});
expect(state).toEqual({counter: 1}); expect(state).toEqual({counter: 1});
@ -41,16 +41,16 @@ test( 'sub reducers', () => {
const foo = updux({ const foo = updux({
initial: 1, initial: 1,
mutations: { mutations: {
doFoo: () => (x) => x + 1, doFoo: () => (x:number) => x + 1,
doAll: () => x => x + 10, doAll: () => (x:number) => x + 10,
}, },
}); });
const bar = updux({ const bar = updux({
initial: 'a', initial: 'a',
mutations: { mutations: {
doBar: () => x => x + 'a', doBar: () => (x:string) => x + 'a',
doAll: () => x => x + 'b', doAll: () => (x:string) => x + 'b',
} }
}); });
@ -64,7 +64,7 @@ test( 'sub reducers', () => {
expect(Object.keys(actions)).toHaveLength(3); expect(Object.keys(actions)).toHaveLength(3);
let state = reducer(null,{}); let state = reducer(null,{type:'noop'});
expect(state).toEqual({ foo: 1, bar: 'a' }); expect(state).toEqual({ foo: 1, bar: 'a' });
@ -92,7 +92,7 @@ test('precedence between root and sub-reducers', () => {
foo: { bar: 4 }, foo: { bar: 4 },
}, },
mutations: { mutations: {
inc: () => state => { inc: () => (state:any) => {
return { return {
...state, ...state,
surprise: state.foo.bar surprise: state.foo.bar
@ -106,7 +106,7 @@ test('precedence between root and sub-reducers', () => {
quux: 3, quux: 3,
}, },
mutations: { mutations: {
inc: () => state => ({...state, bar: state.bar + 1 }) inc: () => (state:any) => ({...state, bar: state.bar + 1 })
}, },
}), }),
} }
@ -122,7 +122,7 @@ test('precedence between root and sub-reducers', () => {
}); });
function timeout(ms) { function timeout(ms:number) {
return new Promise(resolve => setTimeout(resolve, ms)); return new Promise(resolve => setTimeout(resolve, ms));
} }
@ -133,8 +133,8 @@ test( 'middleware', async () => {
} = updux({ } = updux({
initial: "", initial: "",
mutations: { mutations: {
inc: (addition) => state => state + addition, inc: (addition:number) => (state:number) => state + addition,
doEeet: () => state => { doEeet: () => (state:number) => {
return state + 'Z'; return state + 'Z';
}, },
}, },

View File

@ -1,4 +1,4 @@
import { Middleware } from 'redux'; import { Dispatch, Middleware } from 'redux';
export type Action = { export type Action = {
type: string, type: string,
@ -14,6 +14,8 @@ export type ActionPayloadGenerator = (...args:any[]) => any;
export type ActionCreator = (...args: any[] ) => Action; export type ActionCreator = (...args: any[] ) => Action;
export type UpduxDispatch = Dispatch & Dictionary<ActionCreator>;
export type UpduxConfig<S=any> = Partial<{ export type UpduxConfig<S=any> = Partial<{
initial: S, initial: S,
subduxes: {}, subduxes: {},
@ -21,7 +23,7 @@ export type UpduxConfig<S=any> = Partial<{
[ type: string ]: ActionPayloadGenerator [ type: string ]: ActionPayloadGenerator
}, },
mutations: any, mutations: any,
effects: Dictionary<Middleware>, effects: Dictionary<Middleware<{},S,UpduxDispatch>>,
}>; }>;
export type Upreducer<S=any> = (action:Action) => (state:S) => S; export type Upreducer<S=any> = (action:Action) => (state:S) => S;

View File

@ -6,9 +6,13 @@ import buildMutations from './buildMutations';
import buildCreateStore from './buildCreateStore'; import buildCreateStore from './buildCreateStore';
import buildMiddleware from './buildMiddleware'; import buildMiddleware from './buildMiddleware';
import buildUpreducer from './buildUpreducer'; import buildUpreducer from './buildUpreducer';
import { UpduxConfig, Dictionary, Action, ActionCreator, Mutation, Upreducer } from './types'; import { UpduxConfig, Dictionary, Action, ActionCreator, Mutation, Upreducer, UpduxDispatch } from './types';
import { Middleware } from 'redux'; import { Middleware, Store } from 'redux';
type StoreWithDispatchActions<S=any,Actions={ [action: string]: (...args:any) => Action }> = Store<S> & {
dispatch: { [ type in keyof Actions ]: (...args:any) => void }
};
export class Updux<S=any> { export class Updux<S=any> {
@ -24,9 +28,9 @@ export class Updux<S=any> {
reducer: (state:S|undefined,action:Action) => S; reducer: (state:S|undefined,action:Action) => S;
middleware: Middleware; middleware: Middleware<{},S,UpduxDispatch>;
createStore: Function; createStore: () => StoreWithDispatchActions<S>;
constructor(config: UpduxConfig) { constructor(config: UpduxConfig) {
@ -63,7 +67,9 @@ export class Updux<S=any> {
Object.values(this.subduxes).map( sd => sd.middleware ) Object.values(this.subduxes).map( sd => sd.middleware )
); );
this.createStore = buildCreateStore<S>(this.reducer,this.initial,this.middleware,this.actions); const actions = this.actions;
this.createStore = buildCreateStore<S>(this.reducer,this.initial,this.middleware as Middleware,this.actions) as
() => StoreWithDispatchActions< S, typeof actions >;
} }
} }

View File

@ -8,12 +8,12 @@
"target": "ES2019", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ "target": "ES2019", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"lib": [ "dom", "es2019" ], /* Specify library files to be included in the compilation. */ "lib": [ "dom", "es2019" ], /* Specify library files to be included in the compilation. */
"allowJs": true, /* Allow javascript files to be compiled. */ "allowJs": false, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */ // "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
"declaration": false, /* Generates corresponding '.d.ts' file. */ "declaration": true, /* Generates corresponding '.d.ts' file. */
"declarationMap": false, /* Generates a sourcemap for each corresponding '.d.ts' file. */ "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
"sourceMap": false, /* Generates corresponding '.map' file. */ "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */ // "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./dist", /* Redirect output structure to the directory. */ "outDir": "./dist", /* Redirect output structure to the directory. */
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */