diff --git a/docs/updux.md b/docs/updux.md index 4b8b0d1..d95ba2c 100644 --- a/docs/updux.md +++ b/docs/updux.md @@ -283,7 +283,9 @@ store.dispatch.addTodo(...); store.dispatch( actions.addTodo(...) ); ``` -## asDux +## Methods + +### asDux Returns a [ducks](https://github.com/erikras/ducks-modular-redux)-like @@ -291,7 +293,7 @@ plain object holding the reducer from the Updux object and all its trimmings. -## addMutation +### addMutation Adds a mutation and its associated action to the updux. If a local mutation was already associated to the action, @@ -303,3 +305,30 @@ conditionally run the subduxes mutations, check out [[subduxUpreducer]]. ```js updux.addMutation( add, inc => state => state + inc ); ``` + +### addAction + +```js +const action = updux.addAction( name, ...creatorArgs ); +const action = updux.addAction( otherActionCreator ); +``` + +Adds an action to the updux. It can take an already defined action creator, +or any arguments that can be passed to `actionCreator`. + +```js +import {actionCreator, Updux} from 'updux'; + +const updux = new Updux(); + +const foo = updux.addAction('foo'); +const bar = updux.addAction( 'bar', (x) => ({stuff: x+1}) ); + +const baz = actionCreator( 'baz' ); + +foo({ a: 1}); // => { type: 'foo', payload: { a: 1 } } +bar(2); // => { type: 'bar', payload: { stuff: 3 } } +baz(); // => { type: 'baz', payload: undefined } + +``` + diff --git a/src/actions.test.ts b/src/actions.test.ts index 1ce7077..7b90a95 100644 --- a/src/actions.test.ts +++ b/src/actions.test.ts @@ -1,38 +1,65 @@ -import Updux from "."; -import u from "updeep"; +import Updux, {actionCreator} from '.'; +import u from 'updeep'; const noopEffect = () => () => () => {}; -test.only("actions defined in effects and mutations, multi-level", () => { - const { actions } = new Updux({ +test('actions defined in effects and mutations, multi-level', () => { + const {actions} = new Updux({ effects: { - foo: noopEffect + foo: noopEffect, }, - mutations: { bar: () => () => null }, + mutations: {bar: () => () => null}, subduxes: { mysub: { - effects: { baz: noopEffect }, - mutations: { quux: () => () => null }, + effects: {baz: noopEffect}, + mutations: {quux: () => () => null}, actions: { - foo: (limit: number) => ({ limit }) - } + foo: (limit: number) => ({limit}), + }, }, myothersub: { effects: { - foo: noopEffect - } - } - } + foo: noopEffect, + }, + }, + }, }); const types = Object.keys(actions); types.sort(); - expect(types).toEqual(["bar", "baz", "foo", "quux"]); + expect(types).toEqual(['bar', 'baz', 'foo', 'quux']); - expect(actions.bar()).toEqual({ type: "bar" }); - expect(actions.bar("xxx")).toEqual({ type: "bar", payload: "xxx" }); - expect(actions.bar(undefined, "yyy")).toEqual({ type: "bar", meta: "yyy" }); + expect(actions.bar()).toEqual({type: 'bar'}); + expect(actions.bar('xxx')).toEqual({type: 'bar', payload: 'xxx'}); + expect(actions.bar(undefined, 'yyy')).toEqual({type: 'bar', meta: 'yyy'}); - expect(actions.foo(12)).toEqual({ type: "foo", payload: { limit: 12 } }); + expect(actions.foo(12)).toEqual({type: 'foo', payload: {limit: 12}}); +}); + +describe('different calls to addAction', () => { + const updux = new Updux(); + + test('string', () => { + updux.addAction('foo'); + expect(updux.actions.foo('yo')).toMatchObject({ + type: 'foo', + payload: 'yo', + }); + }); + + test('actionCreator', () => { + const bar = actionCreator('bar', null); + updux.addAction(bar); + expect(updux.actions.bar()).toMatchObject({ + type: 'bar', + }); + }); + + test('actionCreator inlined', () => { + updux.addAction('baz', (x) => ({x})); + expect(updux.actions.baz(3)).toMatchObject({ + type: 'baz', payload: { x: 3 } + }); + }); }); diff --git a/src/updux.ts b/src/updux.ts index 4a44afa..2df48c3 100644 --- a/src/updux.ts +++ b/src/updux.ts @@ -21,7 +21,7 @@ import { EffectEntry } from "./types"; -import { Middleware, Store } from "redux"; +import { Middleware, Store, PreloadedState } from "redux"; export { actionCreator } from "./buildActions"; type StoreWithDispatchActions< @@ -129,7 +129,7 @@ export class Updux { return buildCreateStore( this.reducer, - this.initial, + this.initial as PreloadedState, this.middleware as any, actions ) as () => StoreWithDispatchActions; @@ -175,14 +175,17 @@ export class Updux { this.localEffects.push([c.type, middleware, isGenerator]); } - addAction(action: string | ActionCreator) { + addAction(action: string, transform?: any): ActionCreator + addAction(action: ActionCreator, transform?: never): ActionCreator + addAction(action: any,transform:any) { if (typeof action === "string") { if (!this.localActions[action]) { - this.localActions[action] = actionFor(action); + this.localActions[action] = actionCreator(action,transform); } - } else { - this.localActions[action.type] = action; + return this.localActions[action]; } + + return this.localActions[action.type] = action; } get _middlewareEntries() { diff --git a/tsconfig.json b/tsconfig.json index b8a8c14..f45ba03 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -27,7 +27,7 @@ /* Strict Type-Checking Options */ "strict": true, /* Enable all strict type-checking options. */ - "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + "noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ // "strictFunctionTypes": true, /* Enable strict checking of function types. */ // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */