@wordpress/core-data 4.0.1-next.253d9b6e21.0 → 4.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/README.md +11 -3
  2. package/build/actions.js +124 -117
  3. package/build/actions.js.map +1 -1
  4. package/build/batch/default-processor.js +58 -27
  5. package/build/batch/default-processor.js.map +1 -1
  6. package/build/entities.js +24 -18
  7. package/build/entities.js.map +1 -1
  8. package/build/index.js +9 -17
  9. package/build/index.js.map +1 -1
  10. package/build/locks/actions.js +17 -77
  11. package/build/locks/actions.js.map +1 -1
  12. package/build/locks/engine.js +77 -0
  13. package/build/locks/engine.js.map +1 -0
  14. package/build/locks/reducer.js +1 -5
  15. package/build/locks/reducer.js.map +1 -1
  16. package/build/locks/selectors.js +6 -6
  17. package/build/locks/selectors.js.map +1 -1
  18. package/build/queried-data/get-query-parts.js +9 -4
  19. package/build/queried-data/get-query-parts.js.map +1 -1
  20. package/build/queried-data/selectors.js +3 -9
  21. package/build/queried-data/selectors.js.map +1 -1
  22. package/build/reducer.js +1 -4
  23. package/build/reducer.js.map +1 -1
  24. package/build/resolvers.js +120 -91
  25. package/build/resolvers.js.map +1 -1
  26. package/build/selectors.js +31 -11
  27. package/build/selectors.js.map +1 -1
  28. package/build/utils/if-not-resolved.js +6 -21
  29. package/build/utils/if-not-resolved.js.map +1 -1
  30. package/build/utils/index.js +8 -0
  31. package/build/utils/index.js.map +1 -1
  32. package/build/utils/is-raw-attribute.js +19 -0
  33. package/build/utils/is-raw-attribute.js.map +1 -0
  34. package/build-module/actions.js +106 -107
  35. package/build-module/actions.js.map +1 -1
  36. package/build-module/batch/default-processor.js +57 -27
  37. package/build-module/batch/default-processor.js.map +1 -1
  38. package/build-module/entities.js +19 -14
  39. package/build-module/entities.js.map +1 -1
  40. package/build-module/index.js +10 -14
  41. package/build-module/index.js.map +1 -1
  42. package/build-module/locks/actions.js +14 -68
  43. package/build-module/locks/actions.js.map +1 -1
  44. package/build-module/locks/engine.js +66 -0
  45. package/build-module/locks/engine.js.map +1 -0
  46. package/build-module/locks/reducer.js +1 -2
  47. package/build-module/locks/reducer.js.map +1 -1
  48. package/build-module/locks/selectors.js +4 -4
  49. package/build-module/locks/selectors.js.map +1 -1
  50. package/build-module/queried-data/get-query-parts.js +9 -4
  51. package/build-module/queried-data/get-query-parts.js.map +1 -1
  52. package/build-module/queried-data/selectors.js +3 -9
  53. package/build-module/queried-data/selectors.js.map +1 -1
  54. package/build-module/reducer.js +1 -3
  55. package/build-module/reducer.js.map +1 -1
  56. package/build-module/resolvers.js +94 -74
  57. package/build-module/resolvers.js.map +1 -1
  58. package/build-module/selectors.js +30 -10
  59. package/build-module/selectors.js.map +1 -1
  60. package/build-module/utils/if-not-resolved.js +6 -19
  61. package/build-module/utils/if-not-resolved.js.map +1 -1
  62. package/build-module/utils/index.js +1 -0
  63. package/build-module/utils/index.js.map +1 -1
  64. package/build-module/utils/is-raw-attribute.js +12 -0
  65. package/build-module/utils/is-raw-attribute.js.map +1 -0
  66. package/package.json +11 -12
  67. package/src/actions.js +112 -189
  68. package/src/batch/default-processor.js +57 -26
  69. package/src/batch/test/default-processor.js +53 -26
  70. package/src/entities.js +15 -16
  71. package/src/index.js +7 -10
  72. package/src/locks/actions.js +10 -61
  73. package/src/locks/engine.js +43 -0
  74. package/src/locks/reducer.js +1 -3
  75. package/src/locks/selectors.js +4 -4
  76. package/src/locks/test/engine.js +135 -0
  77. package/src/locks/test/reducer.js +1 -1
  78. package/src/locks/test/selectors.js +105 -124
  79. package/src/queried-data/get-query-parts.js +11 -6
  80. package/src/queried-data/selectors.js +2 -9
  81. package/src/queried-data/test/get-query-parts.js +1 -1
  82. package/src/queried-data/test/selectors.js +1 -0
  83. package/src/reducer.js +0 -2
  84. package/src/resolvers.js +86 -106
  85. package/src/selectors.js +113 -40
  86. package/src/test/actions.js +243 -172
  87. package/src/test/entities.js +40 -26
  88. package/src/test/resolvers.js +270 -223
  89. package/src/test/selectors.js +71 -0
  90. package/src/utils/if-not-resolved.js +8 -26
  91. package/src/utils/index.js +1 -0
  92. package/src/utils/is-raw-attribute.js +11 -0
  93. package/src/utils/test/if-not-resolved.js +28 -27
  94. package/src/utils/test/is-raw-attribute.js +22 -0
  95. package/build/controls.js +0 -44
  96. package/build/controls.js.map +0 -1
  97. package/build/locks/index.js +0 -47
  98. package/build/locks/index.js.map +0 -1
  99. package/build-module/controls.js +0 -31
  100. package/build-module/controls.js.map +0 -1
  101. package/build-module/locks/index.js +0 -4
  102. package/build-module/locks/index.js.map +0 -1
  103. package/src/controls.js +0 -31
  104. package/src/locks/index.js +0 -3
  105. package/src/locks/test/actions.js +0 -307
  106. package/src/test/integration.js +0 -264
