From 2591d58b8ce124b28f7dea21b30092f08f8ef53e Mon Sep 17 00:00:00 2001 From: Jarda Snajdr Date: Mon, 14 Sep 2020 11:52:45 +0200 Subject: [PATCH] core-data: use controls from data-controls in favor of the package-local ones (#25235) The generic `apiFetch`, `select` and `dispatch` controls are frequently duplicated in various stores. This patch fixes that for the `core-data` package. --- packages/core-data/src/actions.js | 63 +++++++++++++++----- packages/core-data/src/controls.js | 73 ------------------------ packages/core-data/src/entities.js | 8 ++- packages/core-data/src/index.js | 2 +- packages/core-data/src/resolvers.js | 14 +++-- packages/core-data/src/test/actions.js | 29 ++++++---- packages/core-data/src/test/resolvers.js | 6 +- 7 files changed, 89 insertions(+), 106 deletions(-) delete mode 100644 packages/core-data/src/controls.js diff --git a/packages/core-data/src/actions.js b/packages/core-data/src/actions.js index 2b5d07d6bc4022..3027b1739bc7e5 100644 --- a/packages/core-data/src/actions.js +++ b/packages/core-data/src/actions.js @@ -6,6 +6,7 @@ import { castArray, get, isEqual, find } from 'lodash'; /** * WordPress dependencies */ +import { apiFetch, __unstableSyncSelect } from '@wordpress/data-controls'; import { addQueryArgs } from '@wordpress/url'; /** @@ -13,7 +14,6 @@ import { addQueryArgs } from '@wordpress/url'; */ import { receiveItems, removeItems, receiveQueriedItems } from './queried-data'; import { getKindEntities, DEFAULT_ENTITY_KEY } from './entities'; -import { select, apiFetch } from './controls'; /** * Returns an action object used in signalling that authors have been received. @@ -210,15 +210,27 @@ export function* deleteEntityRecord( kind, name, recordId, query ) { * @return {Object} Action object. */ export function* editEntityRecord( kind, name, recordId, edits, options = {} ) { - const entity = yield select( 'getEntity', kind, name ); + const entity = yield __unstableSyncSelect( + 'core', + 'getEntity', + kind, + name + ); if ( ! entity ) { throw new Error( `The entity being edited (${ kind }, ${ name }) does not have a loaded config.` ); } const { transientEdits = {}, mergedEdits = {} } = entity; - const record = yield select( 'getRawEntityRecord', kind, name, recordId ); - const editedRecord = yield select( + const record = yield __unstableSyncSelect( + 'core', + 'getRawEntityRecord', + kind, + name, + recordId + ); + const editedRecord = yield __unstableSyncSelect( + 'core', 'getEditedEntityRecord', kind, name, @@ -263,7 +275,7 @@ export function* editEntityRecord( kind, name, recordId, edits, options = {} ) { * an entity record, if any. */ export function* undo() { - const undoEdit = yield select( 'getUndoEdit' ); + const undoEdit = yield __unstableSyncSelect( 'core', 'getUndoEdit' ); if ( ! undoEdit ) { return; } @@ -281,7 +293,7 @@ export function* undo() { * edit to an entity record, if any. */ export function* redo() { - const redoEdit = yield select( 'getRedoEdit' ); + const redoEdit = yield __unstableSyncSelect( 'core', 'getRedoEdit' ); if ( ! redoEdit ) { return; } @@ -331,7 +343,13 @@ export function* saveEntityRecord( for ( const [ key, value ] of Object.entries( record ) ) { if ( typeof value === 'function' ) { const evaluatedValue = value( - yield select( 'getEditedEntityRecord', kind, name, recordId ) + yield __unstableSyncSelect( + 'core', + 'getEditedEntityRecord', + kind, + name, + recordId + ) ); yield editEntityRecord( kind, @@ -359,7 +377,8 @@ export function* saveEntityRecord( let currentEdits; try { const path = `${ entity.baseURL }${ recordId ? '/' + recordId : '' }`; - const persistedRecord = yield select( + const persistedRecord = yield __unstableSyncSelect( + 'core', 'getRawEntityRecord', kind, name, @@ -371,9 +390,13 @@ export function* saveEntityRecord( // This is fine for now as it is the only supported autosave, // but ideally this should all be handled in the back end, // so the client just sends and receives objects. - const currentUser = yield select( 'getCurrentUser' ); + const currentUser = yield __unstableSyncSelect( + 'core', + 'getCurrentUser' + ); const currentUserId = currentUser ? currentUser.id : undefined; - const autosavePost = yield select( + const autosavePost = yield __unstableSyncSelect( + 'core', 'getAutosave', persistedRecord.type, persistedRecord.id, @@ -464,13 +487,15 @@ export function* saveEntityRecord( // Get the full local version of the record before the update, // to merge it with the edits and then propagate it to subscribers - persistedEntity = yield select( + persistedEntity = yield __unstableSyncSelect( + 'core', '__experimentalGetEntityRecordNoResolver', kind, name, recordId ); - currentEdits = yield select( + currentEdits = yield __unstableSyncSelect( + 'core', 'getEntityRecordEdits', kind, name, @@ -516,7 +541,8 @@ export function* saveEntityRecord( recordId, { ...currentEdits, - ...( yield select( + ...( yield __unstableSyncSelect( + 'core', 'getEntityRecordEdits', kind, name, @@ -549,11 +575,18 @@ export function* saveEntityRecord( */ export function* saveEditedEntityRecord( kind, name, recordId, options ) { if ( - ! ( yield select( 'hasEditsForEntityRecord', kind, name, recordId ) ) + ! ( yield __unstableSyncSelect( + 'core', + 'hasEditsForEntityRecord', + kind, + name, + recordId + ) ) ) { return; } - const edits = yield select( + const edits = yield __unstableSyncSelect( + 'core', 'getEntityRecordNonTransientEdits', kind, name, diff --git a/packages/core-data/src/controls.js b/packages/core-data/src/controls.js deleted file mode 100644 index 404b142c8adb93..00000000000000 --- a/packages/core-data/src/controls.js +++ /dev/null @@ -1,73 +0,0 @@ -/** - * WordPress dependencies - */ -import { default as triggerApiFetch } from '@wordpress/api-fetch'; -import { createRegistryControl } from '@wordpress/data'; - -/** - * Trigger an API Fetch request. - * - * @param {Object} request API Fetch Request Object. - * @return {Object} control descriptor. - */ -export function apiFetch( request ) { - return { - type: 'API_FETCH', - request, - }; -} - -/** - * Calls a selector using the current state. - * - * @param {string} selectorName Selector name. - * @param {Array} args Selector arguments. - * - * @return {Object} control descriptor. - */ -export function select( selectorName, ...args ) { - return { - type: 'SELECT', - selectorName, - args, - }; -} - -/** - * Dispatches a control action for triggering a registry select that has a - * resolver. - * - * @param {string} selectorName - * @param {Array} args Arguments for the select. - * - * @return {Object} control descriptor. - */ -export function resolveSelect( selectorName, ...args ) { - return { - type: 'RESOLVE_SELECT', - selectorName, - args, - }; -} - -const controls = { - API_FETCH( { request } ) { - return triggerApiFetch( request ); - }, - - SELECT: createRegistryControl( - ( registry ) => ( { selectorName, args } ) => { - return registry.select( 'core' )[ selectorName ]( ...args ); - } - ), - - RESOLVE_SELECT: createRegistryControl( - ( registry ) => ( { selectorName, args } ) => { - return registry - .__experimentalResolveSelect( 'core' ) - [ selectorName ]( ...args ); - } - ), -}; - -export default controls; diff --git a/packages/core-data/src/entities.js b/packages/core-data/src/entities.js index 4918c661c36013..061ff7e8ef4ad5 100644 --- a/packages/core-data/src/entities.js +++ b/packages/core-data/src/entities.js @@ -6,13 +6,13 @@ import { upperFirst, camelCase, map, find, get, startCase } from 'lodash'; /** * WordPress dependencies */ +import { apiFetch, __unstableSyncSelect } from '@wordpress/data-controls'; import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ import { addEntities } from './actions'; -import { apiFetch, select } from './controls'; export const DEFAULT_ENTITY_KEY = 'id'; @@ -188,7 +188,11 @@ export const getMethodName = ( * @return {Array} Entities */ export function* getKindEntities( kind ) { - let entities = yield select( 'getEntitiesByKind', kind ); + let entities = yield __unstableSyncSelect( + 'core', + 'getEntitiesByKind', + kind + ); if ( entities && entities.length !== 0 ) { return entities; } diff --git a/packages/core-data/src/index.js b/packages/core-data/src/index.js index b1ab2f83b01fad..06a74cbab4209d 100644 --- a/packages/core-data/src/index.js +++ b/packages/core-data/src/index.js @@ -2,12 +2,12 @@ * WordPress dependencies */ import { registerStore } from '@wordpress/data'; +import { controls } from '@wordpress/data-controls'; /** * Internal dependencies */ import reducer from './reducer'; -import controls from './controls'; import * as selectors from './selectors'; import * as actions from './actions'; import * as resolvers from './resolvers'; diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 2f477bcb721826..e756895cd0283a 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -8,6 +8,11 @@ import { find, includes, get, hasIn, compact, uniq } from 'lodash'; */ import { addQueryArgs } from '@wordpress/url'; import deprecated from '@wordpress/deprecated'; +import { + apiFetch, + select, + __unstableSyncSelect, +} from '@wordpress/data-controls'; /** * Internal dependencies @@ -23,7 +28,6 @@ import { receiveAutosaves, } from './actions'; import { getKindEntities, DEFAULT_ENTITY_KEY } from './entities'; -import { apiFetch, select, resolveSelect } from './controls'; import { ifNotResolved, getNormalizedCommaSeparable } from './utils'; /** @@ -91,7 +95,8 @@ export function* getEntityRecord( kind, name, key = '', query ) { // The resolution cache won't consider query as reusable based on the // fields, so it's tested here, prior to initiating the REST request, // and without causing `getEntityRecords` resolution to occur. - const hasRecords = yield select( + const hasRecords = yield __unstableSyncSelect( + 'core', 'hasEntityRecords', kind, name, @@ -296,7 +301,8 @@ export function* canUser( action, resource, id ) { * @param {number} postId The id of the parent post. */ export function* getAutosaves( postType, postId ) { - const { rest_base: restBase } = yield resolveSelect( + const { rest_base: restBase } = yield select( + 'core', 'getPostType', postType ); @@ -319,5 +325,5 @@ export function* getAutosaves( postType, postId ) { * @param {number} postId The id of the parent post. */ export function* getAutosave( postType, postId ) { - yield resolveSelect( 'getAutosaves', postType, postId ); + yield select( 'core', 'getAutosaves', postType, postId ); } diff --git a/packages/core-data/src/test/actions.js b/packages/core-data/src/test/actions.js index 9413349f27ba26..6ae6e246682f50 100644 --- a/packages/core-data/src/test/actions.js +++ b/packages/core-data/src/test/actions.js @@ -1,3 +1,8 @@ +/** + * WordPress dependencies + */ +import { __unstableSyncSelect } from '@wordpress/data-controls'; + /** * Internal dependencies */ @@ -10,7 +15,6 @@ import { receiveAutosaves, receiveCurrentUser, } from '../actions'; -import { select } from '../controls'; describe( 'editEntityRecord', () => { it( 'throws when the edited entity does not have a loaded config.', () => { @@ -22,7 +26,12 @@ describe( 'editEntityRecord', () => { {} ); expect( fulfillment.next().value ).toEqual( - select( 'getEntity', entity.kind, entity.name ) + __unstableSyncSelect( + 'core', + 'getEntity', + entity.kind, + entity.name + ) ); // Don't pass back an entity config. expect( fulfillment.next.bind( fulfillment ) ).toThrow( @@ -83,11 +92,11 @@ describe( 'saveEntityRecord', () => { // Should select __experimentalGetEntityRecordNoResolver selector (as opposed to getEntityRecord) // see https://github.com/WordPress/gutenberg/pull/19752#discussion_r368498318. - expect( fulfillment.next().value.type ).toBe( 'SELECT' ); + expect( fulfillment.next().value.type ).toBe( 'SYNC_SELECT' ); expect( fulfillment.next().value.selectorName ).toBe( '__experimentalGetEntityRecordNoResolver' ); - expect( fulfillment.next().value.type ).toBe( 'SELECT' ); + expect( fulfillment.next().value.type ).toBe( 'SYNC_SELECT' ); expect( fulfillment.next().value.type ).toBe( 'RECEIVE_ITEMS' ); const { value: apiFetchAction } = fulfillment.next( {} ); expect( apiFetchAction.request ).toEqual( { @@ -125,9 +134,9 @@ describe( 'saveEntityRecord', () => { expect( fulfillment.next( entities ).value.type ).toBe( 'SAVE_ENTITY_RECORD_START' ); - expect( fulfillment.next().value.type ).toBe( 'SELECT' ); - expect( fulfillment.next().value.type ).toBe( 'SELECT' ); - expect( fulfillment.next().value.type ).toBe( 'SELECT' ); + expect( fulfillment.next().value.type ).toBe( 'SYNC_SELECT' ); + expect( fulfillment.next().value.type ).toBe( 'SYNC_SELECT' ); + expect( fulfillment.next().value.type ).toBe( 'SYNC_SELECT' ); expect( fulfillment.next().value.type ).toBe( 'RECEIVE_ITEMS' ); const { value: apiFetchAction } = fulfillment.next( {} ); expect( apiFetchAction.request ).toEqual( { @@ -162,9 +171,9 @@ describe( 'saveEntityRecord', () => { expect( fulfillment.next( entities ).value.type ).toBe( 'SAVE_ENTITY_RECORD_START' ); - expect( fulfillment.next().value.type ).toBe( 'SELECT' ); - expect( fulfillment.next().value.type ).toBe( 'SELECT' ); - expect( fulfillment.next().value.type ).toBe( 'SELECT' ); + expect( fulfillment.next().value.type ).toBe( 'SYNC_SELECT' ); + expect( fulfillment.next().value.type ).toBe( 'SYNC_SELECT' ); + expect( fulfillment.next().value.type ).toBe( 'SYNC_SELECT' ); expect( fulfillment.next().value.type ).toBe( 'RECEIVE_ITEMS' ); const { value: apiFetchAction } = fulfillment.next( {} ); expect( apiFetchAction.request ).toEqual( { diff --git a/packages/core-data/src/test/resolvers.js b/packages/core-data/src/test/resolvers.js index 74891e8fe17869..f82ef7aee4c986 100644 --- a/packages/core-data/src/test/resolvers.js +++ b/packages/core-data/src/test/resolvers.js @@ -1,3 +1,8 @@ +/** + * WordPress dependencies + */ +import { apiFetch } from '@wordpress/data-controls'; + /** * Internal dependencies */ @@ -16,7 +21,6 @@ import { receiveAutosaves, receiveCurrentUser, } from '../actions'; -import { apiFetch } from '../controls'; describe( 'getEntityRecord', () => { const POST_TYPE = { slug: 'post' };