diff --git a/packages/data/CHANGELOG.md b/packages/data/CHANGELOG.md index f2c2e91e292dc9..92c97ece603287 100644 --- a/packages/data/CHANGELOG.md +++ b/packages/data/CHANGELOG.md @@ -2,6 +2,15 @@ ## Unreleased +### Bug Fix + +- Corrected expect type of action creators and selectors in Redux store configuration type + +### Internal + +- Changed names of store-related types to better reflect their use and role. +- Changed "storeDefinition" to "storeDescriptor" to better reflect its use and role. + ## 6.1.0 (2021-09-09) ### New Features diff --git a/packages/data/README.md b/packages/data/README.md index e184b3328024f0..72fe3f43a235ec 100644 --- a/packages/data/README.md +++ b/packages/data/README.md @@ -16,7 +16,7 @@ _This package assumes that your code will run in an **ES2015+** environment. If ## Registering a Store -Use the `register` function to add your own store to the centralized data registry. This function accepts one argument – a store definition object that can be created with `createReduxStore` factory function. `createReduxStore` accepts two arguments: a name to identify the module, and an object with values describing how your state is represented, modified, and accessed. At a minimum, you must provide a reducer function describing the shape of your state and how it changes in response to actions dispatched to the store. +Use the `register` function to add your own store to the centralized data registry. This function accepts one argument – a store descriptor that can be created with `createReduxStore` factory function. `createReduxStore` accepts two arguments: a name to identify the module, and a configuration object with values describing how your state is represented, modified, and accessed. At a minimum, you must provide a reducer function describing the shape of your state and how it changes in response to actions dispatched to the store. ```js import apiFetch from '@wordpress/api-fetch'; @@ -102,7 +102,7 @@ const store = createReduxStore( 'my-shop', { register( store ); ``` -The return value of `createReduxStore` is the `WPDataStore` object that contains two properties: +The return value of `createReduxStore` is the `StoreDescriptor` object that contains two properties: - `name` (`string`) – the name of the store - `instantiate` (`Function`) - it returns a [Redux-like store object](https://redux.js.org/basics/store) with the following methods: @@ -350,7 +350,7 @@ Undocumented declaration. ### createReduxStore -Creates a data store definition for the provided Redux store options containing +Creates a data store descriptor for the provided Redux store configuration containing properties describing reducer, actions, selectors, controls and resolvers. _Usage_ @@ -369,11 +369,11 @@ const store = createReduxStore( 'demo', { _Parameters_ - _key_ `string`: Unique namespace identifier. -- _options_ `WPDataReduxStoreConfig`: Registered store options, with properties describing reducer, actions, selectors, and resolvers. +- _options_ `ReduxStoreConfig`: Registered store options, with properties describing reducer, actions, selectors, and resolvers. _Returns_ -- `WPDataStore`: Store Object. +- `StoreDescriptor`: Store Object. ### createRegistry @@ -486,7 +486,7 @@ dispatch( 'my-shop' ).setPrice( 'hammer', 9.75 ); _Parameters_ -- _storeNameOrDefinition_ `string|WPDataStore`: Unique namespace identifier for the store or the store definition. +- _storeNameOrDescriptor_ `string|StoreDescriptor`: Unique namespace identifier for the store or the store descriptor. _Returns_ @@ -506,7 +506,7 @@ _Type_ ### register -Registers a standard `@wordpress/data` store definition. +Registers a standard `@wordpress/data` store descriptor. _Usage_ @@ -524,7 +524,7 @@ register( store ); _Parameters_ -- _store_ `WPDataStore`: Store definition. +- _store_ `StoreDescriptor`: Store descriptor. ### registerGenericStore @@ -610,7 +610,7 @@ resolveSelect( 'my-shop' ).getPrice( 'hammer' ).then( console.log ); _Parameters_ -- _storeNameOrDefinition_ `string|WPDataStore`: Unique namespace identifier for the store or the store definition. +- _storeNameOrDescriptor_ `string|StoreDescriptor`: Unique namespace identifier for the store or the store descriptor. _Returns_ @@ -618,7 +618,7 @@ _Returns_ ### select -Given the name or definition of a registered store, returns an object of the store's selectors. +Given the name or descriptor of a registered store, returns an object of the store's selectors. The selector functions are been pre-bound to pass the current state automatically. As a consumer, you need only pass arguments of the selector, if applicable. @@ -632,7 +632,7 @@ select( 'my-shop' ).getPrice( 'hammer' ); _Parameters_ -- _storeNameOrDefinition_ `string|WPDataStore`: Unique namespace identifier for the store or the store definition. +- _storeNameOrDescriptor_ `string|StoreDescriptor`: Unique namespace identifier for the store or the store descriptor. _Returns_ @@ -717,7 +717,7 @@ const SaleButton = ( { children } ) => { _Parameters_ -- _storeNameOrDefinition_ `[string|WPDataStore]`: Optionally provide the name of the store or its definition from which to retrieve action creators. If not provided, the registry.dispatch function is returned instead. +- _storeNameOrDescriptor_ `[string|StoreDescriptor]`: Optionally provide the name of the store or its descriptor from which to retrieve action creators. If not provided, the registry.dispatch function is returned instead. _Returns_ @@ -820,7 +820,7 @@ function Paste( { children } ) { _Parameters_ -- _\_mapSelect_ `Function|WPDataStore|string`: Function called on every state change. The returned value is exposed to the component implementing this hook. The function receives the `registry.select` method on the first argument and the `registry` on the second argument. When a store key is passed, all selectors for the store will be returned. This is only meant for usage of these selectors in event callbacks, not for data needed to create the element tree. +- _\_mapSelect_ `Function|StoreDescriptor|string`: Function called on every state change. The returned value is exposed to the component implementing this hook. The function receives the `registry.select` method on the first argument and the `registry` on the second argument. When a store key is passed, all selectors for the store will be returned. This is only meant for usage of these selectors in event callbacks, not for data needed to create the element tree. - _deps_ `Array`: If provided, this memoizes the mapSelect so the same `mapSelect` is invoked on every state change unless the dependencies change. _Returns_ diff --git a/packages/data/src/components/use-dispatch/test/use-dispatch.js b/packages/data/src/components/use-dispatch/test/use-dispatch.js index 1bae101204b91b..115279dd097df9 100644 --- a/packages/data/src/components/use-dispatch/test/use-dispatch.js +++ b/packages/data/src/components/use-dispatch/test/use-dispatch.js @@ -82,7 +82,7 @@ describe( 'useDispatch', () => { expect( testAction ).toHaveBeenCalledTimes( 1 ); } ); - it( 'returns expected action creators from store for given store definition', () => { + it( 'returns expected action creators from store for given store descriptor', () => { const noop = () => ( { type: '__INERT__' } ); const testAction = jest.fn().mockImplementation( noop ); registry.registerStore( 'demoStore', { diff --git a/packages/data/src/components/use-dispatch/use-dispatch.js b/packages/data/src/components/use-dispatch/use-dispatch.js index 5d0fc86883269b..82656dcabd4457 100644 --- a/packages/data/src/components/use-dispatch/use-dispatch.js +++ b/packages/data/src/components/use-dispatch/use-dispatch.js @@ -3,7 +3,7 @@ */ import useRegistry from '../registry-provider/use-registry'; -/** @typedef {import('./types').WPDataStore} WPDataStore */ +/** @typedef {import('../../types').StoreDescriptor} StoreDescriptor */ /** * A custom react hook returning the current registry dispatch actions creators. @@ -11,11 +11,11 @@ import useRegistry from '../registry-provider/use-registry'; * Note: The component using this hook must be within the context of a * RegistryProvider. * - * @param {string|WPDataStore} [storeNameOrDefinition] Optionally provide the name of the - * store or its definition from which to - * retrieve action creators. If not - * provided, the registry.dispatch - * function is returned instead. + * @param {string|StoreDescriptor} [storeNameOrDescriptor] Optionally provide the name of the + * store or its descriptor from which to + * retrieve action creators. If not + * provided, the registry.dispatch + * function is returned instead. * * @example * This illustrates a pattern where you may need to retrieve dynamic data from @@ -49,11 +49,11 @@ import useRegistry from '../registry-provider/use-registry'; * ``` * @return {Function} A custom react hook. */ -const useDispatch = ( storeNameOrDefinition ) => { +const useDispatch = ( storeNameOrDescriptor ) => { const { dispatch } = useRegistry(); - return storeNameOrDefinition === void 0 + return storeNameOrDescriptor === void 0 ? dispatch - : dispatch( storeNameOrDefinition ); + : dispatch( storeNameOrDescriptor ); }; export default useDispatch; diff --git a/packages/data/src/components/use-select/index.js b/packages/data/src/components/use-select/index.js index 1941305b764745..46ddee6f98ff57 100644 --- a/packages/data/src/components/use-select/index.js +++ b/packages/data/src/components/use-select/index.js @@ -19,7 +19,7 @@ import useAsyncMode from '../async-mode-provider/use-async-mode'; const renderQueue = createQueue(); -/** @typedef {import('./types').WPDataStore} WPDataStore */ +/** @typedef {import('../../types').StoreDescriptor} StoreDescriptor */ /** * Custom react hook for retrieving props from registered selectors. @@ -27,20 +27,20 @@ const renderQueue = createQueue(); * In general, this custom React hook follows the * [rules of hooks](https://reactjs.org/docs/hooks-rules.html). * - * @param {Function|WPDataStore|string} _mapSelect Function called on every state change. The - * returned value is exposed to the component - * implementing this hook. The function receives - * the `registry.select` method on the first - * argument and the `registry` on the second - * argument. - * When a store key is passed, all selectors for - * the store will be returned. This is only meant - * for usage of these selectors in event - * callbacks, not for data needed to create the - * element tree. - * @param {Array} deps If provided, this memoizes the mapSelect so the - * same `mapSelect` is invoked on every state - * change unless the dependencies change. + * @param {Function|StoreDescriptor|string} _mapSelect Function called on every state change. The + * returned value is exposed to the component + * implementing this hook. The function receives + * the `registry.select` method on the first + * argument and the `registry` on the second + * argument. + * When a store key is passed, all selectors for + * the store will be returned. This is only meant + * for usage of these selectors in event + * callbacks, not for data needed to create the + * element tree. + * @param {Array} deps If provided, this memoizes the mapSelect so the + * same `mapSelect` is invoked on every state + * change unless the dependencies change. * * @example * ```js diff --git a/packages/data/src/controls.js b/packages/data/src/controls.js index b3e5175eec306b..9c712ea6224a9d 100644 --- a/packages/data/src/controls.js +++ b/packages/data/src/controls.js @@ -8,7 +8,7 @@ import { isObject } from 'lodash'; */ import { createRegistryControl } from './factory'; -/** @typedef {import('./types').WPDataStore} WPDataStore */ +/** @typedef {import('./types').StoreDescriptor} StoreDescriptor */ const SELECT = '@@data/SELECT'; const RESOLVE_SELECT = '@@data/RESOLVE_SELECT'; @@ -20,9 +20,9 @@ const DISPATCH = '@@data/DISPATCH'; * Note: This control synchronously returns the current selector value, triggering the * resolution, but not waiting for it. * - * @param {string|WPDataStore} storeNameOrDefinition Unique namespace identifier for the store - * @param {string} selectorName The name of the selector. - * @param {Array} args Arguments for the selector. + * @param {string|StoreDescriptor} storeNameOrDescriptor Unique namespace identifier for the store + * @param {string} selectorName The name of the selector. + * @param {Array} args Arguments for the selector. * * @example * ```js @@ -37,12 +37,12 @@ const DISPATCH = '@@data/DISPATCH'; * * @return {Object} The control descriptor. */ -function select( storeNameOrDefinition, selectorName, ...args ) { +function select( storeNameOrDescriptor, selectorName, ...args ) { return { type: SELECT, - storeKey: isObject( storeNameOrDefinition ) - ? storeNameOrDefinition.name - : storeNameOrDefinition, + storeKey: isObject( storeNameOrDescriptor ) + ? storeNameOrDescriptor.name + : storeNameOrDescriptor, selectorName, args, }; @@ -55,9 +55,9 @@ function select( storeNameOrDefinition, selectorName, ...args ) { * selectors that may have a resolver. In such case, it will return a `Promise` that resolves * after the selector finishes resolving, with the final result value. * - * @param {string|WPDataStore} storeNameOrDefinition Unique namespace identifier for the store - * @param {string} selectorName The name of the selector - * @param {Array} args Arguments for the selector. + * @param {string|StoreDescriptor} storeNameOrDescriptor Unique namespace identifier for the store + * @param {string} selectorName The name of the selector + * @param {Array} args Arguments for the selector. * * @example * ```js @@ -72,12 +72,12 @@ function select( storeNameOrDefinition, selectorName, ...args ) { * * @return {Object} The control descriptor. */ -function resolveSelect( storeNameOrDefinition, selectorName, ...args ) { +function resolveSelect( storeNameOrDescriptor, selectorName, ...args ) { return { type: RESOLVE_SELECT, - storeKey: isObject( storeNameOrDefinition ) - ? storeNameOrDefinition.name - : storeNameOrDefinition, + storeKey: isObject( storeNameOrDescriptor ) + ? storeNameOrDescriptor.name + : storeNameOrDescriptor, selectorName, args, }; @@ -86,9 +86,9 @@ function resolveSelect( storeNameOrDefinition, selectorName, ...args ) { /** * Dispatches a control action for triggering a registry dispatch. * - * @param {string|WPDataStore} storeNameOrDefinition Unique namespace identifier for the store - * @param {string} actionName The name of the action to dispatch - * @param {Array} args Arguments for the dispatch action. + * @param {string|StoreDescriptor} storeNameOrDescriptor Unique namespace identifier for the store + * @param {string} actionName The name of the action to dispatch + * @param {Array} args Arguments for the dispatch action. * * @example * ```js @@ -103,12 +103,12 @@ function resolveSelect( storeNameOrDefinition, selectorName, ...args ) { * * @return {Object} The control descriptor. */ -function dispatch( storeNameOrDefinition, actionName, ...args ) { +function dispatch( storeNameOrDescriptor, actionName, ...args ) { return { type: DISPATCH, - storeKey: isObject( storeNameOrDefinition ) - ? storeNameOrDefinition.name - : storeNameOrDefinition, + storeKey: isObject( storeNameOrDescriptor ) + ? storeNameOrDescriptor.name + : storeNameOrDescriptor, actionName, args, }; diff --git a/packages/data/src/index.js b/packages/data/src/index.js index 8ea8f611157bab..925cfecd82d70b 100644 --- a/packages/data/src/index.js +++ b/packages/data/src/index.js @@ -9,7 +9,7 @@ import combineReducers from 'turbo-combine-reducers'; import defaultRegistry from './default-registry'; import * as plugins from './plugins'; -/** @typedef {import('./types').WPDataStore} WPDataStore */ +/** @typedef {import('./types').StoreDescriptor} StoreDescriptor */ export { default as withSelect } from './components/with-select'; export { default as withDispatch } from './components/with-dispatch'; @@ -77,12 +77,12 @@ export { plugins }; export { combineReducers }; /** - * Given the name or definition of a registered store, returns an object of the store's selectors. + * Given the name or descriptor of a registered store, returns an object of the store's selectors. * The selector functions are been pre-bound to pass the current state automatically. * As a consumer, you need only pass arguments of the selector, if applicable. * - * @param {string|WPDataStore} storeNameOrDefinition Unique namespace identifier for the store - * or the store definition. + * @param {string|StoreDescriptor} storeNameOrDescriptor Unique namespace identifier for the store + * or the store descriptor. * * @example * ```js @@ -101,8 +101,8 @@ export const select = defaultRegistry.select; * and modified so that they return promises that resolve to their eventual values, * after any resolvers have ran. * - * @param {string|WPDataStore} storeNameOrDefinition Unique namespace identifier for the store - * or the store definition. + * @param {string|StoreDescriptor} storeNameOrDescriptor Unique namespace identifier for the store + * or the store descriptor. * * @example * ```js @@ -122,8 +122,8 @@ export const resolveSelect = defaultRegistry.resolveSelect; * Note: Action creators returned by the dispatch will return a promise when * they are called. * - * @param {string|WPDataStore} storeNameOrDefinition Unique namespace identifier for the store - * or the store definition. + * @param {string|StoreDescriptor} storeNameOrDescriptor Unique namespace identifier for the store + * or the store descriptor. * * @example * ```js @@ -189,7 +189,7 @@ export const registerStore = defaultRegistry.registerStore; export const use = defaultRegistry.use; /** - * Registers a standard `@wordpress/data` store definition. + * Registers a standard `@wordpress/data` store descriptor. * * @example * ```js @@ -204,6 +204,6 @@ export const use = defaultRegistry.use; * register( store ); * ``` * - * @param {WPDataStore} store Store definition. + * @param {StoreDescriptor} store Store descriptor. */ export const register = defaultRegistry.register; diff --git a/packages/data/src/redux-store/index.js b/packages/data/src/redux-store/index.js index ba0842329dd063..fb52262c17e104 100644 --- a/packages/data/src/redux-store/index.js +++ b/packages/data/src/redux-store/index.js @@ -22,9 +22,9 @@ import metadataReducer from './metadata/reducer'; import * as metadataSelectors from './metadata/selectors'; import * as metadataActions from './metadata/actions'; -/** @typedef {import('../types').WPDataRegistry} WPDataRegistry */ -/** @typedef {import('../types').WPDataStore} WPDataStore */ -/** @typedef {import('../types').WPDataReduxStoreConfig} WPDataReduxStoreConfig */ +/** @typedef {import('../types').DataRegistry} DataRegistry */ +/** @typedef {import('../types').StoreDescriptor} StoreDescriptor */ +/** @typedef {import('../types').ReduxStoreConfig} ReduxStoreConfig */ const trimUndefinedValues = ( array ) => { const result = [ ...array ]; @@ -68,7 +68,7 @@ function createResolversCache() { } /** - * Creates a data store definition for the provided Redux store options containing + * Creates a data store descriptor for the provided Redux store configuration containing * properties describing reducer, actions, selectors, controls and resolvers. * * @example @@ -83,12 +83,12 @@ function createResolversCache() { * } ); * ``` * - * @param {string} key Unique namespace identifier. - * @param {WPDataReduxStoreConfig} options Registered store options, with properties - * describing reducer, actions, selectors, - * and resolvers. + * @param {string} key Unique namespace identifier. + * @param {ReduxStoreConfig} options Registered store options, with properties + * describing reducer, actions, selectors, + * and resolvers. * - * @return {WPDataStore} Store Object. + * @return {StoreDescriptor} Store Object. */ export default function createReduxStore( key, options ) { return { @@ -210,12 +210,12 @@ export default function createReduxStore( key, options ) { /** * Creates a redux store for a namespace. * - * @param {string} key Unique namespace identifier. - * @param {Object} options Registered store options, with properties - * describing reducer, actions, selectors, - * and resolvers. - * @param {WPDataRegistry} registry Registry reference. - * @param {Object} thunkArgs Argument object for the thunk middleware. + * @param {string} key Unique namespace identifier. + * @param {Object} options Registered store options, with properties + * describing reducer, actions, selectors, + * and resolvers. + * @param {DataRegistry} registry Registry reference. + * @param {Object} thunkArgs Argument object for the thunk middleware. * @return {Object} Newly created redux store. */ function instantiateReduxStore( key, options, registry, thunkArgs ) { diff --git a/packages/data/src/registry.js b/packages/data/src/registry.js index 4d1626e810c87f..ff3d98b8475a0d 100644 --- a/packages/data/src/registry.js +++ b/packages/data/src/registry.js @@ -11,7 +11,7 @@ import createCoreDataStore from './store'; import { STORE_NAME } from './store/name'; import { createEmitter } from './utils/emitter'; -/** @typedef {import('./types').WPDataStore} WPDataStore */ +/** @typedef {import('./types').StoreDescriptor} StoreDescriptor */ /** * @typedef {Object} WPDataRegistry An isolated orchestrator of store registrations. @@ -74,15 +74,15 @@ export function createRegistry( storeConfigs = {}, parent = null ) { /** * Calls a selector given the current state and extra arguments. * - * @param {string|WPDataStore} storeNameOrDefinition Unique namespace identifier for the store - * or the store definition. + * @param {string|StoreDescriptor} storeNameOrDescriptor Unique namespace identifier for the store + * or the store descriptor. * * @return {*} The selector's returned value. */ - function select( storeNameOrDefinition ) { - const storeName = isObject( storeNameOrDefinition ) - ? storeNameOrDefinition.name - : storeNameOrDefinition; + function select( storeNameOrDescriptor ) { + const storeName = isObject( storeNameOrDescriptor ) + ? storeNameOrDescriptor.name + : storeNameOrDescriptor; __experimentalListeningStores.add( storeName ); const store = stores[ storeName ]; if ( store ) { @@ -105,15 +105,15 @@ export function createRegistry( storeConfigs = {}, parent = null ) { * and modified so that they return promises that resolve to their eventual values, * after any resolvers have ran. * - * @param {string|WPDataStore} storeNameOrDefinition Unique namespace identifier for the store - * or the store definition. + * @param {string|StoreDescriptor} storeNameOrDescriptor Unique namespace identifier for the store + * or the store descriptor. * * @return {Object} Each key of the object matches the name of a selector. */ - function resolveSelect( storeNameOrDefinition ) { - const storeName = isObject( storeNameOrDefinition ) - ? storeNameOrDefinition.name - : storeNameOrDefinition; + function resolveSelect( storeNameOrDescriptor ) { + const storeName = isObject( storeNameOrDescriptor ) + ? storeNameOrDescriptor.name + : storeNameOrDescriptor; __experimentalListeningStores.add( storeName ); const store = stores[ storeName ]; if ( store ) { @@ -126,15 +126,15 @@ export function createRegistry( storeConfigs = {}, parent = null ) { /** * Returns the available actions for a part of the state. * - * @param {string|WPDataStore} storeNameOrDefinition Unique namespace identifier for the store - * or the store definition. + * @param {string|StoreDescriptor} storeNameOrDescriptor Unique namespace identifier for the store + * or the store descriptor. * * @return {*} The action's returned value. */ - function dispatch( storeNameOrDefinition ) { - const storeName = isObject( storeNameOrDefinition ) - ? storeNameOrDefinition.name - : storeNameOrDefinition; + function dispatch( storeNameOrDescriptor ) { + const storeName = isObject( storeNameOrDescriptor ) + ? storeNameOrDescriptor.name + : storeNameOrDescriptor; const store = stores[ storeName ]; if ( store ) { return store.getActions(); @@ -199,9 +199,9 @@ export function createRegistry( storeConfigs = {}, parent = null ) { } /** - * Registers a new store definition. + * Registers a new store given a store descriptor. * - * @param {WPDataStore} store Store definition. + * @param {StoreDescriptor} store Store descriptor. */ function register( store ) { registerGenericStore( store.name, store.instantiate( registry ) ); diff --git a/packages/data/src/test/registry.js b/packages/data/src/test/registry.js index 58fa9ebcb326f4..fdc1f38ffc466d 100644 --- a/packages/data/src/test/registry.js +++ b/packages/data/src/test/registry.js @@ -276,7 +276,7 @@ describe( 'createRegistry', () => { expect( resolver ).toHaveBeenCalledTimes( 2 ); } ); - it( 'should support the object resolver definition', () => { + it( 'should support the object resolver descriptor', () => { const resolver = jest.fn(); registry.registerStore( 'demo', { reducer: ( state = 'OK' ) => state, @@ -508,7 +508,7 @@ describe( 'createRegistry', () => { } ); describe( 'register', () => { - it( 'should work with the store definition as param for select', () => { + it( 'should work with the store descriptor as param for select', () => { const store = createReduxStore( 'demo', { reducer: ( state = 'OK' ) => state, selectors: { @@ -520,7 +520,7 @@ describe( 'createRegistry', () => { expect( registry.select( store ).getValue() ).toBe( 'OK' ); } ); - it( 'should work with the store definition as param for dispatch', async () => { + it( 'should work with the store descriptor as param for dispatch', async () => { const store = createReduxStore( 'demo', { reducer( state = 'OK', action ) { if ( action.type === 'UPDATE' ) { diff --git a/packages/data/src/types.ts b/packages/data/src/types.ts index 29f72998b3ed44..ae7ddfe804cc8c 100644 --- a/packages/data/src/types.ts +++ b/packages/data/src/types.ts @@ -1,40 +1,68 @@ -export type WPDataFunctionOrGeneratorArray = Array< Function | Generator >; -export type WPDataFunctionArray = Array< Function >; +type MapOf< T > = { [ name: string ]: T }; -export interface WPDataAttachedStore { - getSelectors: () => WPDataFunctionArray; - getActions: () => WPDataFunctionArray; +export type ActionCreator = Function | Generator; +export type Resolver = Function | Generator; +export type Selector = Function; + +export type AnyConfig = ReduxStoreConfig< any, any, any >; + +export interface StoreInstance< Config extends AnyConfig > { + getSelectors: () => SelectorsOf< Config >; + getActions: () => ActionCreatorsOf< Config >; subscribe: ( listener: () => void ) => () => void; } -export interface WPDataStore { +export interface StoreDescriptor< Config extends AnyConfig > { /** * Store Name */ name: string; /** - * Store configuration object. + * Creates a store instance */ - instantiate: ( registry: WPDataRegistry ) => WPDataAttachedStore; + instantiate: ( registry: DataRegistry ) => StoreInstance< Config >; } -export interface WPDataReduxStoreConfig { +export interface ReduxStoreConfig< + State, + ActionCreators extends MapOf< ActionCreator >, + Selectors extends MapOf< Selector > +> { + initialState?: State; reducer: ( state: any, action: any ) => any; - actions?: WPDataFunctionOrGeneratorArray; - resolvers?: WPDataFunctionOrGeneratorArray; - selectors?: WPDataFunctionArray; - controls?: WPDataFunctionArray; + actions?: ActionCreators; + resolvers?: MapOf< Resolver >; + selectors?: Selectors; + controls?: MapOf< Function >; } -export interface WPDataRegistry { - register: ( store: WPDataStore ) => void; +export interface DataRegistry { + register: ( store: StoreDescriptor< any > ) => void; } -export interface WPDataEmitter { +export interface DataEmitter { emit: () => void; subscribe: ( listener: () => void ) => () => void; pause: () => void; resume: () => void; isPaused: boolean; } + +// +// Type Helpers +// + +type ActionCreatorsOf< + Config extends AnyConfig +> = Config extends ReduxStoreConfig< any, infer ActionCreators, any > + ? { [ name in keyof ActionCreators ]: Function | Generator } + : never; + +type SelectorsOf< Config extends AnyConfig > = Config extends ReduxStoreConfig< + any, + any, + infer Selectors +> + ? { [ name in keyof Selectors ]: Function } + : never; diff --git a/packages/data/src/utils/emitter.js b/packages/data/src/utils/emitter.js index 237f1d9958b151..883b4d83c1e748 100644 --- a/packages/data/src/utils/emitter.js +++ b/packages/data/src/utils/emitter.js @@ -1,7 +1,7 @@ /** * Create an event emitter. * - * @return {import("../types").WPDataEmitter} Emitter. + * @return {import("../types").DataEmitter} Emitter. */ export function createEmitter() { let isPaused = false;