package/src/actions.js CHANGED
@@ -1,14 +1,13 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { castArray, get, isEqual, find } from 'lodash';
4
+ import { castArray, isEqual, find } from 'lodash';
5
5
  import { v4 as uuid } from 'uuid';
6
6
 
7
7
  /**
8
8
  * WordPress dependencies
9
9
  */
10
- import { controls } from '@wordpress/data';
11
- import { apiFetch, __unstableAwaitPromise } from '@wordpress/data-controls';
10
+ import apiFetch from '@wordpress/api-fetch';
12
11
  import { addQueryArgs } from '@wordpress/url';
13
12
 
14
13
  /**
@@ -16,12 +15,7 @@ import { addQueryArgs } from '@wordpress/url';
16
15
  */
17
16
  import { receiveItems, removeItems, receiveQueriedItems } from './queried-data';
18
17
  import { getKindEntities, DEFAULT_ENTITY_KEY } from './entities';
19
- import {
20
- __unstableAcquireStoreLock,
21
- __unstableReleaseStoreLock,
22
- } from './locks';
23
18
  import { createBatch } from './batch';
24
- import { getDispatch } from './controls';
25
19
  import { STORE_NAME } from './name';
26
20
 
27
21
  /**
@@ -165,35 +159,36 @@ export function receiveEmbedPreview( url, preview ) {
165
159
  * @param {Object} [options] Delete options.
166
160
  * @param {Function} [options.__unstableFetch] Internal use only. Function to
167
161
  * call instead of `apiFetch()`.
168
- * Must return a control descriptor.
162
+ * Must return a promise.
169
163
  */
