From b3d59ec35c78dba74a1ff10798334e47160a7bcc Mon Sep 17 00:00:00 2001 From: Patrick Borowy Date: Thu, 4 Jul 2019 12:24:36 +0200 Subject: [PATCH 1/9] First commit for a mutation system --- README.md | 2 ++ package.json | 4 ++-- src/index.js | 33 +++++++++++++++++++++++---------- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index f4d4fd4..c74eb52 100644 --- a/README.md +++ b/README.md @@ -147,6 +147,8 @@ Creates a new store, which is a tiny evented state container. **Parameters** - `state` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** Optional initial state (optional, default `{}`) +- `mutations` +- `sync` **Examples** diff --git a/package.json b/package.json index 4345921..2334d1a 100644 --- a/package.json +++ b/package.json @@ -28,11 +28,11 @@ "bundlesize": [ { "path": "full/preact.js", - "maxSize": "760b" + "maxSize": "823b" }, { "path": "dist/unistore.js", - "maxSize": "400b" + "maxSize": "423b" }, { "path": "preact.js", diff --git a/src/index.js b/src/index.js index 4df2006..b43fad7 100644 --- a/src/index.js +++ b/src/index.js @@ -11,9 +11,11 @@ import { assign } from './util'; * store.setState({ a: 'b' }); // logs { a: 'b' } * store.setState({ c: 'd' }); // logs { a: 'b', c: 'd' } */ -export default function createStore(state) { +export default function createStore(state, mutations, sync) { let listeners = []; - state = state || {}; + state = state || {}; + mutations = mutations; + sync = sync || undefined; function unsubscribe(listener) { let out = []; @@ -28,11 +30,17 @@ export default function createStore(state) { listeners = out; } - function setState(update, overwrite, action) { + function setState(update, overwrite, action) { state = overwrite ? update : assign(assign({}, state), update); - let currentListeners = listeners; - for (let i=0; i Date: Thu, 4 Jul 2019 12:28:17 +0200 Subject: [PATCH 2/9] Removed sync parameter --- README.md | 1 - package.json | 4 ++-- src/index.js | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c74eb52..aad772c 100644 --- a/README.md +++ b/README.md @@ -148,7 +148,6 @@ Creates a new store, which is a tiny evented state container. - `state` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** Optional initial state (optional, default `{}`) - `mutations` -- `sync` **Examples** diff --git a/package.json b/package.json index 2334d1a..247e92e 100644 --- a/package.json +++ b/package.json @@ -28,11 +28,11 @@ "bundlesize": [ { "path": "full/preact.js", - "maxSize": "823b" + "maxSize": "817b" }, { "path": "dist/unistore.js", - "maxSize": "423b" + "maxSize": "414b" }, { "path": "preact.js", diff --git a/src/index.js b/src/index.js index b43fad7..aaf87a4 100644 --- a/src/index.js +++ b/src/index.js @@ -11,11 +11,10 @@ import { assign } from './util'; * store.setState({ a: 'b' }); // logs { a: 'b' } * store.setState({ c: 'd' }); // logs { a: 'b', c: 'd' } */ -export default function createStore(state, mutations, sync) { +export default function createStore(state, mutations) { let listeners = []; state = state || {}; mutations = mutations; - sync = sync || undefined; function unsubscribe(listener) { let out = []; From da1a5984f59b3f8519387d72b38e09619e6a6ca0 Mon Sep 17 00:00:00 2001 From: Patrick Borowy Date: Fri, 5 Jul 2019 14:05:14 +0200 Subject: [PATCH 3/9] Added parameters in callback tests and corrected linting --- package.json | 4 ++-- src/index.js | 35 +++++++++++++++++------------------ test/unistore.test.js | 6 +++--- 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index 247e92e..aeebfb7 100644 --- a/package.json +++ b/package.json @@ -28,11 +28,11 @@ "bundlesize": [ { "path": "full/preact.js", - "maxSize": "817b" + "maxSize": "813b" }, { "path": "dist/unistore.js", - "maxSize": "414b" + "maxSize": "411b" }, { "path": "preact.js", diff --git a/src/index.js b/src/index.js index aaf87a4..5021119 100644 --- a/src/index.js +++ b/src/index.js @@ -13,8 +13,7 @@ import { assign } from './util'; */ export default function createStore(state, mutations) { let listeners = []; - state = state || {}; - mutations = mutations; + state = state || {}; function unsubscribe(listener) { let out = []; @@ -29,17 +28,17 @@ export default function createStore(state, mutations) { listeners = out; } - function setState(update, overwrite, action) { + function setState(update, overwrite, action) { state = overwrite ? update : assign(assign({}, state), update); - let currentListeners = listeners; - for (let i=0; i { expect(rval).toBeInstanceOf(Function); store.setState({ a: 'b' }); - expect(sub1).toBeCalledWith(store.getState(), action); + expect(sub1).toBeCalledWith(store.getState(), { a: 'b' }, undefined, undefined); store.subscribe(sub2); store.setState({ c: 'd' }); expect(sub1).toHaveBeenCalledTimes(2); - expect(sub1).toHaveBeenLastCalledWith(store.getState(), action); - expect(sub2).toBeCalledWith(store.getState(), action); + expect(sub1).toHaveBeenLastCalledWith(store.getState(), { c: 'd' }, undefined, undefined); + expect(sub2).toBeCalledWith(store.getState(), { c: 'd' }, undefined, undefined); }); it('should unsubscribe', () => { From 38117fb6247b1aef86c78fd9aacbfcdd858e1238 Mon Sep 17 00:00:00 2001 From: Patrick Borowy Date: Sun, 7 Jul 2019 19:19:43 +0200 Subject: [PATCH 4/9] Corrected mutation function and added a test --- src/index.js | 2 +- test/unistore.test.js | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/index.js b/src/index.js index 5021119..73f652b 100644 --- a/src/index.js +++ b/src/index.js @@ -37,7 +37,7 @@ export default function createStore(state, mutations) { function mutate(act, overwrite) { let key = Object.keys(act)[0]; - setState(mutations[key](state, ...act[key]), overwrite, act); + setState(mutations[key](state, act[key]), overwrite, act); } /** diff --git a/test/unistore.test.js b/test/unistore.test.js index fe065b9..83f7799 100644 --- a/test/unistore.test.js +++ b/test/unistore.test.js @@ -93,5 +93,14 @@ describe('createStore()', () => { expect(sub1).not.toBeCalled(); expect(sub2).not.toBeCalled(); expect(sub3).not.toBeCalled(); - }); + }); + + it('should allow mutations', () => { + let store = createStore({ foo: 0 }, { + setFoo: (state, {v}) => ({ foo: v }), + }) + + store.mutate({ setFoo: { v: 1 } }) + expect(store.getState()).toMatchObject({ foo: 1 }) + }); }); From b435cc2d01b6f84f82b33785f8ee1803a80ba434 Mon Sep 17 00:00:00 2001 From: Patrick Borowy Date: Sun, 7 Jul 2019 23:53:12 +0200 Subject: [PATCH 5/9] action are now sent only when using mutations ; added a test ; removed overwrite parameter in listeners --- README.md | 6 +++--- package.json | 4 ++-- src/index.js | 25 ++++++++++++++----------- test/unistore.test.js | 36 ++++++++++++++++++++++++------------ 4 files changed, 43 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index aad772c..c27d708 100644 --- a/README.md +++ b/README.md @@ -147,15 +147,15 @@ Creates a new store, which is a tiny evented state container. **Parameters** - `state` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** Optional initial state (optional, default `{}`) -- `mutations` +- `mutations` (optional, default `false`) **Examples** ```javascript let store = createStore(); store.subscribe( state => console.log(state) ); -store.setState({ a: 'b' }); // logs { a: 'b' } -store.setState({ c: 'd' }); // logs { a: 'b', c: 'd' } +store.setState({ a: 'b' }); // logs { a: 'b' } +store.setState({ c: 'd' }); // logs { a: 'b', c: 'd' } ``` Returns **[store](#store)** diff --git a/package.json b/package.json index aeebfb7..1d09efd 100644 --- a/package.json +++ b/package.json @@ -28,11 +28,11 @@ "bundlesize": [ { "path": "full/preact.js", - "maxSize": "813b" + "maxSize": "838b" }, { "path": "dist/unistore.js", - "maxSize": "411b" + "maxSize": "439b" }, { "path": "preact.js", diff --git a/src/index.js b/src/index.js index 73f652b..8d210b3 100644 --- a/src/index.js +++ b/src/index.js @@ -8,10 +8,10 @@ import { assign } from './util'; * @example * let store = createStore(); * store.subscribe( state => console.log(state) ); - * store.setState({ a: 'b' }); // logs { a: 'b' } - * store.setState({ c: 'd' }); // logs { a: 'b', c: 'd' } + * store.setState({ a: 'b' }); // logs { a: 'b' } + * store.setState({ c: 'd' }); // logs { a: 'b', c: 'd' } */ -export default function createStore(state, mutations) { +export default function createStore(state, mutations=false) { let listeners = []; state = state || {}; @@ -31,13 +31,16 @@ export default function createStore(state, mutations) { function setState(update, overwrite, action) { state = overwrite ? update : assign(assign({}, state), update); let currentListeners = listeners; - for (let i=0; i { expect(rval).toBeInstanceOf(Function); store.setState({ a: 'b' }); - expect(sub1).toBeCalledWith(store.getState(), { a: 'b' }, undefined, undefined); + expect(sub1).toBeCalledWith(store.getState(), { a: 'b' }); store.subscribe(sub2); store.setState({ c: 'd' }); expect(sub1).toHaveBeenCalledTimes(2); - expect(sub1).toHaveBeenLastCalledWith(store.getState(), { c: 'd' }, undefined, undefined); - expect(sub2).toBeCalledWith(store.getState(), { c: 'd' }, undefined, undefined); - }); + expect(sub1).toHaveBeenLastCalledWith(store.getState(), { c: 'd' }); + expect(sub2).toBeCalledWith(store.getState(), { c: 'd' }); + }); + + it('should invoke subscriptions passing additional action parameter when using mutations', () => { + let store = createStore({ foo: 0 }, { + setFoo: (state, {v}) => ({ foo: v }), + }) + + let sub = jest.fn(); + let rval = store.subscribe(sub); + + store.mutate({ setFoo: { v: 1 } }); + expect(sub).toBeCalledWith(store.getState(), { foo: 1 }, { setFoo: { v: 1 } }) + }); it('should unsubscribe', () => { let store = createStore(); @@ -93,14 +105,14 @@ describe('createStore()', () => { expect(sub1).not.toBeCalled(); expect(sub2).not.toBeCalled(); expect(sub3).not.toBeCalled(); - }); + }); - it('should allow mutations', () => { - let store = createStore({ foo: 0 }, { - setFoo: (state, {v}) => ({ foo: v }), - }) + it('should allow mutations', () => { + let store = createStore({ foo: 0 }, { + setFoo: (state, {v}) => ({ foo: v }), + }) - store.mutate({ setFoo: { v: 1 } }) - expect(store.getState()).toMatchObject({ foo: 1 }) - }); + store.mutate({ setFoo: { v: 1 } }) + expect(store.getState()).toMatchObject({ foo: 1 }) + }); }); From 2c03c330a555d4fc056549ad02c31b6640031bc4 Mon Sep 17 00:00:00 2001 From: Patrick Borowy Date: Mon, 8 Jul 2019 00:22:30 +0200 Subject: [PATCH 6/9] corrected listener parameters to be complient with precedent bahaviour ; corrected missunderstood tests --- src/index.js | 11 ++--------- test/unistore.test.js | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/index.js b/src/index.js index 8d210b3..70039b2 100644 --- a/src/index.js +++ b/src/index.js @@ -31,11 +31,7 @@ export default function createStore(state, mutations=false) { function setState(update, overwrite, action) { state = overwrite ? update : assign(assign({}, state), update); let currentListeners = listeners; - if (mutations) - for (let i=0; i { expect(rval).toBeInstanceOf(Function); store.setState({ a: 'b' }); - expect(sub1).toBeCalledWith(store.getState(), { a: 'b' }); + expect(sub1).toBeCalledWith(store.getState(), action); store.subscribe(sub2); store.setState({ c: 'd' }); expect(sub1).toHaveBeenCalledTimes(2); - expect(sub1).toHaveBeenLastCalledWith(store.getState(), { c: 'd' }); - expect(sub2).toBeCalledWith(store.getState(), { c: 'd' }); - }); + expect(sub1).toHaveBeenLastCalledWith(store.getState(), action); + expect(sub2).toBeCalledWith(store.getState(), action); + }); - it('should invoke subscriptions passing additional action parameter when using mutations', () => { - let store = createStore({ foo: 0 }, { + it('should invoke subscriptions passing additional action parameter when using mutations', () => { + let store = createStore({ foo: 0 }, { setFoo: (state, {v}) => ({ foo: v }), }) - let sub = jest.fn(); - let rval = store.subscribe(sub); + let sub = jest.fn(); + let rval = store.subscribe(sub); - store.mutate({ setFoo: { v: 1 } }); - expect(sub).toBeCalledWith(store.getState(), { foo: 1 }, { setFoo: { v: 1 } }) - }); + store.mutate({ setFoo: { v: 1 } }); + expect(sub).toBeCalledWith(store.getState(), { setFoo: { v: 1 } }) + }); it('should unsubscribe', () => { let store = createStore(); From 0e8c8e2c8626c7293945d34f5aca909f4e575265 Mon Sep 17 00:00:00 2001 From: Patrick Borowy Date: Mon, 8 Jul 2019 00:25:27 +0200 Subject: [PATCH 7/9] corrected useless changes and budget size (preact 818b ; unistore 412b) --- README.md | 4 ++-- package.json | 4 ++-- src/index.js | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c27d708..2306134 100644 --- a/README.md +++ b/README.md @@ -154,8 +154,8 @@ Creates a new store, which is a tiny evented state container. ```javascript let store = createStore(); store.subscribe( state => console.log(state) ); -store.setState({ a: 'b' }); // logs { a: 'b' } -store.setState({ c: 'd' }); // logs { a: 'b', c: 'd' } +store.setState({ a: 'b' }); // logs { a: 'b' } +store.setState({ c: 'd' }); // logs { a: 'b', c: 'd' } ``` Returns **[store](#store)** diff --git a/package.json b/package.json index 1d09efd..45eb546 100644 --- a/package.json +++ b/package.json @@ -28,11 +28,11 @@ "bundlesize": [ { "path": "full/preact.js", - "maxSize": "838b" + "maxSize": "818b" }, { "path": "dist/unistore.js", - "maxSize": "439b" + "maxSize": "412b" }, { "path": "preact.js", diff --git a/src/index.js b/src/index.js index 70039b2..72d19e7 100644 --- a/src/index.js +++ b/src/index.js @@ -8,8 +8,8 @@ import { assign } from './util'; * @example * let store = createStore(); * store.subscribe( state => console.log(state) ); - * store.setState({ a: 'b' }); // logs { a: 'b' } - * store.setState({ c: 'd' }); // logs { a: 'b', c: 'd' } + * store.setState({ a: 'b' }); // logs { a: 'b' } + * store.setState({ c: 'd' }); // logs { a: 'b', c: 'd' } */ export default function createStore(state, mutations=false) { let listeners = []; From 5dea8fa3ca0a9ef7cd6f8f7e7e520c2eb9de1da2 Mon Sep 17 00:00:00 2001 From: Patrick Borowy Date: Mon, 8 Jul 2019 00:50:32 +0200 Subject: [PATCH 8/9] changed test descriptio since there is no additional parameter anymore --- test/unistore.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unistore.test.js b/test/unistore.test.js index ac80e12..65ee594 100644 --- a/test/unistore.test.js +++ b/test/unistore.test.js @@ -47,7 +47,7 @@ describe('createStore()', () => { expect(sub2).toBeCalledWith(store.getState(), action); }); - it('should invoke subscriptions passing additional action parameter when using mutations', () => { + it('should invoke subscriptions using mutations', () => { let store = createStore({ foo: 0 }, { setFoo: (state, {v}) => ({ foo: v }), }) From cc421c0d30b5785c9fc9f4b5f783aeb2a57034fa Mon Sep 17 00:00:00 2001 From: Patrick Borowy Date: Mon, 8 Jul 2019 01:44:28 +0200 Subject: [PATCH 9/9] added mutation condition in apply --- package.json | 4 ++-- src/index.js | 5 ++++- test/unistore.test.js | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 45eb546..64e4cf6 100644 --- a/package.json +++ b/package.json @@ -28,11 +28,11 @@ "bundlesize": [ { "path": "full/preact.js", - "maxSize": "818b" + "maxSize": "819b" }, { "path": "dist/unistore.js", - "maxSize": "412b" + "maxSize": "417b" }, { "path": "preact.js", diff --git a/src/index.js b/src/index.js index 72d19e7..ced5ece 100644 --- a/src/index.js +++ b/src/index.js @@ -55,7 +55,10 @@ export default function createStore(state, mutations=false) { */ action(action) { function apply(result) { - setState(result, false, action); + if (!mutations) + setState(result, false, action); + else + mutate(result, false); } // Note: perf tests verifying this implementation: https://esbench.com/bench/5a295e6299634800a0349500 diff --git a/test/unistore.test.js b/test/unistore.test.js index 65ee594..e4b9ebe 100644 --- a/test/unistore.test.js +++ b/test/unistore.test.js @@ -114,5 +114,5 @@ describe('createStore()', () => { store.mutate({ setFoo: { v: 1 } }) expect(store.getState()).toMatchObject({ foo: 1 }) - }); + }); });