diff --git a/package-lock.json b/package-lock.json index 8a72667def70e3..35022432dc25b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18197,7 +18197,6 @@ "@wordpress/api-fetch": "file:packages/api-fetch", "@wordpress/blocks": "file:packages/blocks", "@wordpress/data": "file:packages/data", - "@wordpress/data-controls": "file:packages/data-controls", "@wordpress/deprecated": "file:packages/deprecated", "@wordpress/element": "file:packages/element", "@wordpress/html-entities": "file:packages/html-entities", diff --git a/packages/core-data/package.json b/packages/core-data/package.json index 557aa1c182e9fd..56fe06013a3220 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -33,7 +33,6 @@ "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blocks": "file:../blocks", "@wordpress/data": "file:../data", - "@wordpress/data-controls": "file:../data-controls", "@wordpress/deprecated": "file:../deprecated", "@wordpress/element": "file:../element", "@wordpress/html-entities": "file:../html-entities", diff --git a/packages/core-data/src/actions.js b/packages/core-data/src/actions.js index d0d7cd12a75766..8dfbaa6571ef33 100644 --- a/packages/core-data/src/actions.js +++ b/packages/core-data/src/actions.js @@ -7,8 +7,7 @@ import { v4 as uuid } from 'uuid'; /** * WordPress dependencies */ -import { __unstableAwaitPromise } from '@wordpress/data-controls'; -import triggerFetch from '@wordpress/api-fetch'; +import apiFetch from '@wordpress/api-fetch'; import { addQueryArgs } from '@wordpress/url'; /** @@ -17,7 +16,6 @@ import { addQueryArgs } from '@wordpress/url'; import { receiveItems, removeItems, receiveQueriedItems } from './queried-data'; import { getKindEntities, DEFAULT_ENTITY_KEY } from './entities'; import { createBatch } from './batch'; -import { getDispatch } from './controls'; import { STORE_NAME } from './name'; /** @@ -168,7 +166,7 @@ export const deleteEntityRecord = ( name, recordId, query, - { __unstableFetch = triggerFetch } = {} + { __unstableFetch = apiFetch } = {} ) => async ( { dispatch } ) => { const entities = await dispatch( getKindEntities( kind ) ); const entity = find( entities, { kind, name } ); @@ -242,7 +240,7 @@ export const editEntityRecord = ( recordId, edits, options = {} -) => async ( { select, dispatch } ) => { +) => ( { select, dispatch } ) => { const entity = select.getEntity( kind, name ); if ( ! entity ) { throw new Error( @@ -270,7 +268,7 @@ export const editEntityRecord = ( }, {} ), transientEdits, }; - return await dispatch( { + dispatch( { type: 'EDIT_ENTITY_RECORD', ...edit, meta: { @@ -347,7 +345,7 @@ export const saveEntityRecord = ( kind, name, record, - { isAutosave = false, __unstableFetch = triggerFetch } = {} + { isAutosave = false, __unstableFetch = apiFetch } = {} ) => async ( { select, resolveSelect, dispatch } ) => { const entities = await dispatch( getKindEntities( kind ) ); const entity = find( entities, { kind, name } ); @@ -371,7 +369,7 @@ export const saveEntityRecord = ( const evaluatedValue = value( select.getEditedEntityRecord( kind, name, recordId ) ); - await dispatch.editEntityRecord( + dispatch.editEntityRecord( kind, name, recordId, @@ -384,7 +382,7 @@ export const saveEntityRecord = ( } } - await dispatch( { + dispatch( { type: 'SAVE_ENTITY_RECORD_START', kind, name, @@ -436,12 +434,11 @@ export const saveEntityRecord = ( : data.status, } ); - const options = { + updatedRecord = await __unstableFetch( { path: `${ path }/autosaves`, method: 'POST', data, - }; - updatedRecord = await __unstableFetch( options ); + } ); // An autosave may be processed by the server as a regular save // when its update is requested by the author and the post had @@ -477,7 +474,7 @@ export const saveEntityRecord = ( }, {} ); - await dispatch.receiveEntityRecords( + dispatch.receiveEntityRecords( kind, name, newRecord, @@ -485,7 +482,7 @@ export const saveEntityRecord = ( true ); } else { - await dispatch.receiveAutosaves( + dispatch.receiveAutosaves( persistedRecord.id, updatedRecord ); @@ -501,13 +498,12 @@ export const saveEntityRecord = ( ), }; } - const options = { + updatedRecord = await __unstableFetch( { path, method: recordId ? 'PUT' : 'POST', data: edits, - }; - updatedRecord = await __unstableFetch( options ); - await dispatch.receiveEntityRecords( + } ); + dispatch.receiveEntityRecords( kind, name, updatedRecord, @@ -530,7 +526,7 @@ export const saveEntityRecord = ( return updatedRecord; } finally { - await dispatch.__unstableReleaseStoreLock( lock ); + dispatch.__unstableReleaseStoreLock( lock ); } }; @@ -556,13 +552,12 @@ export const saveEntityRecord = ( * @return {Promise} A promise that resolves to an array containing the return * values of each function given in `requests`. */ -export function* __experimentalBatch( requests ) { +export const __experimentalBatch = ( requests ) => async ( { dispatch } ) => { const batch = createBatch(); - const dispatch = yield getDispatch(); const api = { saveEntityRecord( kind, name, record, options ) { return batch.add( ( add ) => - dispatch( STORE_NAME ).saveEntityRecord( kind, name, record, { + dispatch.saveEntityRecord( kind, name, record, { ...options, __unstableFetch: add, } ) @@ -570,38 +565,28 @@ export function* __experimentalBatch( requests ) { }, saveEditedEntityRecord( kind, name, recordId, options ) { return batch.add( ( add ) => - dispatch( STORE_NAME ).saveEditedEntityRecord( - kind, - name, - recordId, - { - ...options, - __unstableFetch: add, - } - ) + dispatch.saveEditedEntityRecord( kind, name, recordId, { + ...options, + __unstableFetch: add, + } ) ); }, deleteEntityRecord( kind, name, recordId, query, options ) { return batch.add( ( add ) => - dispatch( STORE_NAME ).deleteEntityRecord( - kind, - name, - recordId, - query, - { - ...options, - __unstableFetch: add, - } - ) + dispatch.deleteEntityRecord( kind, name, recordId, query, { + ...options, + __unstableFetch: add, + } ) ); }, }; const resultPromises = requests.map( ( request ) => request( api ) ); - const [ , ...results ] = yield __unstableAwaitPromise( - Promise.all( [ batch.run(), ...resultPromises ] ) - ); + const [ , ...results ] = await Promise.all( [ + batch.run(), + ...resultPromises, + ] ); return results; -} +}; /** * Action triggered to save an entity record's edits. diff --git a/packages/core-data/src/controls.js b/packages/core-data/src/controls.js deleted file mode 100644 index 00f8ca36641c13..00000000000000 --- a/packages/core-data/src/controls.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * WordPress dependencies - */ -import { createRegistryControl } from '@wordpress/data'; - -export function regularFetch( url ) { - return { - type: 'REGULAR_FETCH', - url, - }; -} - -export function getDispatch() { - return { - type: 'GET_DISPATCH', - }; -} - -const controls = { - async REGULAR_FETCH( { url } ) { - const { data } = await window - .fetch( url ) - .then( ( res ) => res.json() ); - - return data; - }, - - GET_DISPATCH: createRegistryControl( ( { dispatch } ) => () => dispatch ), -}; - -export default controls; diff --git a/packages/core-data/src/index.js b/packages/core-data/src/index.js index bcff6e6c4f4dde..7821e2ecd47459 100644 --- a/packages/core-data/src/index.js +++ b/packages/core-data/src/index.js @@ -2,7 +2,6 @@ * WordPress dependencies */ import { createReduxStore, register } from '@wordpress/data'; -import { controls } from '@wordpress/data-controls'; /** * Internal dependencies @@ -12,7 +11,6 @@ import * as selectors from './selectors'; import * as actions from './actions'; import * as resolvers from './resolvers'; import createLocksActions from './locks/actions'; -import customControls from './controls'; import { defaultEntities, getMethodName } from './entities'; import { STORE_NAME } from './name'; @@ -58,7 +56,6 @@ const entityActions = defaultEntities.reduce( ( result, entity ) => { const storeConfig = () => ( { reducer, - controls: { ...customControls, ...controls }, actions: { ...actions, ...entityActions, ...createLocksActions() }, selectors: { ...selectors, ...entitySelectors }, resolvers: { ...resolvers, ...entityResolvers }, diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 0b02d83b064a54..49f5ae8809ab8d 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -7,16 +7,12 @@ import { find, includes, get, hasIn, compact, uniq } from 'lodash'; * WordPress dependencies */ import { addQueryArgs } from '@wordpress/url'; -import triggerFetch from '@wordpress/api-fetch'; +import apiFetch from '@wordpress/api-fetch'; /** * Internal dependencies */ import { STORE_NAME } from './name'; - -/** - * Internal dependencies - */ import { getKindEntities, DEFAULT_ENTITY_KEY } from './entities'; import { ifNotResolved, getNormalizedCommaSeparable } from './utils'; @@ -31,7 +27,7 @@ export const getAuthors = ( query ) => async ( { dispatch } ) => { '/wp/v2/users/?who=authors&per_page=100', query ); - const users = await triggerFetch( { path } ); + const users = await apiFetch( { path } ); dispatch.receiveUserQuery( path, users ); }; @@ -39,7 +35,7 @@ export const getAuthors = ( query ) => async ( { dispatch } ) => { * Requests the current user from the REST API. */ export const getCurrentUser = () => async ( { dispatch } ) => { - const currentUser = await triggerFetch( { path: '/wp/v2/users/me' } ); + const currentUser = await apiFetch( { path: '/wp/v2/users/me' } ); dispatch.receiveCurrentUser( currentUser ); }; @@ -106,7 +102,7 @@ export const getEntityRecord = ( kind, name, key = '', query ) => async ( { } } - const record = await triggerFetch( { path } ); + const record = await apiFetch( { path } ); dispatch.receiveEntityRecords( kind, name, record, query ); } catch ( error ) { // We need a way to handle and access REST API errors in state @@ -132,14 +128,6 @@ export const getEditedEntityRecord = ifNotResolved( 'getRawEntityRecord' ); -/** - * Requests the entity's records from the REST API. - * - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {Object?} query Query Object. - */ - /** * Requests the entity's records from the REST API. * @@ -181,7 +169,7 @@ export const getEntityRecords = ( kind, name, query = {} ) => async ( { ...query, } ); - let records = Object.values( await triggerFetch( { path } ) ); + let records = Object.values( await apiFetch( { path } ) ); // If we request fields but the result doesn't contain the fields, // explicitely set these fields as "undefined" // that way we consider the query "fullfilled". @@ -237,7 +225,7 @@ getEntityRecords.shouldInvalidate = ( action, kind, name ) => { * Requests the current theme. */ export const getCurrentTheme = () => async ( { dispatch } ) => { - const activeThemes = await triggerFetch( { + const activeThemes = await apiFetch( { path: '/wp/v2/themes?status=active', } ); dispatch.receiveCurrentTheme( activeThemes[ 0 ] ); @@ -247,7 +235,7 @@ export const getCurrentTheme = () => async ( { dispatch } ) => { * Requests theme supports data from the index. */ export const getThemeSupports = () => async ( { dispatch } ) => { - const activeThemes = await triggerFetch( { + const activeThemes = await apiFetch( { path: '/wp/v2/themes?status=active', } ); dispatch.receiveThemeSupports( activeThemes[ 0 ].theme_supports ); @@ -260,7 +248,7 @@ export const getThemeSupports = () => async ( { dispatch } ) => { */ export const getEmbedPreview = ( url ) => async ( { dispatch } ) => { try { - const embedProxyResponse = await triggerFetch( { + const embedProxyResponse = await apiFetch( { path: addQueryArgs( '/oembed/1.0/proxy', { url } ), } ); dispatch.receiveEmbedPreview( url, embedProxyResponse ); @@ -296,7 +284,7 @@ export const canUser = ( action, resource, id ) => async ( { dispatch } ) => { let response; try { - response = await triggerFetch( { + response = await apiFetch( { path, // Ideally this would always be an OPTIONS request, but unfortunately there's // a bug in the REST API which causes the Allow header to not be sent on @@ -359,7 +347,7 @@ export const getAutosaves = ( postType, postId ) => async ( { resolveSelect, } ) => { const { rest_base: restBase } = await resolveSelect.getPostType( postType ); - const autosaves = await triggerFetch( { + const autosaves = await apiFetch( { path: `/wp/v2/${ restBase }/${ postId }/autosaves?context=edit`, } ); diff --git a/packages/core-data/src/test/actions.js b/packages/core-data/src/test/actions.js index 7e015e44442e34..8aa1ecade38548 100644 --- a/packages/core-data/src/test/actions.js +++ b/packages/core-data/src/test/actions.js @@ -33,16 +33,17 @@ describe( 'editEntityRecord', () => { const select = { getEntity: jest.fn(), }; - const fulfillment = editEntityRecord( - entity.kind, - entity.name, - entity.id, - {} - )( { select } ); - expect( select.getEntity ).toHaveBeenCalledTimes( 1 ); - await expect( fulfillment ).rejects.toThrow( + const fulfillment = () => + editEntityRecord( + entity.kind, + entity.name, + entity.id, + {} + )( { select } ); + expect( fulfillment ).toThrow( `The entity being edited (${ entity.kind }, ${ entity.name }) does not have a loaded config.` ); + expect( select.getEntity ).toHaveBeenCalledTimes( 1 ); } ); } ); @@ -386,21 +387,7 @@ describe( 'receiveCurrentUser', () => { describe( '__experimentalBatch', () => { it( 'batches multiple actions together', async () => { - const generator = __experimentalBatch( - [ - ( { saveEntityRecord: _saveEntityRecord } ) => - _saveEntityRecord( 'root', 'widget', {} ), - ( { saveEditedEntityRecord: _saveEditedEntityRecord } ) => - _saveEditedEntityRecord( 'root', 'widget', 123 ), - ( { deleteEntityRecord: _deleteEntityRecord } ) => - _deleteEntityRecord( 'root', 'widget', 123, {} ), - ], - { __unstableProcessor: ( inputs ) => Promise.resolve( inputs ) } - ); - // Run generator up to `yield getDispatch()`. - const { value: getDispatchControl } = generator.next(); - expect( getDispatchControl ).toEqual( { type: 'GET_DISPATCH' } ); - const actions = { + const dispatch = { saveEntityRecord: jest.fn( ( kind, name, record, { __unstableFetch } ) => { __unstableFetch( {} ); @@ -420,36 +407,39 @@ describe( '__experimentalBatch', () => { } ), }; - const dispatch = () => actions; - // Run generator up to `yield __unstableAwaitPromise( ... )`. - const { value: awaitPromiseControl } = generator.next( dispatch ); - expect( actions.saveEntityRecord ).toHaveBeenCalledWith( + + const results = await __experimentalBatch( + [ + ( { saveEntityRecord: _saveEntityRecord } ) => + _saveEntityRecord( 'root', 'widget', {} ), + ( { saveEditedEntityRecord: _saveEditedEntityRecord } ) => + _saveEditedEntityRecord( 'root', 'widget', 123 ), + ( { deleteEntityRecord: _deleteEntityRecord } ) => + _deleteEntityRecord( 'root', 'widget', 123, {} ), + ], + { __unstableProcessor: ( inputs ) => Promise.resolve( inputs ) } + )( { dispatch } ); + + expect( dispatch.saveEntityRecord ).toHaveBeenCalledWith( 'root', 'widget', {}, { __unstableFetch: expect.any( Function ) } ); - expect( actions.saveEditedEntityRecord ).toHaveBeenCalledWith( + expect( dispatch.saveEditedEntityRecord ).toHaveBeenCalledWith( 'root', 'widget', 123, { __unstableFetch: expect.any( Function ) } ); - expect( actions.deleteEntityRecord ).toHaveBeenCalledWith( + expect( dispatch.deleteEntityRecord ).toHaveBeenCalledWith( 'root', 'widget', 123, {}, { __unstableFetch: expect.any( Function ) } ); - expect( awaitPromiseControl ).toEqual( { - type: 'AWAIT_PROMISE', - promise: expect.any( Promise ), - } ); - // Run generator to the end. - const { value: results } = generator.next( - await awaitPromiseControl.promise - ); + expect( results ).toEqual( [ { id: 123, created: true }, { id: 123, updated: true },