170
- export function* deleteEntityRecord(
164
+ export const deleteEntityRecord = (
171
165
  kind,
172
166
  name,
173
167
  recordId,
174
168
  query,
175
- { __unstableFetch = null } = {}
176
- ) {
177
- const entities = yield getKindEntities( kind );
169
+ { __unstableFetch = apiFetch } = {}
170
+ ) => async ( { dispatch } ) => {
171
+ const entities = await dispatch( getKindEntities( kind ) );
178
172
  const entity = find( entities, { kind, name } );
179
173
  let error;
180
174
  let deletedRecord = false;
181
- if ( ! entity ) {
175
+ if ( ! entity || entity?.__experimentalNoFetch ) {
182
176
  return;
183
177
  }
184
178
 
185
- const lock = yield* __unstableAcquireStoreLock(
179
+ const lock = await dispatch.__unstableAcquireStoreLock(
186
180
  STORE_NAME,
187
181
  [ 'entities', 'data', kind, name, recordId ],
188
182
  { exclusive: true }
189
183
  );
184
+
190
185
  try {
191
- yield {
186
+ dispatch( {
192
187
  type: 'DELETE_ENTITY_RECORD_START',
193
188
  kind,
194
189
  name,
195
190
  recordId,
196
- };
191
+ } );
197
192
 
198
193
  try {
199
194
  let path = `${ entity.baseURL }/${ recordId }`;
@@ -202,36 +197,29 @@ export function* deleteEntityRecord(
202
197
  path = addQueryArgs( path, query );
203
198
  }
204
199
 
205
- const options = {
200
+ deletedRecord = await __unstableFetch( {
206
201
  path,
207
202
  method: 'DELETE',
208
- };
209
- if ( __unstableFetch ) {
210
- deletedRecord = yield __unstableAwaitPromise(
211
- __unstableFetch( options )
212
- );
213
- } else {
214
- deletedRecord = yield apiFetch( options );
215
- }
203
+ } );
216
204
 
217
- yield removeItems( kind, name, recordId, true );
205
+ await dispatch( removeItems( kind, name, recordId, true ) );
218
206
  } catch ( _error ) {
219
207
  error = _error;
220
208
  }
221
209
 
222
- yield {
210
+ dispatch( {
223
211
  type: 'DELETE_ENTITY_RECORD_FINISH',
224
212
  kind,
225
213
  name,
226
214
  recordId,
227
215
  error,
228
- };
216
+ } );
229
217
 
230
218
  return deletedRecord;
231
219
  } finally {
232
- yield* __unstableReleaseStoreLock( lock );
220
+ dispatch.__unstableReleaseStoreLock( lock );
233
221
  }
234
- }
222
+ };
235
223
 
236
224
  /**
237
225
  * Returns an action object that triggers an
@@ -246,28 +234,22 @@ export function* deleteEntityRecord(
246
234
  *
247
235
  * @return {Object} Action object.
248
236
  */
249
- export function* editEntityRecord( kind, name, recordId, edits, options = {} ) {
250
- const entity = yield controls.select( STORE_NAME, 'getEntity', kind, name );
237
+ export const editEntityRecord = (
238
+ kind,
239
+ name,
240
+ recordId,
241
+ edits,
242
+ options = {}
243
+ ) => ( { select, dispatch } ) => {
244
+ const entity = select.getEntity( kind, name );
251
245
  if ( ! entity ) {
252
246
  throw new Error(
253
247
  `The entity being edited (${ kind }, ${ name }) does not have a loaded config.`
254
248
  );
255
249
  }
256
250
  const { transientEdits = {}, mergedEdits = {} } = entity;
257
- const record = yield controls.select(
258
- STORE_NAME,
259
- 'getRawEntityRecord',
260
- kind,
261
- name,
262
- recordId
263
- );
264
- const editedRecord = yield controls.select(
265
- STORE_NAME,
266
- 'getEditedEntityRecord',
267
- kind,
268
- name,
269
- recordId
270
- );
251
+ const record = select.getRawEntityRecord( kind, name, recordId );
252
+ const editedRecord = select.getEditedEntityRecord( kind, name, recordId );
271
253
 
272
254
  const edit = {
273
255
  kind,
@@ -286,7 +268,7 @@ export function* editEntityRecord( kind, name, recordId, edits, options = {} ) {
286
268
  }, {} ),
287
269
  transientEdits,
288
270
  };
289
- return {
271
+ dispatch( {
290
272
  type: 'EDIT_ENTITY_RECORD',
291
273
  ...edit,
292
274
  meta: {
@@ -299,44 +281,44 @@ export function* editEntityRecord( kind, name, recordId, edits, options = {} ) {
299
281
  }, {} ),
300
282
  },
301
283
  },
302
- };
303
- }
284
+ } );
285
+ };
304
286
 
