@wordpress/core-data 6.29.0 → 6.31.0
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.
- package/CHANGELOG.md +4 -0
- package/build/actions.js +5 -5
- package/build/actions.js.map +1 -1
- package/build/entities.js +84 -44
- package/build/entities.js.map +1 -1
- package/build/hooks/use-query-select.js +15 -16
- package/build/hooks/use-query-select.js.map +1 -1
- package/build/index.js +16 -10
- package/build/index.js.map +1 -1
- package/build/queried-data/selectors.js +9 -0
- package/build/queried-data/selectors.js.map +1 -1
- package/build/resolvers.js +24 -8
- package/build/resolvers.js.map +1 -1
- package/build/selectors.js +5 -0
- package/build/selectors.js.map +1 -1
- package/build-module/actions.js +5 -5
- package/build-module/actions.js.map +1 -1
- package/build-module/entities.js +84 -44
- package/build-module/entities.js.map +1 -1
- package/build-module/hooks/use-query-select.js +15 -16
- package/build-module/hooks/use-query-select.js.map +1 -1
- package/build-module/index.js +17 -11
- package/build-module/index.js.map +1 -1
- package/build-module/queried-data/selectors.js +8 -0
- package/build-module/queried-data/selectors.js.map +1 -1
- package/build-module/resolvers.js +24 -8
- package/build-module/resolvers.js.map +1 -1
- package/build-module/selectors.js +6 -1
- package/build-module/selectors.js.map +1 -1
- package/build-types/entities.d.ts +26 -52
- package/build-types/entities.d.ts.map +1 -1
- package/build-types/index.d.ts.map +1 -1
- package/build-types/queried-data/selectors.d.ts +1 -0
- package/build-types/queried-data/selectors.d.ts.map +1 -1
- package/build-types/resolvers.d.ts +2 -1
- package/build-types/resolvers.d.ts.map +1 -1
- package/build-types/selectors.d.ts.map +1 -1
- package/package.json +17 -17
- package/src/actions.js +5 -5
- package/src/entities.js +84 -54
- package/src/hooks/test/use-entity-record.js +4 -1
- package/src/hooks/test/use-entity-records.js +2 -0
- package/src/hooks/test/use-query-select.js +3 -0
- package/src/hooks/use-query-select.ts +21 -16
- package/src/index.js +27 -13
- package/src/queried-data/selectors.js +6 -0
- package/src/resolvers.js +40 -7
- package/src/selectors.ts +10 -1
- package/src/test/entities.js +19 -10
- package/tsconfig.json +1 -0
- package/tsconfig.tsbuildinfo +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/core-data",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.31.0",
|
|
4
4
|
"description": "Access to and manipulation of core WordPress entities.",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -31,21 +31,21 @@
|
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@babel/runtime": "^7.16.0",
|
|
34
|
-
"@wordpress/api-fetch": "^6.
|
|
35
|
-
"@wordpress/block-editor": "^12.
|
|
36
|
-
"@wordpress/blocks": "^12.
|
|
37
|
-
"@wordpress/compose": "^6.
|
|
38
|
-
"@wordpress/data": "^9.
|
|
39
|
-
"@wordpress/deprecated": "^3.
|
|
40
|
-
"@wordpress/element": "^5.
|
|
41
|
-
"@wordpress/html-entities": "^3.
|
|
42
|
-
"@wordpress/i18n": "^4.
|
|
43
|
-
"@wordpress/is-shallow-equal": "^4.
|
|
44
|
-
"@wordpress/private-apis": "^0.
|
|
45
|
-
"@wordpress/rich-text": "^6.
|
|
46
|
-
"@wordpress/sync": "^0.
|
|
47
|
-
"@wordpress/undo-manager": "^0.
|
|
48
|
-
"@wordpress/url": "^3.
|
|
34
|
+
"@wordpress/api-fetch": "^6.51.0",
|
|
35
|
+
"@wordpress/block-editor": "^12.22.0",
|
|
36
|
+
"@wordpress/blocks": "^12.31.0",
|
|
37
|
+
"@wordpress/compose": "^6.31.0",
|
|
38
|
+
"@wordpress/data": "^9.24.0",
|
|
39
|
+
"@wordpress/deprecated": "^3.54.0",
|
|
40
|
+
"@wordpress/element": "^5.31.0",
|
|
41
|
+
"@wordpress/html-entities": "^3.54.0",
|
|
42
|
+
"@wordpress/i18n": "^4.54.0",
|
|
43
|
+
"@wordpress/is-shallow-equal": "^4.54.0",
|
|
44
|
+
"@wordpress/private-apis": "^0.36.0",
|
|
45
|
+
"@wordpress/rich-text": "^6.31.0",
|
|
46
|
+
"@wordpress/sync": "^0.16.0",
|
|
47
|
+
"@wordpress/undo-manager": "^0.14.0",
|
|
48
|
+
"@wordpress/url": "^3.55.0",
|
|
49
49
|
"change-case": "^4.1.2",
|
|
50
50
|
"equivalent-key-map": "^0.2.2",
|
|
51
51
|
"fast-deep-equal": "^3.1.3",
|
|
@@ -60,5 +60,5 @@
|
|
|
60
60
|
"publishConfig": {
|
|
61
61
|
"access": "public"
|
|
62
62
|
},
|
|
63
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "ffc07735d0abfb3f69e91d48f25b7fe8d1ef92d2"
|
|
64
64
|
}
|
package/src/actions.js
CHANGED
|
@@ -286,7 +286,7 @@ export const deleteEntityRecord =
|
|
|
286
286
|
{ __unstableFetch = apiFetch, throwOnError = false } = {}
|
|
287
287
|
) =>
|
|
288
288
|
async ( { dispatch } ) => {
|
|
289
|
-
const configs = await dispatch( getOrLoadEntitiesConfig( kind ) );
|
|
289
|
+
const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) );
|
|
290
290
|
const entityConfig = configs.find(
|
|
291
291
|
( config ) => config.kind === kind && config.name === name
|
|
292
292
|
);
|
|
@@ -503,7 +503,7 @@ export const saveEntityRecord =
|
|
|
503
503
|
} = {}
|
|
504
504
|
) =>
|
|
505
505
|
async ( { select, resolveSelect, dispatch } ) => {
|
|
506
|
-
const configs = await dispatch( getOrLoadEntitiesConfig( kind ) );
|
|
506
|
+
const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) );
|
|
507
507
|
const entityConfig = configs.find(
|
|
508
508
|
( config ) => config.kind === kind && config.name === name
|
|
509
509
|
);
|
|
@@ -780,7 +780,7 @@ export const saveEditedEntityRecord =
|
|
|
780
780
|
if ( ! select.hasEditsForEntityRecord( kind, name, recordId ) ) {
|
|
781
781
|
return;
|
|
782
782
|
}
|
|
783
|
-
const configs = await dispatch( getOrLoadEntitiesConfig( kind ) );
|
|
783
|
+
const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) );
|
|
784
784
|
const entityConfig = configs.find(
|
|
785
785
|
( config ) => config.kind === kind && config.name === name
|
|
786
786
|
);
|
|
@@ -824,7 +824,7 @@ export const __experimentalSaveSpecifiedEntityEdits =
|
|
|
824
824
|
setNestedValue( editsToSave, item, getNestedValue( edits, item ) );
|
|
825
825
|
}
|
|
826
826
|
|
|
827
|
-
const configs = await dispatch( getOrLoadEntitiesConfig( kind ) );
|
|
827
|
+
const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) );
|
|
828
828
|
const entityConfig = configs.find(
|
|
829
829
|
( config ) => config.kind === kind && config.name === name
|
|
830
830
|
);
|
|
@@ -948,7 +948,7 @@ export function receiveDefaultTemplateId( query, templateId ) {
|
|
|
948
948
|
export const receiveRevisions =
|
|
949
949
|
( kind, name, recordKey, records, query, invalidateCache = false, meta ) =>
|
|
950
950
|
async ( { dispatch } ) => {
|
|
951
|
-
const configs = await dispatch( getOrLoadEntitiesConfig( kind ) );
|
|
951
|
+
const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) );
|
|
952
952
|
const entityConfig = configs.find(
|
|
953
953
|
( config ) => config.kind === kind && config.name === name
|
|
954
954
|
);
|
package/src/entities.js
CHANGED
|
@@ -39,6 +39,9 @@ export const rootEntitiesConfig = [
|
|
|
39
39
|
'url',
|
|
40
40
|
].join( ',' ),
|
|
41
41
|
},
|
|
42
|
+
// The entity doesn't support selecting multiple records.
|
|
43
|
+
// The property is maintained for backward compatibility.
|
|
44
|
+
plural: '__unstableBases',
|
|
42
45
|
syncConfig: {
|
|
43
46
|
fetch: async () => {
|
|
44
47
|
return apiFetch( { path: '/' } );
|
|
@@ -58,33 +61,6 @@ export const rootEntitiesConfig = [
|
|
|
58
61
|
syncObjectType: 'root/base',
|
|
59
62
|
getSyncObjectId: () => 'index',
|
|
60
63
|
},
|
|
61
|
-
{
|
|
62
|
-
label: __( 'Site' ),
|
|
63
|
-
name: 'site',
|
|
64
|
-
kind: 'root',
|
|
65
|
-
baseURL: '/wp/v2/settings',
|
|
66
|
-
getTitle: ( record ) => {
|
|
67
|
-
return record?.title ?? __( 'Site Title' );
|
|
68
|
-
},
|
|
69
|
-
syncConfig: {
|
|
70
|
-
fetch: async () => {
|
|
71
|
-
return apiFetch( { path: '/wp/v2/settings' } );
|
|
72
|
-
},
|
|
73
|
-
applyChangesToDoc: ( doc, changes ) => {
|
|
74
|
-
const document = doc.getMap( 'document' );
|
|
75
|
-
Object.entries( changes ).forEach( ( [ key, value ] ) => {
|
|
76
|
-
if ( document.get( key ) !== value ) {
|
|
77
|
-
document.set( key, value );
|
|
78
|
-
}
|
|
79
|
-
} );
|
|
80
|
-
},
|
|
81
|
-
fromCRDTDoc: ( doc ) => {
|
|
82
|
-
return doc.getMap( 'document' ).toJSON();
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
syncObjectType: 'root/site',
|
|
86
|
-
getSyncObjectId: () => 'index',
|
|
87
|
-
},
|
|
88
64
|
{
|
|
89
65
|
label: __( 'Post Type' ),
|
|
90
66
|
name: 'postType',
|
|
@@ -92,6 +68,7 @@ export const rootEntitiesConfig = [
|
|
|
92
68
|
key: 'slug',
|
|
93
69
|
baseURL: '/wp/v2/types',
|
|
94
70
|
baseURLParams: { context: 'edit' },
|
|
71
|
+
plural: 'postTypes',
|
|
95
72
|
syncConfig: {
|
|
96
73
|
fetch: async ( id ) => {
|
|
97
74
|
return apiFetch( {
|
|
@@ -220,6 +197,7 @@ export const rootEntitiesConfig = [
|
|
|
220
197
|
kind: 'root',
|
|
221
198
|
baseURL: '/wp/v2/themes',
|
|
222
199
|
baseURLParams: { context: 'edit' },
|
|
200
|
+
plural: 'themes',
|
|
223
201
|
key: 'stylesheet',
|
|
224
202
|
},
|
|
225
203
|
{
|
|
@@ -228,6 +206,7 @@ export const rootEntitiesConfig = [
|
|
|
228
206
|
kind: 'root',
|
|
229
207
|
baseURL: '/wp/v2/plugins',
|
|
230
208
|
baseURLParams: { context: 'edit' },
|
|
209
|
+
plural: 'plugins',
|
|
231
210
|
key: 'plugin',
|
|
232
211
|
},
|
|
233
212
|
{
|
|
@@ -244,6 +223,12 @@ export const rootEntitiesConfig = [
|
|
|
244
223
|
export const additionalEntityConfigLoaders = [
|
|
245
224
|
{ kind: 'postType', loadEntities: loadPostTypeEntities },
|
|
246
225
|
{ kind: 'taxonomy', loadEntities: loadTaxonomyEntities },
|
|
226
|
+
{
|
|
227
|
+
kind: 'root',
|
|
228
|
+
name: 'site',
|
|
229
|
+
plural: 'sites',
|
|
230
|
+
loadEntities: loadSiteEntity,
|
|
231
|
+
},
|
|
247
232
|
];
|
|
248
233
|
|
|
249
234
|
/**
|
|
@@ -401,39 +386,76 @@ async function loadTaxonomyEntities() {
|
|
|
401
386
|
}
|
|
402
387
|
|
|
403
388
|
/**
|
|
404
|
-
* Returns the entity
|
|
389
|
+
* Returns the Site entity.
|
|
390
|
+
*
|
|
391
|
+
* @return {Promise} Entity promise
|
|
392
|
+
*/
|
|
393
|
+
async function loadSiteEntity() {
|
|
394
|
+
const entity = {
|
|
395
|
+
label: __( 'Site' ),
|
|
396
|
+
name: 'site',
|
|
397
|
+
kind: 'root',
|
|
398
|
+
baseURL: '/wp/v2/settings',
|
|
399
|
+
syncConfig: {
|
|
400
|
+
fetch: async () => {
|
|
401
|
+
return apiFetch( { path: '/wp/v2/settings' } );
|
|
402
|
+
},
|
|
403
|
+
applyChangesToDoc: ( doc, changes ) => {
|
|
404
|
+
const document = doc.getMap( 'document' );
|
|
405
|
+
Object.entries( changes ).forEach( ( [ key, value ] ) => {
|
|
406
|
+
if ( document.get( key ) !== value ) {
|
|
407
|
+
document.set( key, value );
|
|
408
|
+
}
|
|
409
|
+
} );
|
|
410
|
+
},
|
|
411
|
+
fromCRDTDoc: ( doc ) => {
|
|
412
|
+
return doc.getMap( 'document' ).toJSON();
|
|
413
|
+
},
|
|
414
|
+
},
|
|
415
|
+
syncObjectType: 'root/site',
|
|
416
|
+
getSyncObjectId: () => 'index',
|
|
417
|
+
meta: {},
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
const site = await apiFetch( {
|
|
421
|
+
path: entity.baseURL,
|
|
422
|
+
method: 'OPTIONS',
|
|
423
|
+
} );
|
|
424
|
+
|
|
425
|
+
const labels = {};
|
|
426
|
+
Object.entries( site?.schema?.properties ?? {} ).forEach(
|
|
427
|
+
( [ key, value ] ) => {
|
|
428
|
+
// Ignore properties `title` and `type` keys.
|
|
429
|
+
if ( typeof value === 'object' && value.title ) {
|
|
430
|
+
labels[ key ] = value.title;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
return [ { ...entity, meta: { labels } } ];
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Returns the entity's getter method name given its kind and name or plural name.
|
|
405
440
|
*
|
|
406
441
|
* @example
|
|
407
442
|
* ```js
|
|
408
443
|
* const nameSingular = getMethodName( 'root', 'theme', 'get' );
|
|
409
444
|
* // nameSingular is getRootTheme
|
|
410
445
|
*
|
|
411
|
-
* const namePlural = getMethodName( 'root', '
|
|
446
|
+
* const namePlural = getMethodName( 'root', 'themes', 'set' );
|
|
412
447
|
* // namePlural is setRootThemes
|
|
413
448
|
* ```
|
|
414
449
|
*
|
|
415
|
-
* @param {string}
|
|
416
|
-
* @param {string}
|
|
417
|
-
* @param {string}
|
|
418
|
-
* @param {boolean} usePlural Whether to use the plural form or not.
|
|
450
|
+
* @param {string} kind Entity kind.
|
|
451
|
+
* @param {string} name Entity name or plural name.
|
|
452
|
+
* @param {string} prefix Function prefix.
|
|
419
453
|
*
|
|
420
454
|
* @return {string} Method name
|
|
421
455
|
*/
|
|
422
|
-
export const getMethodName = (
|
|
423
|
-
kind,
|
|
424
|
-
name,
|
|
425
|
-
prefix = 'get',
|
|
426
|
-
usePlural = false
|
|
427
|
-
) => {
|
|
428
|
-
const entityConfig = rootEntitiesConfig.find(
|
|
429
|
-
( config ) => config.kind === kind && config.name === name
|
|
430
|
-
);
|
|
456
|
+
export const getMethodName = ( kind, name, prefix = 'get' ) => {
|
|
431
457
|
const kindPrefix = kind === 'root' ? '' : pascalCase( kind );
|
|
432
|
-
const
|
|
433
|
-
const suffix =
|
|
434
|
-
usePlural && 'plural' in entityConfig && entityConfig?.plural
|
|
435
|
-
? pascalCase( entityConfig.plural )
|
|
436
|
-
: nameSuffix;
|
|
458
|
+
const suffix = pascalCase( name );
|
|
437
459
|
return `${ prefix }${ kindPrefix }${ suffix }`;
|
|
438
460
|
};
|
|
439
461
|
|
|
@@ -447,17 +469,21 @@ function registerSyncConfigs( configs ) {
|
|
|
447
469
|
}
|
|
448
470
|
|
|
449
471
|
/**
|
|
450
|
-
* Loads the
|
|
472
|
+
* Loads the entities into the store.
|
|
451
473
|
*
|
|
452
|
-
*
|
|
474
|
+
* Note: The `name` argument is used for `root` entities requiring additional server data.
|
|
453
475
|
*
|
|
476
|
+
* @param {string} kind Kind
|
|
477
|
+
* @param {string} name Name
|
|
454
478
|
* @return {(thunkArgs: object) => Promise<Array>} Entities
|
|
455
479
|
*/
|
|
456
480
|
export const getOrLoadEntitiesConfig =
|
|
457
|
-
( kind ) =>
|
|
481
|
+
( kind, name ) =>
|
|
458
482
|
async ( { select, dispatch } ) => {
|
|
459
483
|
let configs = select.getEntitiesConfig( kind );
|
|
460
|
-
|
|
484
|
+
const hasConfig = !! select.getEntityConfig( kind, name );
|
|
485
|
+
|
|
486
|
+
if ( configs?.length > 0 && hasConfig ) {
|
|
461
487
|
if ( window.__experimentalEnableSync ) {
|
|
462
488
|
if ( process.env.IS_GUTENBERG_PLUGIN ) {
|
|
463
489
|
registerSyncConfigs( configs );
|
|
@@ -467,9 +493,13 @@ export const getOrLoadEntitiesConfig =
|
|
|
467
493
|
return configs;
|
|
468
494
|
}
|
|
469
495
|
|
|
470
|
-
const loader = additionalEntityConfigLoaders.find(
|
|
471
|
-
(
|
|
472
|
-
|
|
496
|
+
const loader = additionalEntityConfigLoaders.find( ( l ) => {
|
|
497
|
+
if ( ! name || ! l.name ) {
|
|
498
|
+
return l.kind === kind;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
return l.kind === kind && l.name === name;
|
|
502
|
+
} );
|
|
473
503
|
if ( ! loader ) {
|
|
474
504
|
return [];
|
|
475
505
|
}
|
|
@@ -51,6 +51,7 @@ describe( 'useEntityRecord', () => {
|
|
|
51
51
|
record: undefined,
|
|
52
52
|
save: expect.any( Function ),
|
|
53
53
|
hasResolved: false,
|
|
54
|
+
hasStarted: false,
|
|
54
55
|
isResolving: false,
|
|
55
56
|
status: 'IDLE',
|
|
56
57
|
} );
|
|
@@ -70,6 +71,7 @@ describe( 'useEntityRecord', () => {
|
|
|
70
71
|
record: { hello: 'world', id: 1 },
|
|
71
72
|
save: expect.any( Function ),
|
|
72
73
|
hasResolved: true,
|
|
74
|
+
hasStarted: true,
|
|
73
75
|
isResolving: false,
|
|
74
76
|
status: 'SUCCESS',
|
|
75
77
|
} );
|
|
@@ -99,6 +101,7 @@ describe( 'useEntityRecord', () => {
|
|
|
99
101
|
record: { hello: 'world', id: 1 },
|
|
100
102
|
save: expect.any( Function ),
|
|
101
103
|
hasResolved: true,
|
|
104
|
+
hasStarted: true,
|
|
102
105
|
isResolving: false,
|
|
103
106
|
status: 'SUCCESS',
|
|
104
107
|
} )
|
|
@@ -129,7 +132,7 @@ describe( 'useEntityRecord', () => {
|
|
|
129
132
|
</RegistryProvider>
|
|
130
133
|
);
|
|
131
134
|
|
|
132
|
-
const { rerender } = render( <UI enabled
|
|
135
|
+
const { rerender } = render( <UI enabled /> );
|
|
133
136
|
|
|
134
137
|
// A minimum delay for a fetch request. The same delay is used again as a control.
|
|
135
138
|
await act(
|
|
@@ -49,6 +49,7 @@ describe( 'useEntityRecords', () => {
|
|
|
49
49
|
expect( data ).toEqual( {
|
|
50
50
|
records: null,
|
|
51
51
|
hasResolved: false,
|
|
52
|
+
hasStarted: false,
|
|
52
53
|
isResolving: false,
|
|
53
54
|
status: 'IDLE',
|
|
54
55
|
totalItems: null,
|
|
@@ -65,6 +66,7 @@ describe( 'useEntityRecords', () => {
|
|
|
65
66
|
expect( data ).toEqual( {
|
|
66
67
|
records: TEST_RECORDS,
|
|
67
68
|
hasResolved: true,
|
|
69
|
+
hasStarted: true,
|
|
68
70
|
isResolving: false,
|
|
69
71
|
status: 'SUCCESS',
|
|
70
72
|
totalItems: null,
|
|
@@ -116,6 +116,7 @@ describe( 'useQuerySelect', () => {
|
|
|
116
116
|
data: 'bar',
|
|
117
117
|
isResolving: false,
|
|
118
118
|
hasResolved: false,
|
|
119
|
+
hasStarted: false,
|
|
119
120
|
status: 'IDLE',
|
|
120
121
|
} );
|
|
121
122
|
} );
|
|
@@ -165,6 +166,7 @@ describe( 'useQuerySelect', () => {
|
|
|
165
166
|
data: 10,
|
|
166
167
|
isResolving: false,
|
|
167
168
|
hasResolved: false,
|
|
169
|
+
hasStarted: false,
|
|
168
170
|
status: 'IDLE',
|
|
169
171
|
} );
|
|
170
172
|
|
|
@@ -180,6 +182,7 @@ describe( 'useQuerySelect', () => {
|
|
|
180
182
|
data: 15,
|
|
181
183
|
isResolving: false,
|
|
182
184
|
hasResolved: true,
|
|
185
|
+
hasStarted: true,
|
|
183
186
|
status: 'SUCCESS',
|
|
184
187
|
} )
|
|
185
188
|
);
|
|
@@ -21,7 +21,7 @@ interface QuerySelectResponse< Data > {
|
|
|
21
21
|
/** the requested selector return value */
|
|
22
22
|
data: Data;
|
|
23
23
|
|
|
24
|
-
/** is the record still being resolved? Via the `
|
|
24
|
+
/** is the record still being resolved? Via the `isResolving` meta-selector */
|
|
25
25
|
isResolving: boolean;
|
|
26
26
|
|
|
27
27
|
/** was the resolution started? Via the `hasStartedResolution` meta-selector */
|
|
@@ -108,31 +108,36 @@ const enrichSelectors = memoize( ( ( selectors ) => {
|
|
|
108
108
|
get:
|
|
109
109
|
() =>
|
|
110
110
|
( ...args: unknown[] ) => {
|
|
111
|
-
const { getIsResolving, hasFinishedResolution } = selectors;
|
|
112
|
-
const isResolving = !! getIsResolving( selectorName, args );
|
|
113
|
-
const hasResolved =
|
|
114
|
-
! isResolving &&
|
|
115
|
-
hasFinishedResolution( selectorName, args );
|
|
116
111
|
const data = selectors[ selectorName ]( ...args );
|
|
112
|
+
const resolutionStatus = selectors.getResolutionState(
|
|
113
|
+
selectorName,
|
|
114
|
+
args
|
|
115
|
+
)?.status;
|
|
117
116
|
|
|
118
117
|
let status;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
118
|
+
switch ( resolutionStatus ) {
|
|
119
|
+
case 'resolving':
|
|
120
|
+
status = Status.Resolving;
|
|
121
|
+
break;
|
|
122
|
+
case 'finished':
|
|
123
123
|
status = Status.Success;
|
|
124
|
-
|
|
124
|
+
break;
|
|
125
|
+
case 'error':
|
|
125
126
|
status = Status.Error;
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
break;
|
|
128
|
+
case undefined:
|
|
129
|
+
status = Status.Idle;
|
|
130
|
+
break;
|
|
129
131
|
}
|
|
130
132
|
|
|
131
133
|
return {
|
|
132
134
|
data,
|
|
133
135
|
status,
|
|
134
|
-
isResolving,
|
|
135
|
-
|
|
136
|
+
isResolving: status === Status.Resolving,
|
|
137
|
+
hasStarted: status !== Status.Idle,
|
|
138
|
+
hasResolved:
|
|
139
|
+
status === Status.Success ||
|
|
140
|
+
status === Status.Error,
|
|
136
141
|
};
|
|
137
142
|
},
|
|
138
143
|
} );
|
package/src/index.js
CHANGED
|
@@ -12,7 +12,11 @@ import * as privateSelectors from './private-selectors';
|
|
|
12
12
|
import * as actions from './actions';
|
|
13
13
|
import * as resolvers from './resolvers';
|
|
14
14
|
import createLocksActions from './locks/actions';
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
rootEntitiesConfig,
|
|
17
|
+
additionalEntityConfigLoaders,
|
|
18
|
+
getMethodName,
|
|
19
|
+
} from './entities';
|
|
16
20
|
import { STORE_NAME } from './name';
|
|
17
21
|
import { unlock } from './private-apis';
|
|
18
22
|
|
|
@@ -20,29 +24,39 @@ import { unlock } from './private-apis';
|
|
|
20
24
|
// (getEntityRecord, getEntityRecords, updateEntityRecord, updateEntityRecords)
|
|
21
25
|
// Instead of getEntityRecord, the consumer could use more user-friendly named selector: getPostType, getTaxonomy...
|
|
22
26
|
// The "kind" and the "name" of the entity are combined to generate these shortcuts.
|
|
27
|
+
const entitiesConfig = [
|
|
28
|
+
...rootEntitiesConfig,
|
|
29
|
+
...additionalEntityConfigLoaders.filter( ( config ) => !! config.name ),
|
|
30
|
+
];
|
|
23
31
|
|
|
24
|
-
const entitySelectors =
|
|
25
|
-
const { kind, name } = entity;
|
|
32
|
+
const entitySelectors = entitiesConfig.reduce( ( result, entity ) => {
|
|
33
|
+
const { kind, name, plural } = entity;
|
|
26
34
|
result[ getMethodName( kind, name ) ] = ( state, key, query ) =>
|
|
27
35
|
selectors.getEntityRecord( state, kind, name, key, query );
|
|
28
|
-
|
|
29
|
-
|
|
36
|
+
|
|
37
|
+
if ( plural ) {
|
|
38
|
+
result[ getMethodName( kind, plural, 'get' ) ] = ( state, query ) =>
|
|
39
|
+
selectors.getEntityRecords( state, kind, name, query );
|
|
40
|
+
}
|
|
30
41
|
return result;
|
|
31
42
|
}, {} );
|
|
32
43
|
|
|
33
|
-
const entityResolvers =
|
|
34
|
-
const { kind, name } = entity;
|
|
44
|
+
const entityResolvers = entitiesConfig.reduce( ( result, entity ) => {
|
|
45
|
+
const { kind, name, plural } = entity;
|
|
35
46
|
result[ getMethodName( kind, name ) ] = ( key, query ) =>
|
|
36
47
|
resolvers.getEntityRecord( kind, name, key, query );
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
48
|
+
|
|
49
|
+
if ( plural ) {
|
|
50
|
+
const pluralMethodName = getMethodName( kind, plural, 'get' );
|
|
51
|
+
result[ pluralMethodName ] = ( ...args ) =>
|
|
52
|
+
resolvers.getEntityRecords( kind, name, ...args );
|
|
53
|
+
result[ pluralMethodName ].shouldInvalidate = ( action ) =>
|
|
54
|
+
resolvers.getEntityRecords.shouldInvalidate( action, kind, name );
|
|
55
|
+
}
|
|
42
56
|
return result;
|
|
43
57
|
}, {} );
|
|
44
58
|
|
|
45
|
-
const entityActions =
|
|
59
|
+
const entityActions = entitiesConfig.reduce( ( result, entity ) => {
|
|
46
60
|
const { kind, name } = entity;
|
|
47
61
|
result[ getMethodName( kind, name, 'save' ) ] = ( record, options ) =>
|
|
48
62
|
actions.saveEntityRecord( kind, name, record, options );
|
|
@@ -126,3 +126,9 @@ export function getQueriedTotalItems( state, query = {} ) {
|
|
|
126
126
|
|
|
127
127
|
return state.queries?.[ context ]?.[ stableKey ]?.meta?.totalItems ?? null;
|
|
128
128
|
}
|
|
129
|
+
|
|
130
|
+
export function getQueriedTotalPages( state, query = {} ) {
|
|
131
|
+
const { stableKey, context } = getQueryParts( query );
|
|
132
|
+
|
|
133
|
+
return state.queries?.[ context ]?.[ stableKey ]?.meta?.totalPages ?? null;
|
|
134
|
+
}
|
package/src/resolvers.js
CHANGED
|
@@ -59,7 +59,7 @@ export const getCurrentUser =
|
|
|
59
59
|
export const getEntityRecord =
|
|
60
60
|
( kind, name, key = '', query ) =>
|
|
61
61
|
async ( { select, dispatch } ) => {
|
|
62
|
-
const configs = await dispatch( getOrLoadEntitiesConfig( kind ) );
|
|
62
|
+
const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) );
|
|
63
63
|
const entityConfig = configs.find(
|
|
64
64
|
( config ) => config.name === name && config.kind === kind
|
|
65
65
|
);
|
|
@@ -194,7 +194,7 @@ export const getEditedEntityRecord = forwardResolver( 'getEntityRecord' );
|
|
|
194
194
|
export const getEntityRecords =
|
|
195
195
|
( kind, name, query = {} ) =>
|
|
196
196
|
async ( { dispatch } ) => {
|
|
197
|
-
const configs = await dispatch( getOrLoadEntitiesConfig( kind ) );
|
|
197
|
+
const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) );
|
|
198
198
|
const entityConfig = configs.find(
|
|
199
199
|
( config ) => config.name === name && config.kind === kind
|
|
200
200
|
);
|
|
@@ -238,6 +238,9 @@ export const getEntityRecords =
|
|
|
238
238
|
totalItems: parseInt(
|
|
239
239
|
response.headers.get( 'X-WP-Total' )
|
|
240
240
|
),
|
|
241
|
+
totalPages: parseInt(
|
|
242
|
+
response.headers.get( 'X-WP-TotalPages' )
|
|
243
|
+
),
|
|
241
244
|
};
|
|
242
245
|
} else {
|
|
243
246
|
records = Object.values( await apiFetch( { path } ) );
|
|
@@ -426,7 +429,7 @@ export const canUser =
|
|
|
426
429
|
export const canUserEditEntityRecord =
|
|
427
430
|
( kind, name, recordId ) =>
|
|
428
431
|
async ( { dispatch } ) => {
|
|
429
|
-
const configs = await dispatch( getOrLoadEntitiesConfig( kind ) );
|
|
432
|
+
const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) );
|
|
430
433
|
const entityConfig = configs.find(
|
|
431
434
|
( config ) => config.name === name && config.kind === kind
|
|
432
435
|
);
|
|
@@ -661,12 +664,42 @@ export const getUserPatternCategories =
|
|
|
661
664
|
|
|
662
665
|
export const getNavigationFallbackId =
|
|
663
666
|
() =>
|
|
664
|
-
async ( { dispatch } ) => {
|
|
667
|
+
async ( { dispatch, select } ) => {
|
|
665
668
|
const fallback = await apiFetch( {
|
|
666
|
-
path: addQueryArgs( '/wp-block-editor/v1/navigation-fallback'
|
|
669
|
+
path: addQueryArgs( '/wp-block-editor/v1/navigation-fallback', {
|
|
670
|
+
_embed: true,
|
|
671
|
+
} ),
|
|
667
672
|
} );
|
|
668
673
|
|
|
674
|
+
const record = fallback?._embedded?.self;
|
|
675
|
+
|
|
669
676
|
dispatch.receiveNavigationFallbackId( fallback?.id );
|
|
677
|
+
|
|
678
|
+
if ( record ) {
|
|
679
|
+
// If the fallback is already in the store, don't invalidate navigation queries.
|
|
680
|
+
// Otherwise, invalidate the cache for the scenario where there were no Navigation
|
|
681
|
+
// posts in the state and the fallback created one.
|
|
682
|
+
const existingFallbackEntityRecord = select.getEntityRecord(
|
|
683
|
+
'postType',
|
|
684
|
+
'wp_navigation',
|
|
685
|
+
fallback.id
|
|
686
|
+
);
|
|
687
|
+
const invalidateNavigationQueries = ! existingFallbackEntityRecord;
|
|
688
|
+
dispatch.receiveEntityRecords(
|
|
689
|
+
'postType',
|
|
690
|
+
'wp_navigation',
|
|
691
|
+
record,
|
|
692
|
+
undefined,
|
|
693
|
+
invalidateNavigationQueries
|
|
694
|
+
);
|
|
695
|
+
|
|
696
|
+
// Resolve to avoid further network requests.
|
|
697
|
+
dispatch.finishResolution( 'getEntityRecord', [
|
|
698
|
+
'postType',
|
|
699
|
+
'wp_navigation',
|
|
700
|
+
fallback.id,
|
|
701
|
+
] );
|
|
702
|
+
}
|
|
670
703
|
};
|
|
671
704
|
|
|
672
705
|
export const getDefaultTemplateId =
|
|
@@ -693,7 +726,7 @@ export const getDefaultTemplateId =
|
|
|
693
726
|
export const getRevisions =
|
|
694
727
|
( kind, name, recordKey, query = {} ) =>
|
|
695
728
|
async ( { dispatch } ) => {
|
|
696
|
-
const configs = await dispatch( getOrLoadEntitiesConfig( kind ) );
|
|
729
|
+
const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) );
|
|
697
730
|
const entityConfig = configs.find(
|
|
698
731
|
( config ) => config.name === name && config.kind === kind
|
|
699
732
|
);
|
|
@@ -818,7 +851,7 @@ getRevisions.shouldInvalidate = ( action, kind, name, recordKey ) =>
|
|
|
818
851
|
export const getRevision =
|
|
819
852
|
( kind, name, recordKey, revisionKey, query ) =>
|
|
820
853
|
async ( { dispatch } ) => {
|
|
821
|
-
const configs = await dispatch( getOrLoadEntitiesConfig( kind ) );
|
|
854
|
+
const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) );
|
|
822
855
|
const entityConfig = configs.find(
|
|
823
856
|
( config ) => config.name === name && config.kind === kind
|
|
824
857
|
);
|
package/src/selectors.ts
CHANGED
|
@@ -14,7 +14,11 @@ import deprecated from '@wordpress/deprecated';
|
|
|
14
14
|
* Internal dependencies
|
|
15
15
|
*/
|
|
16
16
|
import { STORE_NAME } from './name';
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
getQueriedItems,
|
|
19
|
+
getQueriedTotalItems,
|
|
20
|
+
getQueriedTotalPages,
|
|
21
|
+
} from './queried-data';
|
|
18
22
|
import { DEFAULT_ENTITY_KEY } from './entities';
|
|
19
23
|
import {
|
|
20
24
|
getNormalizedCommaSeparable,
|
|
@@ -623,6 +627,11 @@ export const getEntityRecordsTotalPages = (
|
|
|
623
627
|
if ( query.per_page === -1 ) return 1;
|
|
624
628
|
const totalItems = getQueriedTotalItems( queriedState, query );
|
|
625
629
|
if ( ! totalItems ) return totalItems;
|
|
630
|
+
// If `per_page` is not set and the query relies on the defaults of the
|
|
631
|
+
// REST endpoint, get the info from query's meta.
|
|
632
|
+
if ( ! query.per_page ) {
|
|
633
|
+
return getQueriedTotalPages( queriedState, query );
|
|
634
|
+
}
|
|
626
635
|
return Math.ceil( totalItems / query.per_page );
|
|
627
636
|
};
|
|
628
637
|
|