createFeature(name, [enabled], [publicFace], [appWillStart], [appDidStart], [extendedAspect]) ⇒ Feature
Create a new Feature
object, cataloging
AspectContent
to be consumed by
launchApp()
. Each feature within an application
promotes it's own Feature
object.
For more information, please refer to
Feature & aspect content
, with examples at
Feature Object
.
Please Note this function uses named parameters.
Param | Type | Default | Description |
---|---|---|---|
name | string | the identity of the feature. Feature names are used to index the App Object (in support of Cross Feature Communication ), and are therefore guaranteed to be unique. Application code can also use the Feature name in various single-source-of-truth operations (see Best Practices ). |
|
[enabled] | boolean | true |
an indicator as to whether this feature is enabled (true) or not (false). When used, this indicator is typically based on a dynamic expression, allowing packaged code to be dynamically enabled/disabled at run-time (please refer to: Feature Enablement ). |
[publicFace] | Any | an optional resource object that is the feature's Public API, promoting Cross Feature Communication . This object is exposed through the App object as: app.{featureName}.{publicFace} (please refer to: publicFace and the App Object ). |
|
[appWillStart] | appWillStartCB |
an optional Application Life Cycle Hook invoked one time, just before the app starts up. This life-cycle hook can do any type of initialization, and/or optionally supplement the app's top-level content (using a non-null return) (please refer to: appWillStart ). |
|
[appDidStart] | appDidStartCB |
an optional Application Life Cycle Hook invoked one time, immediately after the app has started. Because the app is up-and-running at this time, you have access to the appState and the dispatch() function ... assuming you are using redux (when detected by feature-u's plugable aspects) (please refer to: appDidStart ). |
|
[extendedAspect] | AspectContent |
additional aspects, as defined by the feature-u's Aspect plugins (please refer to: Extendable aspects -and- Extending feature-u ). |
Returns: Feature
- a new Feature object (to be consumed by
launchApp()).
extendFeatureProperty(name, owner)
Extend valid Feature properties to include the supplied name ... used when extending APIs forAspect Cross Communication
.
feature-u keeps track of the agent that owns this extension (using the owner parameter). This is used to prevent exceptions when duplicate extension requests are made by the same owner. This can happen when multiple instances of an aspect type are supported, and also in unit testing.
Throws:
- Error when supplied name is already reserved by a different owner
Param | Type | Description |
---|---|---|
name | string | the property name to allow. |
owner | string | the requesting owner id of this extension request. Use any string that uniquely identifies your utility (such as the aspect's npm package name). |
launchApp([aspects], features, registerRootAppElm) ⇒ App
Launch an application by assembling the supplied features, driving
the configuration of the frameworks in use (as orchestrated by the
supplied set of plugable Aspects).
For more information (with examples), please refer to
Launching Your Application
.
Please Note this function uses named parameters.
Param | Type | Description |
---|---|---|
[aspects] | Array.<Aspect> |
the set of plugable Aspects that extend feature-u, integrating other frameworks to match your specific run-time stack. When NO Aspects are supplied (an atypical case), only the very basic feature-u characteristics are in effect (like publicFace and life-cycle hooks). |
features | Array.<Feature> |
the features that comprise this application. |
registerRootAppElm | registerRootAppElmCB |
the callback hook that registers the supplied root application element to the specific React framework used in the app. Because this registration is accomplished by app-specific code, feature-u can operate in any of the react platforms, such as: react web, react-native , expo , etc.Please refer to React Registration for more details and complete examples. |
Returns: App
- the App object used to promote
Cross Feature Communication
.
managedExpansion(managedExpansionCB) ⇒ managedExpansionCB
Mark the supplied managedExpansionCB()
as a "Managed
Expansion Callback", distinguishing it from other functions (such
as reducer functions).
Features may communicate AspectContent
directly, or
through a managedExpansionCB()
. In other words, the
AspectContent
can either be the actual content itself
(ex: reducer, logic modules, etc.), or a function that returns
the content. The latter:
- supports
Cross Feature Communication
(through app object injection), and - minimizes circular dependency issues (of ES6 modules).
Managed Expansion Callbacks are used when a fully resolved
App
object is required during in-line code expansion.
They are merely functions that when invoked (under the control of
feature-u), are supplied the App
object and
return the expanded AspectContent
(ex: reducer, logic
modules, etc.).
For more information (with examples), please refer to
Managed Code Expansion
.
The managedExpansionCB()
function should conform to the
following signature:
API: managedExpansionCB(app): AspectContent
Param | Type | Description |
---|---|---|
managedExpansionCB | managedExpansionCB |
the callback function that when invoked (by feature-u) expands/returns the desired AspectContent . |
Returns: managedExpansionCB
- the supplied managedExpansionCB,
marked as a "managed expansion callback".
createAspect(name, [genesis], validateFeatureContent, [expandFeatureContent], assembleFeatureContent, [assembleAspectResources], [initialRootAppElm], [injectRootAppElm], [config], [additionalMethods]) ⇒ Aspect
Create an Aspect
object, used to extend feature-u.
The Aspect
object promotes a series of life-cycle
methods that feature-u invokes in a controlled way. This
life-cycle is controlled by launchApp()
... it is
supplied the Aspects, and it invokes their methods.
The essential characteristics of the Aspect
life-cycle is to:
- accumulate
AspectContent
across all features - perform the desired setup and configuration
- expose the framework in some way (by injecting a component in the
root DOM, or some
Aspect Cross Communication
mechanism)
The Extending feature-u
section provides more insight on how
Aspect
s are created and used.
Please Note this function uses named parameters. The order in which these items are presented represents the same order they are executed.
Param | Type | Description |
---|---|---|
name | string | the Aspect.name is used to "key" AspectContent of this type in the Feature object.For example: an Aspect.name: 'xyz' would permit a Feature.xyz: xyzContent construct.As a result, Aspect names cannot clash with built-in aspects, and they must be unique (across all aspects that are in-use). |
[genesis] | genesisMeth |
an optional Life Cycle Hook invoked one time, at the very beginning of the app's start up process. This hook can perform Aspect related initialization and validation: |
validateFeatureContent | validateFeatureContentMeth |
a validation hook allowing this aspect to verify it's content on the supplied feature (which is known to contain this aspect). |
[expandFeatureContent] | expandFeatureContentMeth |
an optional aspect expansion hook, defaulting to the algorithm defined by managedExpansion() .This function rarely needs to be overridden. It provides a hook to aspects that need to transfer additional content from the expansion function to the expanded content. |
assembleFeatureContent | assembleFeatureContentMeth |
the Aspect method that assembles content for this aspect across all features, retaining needed state for subsequent ops. This method is required because this is the primary task that is accomplished by all aspects. |
[assembleAspectResources] | assembleAspectResourcesMeth |
an optional Aspect method that assemble resources for this aspect across all other aspects, retaining needed state for subsequent ops. This hook is executed after all the aspects have assembled their feature content (i.e. after assembleFeatureContent() ). |
[initialRootAppElm] | initialRootAppElmMeth |
an optional callback hook that promotes some characteristic of this aspect within the rootAppElm ... the top-level react DOM that represents the display of the entire application.The Defining rootAppElm section highlights when to use initialRootAppElm() verses injectRootAppElm() . |
[injectRootAppElm] | injectRootAppElmMeth |
an optional callback hook that promotes some characteristic of this aspect within the rootAppElm ... the top-level react DOM that represents the display of the entire application.The Defining rootAppElm section highlights when to use initialRootAppElm() verses injectRootAppElm() . |
[config] | Any | an optional sub-object that can be used for any type of configuration that a specific Aspect may need (see: Aspect.config ). |
[additionalMethods] | Any | additional methods (proprietary to specific Aspects), supporting Aspect Cross Communication ... a contract between one or more aspects (see: Aspect.additionalMethods() ). |
Returns: Aspect
- a new Aspect object (to be consumed by launchApp()
).
extendAspectProperty(name, owner)
Extend valid Aspect properties to include the supplied name ... used when extending APIs forAspect Cross Communication
.
feature-u keeps track of the agent that owns this extension (using the owner parameter). This is used to prevent exceptions when duplicate extension requests are made by the same owner. This can happen when multiple instances of an aspect type are supported, and also in unit testing.
Throws:
- Error when supplied name is already reserved by a different owner
Param | Type | Description |
---|---|---|
name | string | the property name to extend. |
owner | string | the requesting owner id of this extension request. Use any string that uniquely identifies your utility (such as the aspect's npm package name). |
Feature : Object
The Feature object is a container that holdsAspectContent
that is of interest to feature-u.
Each feature within an application promotes a Feature object (using
createFeature()
) that catalogs the aspects of that
feature.
Ultimately, all Feature objects are consumed by
launchApp()
.
For more information, please refer to
Feature & aspect content
, with examples at
Feature Object
.
appWillStartCB ⇒ reactElm
An optionalApplication Life Cycle Hook
invoked one time, just
before the app starts up.
This life-cycle hook can do any type of initialization. For example: initialize FireBase.
In addition, it can optionally supplement the app's top-level root element (i.e. react component instance). Any significant return (truthy) is interpreted as the app's new rootAppElm. IMPORTANT: When this is used, the supplied curRootAppElm MUST be included as part of this definition (accommodating the accumulative process of other feature injections)!
For more information (with examples), please refer to the
Guide's appWillStart
.
Please Note this function uses named parameters.
Param | Type | Description |
---|---|---|
app | App |
the App object used in feature cross-communication. |
curRootAppElm | reactElm | the current react app element root. |
Returns: reactElm - optionally, new top-level content (which in turn must contain the supplied curRootAppElm), or falsy for unchanged.
appDidStartCB ⇒
An optionalApplication Life Cycle Hook
invoked one time,
immediately after the app has started.
Because the app is up-and-running at this time, you have access to
the appState
and dispatch()
function ... assuming you are using
redux
(when detected by feature-u's plugable aspects).
For more info with examples, please see the Guide's
appDidStart
.
Please Note this function uses named parameters.
Param | Type | Description |
---|---|---|
app | App |
the App object used in feature cross-communication. |
[appState] | Any | the redux top-level app state (when redux is in use). |
[dispatch] | function | the redux dispatch() function (when redux is in use). |
Returns: void
registerRootAppElmCB ⇒
ThelaunchApp()
callback hook that registers the
supplied root application element to the specific React framework
used in the app.
Because this registration is accomplished by app-specific code,
feature-u can operate in any of the React platforms, such as:
react
web, react-native
,
expo
, etc.
Please refer to React Registration
for more
details and complete examples.
Param | Type | Description |
---|---|---|
rootAppElm | reactElm | the root application element to be registered. |
Returns: void
App : Object
The App object (emitted fromlaunchApp()
) facilitates
Cross Feature Communication
by accumulating the Public API of all
features, through named feature nodes structured as follows:
App.{featureName}.{publicFace}
For more information, please refer to
publicFace and the App Object
and
App Object
.
managedExpansionCB ⇒ AspectContent
A "managed expansion callback" (defined by
managedExpansion()
) that when invoked (by feature-u)
expands and returns the desired AspectContent
.
For more information (with examples), please refer to
Managed Code Expansion
.
Param | Type | Description |
---|---|---|
app | App |
The feature-u app object, promoting the publicFace of each feature. |
Returns: AspectContent
- The desired AspectContent (ex: reducer,
logic module, etc.).
Aspect : Object
Aspect objects (emitted fromcreateAspect()
) are used to
extend feature-u.
The Aspect object promotes a series of life-cycle methods that
feature-u invokes in a controlled way. This life-cycle is
controlled by launchApp()
` ... it is supplied the
Aspects, and it invokes their methods.
Typically Aspects are packaged separately (as an external npm feature-u extension), although they can be created locally within a project (if needed).
For more information, please refer to
Extendable aspects
and
Extending feature-u
.
AspectContent : Any
The content (or payload) of anAspect
, specified
within a Feature
.
An Aspect
object extends feature-u by accumulating
information of interest from Feature
objects (indexed
by the Aspect name).
The content type is specific to the Aspect. For example, a redux
Aspect assembles reducers (via Feature.reducer
), while a
redux-logic Aspect gathers logic modules (via Feature.logic
),
etc.
For more information, please refer to
Feature & aspect content
.
genesisMeth ⇒ string
An optional Life Cycle Hook invoked one time, at the very beginning of the app's start up process.This hook can perform Aspect related initialization and validation:
initialization: this is where where proprietary Aspect/Feature APIs should be registered (if any) - via
extendAspectProperty()
andextendFeatureProperty()
(please see:Aspect Cross Communication
).validation: this is where an aspect can verify it's own required configuration (if any). Some aspects require certain settings (set by the application) in self for them to operate.
API: genesis(): string
Returns: string - an error message when self is in an invalid state
(falsy when valid). Because this validation occurs under the
control of launchApp()
, any message is prefixed with:
'launchApp() parameter violation: '
.
validateFeatureContentMeth ⇒ string
A validation hook allowing this aspect to verify it's content on the supplied feature.API: validateFeatureContent(feature): string
Param | Type | Description |
---|---|---|
feature | Feature |
the feature to validate, which is known to contain this aspect. |
Returns: string - an error message string when the supplied feature
contains invalid content for this aspect (falsy when valid).
Because this validation conceptually occurs under the control of
createFeature()
, any message is prefixed with:
'createFeature() parameter violation: '
.
expandFeatureContentMeth ⇒ string
Expand self'sAspectContent
in the supplied feature,
replacing that content (within the feature). Once expansion is
complete, feature-u will perform a delayed validation of the
expanded content.
API: expandFeatureContent(app, feature): string
The default behavior simply implements the expansion algorithm
defined by managedExpansion()
:
feature[this.name] = feature[this.name](app);
This default behavior rarely needs to change. It however provides
a hook for aspects that need to transfer additional content from
the expansion function to the expanded content. As an example, the
reducer
aspect must transfer the slice property from the
expansion function to the expanded reducer.
Param | Type | Description |
---|---|---|
app | App |
the App object used in feature cross-communication. |
feature | Feature |
the feature which is known to contain this aspect and is in need of expansion (as defined by managedExpansion() ). |
Returns: string - an optional error message when the supplied
feature contains invalid content for this aspect (falsy when
valid). This is a specialized validation of the expansion
function, over-and-above what is checked in the standard
validateFeatureContent()
hook.
assembleFeatureContentMeth ⇒
The required Aspect method that assembles content for this aspect across all features, retaining needed state for subsequent ops. This method is required because this is the primary task that is accomplished by all aspects.API: assembleFeatureContent(app, activeFeatures): void
Param | Type | Description |
---|---|---|
app | App |
the App object used in feature cross-communication. |
activeFeatures | Array.<Feature> |
The set of active (enabled) features that comprise this application. |
Returns: void
assembleAspectResourcesMeth ⇒
An optional Aspect method that assembles resources for this aspect across all other aspects, retaining needed state for subsequent ops. This hook is executed after all the aspects have assembled their feature content (i.e. afterassembleFeatureContent()
).
API: assembleAspectResources(app, aspects): void
This is an optional second-pass (so-to-speak) of Aspect data
gathering, that facilitates
Aspect Cross Communication
. It allows an
extending aspect to gather resources from other aspects, using an
additional API (ex: Aspect.getXyz()
).
Param | Type | Description |
---|---|---|
app | App |
the App object used in feature cross-communication. |
aspects | Array.<Aspect> |
The set of feature-u Aspect objects used in this this application. |
Returns: void
initialRootAppElmMeth ⇒ reactElm
An optional callback hook that promotes some characteristic of this aspect within therootAppElm
... the top-level react DOM that
represents the display of the entire application.
API: initialRootAppElm(app, curRootAppElm): rootAppElm
The Defining rootAppElm
section highlights when
to use initialRootAppElm()
verses
injectRootAppElm()
.
NOTE: When this hook is used, the supplied curRootAppElm MUST be included as part of this definition!
Param | Type | Description |
---|---|---|
app | App |
the App object used in feature cross-communication. |
curRootAppElm | reactElm | the current react app element root. |
Returns: reactElm - a new react app element root (which in turn must contain the supplied curRootAppElm), or simply the supplied curRootAppElm (if no change).
injectRootAppElmMeth ⇒ reactElm
An optional callback hook that promotes some characteristic of this aspect within therootAppElm
... the top-level react DOM that
represents the display of the entire application.
API: injectRootAppElm(app, curRootAppElm): rootAppElm
The Defining rootAppElm
section highlights when
to use initialRootAppElm()
verses
injectRootAppElm()
.
NOTE: When this hook is used, the supplied curRootAppElm MUST be included as part of this definition!
Param | Type | Description |
---|---|---|
app | App |
the App object used in feature cross-communication. |
curRootAppElm | reactElm | the current react app element root. |
Returns: reactElm - a new react app element root (which in turn must contain the supplied curRootAppElm), or simply the supplied curRootAppElm (if no change).