305
287
  /**
306
288
  * Action triggered to undo the last edit to
307
289
  * an entity record, if any.
290
+ *
291
+ * @return {undefined}
308
292
  */
309
- export function* undo() {
310
- const undoEdit = yield controls.select( STORE_NAME, 'getUndoEdit' );
293
+ export const undo = () => ( { select, dispatch } ) => {
294
+ const undoEdit = select.getUndoEdit();
311
295
  if ( ! undoEdit ) {
312
296
  return;
313
297
  }
314
- yield {
298
+ dispatch( {
315
299
  type: 'EDIT_ENTITY_RECORD',
316
300
  ...undoEdit,
317
- meta: {
318
- isUndo: true,
319
- },
320
- };
321
- }
301
+ meta: { isUndo: true },
302
+ } );
303
+ };
322
304
 
323
305
  /**
324
306
  * Action triggered to redo the last undoed
325
307
  * edit to an entity record, if any.
308
+ *
309
+ * @return {undefined}
326
310
  */
327
- export function* redo() {
328
- const redoEdit = yield controls.select( STORE_NAME, 'getRedoEdit' );
311
+ export const redo = () => ( { select, dispatch } ) => {
312
+ const redoEdit = select.getRedoEdit();
329
313
  if ( ! redoEdit ) {
330
314
  return;
331
315
  }
332
- yield {
316
+ dispatch( {
333
317
  type: 'EDIT_ENTITY_RECORD',
334
318
  ...redoEdit,
335
- meta: {
336
- isRedo: true,
337
- },
338
- };
339
- }
319
+ meta: { isRedo: true },
320
+ } );
321
+ };
340
322
 
341
323
  /**
342
324
  * Forces the creation of a new undo level.
@@ -357,43 +339,37 @@ export function __unstableCreateUndoLevel() {
357
339
  * @param {boolean} [options.isAutosave=false] Whether this is an autosave.
358
340
  * @param {Function} [options.__unstableFetch] Internal use only. Function to
359
341
  * call instead of `apiFetch()`.
360
- * Must return a control
361
- * descriptor.
342
+ * Must return a promise.
362
343
  */
