{"id":20495327,"url":"https://github.com/kevinast/feature-redux-logic","last_synced_at":"2026-05-08T03:12:03.745Z","repository":{"id":29097560,"uuid":"120184751","full_name":"KevinAst/feature-redux-logic","owner":"KevinAst","description":"feature-u redux-logic integration","archived":false,"fork":false,"pushed_at":"2022-12-07T20:36:38.000Z","size":1283,"stargazers_count":0,"open_issues_count":13,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-16T09:04:07.410Z","etag":null,"topics":["feature","feature-u","features","react","redux","redux-logic"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/KevinAst.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-02-04T12:54:40.000Z","updated_at":"2019-12-10T21:45:54.000Z","dependencies_parsed_at":"2023-01-14T14:08:42.382Z","dependency_job_id":null,"html_url":"https://github.com/KevinAst/feature-redux-logic","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KevinAst%2Ffeature-redux-logic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KevinAst%2Ffeature-redux-logic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KevinAst%2Ffeature-redux-logic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KevinAst%2Ffeature-redux-logic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/KevinAst","download_url":"https://codeload.github.com/KevinAst/feature-redux-logic/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242077475,"owners_count":20068367,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["feature","feature-u","features","react","redux","redux-logic"],"created_at":"2024-11-15T17:45:27.317Z","updated_at":"2026-05-08T03:12:03.663Z","avatar_url":"https://github.com/KevinAst.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# feature-redux-logic (feature-u redux-logic integration)\n\n**feature-redux-logic** is your [feature-u] integration point to\n[redux-logic]!  It promotes the [`logicAspect`] _(a [feature-u]\nplugin)_ that facilitates [redux-logic] integration to your features.\n\n**Backdrop:**\n\n\u003cul\u003e\u003c!--- indentation hack for github - other attempts with style is stripped (be careful with number bullets) ---\u003e \n\n[feature-u] is a utility that facilitates feature-based project\norganization for your [react] project. It helps organize your\nproject by individual features.  [feature-u] is extendable. It\noperates under an open plugin architecture where Aspects integrate\n**feature-u** to other framework/utilities that match your specific\nrun-time stack.\n\n\u003c/ul\u003e\n\n\n\u003c!--- Badges for CI Builds ---\u003e \n[![Build Status](https://travis-ci.org/KevinAst/feature-redux-logic.svg?branch=master)](https://travis-ci.org/KevinAst/feature-redux-logic)\n[![Codacy Badge](https://api.codacy.com/project/badge/Grade/81530601c0f2449481882ac285add698)](https://www.codacy.com/app/KevinAst/feature-redux-logic?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=KevinAst/feature-redux-logic\u0026amp;utm_campaign=Badge_Grade)\n[![Codacy Badge](https://api.codacy.com/project/badge/Coverage/81530601c0f2449481882ac285add698)](https://www.codacy.com/app/KevinAst/feature-redux-logic?utm_source=github.com\u0026utm_medium=referral\u0026utm_content=KevinAst/feature-redux-logic\u0026utm_campaign=Badge_Coverage)\n[![Known Vulnerabilities](https://snyk.io/test/github/kevinast/feature-redux-logic/badge.svg?targetFile=package.json)](https://snyk.io/test/github/kevinast/feature-redux-logic?targetFile=package.json)\n[![NPM Version Badge](https://img.shields.io/npm/v/feature-redux-logic.svg)](https://www.npmjs.com/package/feature-redux-logic)\n\n\n**Overview:**\n\n\u003cul\u003e\u003c!--- indentation hack for github - other attempts with style is stripped (be careful with number bullets) ---\u003e \n\n**feature-redux-logic** configures [redux-logic] through the [`logicAspect`]\n(_which is supplied to_ **feature-u**'s [`launchApp()`]).  This\nextends **feature-u**'s [`Feature`] object by adding support for the\n`Feature.logic` property, referencing an array of feature-based logic modules.\n\nIt is important to understand that you continue to use [redux-logic] the\nsame way you always have.  It's just that now you are dealing with a\n**smaller context** ... _within the boundaries of your feature_!\n\n\u003c/ul\u003e\n\nLet's see how this all works together ...\n\n## At a Glance\n\n- [Install](#install)\n- [Usage](#usage)\n- [A Closer Look](#a-closer-look)\n  - [Single Source of Truth](#single-source-of-truth)\n  - [Why redux-logic?](#why-redux-logic)\n- [Interface Points](#interface-points)\n  - [Input](#input)\n  - [Exposure](#exposure)\n  - [Error Conditions](#error-conditions)\n- [API](#api)\n  - [`logicAspect: Aspect`](#logicaspect-aspect)\n- [Potential Need for Polyfills](#potential-need-for-polyfills)\n\n\n\n## Install\n\n- **peerDependencies** ... you should already have these, **because\n  this is our integration point** _(but just in case)_:\n\n  ```shell\n  npm install --save feature-u\n  npm install --save redux-logic\n  ```\n  \u003c!--- WITH REVEAL of USAGE:\n  npm install --save feature-u    # VER: \u003e=1.0.0    USAGE: createAspect() (v1 replaces App with Fassets obj -AND- publicFace with fassets aspect)\n  npm install --save redux-logic  # VER: \u003e=0.7.0    USAGE: createLogicMiddleware()\n  ---\u003e \n\n- **the main event**:\n\n  ```shell\n  npm install --save feature-redux-logic\n  ```\n\n**SideBar**: Depending on how current your target browser is\n_(i.e. it's JavaScript engine)_, you may need to polyfill your app\n_(please refer to [Potential Need for\nPolyfills](#potential-need-for-polyfills))_.\n\n\n## Usage\n\n1. Within your mainline, register the **feature-redux-logic**\n   [`logicAspect`] to **feature-u**'s [`launchApp()`] _(see: `**1**`\n   below)_.\n\n   **Please Note**: [redux] must also be present in your run-time\n   stack, because [redux-logic] is a middleware agent of [redux]\n   _(see: `**2**` below)_.\n\n   **src/app.js**\n   ```js\n   import {launchApp}           from 'feature-u';\n   import {createReducerAspect} from 'feature-redux';       // **2**\n   import {createLogicAspect}   from 'feature-redux-logic'; // **1**\n   import features              from './feature';\n\n   export default launchApp({\n\n     aspects: [\n       createReducerAspect(), // **2**\n       createLogicAspect(),   // **1**\n       ... other Aspects here\n     ],\n\n     features,\n\n     registerRootAppElm(rootAppElm) {\n       ReactDOM.render(rootAppElm,\n                       getElementById('myAppRoot'));\n     }\n   });\n   ```\n\n2. Within each feature that maintains logic, simply register the\n   feature's logic modules through the `Feature.logic` property\n   _(using **feature-u**'s [`createFeature()`])_ ... _see: `**3**`\n   below_.\n\n   **src/feature/myXyzFeature/index.js**\n   ```js\n   import {createFeature}  from 'feature-u';\n   import logic            from './logic';\n   \n   export default createFeature({\n\n     name:     'myXyzFeature',\n\n     logic,  // **3** myXyzFeature logic[]\n\n     ... snip snip (other aspect properties here)\n   });\n   ```\n\n3. As a convenience, **feature-redux-logic** auto injects the\n   **feature-u** [`Fassets object`] as a dependency in your logic\n   modules.  This promotes full [Cross Feature Communication].  \n\n   The following example, demonstrates the availability of the\n   `fassets` named parameter:\n\n   ```js\n   import {createLogic}      from 'redux-logic';\n\n   export const someLogic = createLogic({\n\n     ... snip snip\n\n     transform({getState, action, fassets}, next, reject) {\n       ... fassets may be used for cross-feature-communication\n     },\n\n     process({getState, action, fassets}, dispatch, done) {\n       ... fassets may be used for cross-feature-communication\n     }\n\n   });\n   ```\n\n\n**Well that was easy!!** At this point **redux-logic** is **completely\nsetup for your application!**\n\nIn the nutshell, that's a highlight of most everything you need to\nknow to use **feature-redux-logic**!  _Go forth and compute!_\n\n\n## A Closer Look\n\nAny feature that maintains business logic promotes it's own set of\nlogic modules through the `Feature.logic` property _(using\n**feature-u**'s [`createFeature()`])_.  While these logic modules are\ntruly opaque assets _(internal to the feature)_, they are of interest\nto **feature-redux-logic** to the extent that they are needed to configure\n[redux-logic].\n\nBecause logic modules may require access to **feature-u**'s [`Fassets\nobject`] during code expansion, this property can also be a\n**feature-u** [`expandWithFassets()`] callback _(a function that\nreturns the logic modules)_ ... please refer to **feature-u**'s\ndiscussion of [Managed Code Expansion].\n\nIt is important to understand that your interface to [redux-logic] has not\nchanged in any way.  In other words, you continue to use [redux-logic] the\nsame way you always have.  It's just that now you are dealing with a\n**smaller context** ... _within the boundaries of your feature_!\n\nAs always, you should strive to keep each feature isolated, so it is\ntruly **plug-and-play**.\n\n\n### Single Source of Truth\n\nThe featureName (i.e. `Feature.name`) is a critical item that can be\nused throughout your feature implementation to promote a consistent\nfeature identity.\n\nA key aspect of the featureName is that [feature-u] guarantees it's\nuniqueness.  As a result, it can be used to qualify the identity of\nseveral feature aspects.\n\nA **best practice** in consideration of feature-based logic modules,\nis to prefix all logic module names with featureName.  While this is\nnot required, it helps (in diagnostic logs) to identify where that\nmodule lives.\n\nHere is an example _(see: `**4**`)_:\n\n**src/feature/myXyzFeature/logic/doSomething.js**\n```js\nimport {createLogic}      from 'redux-logic';\nimport featureName        from './featureName';\nimport actions            from './actions';\n\nexport const doSomething = createLogic({\n\n  name: `${featureName}.doSomething`, // **4**\n  type: String(actions.some.action),\n\n  transform({getState, action}, next, reject) {\n    ... snip snip\n  },\n\n  process({getState, action, fassets}, dispatch, done) {\n    ... snip snip\n  }\n\n});\n```\n\n### Why redux-logic?\n\nThere are many ways to introduce logic in your [react] app.  This\narticle breaks down the various options: **_[Where do I put my\nbusiness logic in a React-Redux\napplication?](https://medium.com/@jeffbski/where-do-i-put-my-business-logic-in-a-react-redux-application-9253ef91ce1)_**\nThe article is an introduction (and motivation) for the development of\n**_[redux-logic]_** ... *redux middleware for organizing all your\nbusiness logic*.\n\nI have been using [redux-logic] since it's inception and believe it is\nthe _**best approach to encapsulate your business logic**_. Prior to\nredux-logic, my business logic was spread out in a variety of\ndifferent places, including:\n\n- component methods\n- thunks\n- and various middleware components\n\nIn addition, I relied heavily on batched actions, where logic entry\npoints would stimulate multiple actions in one procedural chunk of\ncode.  Needless to say, this was less than ideal. Even tools like\nredux-dev-tools could not give me adequate insight into \"what was\nstimulating what\"!\n\nAll of these techniques were replaced with \"true\" business logic,\norganizing all my logic in one isolated spot, all orchestrated by\n[redux-logic]!\n\nMy business logic is now:\n\n- located in one logical discipline (i.e. dedicated \"logic\" modules)\n- making it testable in isolation (very nice)!!\n- has more concise and succinct goals\n- promotes modular reuse\n- provides traceable \"cause and effects\"\n- is greatly simplified!\n\n\n## Interface Points\n\n**feature-redux-logic** accumulates all the logic modules from the\nvarious features of your app, and registers them to [redux-logic].  This\nis accomplished by creating the [redux middleware] which\nis in turn registered to [redux].  The **Aspect Interface** to this\nprocess (_i.e. the inputs and outputs_) are documented here.\n\n\n### Input\n\n- The input to **feature-redux-logic** are [redux-logic] modules.\n  This is specified by each of your features (_that maintain logic_)\n  through the `Feature.logic` property, containing a logic modules\n  array.\n\n\n### Exposure\n\n- The output from **feature-redux-logic** is the [redux middleware]\n  component, exposed through the `Aspect.getReduxMiddleware()` API\n  (an \"aspect cross-communication mechanism\").  This middleware\n  component must be consumed by yet another aspect (_such as\n  [feature-redux]_) that in turn manages [redux].\n\n- As a convenience, **feature-redux-logic** auto injects the\n  **feature-u** [`Fassets object`] as a dependency in your logic\n  modules.  This promotes full [Cross Feature Communication].\n  Please refer to the [Usage] section for examples.\n\n\n### Error Conditions\n\nWhen **feature-redux-logic** detects that no logic modules have been\nspecified by any of your features, it will (by default) throw the\nfollowing exception:\n\n```\n***ERROR*** feature-redux-logic found NO logic modules within your features\n            ... did you forget to register Feature.logic aspects in your features?\n            (please refer to the feature-redux-logic docs to see how to override this behavior).\n```\n\nMost likely this should in fact be considered an error _(for example\nyou neglected to specify the logic modules within your features)_.  **The\nreasoning is**: _why would you not specify any logic modules if\nyour using redux-logic?_\n\nYou can change this behavior through the following configuration:\n\n```js\nlogicAspect.config.allowNoLogic$ = true;\n```\n\nWith this option enabled, when no logic modules are found,\nredux-logic will simply NOT be configured (accompanied with a WARNING\nlogging probe).\n\nYou can also specify your own array of logic modules in place of the\n`true` value, which will be used ONLY in the scenario where no logic\nmodules were specified by your features.\n\n\n\n## API\n\n### logicAspect: Aspect\n\n\u003cul\u003e\u003c!--- indentation hack for github - other attempts with style is stripped (be careful with number bullets) ---\u003e \n\n`API: createLogicAspect([name='logic']): logicAspect`\n\nThe `logicAspect` is the [feature-u] plugin that facilitates\n[redux-logic] integration to your features.\n\nTo use this aspect:\n\n- Within your mainline, register the **feature-redux-logic**\n  `logicAspect` to **feature-u**'s [`launchApp()`].\n\n- Within each feature that maintains business logic, simply register\n  the feature's logic modules through the `Feature.logic` property\n  _(using **feature-u**'s [`createFeature()`])_.\n\nPlease refer to the [Usage] section for examples of this process.\n\n\u003c/ul\u003e\n\n\n## Potential Need for Polyfills\n\nThe implementation of this library employs modern es2015+ JavaScript\nconstructs.  Even though the library distribution is transpiled to\n[es5](https://en.wikipedia.org/wiki/ECMAScript#5th_Edition) _(the\nleast common denominator)_, **polyfills may be required** if you are\nusing an antiquated JavaScript engine _(such as the IE browser)_.\n\nWe take the approach that **polyfills are the responsibility of the\nclient app**.  This is a legitimate approach, as specified by the [W3C\nPolyfill Findings](https://www.w3.org/2001/tag/doc/polyfills/)\n_(specifically [Advice for library\nauthors](https://www.w3.org/2001/tag/doc/polyfills/#advice-for-library-and-framework-authors))_.\n\n- polyfills should only be introduced one time _(during code expansion\n  of the app)_\n- a library should not pollute the global name space _(by including\n  polyfills at the library level)_\n- a library should not needlessly increase it's bundle size _(by\n  including polyfills that are unneeded in a majority of target\n  environments)_\n\nAs it turns out, **app-level polyfills are not hard to implement**,\nwith the advent of third-party utilities, such as babel:\n\n- simply import [babel-polyfill](https://babeljs.io/docs/en/babel-polyfill.html)\n- or use babel's\n  [babel-preset-env](https://babeljs.io/docs/en/babel-preset-env.html)\n  in conjunction with babel 7's `\"useBuiltins\": \"usage\"` option\n\n**If your target JavaScript engine is inadequate, it will generate\nnative run-time errors, and you will need to address the polyfills.**\nUnfortunately, in many cases these errors can be very obscure _(even\nto seasoned developers)_.  The following [Babel Feature\nRequest](https://github.com/babel/babel/issues/8089) _(if/when\nimplemented)_ is intended to address this issue.\n\n\n\n\n\u003c!--- *** REFERENCE LINKS *** ---\u003e \n\n\u003c!--- **feature-redux-logic** ---\u003e \n[Usage]:          #usage\n[`logicAspect`]:  #logicaspect-aspect\n\n\u003c!--- **feature-redux** ---\u003e \n[feature-redux]:          https://github.com/KevinAst/feature-redux\n\n\n\u003c!--- feature-u ---\u003e \n[feature-u]:                   https://feature-u.js.org/\n[`launchApp()`]:               https://feature-u.js.org/cur/api.html#launchApp\n[`createFeature()`]:           https://feature-u.js.org/cur/api.html#createFeature\n[`expandWithFassets()`]:       https://feature-u.js.org/cur/api.html#expandWithFassets\n[`Feature`]:                   https://feature-u.js.org/cur/api.html#Feature\n[`Fassets object`]:            https://feature-u.js.org/cur/api.html#Fassets\n[Managed Code Expansion]:      https://feature-u.js.org/cur/crossCommunication.html#managed-code-expansion\n[Cross Feature Communication]: https://feature-u.js.org/cur/crossCommunication.html\n\n\n\u003c!--- react ---\u003e \n[react]:            https://reactjs.org/\n\n\n\u003c!--- redux ---\u003e \n[redux]:            https://redux.js.org/\n[redux middleware]: https://redux.js.org/docs/advanced/Middleware.html\n\n\u003c!--- redux-logic ---\u003e \n[redux-logic]:      https://github.com/jeffbski/redux-logic\n\n\u003c!--- 3rd party action managers ---\u003e \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkevinast%2Ffeature-redux-logic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkevinast%2Ffeature-redux-logic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkevinast%2Ffeature-redux-logic/lists"}