|
1 | 1 | import {createLogicMiddleware} from 'redux-logic'; // peerDependency
|
2 |
| -import {createAspect} from 'feature-u'; // peerDependency: |
| 2 | +import {createAspect, |
| 3 | + extendAspectProperty, |
| 4 | + launchApp} from 'feature-u'; // peerDependency: |
3 | 5 |
|
| 6 | +// our logger (integrated/activated via feature-u) |
| 7 | +const logf = launchApp.diag.logf.newLogger('- ***feature-redux-logic*** logicAspect: '); |
4 | 8 |
|
5 | 9 | // NOTE: See README for complete description
|
6 | 10 | export default createAspect({
|
7 | 11 | name: 'logic',
|
| 12 | + genesis, |
8 | 13 | validateFeatureContent,
|
9 | 14 | assembleFeatureContent,
|
| 15 | + createLogicMiddleware$, |
10 | 16 | getReduxMiddleware,
|
11 | 17 | });
|
12 | 18 |
|
13 | 19 |
|
| 20 | +/** |
| 21 | + * Register feature-redux-logic proprietary Aspect APIs (required to |
| 22 | + * pass feature-u validation). |
| 23 | + * This must occur early in the life-cycle (i.e. this method) to |
| 24 | + * guarantee the new API is available during feature-u validation. |
| 25 | + * |
| 26 | + * @return {string} NONE FOR US ... an error message when self is in an invalid state |
| 27 | + * (falsy when valid). |
| 28 | + * |
| 29 | + * @private |
| 30 | + */ |
| 31 | +function genesis() { |
| 32 | + logf('genesis() registering internal Aspect properties'); |
| 33 | + |
| 34 | + extendAspectProperty('allowNoLogic$'); // Aspect.allowNoLogic$: true || [{logicModules}] |
| 35 | + // ... AI: technically this is for reducerAspect only (if the API ever supports this) |
| 36 | + extendAspectProperty('createLogicMiddleware$'); // Aspect.createLogicMiddleware$(app, appLogic): reduxMiddleware |
| 37 | + // ... AI: technically this is for reducerAspect only (if the API ever supports this) |
| 38 | +} |
| 39 | + |
| 40 | + |
14 | 41 | /**
|
15 | 42 | * Validate self's aspect content on supplied feature.
|
16 | 43 | *
|
@@ -48,20 +75,89 @@ function validateFeatureContent(feature) {
|
48 | 75 | function assembleFeatureContent(app, activeFeatures) {
|
49 | 76 |
|
50 | 77 | // accumulate logic modules across all features
|
51 |
| - const appLogic = activeFeatures.reduce( (accum, feature) => { |
| 78 | + const hookSummary = []; |
| 79 | + let appLogic = activeFeatures.reduce( (accum, feature) => { |
52 | 80 | if (feature[this.name]) {
|
53 | 81 | accum = [...accum, ...feature[this.name]];
|
| 82 | + hookSummary.push(`\n Feature.name:${feature.name} <-- promotes ${this.name} AspectContent`); |
| 83 | + } |
| 84 | + else { |
| 85 | + hookSummary.push(`\n Feature.name:${feature.name}`); |
54 | 86 | }
|
55 | 87 | return accum;
|
56 | 88 | }, []);
|
57 | 89 |
|
58 |
| - // ?? how should NO logic be handled: silenty ignore, with NO redux-logic OR throw error? |
59 | 90 |
|
60 |
| - // define our redux middleware of redux-logic |
61 |
| - this.logicMiddleware = createLogicMiddleware(appLogic, |
62 |
| - { // inject our app as a redux-logic dependancy |
63 |
| - app, |
64 |
| - }); |
| 91 | + // report the accumulation of logic modules |
| 92 | + if (appLogic.length > 0) { |
| 93 | + logf(`assembleFeatureContent() gathered logic modules from the following Features: ${hookSummary}`); |
| 94 | + } |
| 95 | + |
| 96 | + // handle special case where NO logic modules were gathered from features |
| 97 | + else { |
| 98 | + |
| 99 | + // by default, this is an error condition (when NOT overridden by client) |
| 100 | + if (!this.allowNoLogic$) { |
| 101 | + throw new Error('***ERROR*** feature-redux-logic found NO logic modules within your features ' + |
| 102 | + `... did you forget to register Feature.${this.name} aspects in your features? ` + |
| 103 | + '(please refer to the feature-redux-logic docs to see how to override this behavior).'); |
| 104 | + } |
| 105 | + |
| 106 | + // when client override is an array, interpret it as logic modules |
| 107 | + if (Array.isArray(this.allowNoLogic$)) { |
| 108 | + logf.force('WARNING: NO logic modules were found in your Features (i.e. Feature.${this.name}), ' + |
| 109 | + 'but client override (logicAspect.allowNoLogic$=[{logicModules}];) ' + |
| 110 | + 'directed a continuation WITH specified logic modules.'); |
| 111 | + appLogic = this.allowNoLogic$; |
| 112 | + } |
| 113 | + // otherwise, we simply disable redux-logic and continue on |
| 114 | + else { |
| 115 | + logf.force('WARNING: NO logic modules were found in your Features, ' + |
| 116 | + 'but client override (logicAspect.allowNoLogic$=true;) ' + |
| 117 | + 'directed a continuation WITHOUT redux-logic.'); |
| 118 | + } |
| 119 | + } |
| 120 | + |
| 121 | + // define our redux middleware for redux-logic |
| 122 | + // ... conditionally when we have logic modules |
| 123 | + // ... retained in self for promotion to feature-redux plugin |
| 124 | + if (appLogic.length > 0) { |
| 125 | + // ... accomplished in internal micro method (a defensive measure to allow easier overriding by client) |
| 126 | + this.logicMiddleware = this.createLogicMiddleware$(app, appLogic); |
| 127 | + } |
| 128 | + // if we have no logic ... we have no middleware |
| 129 | + else { |
| 130 | + this.logicMiddleware = null; |
| 131 | + } |
| 132 | +} |
| 133 | + |
| 134 | + |
| 135 | +/** |
| 136 | + * An internal micro method that creates/returns the redux middleware |
| 137 | + * for redux-logic. |
| 138 | + * |
| 139 | + * This logic is broken out in this internal method as a defensive |
| 140 | + * measure to make it easier for a client to override (if needed for |
| 141 | + * some unknown reason). |
| 142 | + * |
| 143 | + * @param {App} app the App object used in feature |
| 144 | + * cross-communication. This must be dependancy injected into |
| 145 | + * redux-logic. |
| 146 | + * |
| 147 | + * @param {logicModuls[]} appLogicArr - an array of redux-logic |
| 148 | + * modules (gaurenteed to have at least one entry). |
| 149 | + * |
| 150 | + * @return {reduxMiddleware} the newly created redux middleware for |
| 151 | + * redux-logic. |
| 152 | + * |
| 153 | + * @private |
| 154 | + */ |
| 155 | +function createLogicMiddleware$(app, appLogic) { |
| 156 | + // define our redux middleware for redux-logic |
| 157 | + return createLogicMiddleware(appLogic, |
| 158 | + { // inject our app as a redux-logic dependancy |
| 159 | + app, |
| 160 | + }); |
65 | 161 | }
|
66 | 162 |
|
67 | 163 |
|
|
0 commit comments