Comparing version 0.1.3 to 0.1.4
@@ -1,2 +0,2 @@ | ||
var n="development"===process.env.NODE_ENV,t={effects:{},coeffects:{},events:{}},e=Object.assign({},t),o={};function c(t){var e=t.eventId,c=t.payload;void 0===c&&(c={}),function(t,e){n&&(console.group("Dispatching event:"),console.info("EventId:",t),console.log("Payload:",e),console.groupEnd())}(e,c),function(n){n&&Object.keys(n).forEach(function(t){var e=n[t];v(t)(e)})}(p(e)(o[e].reduce(function(n,t){if("string"==(c=typeof(o=t))||"object"===c&&null!=o&&!Array.isArray(o)&&"[object String]"===y.call(o)){var e=l(t);return Object.assign({},n,e())}var o,c;!function(n){if(!n||null==n.id)throw new Error("Coeffect description is not a valid object, an id property is required")}(t);var i=t.data,r=l(t.id);return Object.assign({},n,r(i))},{}),c))}function i(n){n.forEach(function(n){c(n)})}function r(n,t,e){void 0===e&&(e=[]),d("events",n,t),o[n]=e}function f(n,t){d("coeffects",n,t)}function u(n,t){d("effects",n,t)}function a(n,t){n.forEach(function(n){r(n,function(n,e){return{dispatch:{eventId:t,payload:e}}})})}function s(n,t){var o=e[n][t];if(!o)throw new Error("There is no handler called '"+t+"'.");return o}function d(n,t,o){e[n][t]=o}function l(n){return s("coeffects",n)}function v(n){return s("effects",n)}function p(n){return s("events",n)}function h(){e=Object.assign({},t),o={}}function g(t){n=t}u("dispatch",function(n){c(n)}),u("dispatchMany",function(n){i(n)}),u("dispatchLater",function(n){!function(n){setTimeout(function(){c(n)},n.milliseconds)}(n)});var y=Object.prototype.toString;export{c as dispatch,i as dispatchMany,r as registerEventHandler,f as registerCoeffectHandler,u as registerEffectHandler,a as registerEventsDelegation,l as getCoeffectHandler,v as getEffectHandler,p as getEventHandler,h as clearHandlers,g as setVerbosity}; | ||
var n="development"===process.env.NODE_ENV,o={effects:{},coeffects:{},events:{}},t=Object.assign({},o),e={};function c(o){j(o,"event");var t=function(n){return y(n)?{id:n}:n}(o),c=t.id,i=t.payload;!function(o,t){n&&(console.groupCollapsed("Dispatching event: "+o),console.info("EventId:",o),console.log("Payload:",t),console.groupEnd())}(c,i),function(o){o&&Object.entries(o).forEach(function(o){var t=o[0],e=o[1];!function(o,t){n&&(console.groupCollapsed("Applying effect: "+o),console.info("Effect id:",o),t&&console.log("Effect data:",coeffectDescription.data),console.groupEnd())}(t,e),E(t)(e)})}(g(c)(e[c].reduce(function(o,t){return Object.assign({},o,function(o){return j(o,"coeffect"),function(o){n&&(console.groupCollapsed("Extracting values of coeffect: "+o.id),console.info("Coeffect id:",o.id),console.log("Coeffect data:",o.data),console.groupEnd())}(o),y(o)?p(o)():p(o.id)(o.data)}(t))},{}),i))}function i(n){n.forEach(function(n){c(n)})}function f(n,o,t){void 0===t&&(t=[]),l("events",n,o),e[n]=t}function r(n,o){l("coeffects",n,o)}function a(n,o){l("effects",n,o)}function u(n,o){n.forEach(function(n){f(n,function(n,t){return{dispatch:{id:o,payload:t}}})})}function s(n,o){var e=t[n][o];if(!e)throw new Error("There is no handler called '"+o+"'.");return e}function d(n,o){return o?{id:n,data:o}:n}function l(n,o,e){t[n][o]=e}function p(n){return s("coeffects",n)}function E(n){return s("effects",n)}function g(n){return s("events",n)}function v(){t=Object.assign({},o),e={}}function h(o){n=o}a("dispatch",function(n){c(n)}),a("dispatchMany",function(n){i(n)}),a("dispatchLater",function(n){!function(n){setTimeout(function(){c(n)},n.milliseconds)}(n)});var b=Object.prototype.toString;function y(n){var o=typeof n;return"string"===o||"object"===o&&null!=n&&!Array.isArray(n)&&"[object String]"===b.call(n)}function j(n,o){var t={coeffect:"It must be an object with the following format `{ id: 'COEFFECT_ID', data: <Object | any> }`, or a string if no data is needed: 'EVENT_ID'",event:"It must be an object with the following format `{ id: 'EVENT_ID', payload: <Object | any> }`, or a string if no payload is needed: 'EVENT_ID'"};n||function(n){throw new Error("Not defined "+o+".\n"+t[o])}(),y(n)||null!=n.id||function(n){throw new Error("Not valid "+o+".\n"+t[o])}()}export{c as dispatch,i as dispatchMany,f as registerEventHandler,r as registerCoeffectHandler,a as registerEffectHandler,u as registerEventsDelegation,d as coeffect,p as getCoeffectHandler,E as getEffectHandler,g as getEventHandler,v as clearHandlers,h as setVerbosity}; | ||
//# sourceMappingURL=reffects.es.js.map |
@@ -1,2 +0,2 @@ | ||
var e="development"===process.env.NODE_ENV,t={effects:{},coeffects:{},events:{}},n=Object.assign({},t),o={};function r(t){var n=t.eventId,r=t.payload;void 0===r&&(r={}),function(t,n){e&&(console.group("Dispatching event:"),console.info("EventId:",t),console.log("Payload:",n),console.groupEnd())}(n,r),function(e){e&&Object.keys(e).forEach(function(t){var n=e[t];d(t)(n)})}(l(n)(o[n].reduce(function(e,t){if("string"==(r=typeof(o=t))||"object"===r&&null!=o&&!Array.isArray(o)&&"[object String]"===p.call(o)){var n=u(t);return Object.assign({},e,n())}var o,r;!function(e){if(!e||null==e.id)throw new Error("Coeffect description is not a valid object, an id property is required")}(t);var c=t.data,i=u(t.id);return Object.assign({},e,i(c))},{}),r))}function c(e){e.forEach(function(e){r(e)})}function i(e,t,n){void 0===n&&(n=[]),a("events",e,t),o[e]=n}function s(e,t){a("effects",e,t)}function f(e,t){var o=n[e][t];if(!o)throw new Error("There is no handler called '"+t+"'.");return o}function a(e,t,o){n[e][t]=o}function u(e){return f("coeffects",e)}function d(e){return f("effects",e)}function l(e){return f("events",e)}s("dispatch",function(e){r(e)}),s("dispatchMany",function(e){c(e)}),s("dispatchLater",function(e){!function(e){setTimeout(function(){r(e)},e.milliseconds)}(e)});var p=Object.prototype.toString;exports.dispatch=r,exports.dispatchMany=c,exports.registerEventHandler=i,exports.registerCoeffectHandler=function(e,t){a("coeffects",e,t)},exports.registerEffectHandler=s,exports.registerEventsDelegation=function(e,t){e.forEach(function(e){i(e,function(e,n){return{dispatch:{eventId:t,payload:n}}})})},exports.getCoeffectHandler=u,exports.getEffectHandler=d,exports.getEventHandler=l,exports.clearHandlers=function(){n=Object.assign({},t),o={}},exports.setVerbosity=function(t){e=t}; | ||
var e="development"===process.env.NODE_ENV,t={effects:{},coeffects:{},events:{}},n=Object.assign({},t),o={};function c(t){E(t,"event");var n=function(e){return g(e)?{id:e}:e}(t),c=n.id,r=n.payload;!function(t,n){e&&(console.groupCollapsed("Dispatching event: "+t),console.info("EventId:",t),console.log("Payload:",n),console.groupEnd())}(c,r),function(t){t&&Object.entries(t).forEach(function(t){var n=t[0],o=t[1];!function(t,n){e&&(console.groupCollapsed("Applying effect: "+t),console.info("Effect id:",t),n&&console.log("Effect data:",coeffectDescription.data),console.groupEnd())}(n,o),u(n)(o)})}(l(c)(o[c].reduce(function(t,n){return Object.assign({},t,function(t){return E(t,"coeffect"),function(t){e&&(console.groupCollapsed("Extracting values of coeffect: "+t.id),console.info("Coeffect id:",t.id),console.log("Coeffect data:",t.data),console.groupEnd())}(t),g(t)?d(t)():d(t.id)(t.data)}(n))},{}),r))}function r(e){e.forEach(function(e){c(e)})}function i(e,t,n){void 0===n&&(n=[]),s("events",e,t),o[e]=n}function f(e,t){s("effects",e,t)}function a(e,t){var o=n[e][t];if(!o)throw new Error("There is no handler called '"+t+"'.");return o}function s(e,t,o){n[e][t]=o}function d(e){return a("coeffects",e)}function u(e){return a("effects",e)}function l(e){return a("events",e)}f("dispatch",function(e){c(e)}),f("dispatchMany",function(e){r(e)}),f("dispatchLater",function(e){!function(e){setTimeout(function(){c(e)},e.milliseconds)}(e)});var p=Object.prototype.toString;function g(e){var t=typeof e;return"string"===t||"object"===t&&null!=e&&!Array.isArray(e)&&"[object String]"===p.call(e)}function E(e,t){var n={coeffect:"It must be an object with the following format `{ id: 'COEFFECT_ID', data: <Object | any> }`, or a string if no data is needed: 'EVENT_ID'",event:"It must be an object with the following format `{ id: 'EVENT_ID', payload: <Object | any> }`, or a string if no payload is needed: 'EVENT_ID'"};e||function(e){throw new Error("Not defined "+t+".\n"+n[t])}(),g(e)||null!=e.id||function(e){throw new Error("Not valid "+t+".\n"+n[t])}()}exports.dispatch=c,exports.dispatchMany=r,exports.registerEventHandler=i,exports.registerCoeffectHandler=function(e,t){s("coeffects",e,t)},exports.registerEffectHandler=f,exports.registerEventsDelegation=function(e,t){e.forEach(function(e){i(e,function(e,n){return{dispatch:{id:t,payload:n}}})})},exports.coeffect=function(e,t){return t?{id:e,data:t}:e},exports.getCoeffectHandler=d,exports.getEffectHandler=u,exports.getEventHandler=l,exports.clearHandlers=function(){n=Object.assign({},t),o={}},exports.setVerbosity=function(t){e=t}; | ||
//# sourceMappingURL=reffects.js.map |
@@ -1,2 +0,2 @@ | ||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n(e.reffects={})}(this,function(e){var n="development"===process.env.NODE_ENV,t={effects:{},coeffects:{},events:{}},o=Object.assign({},t),c={};function i(e){var t=e.eventId,o=e.payload;void 0===o&&(o={}),function(e,t){n&&(console.group("Dispatching event:"),console.info("EventId:",e),console.log("Payload:",t),console.groupEnd())}(t,o),function(e){e&&Object.keys(e).forEach(function(n){var t=e[n];l(n)(t)})}(p(t)(c[t].reduce(function(e,n){if("string"==(c=typeof(o=n))||"object"===c&&null!=o&&!Array.isArray(o)&&"[object String]"===v.call(o)){var t=d(n);return Object.assign({},e,t())}var o,c;!function(e){if(!e||null==e.id)throw new Error("Coeffect description is not a valid object, an id property is required")}(n);var i=n.data,r=d(n.id);return Object.assign({},e,r(i))},{}),o))}function r(e){e.forEach(function(e){i(e)})}function f(e,n,t){void 0===t&&(t=[]),u("events",e,n),c[e]=t}function s(e,n){u("effects",e,n)}function a(e,n){var t=o[e][n];if(!t)throw new Error("There is no handler called '"+n+"'.");return t}function u(e,n,t){o[e][n]=t}function d(e){return a("coeffects",e)}function l(e){return a("effects",e)}function p(e){return a("events",e)}s("dispatch",function(e){i(e)}),s("dispatchMany",function(e){r(e)}),s("dispatchLater",function(e){!function(e){setTimeout(function(){i(e)},e.milliseconds)}(e)});var v=Object.prototype.toString;e.dispatch=i,e.dispatchMany=r,e.registerEventHandler=f,e.registerCoeffectHandler=function(e,n){u("coeffects",e,n)},e.registerEffectHandler=s,e.registerEventsDelegation=function(e,n){e.forEach(function(e){f(e,function(e,t){return{dispatch:{eventId:n,payload:t}}})})},e.getCoeffectHandler=d,e.getEffectHandler=l,e.getEventHandler=p,e.clearHandlers=function(){o=Object.assign({},t),c={}},e.setVerbosity=function(e){n=e}}); | ||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n(e.reffects={})}(this,function(e){var n="development"===process.env.NODE_ENV,t={effects:{},coeffects:{},events:{}},o=Object.assign({},t),c={};function f(e){v(e,"event");var t=function(e){return E(e)?{id:e}:e}(e),o=t.id,f=t.payload;!function(e,t){n&&(console.groupCollapsed("Dispatching event: "+e),console.info("EventId:",e),console.log("Payload:",t),console.groupEnd())}(o,f),function(e){e&&Object.entries(e).forEach(function(e){var t=e[0],o=e[1];!function(e,t){n&&(console.groupCollapsed("Applying effect: "+e),console.info("Effect id:",e),t&&console.log("Effect data:",coeffectDescription.data),console.groupEnd())}(t,o),l(t)(o)})}(p(o)(c[o].reduce(function(e,t){return Object.assign({},e,function(e){return v(e,"coeffect"),function(e){n&&(console.groupCollapsed("Extracting values of coeffect: "+e.id),console.info("Coeffect id:",e.id),console.log("Coeffect data:",e.data),console.groupEnd())}(e),E(e)?u(e)():u(e.id)(e.data)}(t))},{}),f))}function i(e){e.forEach(function(e){f(e)})}function r(e,n,t){void 0===t&&(t=[]),d("events",e,n),c[e]=t}function a(e,n){d("effects",e,n)}function s(e,n){var t=o[e][n];if(!t)throw new Error("There is no handler called '"+n+"'.");return t}function d(e,n,t){o[e][n]=t}function u(e){return s("coeffects",e)}function l(e){return s("effects",e)}function p(e){return s("events",e)}a("dispatch",function(e){f(e)}),a("dispatchMany",function(e){i(e)}),a("dispatchLater",function(e){!function(e){setTimeout(function(){f(e)},e.milliseconds)}(e)});var g=Object.prototype.toString;function E(e){var n=typeof e;return"string"===n||"object"===n&&null!=e&&!Array.isArray(e)&&"[object String]"===g.call(e)}function v(e,n){var t={coeffect:"It must be an object with the following format `{ id: 'COEFFECT_ID', data: <Object | any> }`, or a string if no data is needed: 'EVENT_ID'",event:"It must be an object with the following format `{ id: 'EVENT_ID', payload: <Object | any> }`, or a string if no payload is needed: 'EVENT_ID'"};e||function(e){throw new Error("Not defined "+n+".\n"+t[n])}(),E(e)||null!=e.id||function(e){throw new Error("Not valid "+n+".\n"+t[n])}()}e.dispatch=f,e.dispatchMany=i,e.registerEventHandler=r,e.registerCoeffectHandler=function(e,n){d("coeffects",e,n)},e.registerEffectHandler=a,e.registerEventsDelegation=function(e,n){e.forEach(function(e){r(e,function(e,t){return{dispatch:{id:n,payload:t}}})})},e.coeffect=function(e,n){return n?{id:e,data:n}:e},e.getCoeffectHandler=u,e.getEffectHandler=l,e.getEventHandler=p,e.clearHandlers=function(){o=Object.assign({},t),c={}},e.setVerbosity=function(e){n=e}}); | ||
//# sourceMappingURL=reffects.umd.js.map |
@@ -6,11 +6,17 @@ ## `dispatch` | ||
The **event** object has two keys `eventId` and `payload`. The value associated with `eventId` identifies the event and the value associated with `payload` is the payload of the event which is optional and it's an empty object by default. | ||
The **event** object has two keys `id` and `payload`. The value associated with `id` identifies the event and the value associated with `payload` is the payload of the event which is optional and it's an empty object by default. | ||
**Important**: The **event handler** associated to the given `eventId` will be **synchronously** executed. | ||
**Important**: The **event handler** associated to the given `id` will be **synchronously** executed. | ||
Example: | ||
```js | ||
dispatch({eventId: 'todoClicked', payload: { id, text, isDone }}); | ||
dispatch({id: 'todoClicked', payload: { id, text, isDone }}); | ||
``` | ||
If there's no payload, there's an alternative way to dispatch an event: | ||
```js | ||
dispatch("idOfEventNotNeedingPayload"); | ||
``` | ||
## `dispatchMany` | ||
@@ -23,4 +29,5 @@ This function dispatches several events that will be sequentially processed by the event handling machinery. | ||
```js | ||
dispatchMany([{eventId: 'todoClicked', payload: { id, text, isDone }}, | ||
{eventId: 'descriptionsRequested', payload: { id }}]); | ||
dispatchMany([{id: 'todoClicked', payload: { id, text, isDone }}, | ||
{id: 'descriptionsRequested', payload: { id }}, | ||
"idOfEventNotNeedingPayload"]); | ||
``` | ||
@@ -41,4 +48,5 @@ | ||
function(coeffects, selectedChartsRange) { | ||
return {dispatchMany: [{eventId: "modifyComboSelection", payload: selected-charts-range}, | ||
{eventId: "loadChartData", payload: selected-charts-range}]}; | ||
return {dispatchMany: [{id: "modifyComboSelection", payload: selected-charts-range}, | ||
{id: "loadChartData", payload: selected-charts-range}, | ||
"idOfEventNotNeedingPayload"]}; | ||
} | ||
@@ -60,3 +68,3 @@ ); | ||
}, | ||
[coeffects.injectApiUrl()]); | ||
[coeffect("apiUrl")]); | ||
``` | ||
@@ -159,1 +167,6 @@ | ||
``` | ||
## `coeffect` | ||
This function is syntax sugar for creating coeffect descriptions. | ||
Doing `coeffect("state", {'todoCount': 'todo.count'})` is equivalent to `{id: "state", data: {'todoCount': 'todo.count'}}`. |
@@ -8,3 +8,3 @@ # Built-in effects in reffects | ||
The **event** object has two keys: `eventId` and `payload`. The value associated with `eventId` identifies the event and the value associated with `payload` is the payload of the event which is optional and it's an empty object by default. | ||
The **event** object has two keys: `id` and `payload`. The value associated with `id` is a string that identifies the event and the value associated with `payload` is the payload of the event which is optional and it's an empty object by default. When the event has no payload it can also be represented by a string which would be its id. | ||
@@ -18,3 +18,3 @@ In the following example, the event handler for the `"showAlertOnRim"` event handler returns an **effects object** containing a `"dispatch"` effect that describes the dispatch of a `"displayNotification"` event with a **payload** that will be the following object: `{id: alert.id, text: alert.message}`. | ||
return { | ||
dispatch: {eventId: "displayNotification", payload: {id: alert.id, text: alert.message}} | ||
dispatch: {id: "displayNotification", payload: {id: alert.id, text: alert.message}} | ||
}; | ||
@@ -32,3 +32,3 @@ } | ||
return { | ||
dispatch: {eventId: "fetchSvg"}} | ||
dispatch: {id: "fetchSvg"}} | ||
}; | ||
@@ -39,2 +39,15 @@ } | ||
An alternative way of writing it would be: | ||
```js | ||
registerEventHandler( | ||
"fetchData", | ||
function(coeffects) { | ||
return { | ||
dispatch: "fetchSvg"} | ||
}; | ||
} | ||
); | ||
``` | ||
## `"dispatchMany"` | ||
@@ -45,3 +58,3 @@ The `"dispatchMany"` effect is **used to describe the dispatch of a sequence of events in order**. | ||
Each **event** object has two keys: `eventId` and `payload`. The value associated with `eventId` identifies the event and the value associated with `payload` is the payload of the event which is optional and it's an empty object by default. | ||
The **event** object has two keys: `id` and `payload`. The value associated with `id` is a string that identifies the event and the value associated with `payload` is the payload of the event which is optional and it's an empty object by default. When the event has no payload it can also be represented by a string which would be its id. | ||
@@ -58,3 +71,3 @@ In the following example the event handler for the `"pageChanged"` event returns an **effects object** that includes a | ||
return { | ||
dispatchMany: [{eventId: "fetchMetadata", payload: 35}, {eventId: "fetchSvg"}] | ||
dispatchMany: [{id: "fetchMetadata", payload: 35}, "fetchSvg"] | ||
}; | ||
@@ -70,5 +83,5 @@ } | ||
A delayed event object has three keys: `eventId`, `payload` and `milliseconds`. | ||
A delayed event object has three keys: `id`, `payload` and `milliseconds`. | ||
The value associated with the `eventId` key identifies the event, the value associated with the `payload` key is the payload of the event which is optional and it's an empty object by default, and the value associated with the `milliseconds` key is the number of milliseconds the dispatch will be delayed. | ||
The value associated with the `id` key identifies the event, the value associated with the `payload` key is the payload of the event which is optional and it's an empty object by default, and the value associated with the `milliseconds` key is the number of milliseconds the dispatch will be delayed. | ||
@@ -82,3 +95,3 @@ In the following example the event handler for the `"removeCalendarWithDelay"` event returns an **effects object** that includes a `"dispatchLater"` effect which describes the dispatch of the `"removeCalendar"` that will happen after 200 milliseconds. | ||
return { | ||
dispatchLater: {eventId: "removeCalendar", payload: message, milliseconds: 200} | ||
dispatchLater: {id: "removeCalendar", payload: message, milliseconds: 200} | ||
}; | ||
@@ -98,3 +111,3 @@ } | ||
return { | ||
dispatchLater: {eventId: "updateTodos", milliseconds: retryTimeInMilliSeconds} | ||
dispatchLater: {id: "updateTodos", milliseconds: retryTimeInMilliSeconds} | ||
}; | ||
@@ -101,0 +114,0 @@ } else { |
@@ -40,3 +40,3 @@ # Registering custom coeffect handlers in reffects | ||
}, | ||
[{id: "localStore", data: "lastConnectionDate"}] | ||
[coeffect("localStore", "lastConnectionDate")] | ||
); | ||
@@ -73,3 +73,3 @@ ``` | ||
}, | ||
["datetime"] | ||
[coeffect("datetime")] | ||
); | ||
@@ -76,0 +76,0 @@ ``` |
@@ -15,6 +15,6 @@ # Registering custom effect handlers in reffects | ||
registerEffectHandler( | ||
"mutate", | ||
function mutateEffect(mutations) { | ||
mutations.forEach(function (mutation) { | ||
store.setState(mutation); | ||
"setState", | ||
function setStateEffect(mutations) { | ||
Object.entries(mutations).forEach(function ([path, newValue]) { | ||
store.setState({path, newValue}); | ||
}); | ||
@@ -25,4 +25,4 @@ } | ||
In this example we're registering a handler for the `"mutate"` effect. | ||
This handler interprets the description of mutations of values of the application state (`store`) that is associated to the `"mutate"` key in the effects object and performs them. This effect would allow you to mutate the application state from pure event handlers as shown in the following code snippet: | ||
In this example we're registering a handler for the `"setState"` effect. | ||
This handler interprets the description of mutations of values of the application state (`store`) that is associated to the `"setState"` key in the effects object and performs them. This effect would allow you to setState the application state from pure event handlers as shown in the following code snippet: | ||
@@ -34,15 +34,16 @@ ```js | ||
return { | ||
mutate: [{ path: ['visible'], newValue: !coeffects.state.visible }] | ||
setState: {'visible': !coeffects.state.visible} | ||
}; | ||
}, | ||
[{id: 'state', data: [{ path: ['visible'], key: 'visible' }]}] | ||
[coeffect('state', {'visible', 'visible'})] | ||
); | ||
``` | ||
In this example, the event handler for the `"toggleVisibilityOnClick"` event returns an **effects object** containing the `"mutate"` effect which **describes a mutation** of the values associated to the `'visible'` keywords in the application state. | ||
In this example, the event handler for the `"toggleVisibilityOnClick"` event returns an **effects object** containing the `"setState"` effect which **describes a mutation** of the values associated to the `'visible'` keywords in the application state. | ||
Notice how the value associated to the `"mutate"` effect in the **effects object** is an array whose elements are the mutations to be done on the application state. Each mutation is described by a `path` which indicates where to do the mutation and a `newValue` which is the value that we'll find in the given path after the mutation takes place. | ||
Notice how the value associated to the `"setState"` effect in the **effects object** is an boject whose entries (key-value pairs) are the mutations to be done on the application state. Each mutation is described by a key-value pair in which *the key* is the *path* which indicates where to do the mutation and *the value* is the *new value* that we'll find in the given path after the mutation takes place. | ||
Notice also that the previous value of `'visible'` was retrieved using a custom coeffect 'state' whose data are are an array of extractions. Each extraction is described by a `path` which indicates where the value is and a `key` which tells the key which the extracte value will be associate with in the object associated with the `"state"` key in the coeffects object. | ||
Notice also that the previous value of `'visible'` was retrieved using a custom coeffect 'state' whose data are are an object whose entries are extractions. Each extraction is described by a key-value pair in which *the key* | ||
tells *the key which the extracted value will be associated with* in the object associated with the `"state"` key in the coeffects object, and *the value* is the *path* which indicates where the value is. | ||
If you want to know how to register custom coeffect handlers, have a look at [Registering custom coeffect handlers in reffects](https://github.com/mariosanchez/spike-todo-declarative-effects/blob/master/docs/reffects/custom-coeffects.md). |
# Testing event handlers in reffects | ||
TODO | ||
Since event handlers are very easy to test bla bla... TODO |
{ | ||
"name": "reffects", | ||
"version": "0.1.3", | ||
"version": "0.1.4", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "source": "src/index.js", |
130
src/index.js
var verbosityOn = process.env.NODE_ENV === 'development'; | ||
const initialHandlers = { | ||
effects: {}, | ||
coeffects: {}, | ||
events: {} | ||
}; | ||
let handlers = { ...initialHandlers }; | ||
let coeffectsByEvent = {}; | ||
function logEvent(eventId, payload) { | ||
if (verbosityOn) { | ||
console.group('Dispatching event:'); | ||
console.groupCollapsed(`Dispatching event: ${eventId}`); | ||
console.info('EventId:', eventId); | ||
@@ -12,34 +21,43 @@ console.log('Payload:', payload); | ||
const initialHandlers = { | ||
effects: {}, | ||
coeffects: {}, | ||
events: {} | ||
}; | ||
function logCoeffect(coeffectDescription) { | ||
if (verbosityOn) { | ||
console.groupCollapsed(`Extracting values of coeffect: ${coeffectDescription.id}`); | ||
console.info('Coeffect id:', coeffectDescription.id); | ||
console.log('Coeffect data:', coeffectDescription.data); | ||
console.groupEnd(); | ||
} | ||
} | ||
let handlers = { ...initialHandlers }; | ||
let coeffectsByEvent = {}; | ||
function extractCoeffectsValues(coeffectDescriptions) { | ||
return coeffectDescriptions.reduce(function(acc, coeffectDescription) { | ||
if (isString(coeffectDescription)) { | ||
const coeffectId = coeffectDescription; | ||
const coeffectHandler = getCoeffectHandler(coeffectId); | ||
return Object.assign({}, acc, coeffectHandler()); | ||
function logEffect(effectId, effectData) { | ||
if (verbosityOn) { | ||
console.groupCollapsed(`Applying effect: ${effectId}`); | ||
console.info('Effect id:', effectId); | ||
if (effectData) { | ||
console.log('Effect data:', coeffectDescription.data); | ||
} | ||
console.groupEnd(); | ||
} | ||
} | ||
guardValidCoeffectDescriptionObject(coeffectDescription); | ||
function extractCoeffectValue(coeffectDescription) { | ||
checkElementValidity(coeffectDescription, "coeffect") | ||
logCoeffect(coeffectDescription); | ||
const coeffectId = coeffectDescription.id; | ||
const coeffectData = coeffectDescription.data; | ||
if (isString(coeffectDescription)) { | ||
const coeffectId = coeffectDescription; | ||
const coeffectHandler = getCoeffectHandler(coeffectId); | ||
return Object.assign({}, acc, coeffectHandler(coeffectData)); | ||
}, {}); | ||
return coeffectHandler(); | ||
} | ||
const coeffectHandler = getCoeffectHandler(coeffectDescription.id); | ||
return coeffectHandler(coeffectDescription.data); | ||
} | ||
function guardValidCoeffectDescriptionObject(coeffectDescription) { | ||
if (!coeffectDescription || coeffectDescription.id == null) { | ||
throw new Error( | ||
'Coeffect description is not a valid object, an id property is required' | ||
); | ||
} | ||
function extractCoeffectsValues(coeffectDescriptions) { | ||
return coeffectDescriptions.reduce( | ||
function(acc, coeffectDescription) { | ||
return Object.assign({}, acc, extractCoeffectValue(coeffectDescription)); | ||
}, | ||
{} | ||
); | ||
} | ||
@@ -51,8 +69,5 @@ | ||
} | ||
const effectIds = Object.keys(effects); | ||
effectIds.forEach(function(effectId) { | ||
const effectData = effects[effectId]; | ||
Object.entries(effects).forEach(function([effectId, effectData]) { | ||
logEffect(effectId, effectData); | ||
const effectHandler = getEffectHandler(effectId); | ||
effectHandler(effectData); | ||
@@ -62,7 +77,15 @@ }); | ||
export function dispatch({ eventId, payload = {} }) { | ||
logEvent(eventId, payload); | ||
function completeEventParts(event) { | ||
if(isString(event)) { | ||
return {id: event}; | ||
} | ||
return event; | ||
} | ||
const eventHandler = getEventHandler(eventId); | ||
const coeffectDescriptions = coeffectsByEvent[eventId]; | ||
export function dispatch(event) { | ||
checkElementValidity(event, "event"); | ||
const { id, payload } = completeEventParts(event); | ||
logEvent(id, payload); | ||
const eventHandler = getEventHandler(id); | ||
const coeffectDescriptions = coeffectsByEvent[id]; | ||
const coeffects = extractCoeffectsValues(coeffectDescriptions); | ||
@@ -103,6 +126,6 @@ const effects = eventHandler(coeffects, payload); | ||
export function registerEventsDelegation(originalEvents, targetEvent) { | ||
originalEvents.forEach(function(eventId) { | ||
registerEventHandler(eventId, function(coeffects, payload) { | ||
originalEvents.forEach(function(id) { | ||
registerEventHandler(id, function(coeffects, payload) { | ||
return { | ||
dispatch: { eventId: targetEvent, payload: payload } | ||
dispatch: { id: targetEvent, payload: payload } | ||
}; | ||
@@ -133,2 +156,9 @@ }); | ||
export function coeffect(id, data) { | ||
if (!data) { | ||
return id; | ||
} | ||
return { id: id, data: data }; | ||
} | ||
function setHandler(handlerType, handlerId, handler) { | ||
@@ -171,1 +201,25 @@ handlers[handlerType][handlerId] = handler; | ||
} | ||
function checkElementValidity(element, elementType) { | ||
const shapeDescriptionsByElement = { | ||
"coeffect": "It must be an object with the following format `{ id: 'COEFFECT_ID', data: <Object | any> }`, or a string if no data is needed: 'EVENT_ID'", | ||
"event": "It must be an object with the following format `{ id: 'EVENT_ID', payload: <Object | any> }`, or a string if no payload is needed: 'EVENT_ID'", | ||
}; | ||
if (!element) { | ||
throwNotDefinedError(elementType); | ||
} | ||
if(!isString(element) && element.id == null) { | ||
throwNotValidError(elementType); | ||
} | ||
function throwNotDefinedError(element) { | ||
throw new Error("Not defined " + element + ".\n" + shapeDescriptionsByElement[element]); | ||
} | ||
function throwNotValidError(element) { | ||
throw new Error("Not valid " + element + ".\n" + shapeDescriptionsByElement[element]); | ||
} | ||
} | ||
@@ -23,3 +23,3 @@ import * as reffects from "."; | ||
reffects.dispatch({ eventId, payload: passedPayload }); | ||
reffects.dispatch({ id: eventId, payload: passedPayload }); | ||
@@ -29,4 +29,20 @@ expect(callsCounter).toEqual(1); | ||
test("checking coeffect values whose handlers do not receive parameters are injected into event handler when dispatching an event", () => { | ||
test("dispatching an event represented as a string because it does not need payload", () => { | ||
var callsCounter = 0; | ||
const eventId = "anEventHandlerThatWillBeCalled"; | ||
reffects.registerEventHandler( | ||
eventId, | ||
function (coeffects, payload) { | ||
callsCounter++; | ||
}); | ||
reffects.dispatch(eventId); | ||
expect(callsCounter).toEqual(1); | ||
}); | ||
test("when dispatching an event, coeffect values, whose handlers do not receive parameters, are injected into event handler", () => { | ||
var callsCounter = 0; | ||
const datetimeCoeffectId = "datetime"; | ||
@@ -66,3 +82,3 @@ const expectedDateTime = "anyDate"; | ||
reffects.dispatch({ eventId, payload: passedPayload }); | ||
reffects.dispatch({ id: eventId, payload: passedPayload }); | ||
@@ -72,3 +88,3 @@ expect(callsCounter).toEqual(1); | ||
test("checking a coeffect value whose handler receives parameters is injected into event handler when dispatching an event", () => { | ||
test("when dispatching an event, a coeffect value, whose handler receives parameters, is injected into event handler", () => { | ||
var callsCounter = 0; | ||
@@ -100,3 +116,3 @@ const expectedData = "koko"; | ||
reffects.dispatch({ eventId, payload: passedPayload }); | ||
reffects.dispatch({ id: eventId, payload: passedPayload }); | ||
@@ -106,3 +122,3 @@ expect(callsCounter).toEqual(1); | ||
test("checking a coeffect description as string whose handler receives parameters is injected into event handler when dispatching an event", () => { | ||
test("when dispatching an event, a coeffect description as string, whose handler receives parameters, is injected into event handler", () => { | ||
var callsCounter = 0; | ||
@@ -134,3 +150,3 @@ const expectedData = "koko"; | ||
reffects.dispatch({ eventId, payload: passedPayload }); | ||
reffects.dispatch({ id: eventId, payload: passedPayload }); | ||
@@ -140,24 +156,13 @@ expect(callsCounter).toEqual(1); | ||
test("checking an invalid coeffect description object whose handler receives parameters is injected into event handler when dispatching an event", () => { | ||
const mokoCoeffectDescription = undefined; | ||
test("a not registered handler id throws an error", () => { | ||
const passedPayload = "somePayload"; | ||
const eventId = "eventHandlerInWhichCoeffectsValuesAreInjected"; | ||
const notRegisteredHandler = "noopEventHandler"; | ||
const dummyEvent = jest.fn(); | ||
reffects.registerEventHandler( | ||
eventId, | ||
dummyEvent, | ||
[mokoCoeffectDescription]); | ||
expect(() => reffects.dispatch({ eventId, payload: passedPayload })).toThrowError("Coeffect description is not a valid object, an id property is required"); | ||
expect(() => reffects.dispatch({ | ||
id: notRegisteredHandler, | ||
payload: passedPayload | ||
})).toThrowError(`There is no handler called '${notRegisteredHandler}'.`); | ||
}); | ||
test("checking a not existing handler id throws an error", () => { | ||
const passedPayload = "somePayload"; | ||
const noopEventId = "noopEventHandler"; | ||
expect(() => reffects.dispatch({ eventId: noopEventId, payload: passedPayload })).toThrowError(`There is no handler called '${noopEventId}'.`); | ||
}); | ||
test("checking effects are applied after executing the eventHandler", () => { | ||
test("applying effects after executing the eventHandler", () => { | ||
const eventId = "eventHandlerAfterWhichAnEffectIsApplied"; | ||
@@ -179,3 +184,3 @@ const effectId = "someEffectId"; | ||
reffects.dispatch({ eventId, payload: fakeEventPayload }); | ||
reffects.dispatch({ id: eventId, payload: fakeEventPayload }); | ||
@@ -200,7 +205,7 @@ expect(dummyEffect).toHaveBeenCalledWith(fakeEventPayload); | ||
function (coeffects, payload) { | ||
return { "dispatch": { eventId: "eventDispatchedUsingDispatchEffect", payload: ["arg1", "arg2"] } }; | ||
return { "dispatch": { id: "eventDispatchedUsingDispatchEffect", payload: ["arg1", "arg2"] } }; | ||
} | ||
); | ||
reffects.dispatch({ eventId: "eventReturningDispatchEffect" }); | ||
reffects.dispatch({ id: "eventReturningDispatchEffect" }); | ||
@@ -234,8 +239,9 @@ expect(callsCounter).toEqual(1); | ||
return { | ||
"dispatchMany": [{ eventId: "firstEventDispatchedUsingDispatchMany", payload: expectedPayloadForFirstEvent }, | ||
{ eventId: "secondEventDispatchedUsingDispatchMany", payload: expectedPayloadForSecondEvent }] | ||
"dispatchMany": [ | ||
{ id: "firstEventDispatchedUsingDispatchMany", payload: expectedPayloadForFirstEvent }, | ||
{ id: "secondEventDispatchedUsingDispatchMany", payload: expectedPayloadForSecondEvent }] | ||
} | ||
}); | ||
reffects.dispatch({ eventId: "eventReturningDispatchManyEffect" }); | ||
reffects.dispatch({ id: "eventReturningDispatchManyEffect" }); | ||
@@ -263,7 +269,13 @@ expect(firstEventCallsCounter).toEqual(1); | ||
function (coeffects, payload) { | ||
return { dispatchLater: { eventId: "eventDispatchedUsingDispatchLaterEffect", payload: ["arg1", "arg2"], milliseconds: 1000 } }; | ||
return { | ||
dispatchLater: { | ||
id: "eventDispatchedUsingDispatchLaterEffect", | ||
payload: ["arg1", "arg2"], | ||
milliseconds: 1000 | ||
} | ||
}; | ||
} | ||
); | ||
reffects.dispatch({ eventId: "eventReturningDispatchLaterEffect" }); | ||
reffects.dispatch({ id: "eventReturningDispatchLaterEffect" }); | ||
@@ -296,7 +308,54 @@ jest.runAllTimers(); | ||
reffects.dispatch({ eventId: delegatedEventId1, payload: expectedPayload }); | ||
reffects.dispatch({ eventId: delegatedEventId2, payload: expectedPayload }); | ||
reffects.dispatch({ eventId: delegatedEventId3, payload: expectedPayload }); | ||
reffects.dispatch({ id: delegatedEventId1, payload: expectedPayload }); | ||
reffects.dispatch({ id: delegatedEventId2, payload: expectedPayload }); | ||
reffects.dispatch({ id: delegatedEventId3, payload: expectedPayload }); | ||
expect(callsCounter).toEqual(3); | ||
}); | ||
}); | ||
test("creating coeffects sugar", () => { | ||
expect(reffects.coeffect("apiUrl")).toEqual("apiUrl"); | ||
expect(reffects.coeffect("apiUrl", {someData: "koko"})).toEqual({"id": "apiUrl", "data": {"someData": "koko"}}); | ||
}); | ||
test("an exception is thrown, when a coeffect is not defined", () => { | ||
const mokoCoeffectDescription = undefined; | ||
const passedPayload = "somePayload"; | ||
const eventId = "eventHandlerInWhichCoeffectsValuesAreInjected"; | ||
const dummyEventHandler = jest.fn(); | ||
reffects.registerEventHandler( | ||
eventId, | ||
dummyEventHandler, | ||
[mokoCoeffectDescription]); | ||
expect(() => reffects.dispatch({ | ||
id: eventId, | ||
payload: passedPayload | ||
})).toThrowError("Not defined coeffect."); | ||
}); | ||
test("an exception is thrown, when a coeffect description is not valid", () => { | ||
const mokoCoeffectDescription = {a: "lala"}; | ||
const passedPayload = "somePayload"; | ||
const eventId = "eventHandlerInWhichCoeffectsValuesAreInjected"; | ||
const dummyEventHandler = jest.fn(); | ||
reffects.registerEventHandler( | ||
eventId, | ||
dummyEventHandler, | ||
[mokoCoeffectDescription]); | ||
expect(() => reffects.dispatch({ | ||
id: eventId, | ||
payload: passedPayload | ||
})).toThrowError("Not valid coeffect."); | ||
}); | ||
test("an exception is thrown, when an event is not defined", () => { | ||
const event = undefined; | ||
expect(() => reffects.dispatch(event)).toThrowError("Not defined event."); | ||
}); | ||
test("an exception is thrown, when an event is not valid", () => { | ||
const event = {oh: "lala"}; | ||
expect(() => reffects.dispatch(event)).toThrowError("Not valid event."); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
72172
509