@wordpress/data
Version:
Data module for WordPress.
64 lines (57 loc) • 1.99 kB
text/typescript
/**
* External dependencies
*/
import type { Middleware } from 'redux';
/**
* Internal dependencies
*/
import type { DataRegistry } from './types';
/**
* Creates a middleware handling resolvers cache invalidation.
*
* @param registry Registry for which to create the middleware.
* @param storeName Name of the store for which to create the middleware.
*
* @return Middleware function.
*/
const createResolversCacheMiddleware =
( registry: DataRegistry, storeName: string ): Middleware =>
() =>
( next ) =>
( action ) => {
const resolvers = registry.select( storeName ).getCachedResolvers();
const resolverEntries =
Object.entries< Map< string, { status: 'finished' | 'error' } > >(
resolvers
);
resolverEntries.forEach( ( [ selectorName, resolversByArgs ] ) => {
const resolver =
registry.stores[ storeName ]?.resolvers?.[ selectorName ];
if ( ! resolver || ! resolver.shouldInvalidate ) {
return;
}
const { shouldInvalidate } = resolver;
resolversByArgs.forEach( ( value, args ) => {
// Works around a bug in `EquivalentKeyMap` where `map.delete` merely sets an entry value
// to `undefined` and `map.forEach` then iterates also over these orphaned entries.
if ( value === undefined ) {
return;
}
// resolversByArgs is the map Map([ args ] => boolean) storing the cache resolution status for a given selector.
// If the value is "finished" or "error" it means this resolver has finished its resolution which means we need
// to invalidate it, if it's true it means it's inflight and the invalidation is not necessary.
if ( value.status !== 'finished' && value.status !== 'error' ) {
return;
}
if ( ! shouldInvalidate( action, ...args ) ) {
return;
}
// Trigger cache invalidation
registry
.dispatch( storeName )
.invalidateResolution( selectorName, args );
} );
} );
return next( action );
};
export default createResolversCacheMiddleware;