-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Data Module: Support controls in resolvers (#9507)
* Redux Routine: Make it more flexible allowing runtimes without middlewares * Use rungen to implement the co-routine middleware * Refactor resolvers to allow extending fullfillement in plugins * Simplify the signature of the fulfill function * Fallback to regular resolution if controls are not supported * Treat async generators in resolvers as a plugin * Fix async generator middleware * Don't proxy the namespaces registry property * Avoid useless middleware file * Fix proxifying the registry attributes by auto-decting functions * Performance: Bind resolvers to selectors at registration time * Remove useless alignment change * Avoid a middlewares folder and move middlewares to plugins and core * Make the fulfill registry method experimental * fix wording and typos
- Loading branch information
1 parent
41cb78b
commit cbee072
Showing
16 changed files
with
442 additions
and
443 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { applyMiddleware } from 'redux'; | ||
import { get } from 'lodash'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import asyncGeneratorMiddleware, { toAsyncIterable } from './middleware'; | ||
|
||
export default function( registry ) { | ||
return { | ||
registerStore( reducerKey, options ) { | ||
const store = registry.registerStore( reducerKey, options ); | ||
const enhancer = applyMiddleware( asyncGeneratorMiddleware ); | ||
const createStore = () => store; | ||
Object.assign( | ||
store, | ||
enhancer( createStore )( options.reducer ) | ||
); | ||
return store; | ||
}, | ||
|
||
async __experimentalFulfill( reducerKey, selectorName, ...args ) { | ||
const resolver = get( registry.namespaces, [ reducerKey, 'resolvers', selectorName ] ); | ||
if ( ! resolver ) { | ||
return; | ||
} | ||
const store = registry.namespaces[ reducerKey ].store; | ||
const state = store.getState(); | ||
const action = resolver.fulfill( state, ...args ); | ||
if ( action ) { | ||
await store.dispatch( toAsyncIterable( action ) ); | ||
} | ||
}, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/** | ||
* Returns true if the given argument appears to be a dispatchable action. | ||
* | ||
* @param {*} action Object to test. | ||
* | ||
* @return {boolean} Whether object is action-like. | ||
*/ | ||
function isActionLike( action ) { | ||
return ( | ||
!! action && | ||
typeof action.type === 'string' | ||
); | ||
} | ||
|
||
/** | ||
* Returns true if the given object is an async iterable, or false otherwise. | ||
* | ||
* @param {*} object Object to test. | ||
* | ||
* @return {boolean} Whether object is an async iterable. | ||
*/ | ||
function isAsyncIterable( object ) { | ||
return ( | ||
!! object && | ||
typeof object[ Symbol.asyncIterator ] === 'function' | ||
); | ||
} | ||
|
||
/** | ||
* Returns true if the given object is iterable, or false otherwise. | ||
* | ||
* @param {*} object Object to test. | ||
* | ||
* @return {boolean} Whether object is iterable. | ||
*/ | ||
function isIterable( object ) { | ||
return ( | ||
!! object && | ||
typeof object[ Symbol.iterator ] === 'function' | ||
); | ||
} | ||
|
||
/** | ||
* Normalizes the given object argument to an async iterable, asynchronously | ||
* yielding on a singular or array of generator yields or promise resolution. | ||
* | ||
* @param {*} object Object to normalize. | ||
* | ||
* @return {AsyncGenerator} Async iterable actions. | ||
*/ | ||
export function toAsyncIterable( object ) { | ||
if ( isAsyncIterable( object ) ) { | ||
return object; | ||
} | ||
|
||
return ( async function* () { | ||
// Normalize as iterable... | ||
if ( ! isIterable( object ) ) { | ||
object = [ object ]; | ||
} | ||
|
||
for ( const maybeAction of object ) { | ||
yield maybeAction; | ||
} | ||
}() ); | ||
} | ||
|
||
/** | ||
* Simplest possible promise redux middleware. | ||
* | ||
* @param {Object} store Redux store. | ||
* | ||
* @return {function} middleware. | ||
*/ | ||
const asyncGeneratorMiddleware = ( store ) => ( next ) => ( action ) => { | ||
if ( ! isAsyncIterable( action ) ) { | ||
return next( action ); | ||
} | ||
|
||
const runtime = async ( fulfillment ) => { | ||
for await ( const maybeAction of fulfillment ) { | ||
// Dispatch if it quacks like an action. | ||
if ( isActionLike( maybeAction ) ) { | ||
store.dispatch( maybeAction ); | ||
} | ||
} | ||
}; | ||
|
||
return runtime( action ); | ||
}; | ||
|
||
export default asyncGeneratorMiddleware; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export { default as controls } from './controls'; | ||
export { default as persistence } from './persistence'; | ||
export { default as asyncGenerator } from './async-generator'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/** | ||
* Simplest possible promise redux middleware. | ||
* | ||
* @return {function} middleware. | ||
*/ | ||
const promiseMiddleware = () => ( next ) => ( action ) => { | ||
if ( action instanceof Promise ) { | ||
return action.then( next ); | ||
} | ||
|
||
return next( action ); | ||
}; | ||
|
||
export default promiseMiddleware; |
Oops, something went wrong.