363
- export function* saveEntityRecord(
344
+ export const saveEntityRecord = (
364
345
  kind,
365
346
  name,
366
347
  record,
367
- { isAutosave = false, __unstableFetch = null } = {}
368
- ) {
369
- const entities = yield getKindEntities( kind );
348
+ { isAutosave = false, __unstableFetch = apiFetch } = {}
349
+ ) => async ( { select, resolveSelect, dispatch } ) => {
350
+ const entities = await dispatch( getKindEntities( kind ) );
370
351
  const entity = find( entities, { kind, name } );
371
- if ( ! entity ) {
352
+ if ( ! entity || entity?.__experimentalNoFetch ) {
372
353
  return;
373
354
  }
374
355
  const entityIdKey = entity.key || DEFAULT_ENTITY_KEY;
375
356
  const recordId = record[ entityIdKey ];
376
357
 
377
- const lock = yield* __unstableAcquireStoreLock(
358
+ const lock = await dispatch.__unstableAcquireStoreLock(
378
359
  STORE_NAME,
379
360
  [ 'entities', 'data', kind, name, recordId || uuid() ],
380
361
  { exclusive: true }
381
362
  );
363
+
382
364
  try {
383
365
  // Evaluate optimized edits.
384
366
  // (Function edits that should be evaluated on save to avoid expensive computations on every edit.)
385
367
  for ( const [ key, value ] of Object.entries( record ) ) {
386
368
  if ( typeof value === 'function' ) {
387
369
  const evaluatedValue = value(
388
- yield controls.select(
389
- STORE_NAME,
390
- 'getEditedEntityRecord',
391
- kind,
392
- name,
393
- recordId
394
- )
370
+ select.getEditedEntityRecord( kind, name, recordId )
395
371
  );
396
- yield editEntityRecord(
372
+ dispatch.editEntityRecord(
397
373
  kind,
398
374
  name,
399
375
  recordId,
@@ -406,22 +382,20 @@ export function* saveEntityRecord(
406
382
  }
407
383
  }
408
384
 
409
- yield {
385
+ dispatch( {
410
386
  type: 'SAVE_ENTITY_RECORD_START',
411
387
  kind,
412
388
  name,
413
389
  recordId,
414
390
  isAutosave,
415
- };
391
+ } );
416
392
  let updatedRecord;
417
393
  let error;
418
394
  try {
419
395
  const path = `${ entity.baseURL }${
420
396
  recordId ? '/' + recordId : ''
421
397
  }`;
422
- const persistedRecord = yield controls.select(
423
- STORE_NAME,
424
- 'getRawEntityRecord',
398
+ const persistedRecord = select.getRawEntityRecord(
425
399
  kind,
426
400
  name,
427
401
  recordId
@@ -432,14 +406,9 @@ export function* saveEntityRecord(
432
406
  // This is fine for now as it is the only supported autosave,
433
407
  // but ideally this should all be handled in the back end,
434
408
  // so the client just sends and receives objects.
435
- const currentUser = yield controls.select(
436
- STORE_NAME,
437
- 'getCurrentUser'
438
- );
409
+ const currentUser = select.getCurrentUser();
439
410
  const currentUserId = currentUser ? currentUser.id : undefined;
440
- const autosavePost = yield controls.select(
441
- STORE_NAME,
442
- 'getAutosave',
411
+ const autosavePost = resolveSelect.getAutosave(
443
412
  persistedRecord.type,
444
413
  persistedRecord.id,
445
414
  currentUserId
@@ -454,8 +423,7 @@ export function* saveEntityRecord(
454
423
  if (
455
424
  [ 'title', 'excerpt', 'content' ].includes( key )
456
425
  ) {
457
- // Edits should be the "raw" attribute values.
458
- acc[ key ] = get( data[ key ], 'raw', data[ key ] );
426
+ acc[ key ] = data[ key ];
459
427
  }
460
428
  return acc;
461
429
  },
@@ -466,18 +434,12 @@ export function* saveEntityRecord(
466
434
  : data.status,
467
435
  }
468
436
  );
469
- const options = {
437
+ updatedRecord = await __unstableFetch( {
470
438
  path: `${ path }/autosaves`,
471
439
  method: 'POST',
472
440
  data,
473
- };
474
- if ( __unstableFetch ) {
475
- updatedRecord = yield __unstableAwaitPromise(
476
- __unstableFetch( options )
477
- );
478
- } else {
479
- updatedRecord = yield apiFetch( options );
480
- }
441
+ } );
442
+
481
443
  // An autosave may be processed by the server as a regular save
482
444
  // when its update is requested by the author and the post had
483
445
  // draft or auto-draft status.
@@ -495,12 +457,7 @@ export function* saveEntityRecord(
495
457
  key
496
458
  )
497
459
  ) {
498
- // Edits should be the "raw" attribute values.
499
- acc[ key ] = get(
500
- newRecord[ key ],
501
- 'raw',
502
- newRecord[ key ]
503
- );
460
+ acc[ key ] = newRecord[ key ];
504
461
  } else if ( key === 'status' ) {
505
462
  // Status is only persisted in autosaves when going from
506
463
  // "auto-draft" to "draft".
@@ -511,17 +468,13 @@ export function* saveEntityRecord(
511
468
  : persistedRecord.status;
512
469
  } else {
513
470
  // These properties are not persisted in autosaves.
514
- acc[ key ] = get(
515
- persistedRecord[ key ],
516
- 'raw',
517
- persistedRecord[ key ]
518
- );
471
+ acc[ key ] = persistedRecord[ key ];
519
472
  }
520
473
  return acc;
521
474
  },
522
475
  {}
523
476
  );
524
- yield receiveEntityRecords(
477
+ dispatch.receiveEntityRecords(
525
478
  kind,
526
479
  name,
527
480
  newRecord,
@@ -529,7 +482,10 @@ export function* saveEntityRecord(
529
482
  true
530
483
  );
531
484
  } else {
532
- yield receiveAutosaves( persistedRecord.id, updatedRecord );
485
+ dispatch.receiveAutosaves(
486
+ persistedRecord.id,
487
+ updatedRecord
488
+ );
533
489
  }
534
490
  } else {
535
491
  let edits = record;
@@ -542,19 +498,12 @@ export function* saveEntityRecord(
542
498
  ),
543
499
  };
544
500
  }
545
- const options = {
501
+ updatedRecord = await __unstableFetch( {
546
502
  path,
547
503
  method: recordId ? 'PUT' : 'POST',
548
504
  data: edits,
549
- };
550
- if ( __unstableFetch ) {
551
- updatedRecord = yield __unstableAwaitPromise(
552
- __unstableFetch( options )
553
- );
554
- } else {
555
- updatedRecord = yield apiFetch( options );
556
- }
557
- yield receiveEntityRecords(
505
+ } );
506
+ dispatch.receiveEntityRecords(
558
507
  kind,
559
508
  name,
560
509
  updatedRecord,
@@ -566,20 +515,20 @@ export function* saveEntityRecord(
566
515
  } catch ( _error ) {
567
516
  error = _error;
568
517
  }
569
- yield {
518
+ dispatch( {
570
519
  type: 'SAVE_ENTITY_RECORD_FINISH',
571
520
  kind,
572
521
  name,
573
522
  recordId,
574
523
  error,
575
524
  isAutosave,
576
- };
525
+ } );
577
526
 
578
527
  return updatedRecord;
579
528
  } finally {
580
- yield* __unstableReleaseStoreLock( lock );
529
+ dispatch.__unstableReleaseStoreLock( lock );
581
530
  }
582
- }
531
+ };
583
532
 
584
533
  /**
585
534
  * Runs multiple core-data actions at the same time using one API request.
@@ -603,13 +552,12 @@ export function* saveEntityRecord(
603
552
  * @return {Promise} A promise that resolves to an array containing the return
604
553
  * values of each function given in `requests`.
605
554
  */
606
- export function* __experimentalBatch( requests ) {
555
+ export const __experimentalBatch = ( requests ) => async ( { dispatch } ) => {
607
556
  const batch = createBatch();
608
- const dispatch = yield getDispatch();
609
557
  const api = {
610
558
  saveEntityRecord( kind, name, record, options ) {
611
559
  return batch.add( ( add ) =>
612
- dispatch( STORE_NAME ).saveEntityRecord( kind, name, record, {
560
+ dispatch.saveEntityRecord( kind, name, record, {
613
561
  ...options,
614
562
  __unstableFetch: add,
615
563
  } )
@@ -617,38 +565,28 @@ export function* __experimentalBatch( requests ) {
617
565
  },
618
566
  saveEditedEntityRecord( kind, name, recordId, options ) {
619
567
  return batch.add( ( add ) =>
620
- dispatch( STORE_NAME ).saveEditedEntityRecord(
621
- kind,
622
- name,
623
- recordId,
624
- {
625
- ...options,
626
- __unstableFetch: add,
627
- }
628
- )
568
+ dispatch.saveEditedEntityRecord( kind, name, recordId, {
569
+ ...options,
570
+ __unstableFetch: add,
571
+ } )
629
572
  );
630
573
  },
631
574
  deleteEntityRecord( kind, name, recordId, query, options ) {
632
575
  return batch.add( ( add ) =>
633
- dispatch( STORE_NAME ).deleteEntityRecord(
634
- kind,
635
- name,
636
- recordId,
637
- query,
638
- {
639
- ...options,
640
- __unstableFetch: add,
641
- }
642
- )
576
+ dispatch.deleteEntityRecord( kind, name, recordId, query, {
577
+ ...options,
578
+ __unstableFetch: add,
579
+ } )
643
580
  );
644
581
  },
645
582
  };
646
583
  const resultPromises = requests.map( ( request ) => request( api ) );
647
- const [ , ...results ] = yield __unstableAwaitPromise(
648
- Promise.all( [ batch.run(), ...resultPromises ] )
649
- );
584
+ const [ , ...results ] = await Promise.all( [
585
+ batch.run(),
586
+ ...resultPromises,
587
+ ] );
650
588
  return results;
651
- }
589
+ };
652
590
 
653
591
  /**
654
592
  * Action triggered to save an entity record's edits.
@@ -658,28 +596,23 @@ export function* __experimentalBatch( requests ) {
658
596
  * @param {Object} recordId ID of the record.
659
597
  * @param {Object} options Saving options.
660
598
  */
661
- export function* saveEditedEntityRecord( kind, name, recordId, options ) {
662
- if (
663
- ! ( yield controls.select(
664
- STORE_NAME,
665
- 'hasEditsForEntityRecord',
666
- kind,
667
- name,
668
- recordId
669
- ) )
670
- ) {
599
+ export const saveEditedEntityRecord = (
600
+ kind,
601
+ name,
602
+ recordId,
603
+ options
604
+ ) => async ( { select, dispatch } ) => {
605
+ if ( ! select.hasEditsForEntityRecord( kind, name, recordId ) ) {
671
606
  return;
672
607
  }
673
- const edits = yield controls.select(
674
- STORE_NAME,
675
- 'getEntityRecordNonTransientEdits',
608
+ const edits = select.getEntityRecordNonTransientEdits(
676
609
  kind,
677
610
  name,
678
611
  recordId
679
612
  );
680
613
  const record = { id: recordId, ...edits };
681
- return yield* saveEntityRecord( kind, name, record, options );
682
- }
614
+ return await dispatch.saveEntityRecord( kind, name, record, options );
615
+ };
683
616
 
684
617
  /**
685
618
  * Action triggered to save only specified properties for the entity.
@@ -690,27 +623,17 @@ export function* saveEditedEntityRecord( kind, name, recordId, options ) {
690
623
  * @param {Array} itemsToSave List of entity properties to save.
691
624
  * @param {Object} options Saving options.
692
625
  */
693
- export function* __experimentalSaveSpecifiedEntityEdits(
626
+ export const __experimentalSaveSpecifiedEntityEdits = (
694
627
  kind,
695
628
  name,
696
629
  recordId,
697
630
  itemsToSave,
698
631
  options
699
- ) {
700
- if (
701
- ! ( yield controls.select(
702
- STORE_NAME,
703
- 'hasEditsForEntityRecord',
704
- kind,
705
- name,
706
- recordId
707
- ) )
708
- ) {
632
+ ) => async ( { select, dispatch } ) => {
633
+ if ( ! select.hasEditsForEntityRecord( kind, name, recordId ) ) {
709
634
  return;
710
635
  }
711
- const edits = yield controls.select(
712
- STORE_NAME,
713
- 'getEntityRecordNonTransientEdits',
636
+ const edits = select.getEntityRecordNonTransientEdits(
714
637
  kind,
715
638
  name,
716
639
  recordId
@@ -721,8 +644,8 @@ export function* __experimentalSaveSpecifiedEntityEdits(
721
644
  editsToSave[ edit ] = edits[ edit ];
722
645
  }
723
646
  }
724
- return yield* saveEntityRecord( kind, name, editsToSave, options );
725
- }
647
+ return await dispatch.saveEntityRecord( kind, name, editsToSave, options );
648
+ };
726
649
 
727
650
  /**
728
651
  * Returns an action object used in signalling that Upload permissions have been received.
@@ -1,10 +1,23 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { chunk } from 'lodash';
5
+
1
6
  /**
2
7
  * WordPress dependencies
3
8
  */
4
9
  import apiFetch from '@wordpress/api-fetch';
5
10
 
6
11
  /**
7
- * Default batch processor. Sends its input requests to /v1/batch.
12
+ * Maximum number of requests to place in a single batch request. Obtained by
13
+ * sending a preflight OPTIONS request to /batch/v1/.
14
+ *
15
+ * @type {number?}
16
+ */
17
+ let maxItems = null;
18
+
19
+ /**
20
+ * Default batch processor. Sends its input requests to /batch/v1.
8
21
  *
9
22
  * @param {Array} requests List of API requests to perform at once.
10
23
  *
@@ -13,33 +26,51 @@ import apiFetch from '@wordpress/api-fetch';
13
26
  * (if not ).
14
27
  */
15
28
  export default async function defaultProcessor( requests ) {
16
- const batchResponse = await apiFetch( {
17
- path: '/batch/v1',
18
- method: 'POST',
19
- data: {
20
- validation: 'require-all-validate',
21
- requests: requests.map( ( request ) => ( {
22
- path: request.path,
23
- body: request.data, // Rename 'data' to 'body'.
24
- method: request.method,
25
- headers: request.headers,
26
- } ) ),
27
- },
28
- } );
29
-
30
- if ( batchResponse.failed ) {
31
- return batchResponse.responses.map( ( response ) => ( {
32
- error: response?.body,
33
- } ) );
29
+ if ( maxItems === null ) {
30
+ const preflightResponse = await apiFetch( {
31
+ path: '/batch/v1',
32
+ method: 'OPTIONS',
33
+ } );
34
+ maxItems = preflightResponse.endpoints[ 0 ].args.requests.maxItems;
34
35
  }
35
36
 
36
- return batchResponse.responses.map( ( response ) => {
37
- const result = {};
38
- if ( response.status >= 200 && response.status < 300 ) {
39
- result.output = response.body;
37
+ const results = [];
38
+
39
+ for ( const batchRequests of chunk( requests, maxItems ) ) {
40
+ const batchResponse = await apiFetch( {
41
+ path: '/batch/v1',
42
+ method: 'POST',
43
+ data: {
44
+ validation: 'require-all-validate',
45
+ requests: batchRequests.map( ( request ) => ( {
46
+ path: request.path,
47
+ body: request.data, // Rename 'data' to 'body'.
48
+ method: request.method,
49
+ headers: request.headers,
50
+ } ) ),
51
+ },
52
+ } );
53
+
54
+ let batchResults;
55
+
56
+ if ( batchResponse.failed ) {
57
+ batchResults = batchResponse.responses.map( ( response ) => ( {
58
+ error: response?.body,
59
+ } ) );
40
60
  } else {
41
- result.error = response.body;
61
+ batchResults = batchResponse.responses.map( ( response ) => {
62
+ const result = {};
63
+ if ( response.status >= 200 && response.status < 300 ) {
64
+ result.output = response.body;
65
+ } else {
66
+ result.error = response.body;
67
+ }
68
+ return result;
69
+ } );
42
70
  }
43
- return result;
44
- } );
71
+
72
+ results.push( ...batchResults );
73
+ }
74
+
75
+ return results;
45
76
  }