@wordpress/core-data 4.8.0 → 4.11.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 +6 -0
- package/README.md +56 -56
- package/build/actions.js.map +1 -1
- package/build/batch/create-batch.js +1 -1
- package/build/batch/create-batch.js.map +1 -1
- package/build/batch/default-processor.js +13 -7
- package/build/batch/default-processor.js.map +1 -1
- package/build/entities.js.map +1 -1
- package/build/entity-provider.js.map +1 -1
- package/build/hooks/use-entity-record.js.map +1 -1
- package/build/hooks/use-query-select.js.map +1 -1
- package/build/hooks/use-resource-permissions.js +94 -0
- package/build/hooks/use-resource-permissions.js.map +1 -0
- package/build/index.js +28 -1
- package/build/index.js.map +1 -1
- package/build/queried-data/selectors.js.map +1 -1
- package/build/reducer.js +4 -1
- package/build/reducer.js.map +1 -1
- package/build/resolvers.js +4 -14
- package/build/resolvers.js.map +1 -1
- package/build/selectors.js +45 -8
- package/build/selectors.js.map +1 -1
- package/build/utils/forward-resolver.js.map +1 -1
- package/build/utils/on-sub-key.js.map +1 -1
- package/build/utils/with-weak-map-cache.js +1 -7
- package/build/utils/with-weak-map-cache.js.map +1 -1
- package/build-module/actions.js.map +1 -1
- package/build-module/batch/create-batch.js +2 -2
- package/build-module/batch/create-batch.js.map +1 -1
- package/build-module/batch/default-processor.js +12 -5
- package/build-module/batch/default-processor.js.map +1 -1
- package/build-module/entities.js.map +1 -1
- package/build-module/entity-provider.js.map +1 -1
- package/build-module/hooks/use-entity-record.js.map +1 -1
- package/build-module/hooks/use-query-select.js.map +1 -1
- package/build-module/hooks/use-resource-permissions.js +82 -0
- package/build-module/hooks/use-resource-permissions.js.map +1 -0
- package/build-module/index.js +3 -0
- package/build-module/index.js.map +1 -1
- package/build-module/queried-data/selectors.js.map +1 -1
- package/build-module/reducer.js +5 -2
- package/build-module/reducer.js.map +1 -1
- package/build-module/resolvers.js +5 -15
- package/build-module/resolvers.js.map +1 -1
- package/build-module/selectors.js +40 -4
- package/build-module/selectors.js.map +1 -1
- package/build-module/utils/forward-resolver.js.map +1 -1
- package/build-module/utils/on-sub-key.js.map +1 -1
- package/build-module/utils/with-weak-map-cache.js +1 -6
- package/build-module/utils/with-weak-map-cache.js.map +1 -1
- package/package.json +11 -11
- package/src/actions.js +389 -372
- package/src/batch/create-batch.js +2 -2
- package/src/batch/default-processor.js +10 -5
- package/src/entities.ts +16 -17
- package/src/entity-provider.js +4 -6
- package/src/entity-types/attachment.ts +4 -3
- package/src/entity-types/comment.ts +4 -3
- package/src/entity-types/entities.ts +5 -2
- package/src/entity-types/index.ts +114 -20
- package/src/entity-types/menu-location.ts +4 -3
- package/src/entity-types/nav-menu-item.ts +4 -3
- package/src/entity-types/nav-menu.ts +3 -3
- package/src/entity-types/page.ts +3 -3
- package/src/entity-types/plugin.ts +3 -3
- package/src/entity-types/post.ts +3 -3
- package/src/entity-types/settings.ts +3 -3
- package/src/entity-types/sidebar.ts +4 -3
- package/src/entity-types/taxonomy.ts +4 -3
- package/src/entity-types/theme.ts +3 -3
- package/src/entity-types/type.ts +3 -3
- package/src/entity-types/user.ts +3 -3
- package/src/entity-types/widget-type.ts +4 -3
- package/src/entity-types/widget.ts +3 -3
- package/src/entity-types/wp-template-part.ts +4 -3
- package/src/entity-types/wp-template.ts +4 -3
- package/src/fetch/test/__experimental-fetch-link-suggestions.js +2 -4
- package/src/hooks/test/use-query-select.js +4 -2
- package/src/hooks/test/use-resource-permissions.js +115 -0
- package/src/hooks/use-entity-record.ts +0 -1
- package/src/hooks/use-query-select.ts +26 -24
- package/src/hooks/use-resource-permissions.ts +120 -0
- package/src/index.js +3 -0
- package/src/locks/test/selectors.js +2 -1
- package/src/queried-data/selectors.js +2 -8
- package/src/reducer.js +9 -2
- package/src/resolvers.js +344 -326
- package/src/selectors.ts +347 -194
- package/src/test/reducer.js +5 -4
- package/src/test/resolvers.js +1 -3
- package/src/test/selectors.js +1 -2
- package/src/utils/forward-resolver.js +6 -5
- package/src/utils/on-sub-key.js +20 -20
- package/src/utils/with-weak-map-cache.js +1 -6
package/src/selectors.ts
CHANGED
|
@@ -18,7 +18,18 @@ import { STORE_NAME } from './name';
|
|
|
18
18
|
import { getQueriedItems } from './queried-data';
|
|
19
19
|
import { DEFAULT_ENTITY_KEY } from './entities';
|
|
20
20
|
import { getNormalizedCommaSeparable, isRawAttribute } from './utils';
|
|
21
|
-
import type {
|
|
21
|
+
import type {
|
|
22
|
+
Context,
|
|
23
|
+
DefaultContextOf,
|
|
24
|
+
EntityRecordOf,
|
|
25
|
+
KeyOf,
|
|
26
|
+
Kind,
|
|
27
|
+
KindOf,
|
|
28
|
+
Name,
|
|
29
|
+
NameOf,
|
|
30
|
+
User,
|
|
31
|
+
WpTemplate,
|
|
32
|
+
} from './entity-types';
|
|
22
33
|
|
|
23
34
|
// This is an incomplete, high-level approximation of the State type.
|
|
24
35
|
// It makes the selectors slightly more safe, but is intended to evolve
|
|
@@ -29,7 +40,7 @@ interface State {
|
|
|
29
40
|
blockPatterns: Array< unknown >;
|
|
30
41
|
blockPatternCategories: Array< unknown >;
|
|
31
42
|
currentGlobalStylesId: string;
|
|
32
|
-
currentTheme:
|
|
43
|
+
currentTheme: string;
|
|
33
44
|
currentUser: User< 'edit' >;
|
|
34
45
|
embedPreviews: Record< string, { html: string } >;
|
|
35
46
|
entities: EntitiesState;
|
|
@@ -41,12 +52,17 @@ interface State {
|
|
|
41
52
|
|
|
42
53
|
interface EntitiesState {
|
|
43
54
|
config: EntityConfig[];
|
|
44
|
-
records: Record<
|
|
55
|
+
records: Record< Kind, Record< Name, EntityState< Kind, Name > > >;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface EntityState< K extends Kind, N extends Name > {
|
|
59
|
+
edits: Record< KeyOf< K, N >, Partial< EntityRecordOf< K, N > > >;
|
|
60
|
+
saving: Record< KeyOf< K, N >, { pending: boolean } >;
|
|
45
61
|
}
|
|
46
62
|
|
|
47
63
|
interface EntityConfig {
|
|
48
|
-
name:
|
|
49
|
-
kind:
|
|
64
|
+
name: Name;
|
|
65
|
+
kind: Kind;
|
|
50
66
|
}
|
|
51
67
|
|
|
52
68
|
interface UndoState extends Array< Object > {
|
|
@@ -55,11 +71,11 @@ interface UndoState extends Array< Object > {
|
|
|
55
71
|
}
|
|
56
72
|
|
|
57
73
|
interface UserState {
|
|
58
|
-
queries: Record< string,
|
|
59
|
-
byId: Record<
|
|
74
|
+
queries: Record< string, GenericRecordKey[] >;
|
|
75
|
+
byId: Record< GenericRecordKey, User< 'edit' > >;
|
|
60
76
|
}
|
|
61
77
|
|
|
62
|
-
type
|
|
78
|
+
type GenericRecordKey = number | string;
|
|
63
79
|
type EntityRecord = any;
|
|
64
80
|
type Optional< T > = T | undefined;
|
|
65
81
|
|
|
@@ -68,15 +84,18 @@ type Optional< T > = T | undefined;
|
|
|
68
84
|
*/
|
|
69
85
|
export type EntityQuery<
|
|
70
86
|
C extends Context,
|
|
71
|
-
|
|
72
|
-
> = Record< string, any > & {
|
|
87
|
+
WithFields extends boolean = true
|
|
88
|
+
> = Omit< Record< string, any >, '_fields' > & {
|
|
73
89
|
context?: C;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
90
|
+
} & ( WithFields extends true
|
|
91
|
+
? {
|
|
92
|
+
/**
|
|
93
|
+
* The requested fields. If specified, the REST API will remove from the response
|
|
94
|
+
* any fields not on that list.
|
|
95
|
+
*/
|
|
96
|
+
_fields: string[];
|
|
97
|
+
}
|
|
98
|
+
: {} );
|
|
80
99
|
|
|
81
100
|
/**
|
|
82
101
|
* Shared reference to an empty object for cases where it is important to avoid
|
|
@@ -97,9 +116,12 @@ const EMPTY_OBJECT = {};
|
|
|
97
116
|
* @return Whether a request is in progress for an embed preview.
|
|
98
117
|
*/
|
|
99
118
|
export const isRequestingEmbedPreview = createRegistrySelector(
|
|
100
|
-
( select ) =>
|
|
101
|
-
|
|
102
|
-
|
|
119
|
+
( select ) =>
|
|
120
|
+
( state: State, url: string ): boolean => {
|
|
121
|
+
return select( STORE_NAME ).isResolving( 'getEmbedPreview', [
|
|
122
|
+
url,
|
|
123
|
+
] );
|
|
124
|
+
}
|
|
103
125
|
);
|
|
104
126
|
|
|
105
127
|
/**
|
|
@@ -168,7 +190,7 @@ export const getUserQueryResults = createSelector(
|
|
|
168
190
|
*
|
|
169
191
|
* @return Array of entities with config matching kind.
|
|
170
192
|
*/
|
|
171
|
-
export function getEntitiesByKind( state: State, kind:
|
|
193
|
+
export function getEntitiesByKind( state: State, kind: Kind ): Array< any > {
|
|
172
194
|
deprecated( "wp.data.select( 'core' ).getEntitiesByKind()", {
|
|
173
195
|
since: '6.0',
|
|
174
196
|
alternative: "wp.data.select( 'core' ).getEntitiesConfig()",
|
|
@@ -184,7 +206,7 @@ export function getEntitiesByKind( state: State, kind: string ): Array< any > {
|
|
|
184
206
|
*
|
|
185
207
|
* @return Array of entities with config matching kind.
|
|
186
208
|
*/
|
|
187
|
-
export function getEntitiesConfig( state: State, kind:
|
|
209
|
+
export function getEntitiesConfig( state: State, kind: Kind ): Array< any > {
|
|
188
210
|
return filter( state.entities.config, { kind } );
|
|
189
211
|
}
|
|
190
212
|
|
|
@@ -198,7 +220,7 @@ export function getEntitiesConfig( state: State, kind: string ): Array< any > {
|
|
|
198
220
|
*
|
|
199
221
|
* @return Entity config
|
|
200
222
|
*/
|
|
201
|
-
export function getEntity( state: State, kind:
|
|
223
|
+
export function getEntity( state: State, kind: Kind, name: Name ): any {
|
|
202
224
|
deprecated( "wp.data.select( 'core' ).getEntity()", {
|
|
203
225
|
since: '6.0',
|
|
204
226
|
alternative: "wp.data.select( 'core' ).getEntityConfig()",
|
|
@@ -215,14 +237,56 @@ export function getEntity( state: State, kind: string, name: string ): any {
|
|
|
215
237
|
*
|
|
216
238
|
* @return Entity config
|
|
217
239
|
*/
|
|
218
|
-
export function getEntityConfig(
|
|
219
|
-
state: State,
|
|
220
|
-
kind: string,
|
|
221
|
-
name: string
|
|
222
|
-
): any {
|
|
240
|
+
export function getEntityConfig( state: State, kind: Kind, name: Name ): any {
|
|
223
241
|
return find( state.entities.config, { kind, name } );
|
|
224
242
|
}
|
|
225
243
|
|
|
244
|
+
/**
|
|
245
|
+
* GetEntityRecord is declared as an *interface*, but it actually describes
|
|
246
|
+
* the specifies the getEntityRecord *function* signature. It may seem unusual,
|
|
247
|
+
* but it's just how TypeScript implements function overloading.
|
|
248
|
+
*
|
|
249
|
+
* More accurately, GetEntityRecord distinguishes between two different signatures
|
|
250
|
+
* the getEntityRecord selector has:
|
|
251
|
+
*
|
|
252
|
+
* 1. When query._fields is not given, the returned type is EntityRecordOf< K, N, C >
|
|
253
|
+
* 2. When query._fields is given, the returned type is Partial<EntityRecordOf< K, N, C >>
|
|
254
|
+
*
|
|
255
|
+
* Unfortunately, due to a TypeScript limitation (https://github.com/microsoft/TypeScript/issues/23132)
|
|
256
|
+
* we can't use a single function signature with a return type such as:
|
|
257
|
+
*
|
|
258
|
+
* Fields extends undefined
|
|
259
|
+
* ? EntityRecordOf< K, N, C >
|
|
260
|
+
* : Partial< EntityRecordOf< K, N, C > >
|
|
261
|
+
*/
|
|
262
|
+
interface GetEntityRecord {
|
|
263
|
+
<
|
|
264
|
+
R extends EntityRecordOf< K, N >,
|
|
265
|
+
C extends Context = DefaultContextOf< R >,
|
|
266
|
+
K extends Kind = KindOf< R >,
|
|
267
|
+
N extends Name = NameOf< R >
|
|
268
|
+
>(
|
|
269
|
+
state: State,
|
|
270
|
+
kind: K,
|
|
271
|
+
name: N,
|
|
272
|
+
key: KeyOf< K, N >,
|
|
273
|
+
query: EntityQuery< C, true >
|
|
274
|
+
): Partial< EntityRecordOf< K, N, C > > | null | undefined;
|
|
275
|
+
|
|
276
|
+
<
|
|
277
|
+
R extends EntityRecordOf< K, N >,
|
|
278
|
+
C extends Context = DefaultContextOf< R >,
|
|
279
|
+
K extends Kind = KindOf< R >,
|
|
280
|
+
N extends Name = NameOf< R >
|
|
281
|
+
>(
|
|
282
|
+
state: State,
|
|
283
|
+
kind: K,
|
|
284
|
+
name: N,
|
|
285
|
+
key: KeyOf< K, N >,
|
|
286
|
+
query?: EntityQuery< C, false >
|
|
287
|
+
): EntityRecordOf< K, N, C > | null | undefined;
|
|
288
|
+
}
|
|
289
|
+
|
|
226
290
|
/**
|
|
227
291
|
* Returns the Entity's record object by key. Returns `null` if the value is not
|
|
228
292
|
* yet received, undefined if the value entity is known to not exist, or the
|
|
@@ -236,14 +300,19 @@ export function getEntityConfig(
|
|
|
236
300
|
*
|
|
237
301
|
* @return Record.
|
|
238
302
|
*/
|
|
239
|
-
export const getEntityRecord = createSelector(
|
|
240
|
-
|
|
303
|
+
export const getEntityRecord: GetEntityRecord = createSelector(
|
|
304
|
+
<
|
|
305
|
+
R extends EntityRecordOf< K, N >,
|
|
306
|
+
C extends Context = DefaultContextOf< R >,
|
|
307
|
+
K extends Kind = KindOf< R >,
|
|
308
|
+
N extends Name = NameOf< R >
|
|
309
|
+
>(
|
|
241
310
|
state: State,
|
|
242
|
-
kind:
|
|
243
|
-
name:
|
|
244
|
-
key:
|
|
245
|
-
query
|
|
246
|
-
)
|
|
311
|
+
kind: K,
|
|
312
|
+
name: N,
|
|
313
|
+
key: KeyOf< R >,
|
|
314
|
+
query
|
|
315
|
+
) => {
|
|
247
316
|
const queriedState = get( state.entities.records, [
|
|
248
317
|
kind,
|
|
249
318
|
name,
|
|
@@ -277,13 +346,7 @@ export const getEntityRecord = createSelector(
|
|
|
277
346
|
|
|
278
347
|
return item;
|
|
279
348
|
},
|
|
280
|
-
(
|
|
281
|
-
state: State,
|
|
282
|
-
kind: string,
|
|
283
|
-
name: string,
|
|
284
|
-
recordId: RecordKey,
|
|
285
|
-
query?: EntityQuery< any >
|
|
286
|
-
) => {
|
|
349
|
+
( state: State, kind, name, recordId, query ) => {
|
|
287
350
|
const context = query?.context ?? 'default';
|
|
288
351
|
return [
|
|
289
352
|
get( state.entities.records, [
|
|
@@ -316,12 +379,10 @@ export const getEntityRecord = createSelector(
|
|
|
316
379
|
*
|
|
317
380
|
* @return Record.
|
|
318
381
|
*/
|
|
319
|
-
export function __experimentalGetEntityRecordNoResolver
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
key: RecordKey
|
|
324
|
-
): EntityRecord | null {
|
|
382
|
+
export function __experimentalGetEntityRecordNoResolver<
|
|
383
|
+
K extends Kind,
|
|
384
|
+
N extends Name
|
|
385
|
+
>( state: State, kind: K, name: N, key: KeyOf< K, N > ) {
|
|
325
386
|
return getEntityRecord( state, kind, name, key );
|
|
326
387
|
}
|
|
327
388
|
|
|
@@ -337,11 +398,11 @@ export function __experimentalGetEntityRecordNoResolver(
|
|
|
337
398
|
* @return Object with the entity's raw attributes.
|
|
338
399
|
*/
|
|
339
400
|
export const getRawEntityRecord = createSelector(
|
|
340
|
-
(
|
|
401
|
+
< K extends Kind, N extends Name >(
|
|
341
402
|
state: State,
|
|
342
|
-
kind:
|
|
343
|
-
name:
|
|
344
|
-
key:
|
|
403
|
+
kind: K,
|
|
404
|
+
name: N,
|
|
405
|
+
key: KeyOf< K, N >
|
|
345
406
|
): EntityRecord | undefined => {
|
|
346
407
|
const record = getEntityRecord( state, kind, name, key );
|
|
347
408
|
return (
|
|
@@ -367,9 +428,9 @@ export const getRawEntityRecord = createSelector(
|
|
|
367
428
|
},
|
|
368
429
|
(
|
|
369
430
|
state: State,
|
|
370
|
-
kind:
|
|
371
|
-
name:
|
|
372
|
-
recordId:
|
|
431
|
+
kind: Kind,
|
|
432
|
+
name: Name,
|
|
433
|
+
recordId: GenericRecordKey,
|
|
373
434
|
query?: EntityQuery< any >
|
|
374
435
|
) => {
|
|
375
436
|
const context = query?.context ?? 'default';
|
|
@@ -406,15 +467,59 @@ export const getRawEntityRecord = createSelector(
|
|
|
406
467
|
*
|
|
407
468
|
* @return Whether entity records have been received.
|
|
408
469
|
*/
|
|
409
|
-
export function hasEntityRecords
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
): boolean {
|
|
470
|
+
export function hasEntityRecords<
|
|
471
|
+
R extends EntityRecordOf< K, N >,
|
|
472
|
+
C extends Context = DefaultContextOf< R >,
|
|
473
|
+
K extends Kind = KindOf< R >,
|
|
474
|
+
N extends Name = NameOf< R >
|
|
475
|
+
>( state: State, kind: K, name: N, query?: EntityQuery< C > ): boolean {
|
|
415
476
|
return Array.isArray( getEntityRecords( state, kind, name, query ) );
|
|
416
477
|
}
|
|
417
478
|
|
|
479
|
+
/**
|
|
480
|
+
* GetEntityRecord is declared as an *interface*, but it actually describes
|
|
481
|
+
* the specifies the getEntityRecord *function* signature. It may seem unusual,
|
|
482
|
+
* but it's just how TypeScript implements function overloading.
|
|
483
|
+
*
|
|
484
|
+
* More accurately, GetEntityRecord distinguishes between two different signatures
|
|
485
|
+
* the getEntityRecord selector has:
|
|
486
|
+
*
|
|
487
|
+
* 1. When query._fields is not given, the returned type is EntityRecordOf< K, N, C >[]
|
|
488
|
+
* 2. When query._fields is given, the returned type is Partial<EntityRecordOf< K, N, C >>[]
|
|
489
|
+
*
|
|
490
|
+
* Unfortunately, due to a TypeScript limitation (https://github.com/microsoft/TypeScript/issues/23132)
|
|
491
|
+
* we can't use a single function signature with a return type such as:
|
|
492
|
+
*
|
|
493
|
+
* Fields extends undefined
|
|
494
|
+
* ? EntityRecordOf< K, N, C >[]
|
|
495
|
+
* : Partial< EntityRecordOf< K, N, C > >[]
|
|
496
|
+
*/
|
|
497
|
+
interface GetEntityRecords {
|
|
498
|
+
<
|
|
499
|
+
R extends EntityRecordOf< K, N >,
|
|
500
|
+
C extends Context = DefaultContextOf< R >,
|
|
501
|
+
K extends Kind = KindOf< R >,
|
|
502
|
+
N extends Name = NameOf< R >
|
|
503
|
+
>(
|
|
504
|
+
state: State,
|
|
505
|
+
kind: K,
|
|
506
|
+
name: N,
|
|
507
|
+
query: EntityQuery< C, true >
|
|
508
|
+
): Partial< EntityRecordOf< K, N, C > >[] | null | undefined;
|
|
509
|
+
|
|
510
|
+
<
|
|
511
|
+
R extends EntityRecordOf< K, N >,
|
|
512
|
+
C extends Context = DefaultContextOf< R >,
|
|
513
|
+
K extends Kind = KindOf< R >,
|
|
514
|
+
N extends Name = NameOf< R >
|
|
515
|
+
>(
|
|
516
|
+
state: State,
|
|
517
|
+
kind: K,
|
|
518
|
+
name: N,
|
|
519
|
+
query?: EntityQuery< C, false >
|
|
520
|
+
): EntityRecordOf< K, N, C >[] | null | undefined;
|
|
521
|
+
}
|
|
522
|
+
|
|
418
523
|
/**
|
|
419
524
|
* Returns the Entity's records.
|
|
420
525
|
*
|
|
@@ -425,12 +530,17 @@ export function hasEntityRecords(
|
|
|
425
530
|
*
|
|
426
531
|
* @return Records.
|
|
427
532
|
*/
|
|
428
|
-
export
|
|
533
|
+
export const getEntityRecords: GetEntityRecords = <
|
|
534
|
+
R extends EntityRecordOf< K, N >,
|
|
535
|
+
C extends Context = DefaultContextOf< R >,
|
|
536
|
+
K extends Kind = KindOf< R >,
|
|
537
|
+
N extends Name = NameOf< R >
|
|
538
|
+
>(
|
|
429
539
|
state: State,
|
|
430
|
-
kind:
|
|
431
|
-
name:
|
|
432
|
-
query
|
|
433
|
-
)
|
|
540
|
+
kind: K,
|
|
541
|
+
name: N,
|
|
542
|
+
query
|
|
543
|
+
) => {
|
|
434
544
|
// Queried data state is prepopulated for all known entities. If this is not
|
|
435
545
|
// assigned for the given parameters, then it is known to not exist.
|
|
436
546
|
const queriedState = get( state.entities.records, [
|
|
@@ -442,13 +552,13 @@ export function getEntityRecords(
|
|
|
442
552
|
return null;
|
|
443
553
|
}
|
|
444
554
|
return getQueriedItems( queriedState, query );
|
|
445
|
-
}
|
|
555
|
+
};
|
|
446
556
|
|
|
447
557
|
type DirtyEntityRecord = {
|
|
448
558
|
title: string;
|
|
449
|
-
key:
|
|
450
|
-
name:
|
|
451
|
-
kind:
|
|
559
|
+
key: GenericRecordKey;
|
|
560
|
+
name: Name;
|
|
561
|
+
kind: Kind;
|
|
452
562
|
};
|
|
453
563
|
/**
|
|
454
564
|
* Returns the list of dirty entity records.
|
|
@@ -462,44 +572,65 @@ export const __experimentalGetDirtyEntityRecords = createSelector(
|
|
|
462
572
|
const {
|
|
463
573
|
entities: { records },
|
|
464
574
|
} = state;
|
|
465
|
-
const dirtyRecords = [];
|
|
466
|
-
Object.keys( records )
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
575
|
+
const dirtyRecords: DirtyEntityRecord[] = [];
|
|
576
|
+
( Object.keys( records ) as Kind[] ).forEach(
|
|
577
|
+
< K extends Kind >( kind: K ) => {
|
|
578
|
+
( Object.keys( records[ kind ] ) as Name[] ).forEach(
|
|
579
|
+
< N extends Name >( name: N ) => {
|
|
580
|
+
const primaryKeys = (
|
|
581
|
+
Object.keys(
|
|
582
|
+
records[ kind ][ name ].edits
|
|
583
|
+
) as KeyOf< K, N >[]
|
|
584
|
+
).filter(
|
|
585
|
+
( primaryKey ) =>
|
|
586
|
+
// The entity record must exist (not be deleted),
|
|
587
|
+
// and it must have edits.
|
|
588
|
+
getEntityRecord(
|
|
589
|
+
state,
|
|
590
|
+
kind,
|
|
591
|
+
name,
|
|
592
|
+
primaryKey
|
|
593
|
+
) &&
|
|
594
|
+
hasEditsForEntityRecord(
|
|
595
|
+
state,
|
|
596
|
+
kind,
|
|
597
|
+
name,
|
|
598
|
+
primaryKey
|
|
599
|
+
)
|
|
486
600
|
);
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
601
|
+
|
|
602
|
+
if ( primaryKeys.length ) {
|
|
603
|
+
const entityConfig = getEntityConfig(
|
|
604
|
+
state,
|
|
605
|
+
kind,
|
|
606
|
+
name
|
|
607
|
+
);
|
|
608
|
+
primaryKeys.forEach( ( primaryKey ) => {
|
|
609
|
+
const entityRecord = getEditedEntityRecord(
|
|
610
|
+
state,
|
|
611
|
+
kind,
|
|
612
|
+
name,
|
|
613
|
+
primaryKey
|
|
614
|
+
);
|
|
615
|
+
dirtyRecords.push( {
|
|
616
|
+
// We avoid using primaryKey because it's transformed into a string
|
|
617
|
+
// when it's used as an object key.
|
|
618
|
+
key: entityRecord[
|
|
619
|
+
entityConfig.key || DEFAULT_ENTITY_KEY
|
|
620
|
+
],
|
|
621
|
+
title:
|
|
622
|
+
entityConfig?.getTitle?.(
|
|
623
|
+
entityRecord
|
|
624
|
+
) || '',
|
|
625
|
+
name,
|
|
626
|
+
kind,
|
|
627
|
+
} );
|
|
628
|
+
} );
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
);
|
|
503
634
|
|
|
504
635
|
return dirtyRecords;
|
|
505
636
|
},
|
|
@@ -518,40 +649,56 @@ export const __experimentalGetEntitiesBeingSaved = createSelector(
|
|
|
518
649
|
const {
|
|
519
650
|
entities: { records },
|
|
520
651
|
} = state;
|
|
521
|
-
const recordsBeingSaved = [];
|
|
522
|
-
Object.keys( records )
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
primaryKey
|
|
652
|
+
const recordsBeingSaved: DirtyEntityRecord[] = [];
|
|
653
|
+
( Object.keys( records ) as Kind[] ).forEach(
|
|
654
|
+
< K extends Kind >( kind: K ) => {
|
|
655
|
+
( Object.keys( records[ kind ] ) as Name[] ).forEach(
|
|
656
|
+
< N extends Name >( name: N ) => {
|
|
657
|
+
const primaryKeys = (
|
|
658
|
+
Object.keys(
|
|
659
|
+
records[ kind ][ name ].saving
|
|
660
|
+
) as KeyOf< K, N >[]
|
|
661
|
+
).filter( ( primaryKey ) =>
|
|
662
|
+
isSavingEntityRecord(
|
|
663
|
+
state,
|
|
664
|
+
kind,
|
|
665
|
+
name,
|
|
666
|
+
primaryKey
|
|
667
|
+
)
|
|
538
668
|
);
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
669
|
+
|
|
670
|
+
if ( primaryKeys.length ) {
|
|
671
|
+
const entityConfig = getEntityConfig(
|
|
672
|
+
state,
|
|
673
|
+
kind,
|
|
674
|
+
name
|
|
675
|
+
);
|
|
676
|
+
primaryKeys.forEach( ( primaryKey ) => {
|
|
677
|
+
const entityRecord = getEditedEntityRecord(
|
|
678
|
+
state,
|
|
679
|
+
kind,
|
|
680
|
+
name,
|
|
681
|
+
primaryKey
|
|
682
|
+
);
|
|
683
|
+
recordsBeingSaved.push( {
|
|
684
|
+
// We avoid using primaryKey because it's transformed into a string
|
|
685
|
+
// when it's used as an object key.
|
|
686
|
+
key: entityRecord[
|
|
687
|
+
entityConfig.key || DEFAULT_ENTITY_KEY
|
|
688
|
+
],
|
|
689
|
+
title:
|
|
690
|
+
entityConfig?.getTitle?.(
|
|
691
|
+
entityRecord
|
|
692
|
+
) || '',
|
|
693
|
+
name,
|
|
694
|
+
kind,
|
|
695
|
+
} );
|
|
696
|
+
} );
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
);
|
|
700
|
+
}
|
|
701
|
+
);
|
|
555
702
|
return recordsBeingSaved;
|
|
556
703
|
},
|
|
557
704
|
( state ) => [ state.entities.records ]
|
|
@@ -567,13 +714,18 @@ export const __experimentalGetEntitiesBeingSaved = createSelector(
|
|
|
567
714
|
*
|
|
568
715
|
* @return The entity record's edits.
|
|
569
716
|
*/
|
|
570
|
-
export function getEntityRecordEdits(
|
|
717
|
+
export function getEntityRecordEdits< K extends Kind, N extends Name >(
|
|
571
718
|
state: State,
|
|
572
|
-
kind:
|
|
573
|
-
name:
|
|
574
|
-
recordId:
|
|
719
|
+
kind: K,
|
|
720
|
+
name: N,
|
|
721
|
+
recordId: KeyOf< K, N >
|
|
575
722
|
): Optional< any > {
|
|
576
|
-
return get( state.entities.records, [
|
|
723
|
+
return get( state.entities.records, [
|
|
724
|
+
kind,
|
|
725
|
+
name,
|
|
726
|
+
'edits',
|
|
727
|
+
recordId as string | number,
|
|
728
|
+
] );
|
|
577
729
|
}
|
|
578
730
|
|
|
579
731
|
/**
|
|
@@ -591,11 +743,11 @@ export function getEntityRecordEdits(
|
|
|
591
743
|
* @return The entity record's non transient edits.
|
|
592
744
|
*/
|
|
593
745
|
export const getEntityRecordNonTransientEdits = createSelector(
|
|
594
|
-
(
|
|
746
|
+
< K extends Kind, N extends Name >(
|
|
595
747
|
state: State,
|
|
596
|
-
kind:
|
|
597
|
-
name:
|
|
598
|
-
recordId:
|
|
748
|
+
kind: K,
|
|
749
|
+
name: N,
|
|
750
|
+
recordId: KeyOf< K, N >
|
|
599
751
|
): Optional< any > => {
|
|
600
752
|
const { transientEdits } = getEntityConfig( state, kind, name ) || {};
|
|
601
753
|
const edits = getEntityRecordEdits( state, kind, name, recordId ) || {};
|
|
@@ -609,7 +761,7 @@ export const getEntityRecordNonTransientEdits = createSelector(
|
|
|
609
761
|
return acc;
|
|
610
762
|
}, {} );
|
|
611
763
|
},
|
|
612
|
-
( state: State, kind:
|
|
764
|
+
( state: State, kind: Kind, name: Name, recordId: GenericRecordKey ) => [
|
|
613
765
|
state.entities.config,
|
|
614
766
|
get( state.entities.records, [ kind, name, 'edits', recordId ] ),
|
|
615
767
|
]
|
|
@@ -626,11 +778,11 @@ export const getEntityRecordNonTransientEdits = createSelector(
|
|
|
626
778
|
*
|
|
627
779
|
* @return Whether the entity record has edits or not.
|
|
628
780
|
*/
|
|
629
|
-
export function hasEditsForEntityRecord(
|
|
781
|
+
export function hasEditsForEntityRecord< K extends Kind, N extends Name >(
|
|
630
782
|
state: State,
|
|
631
|
-
kind:
|
|
632
|
-
name:
|
|
633
|
-
recordId:
|
|
783
|
+
kind: K,
|
|
784
|
+
name: N,
|
|
785
|
+
recordId: KeyOf< K, N >
|
|
634
786
|
): boolean {
|
|
635
787
|
return (
|
|
636
788
|
isSavingEntityRecord( state, kind, name, recordId ) ||
|
|
@@ -651,20 +803,20 @@ export function hasEditsForEntityRecord(
|
|
|
651
803
|
* @return The entity record, merged with its edits.
|
|
652
804
|
*/
|
|
653
805
|
export const getEditedEntityRecord = createSelector(
|
|
654
|
-
(
|
|
806
|
+
< K extends Kind, N extends Name >(
|
|
655
807
|
state: State,
|
|
656
|
-
kind:
|
|
657
|
-
name:
|
|
658
|
-
recordId:
|
|
808
|
+
kind: K,
|
|
809
|
+
name: N,
|
|
810
|
+
recordId: KeyOf< K, N >
|
|
659
811
|
): EntityRecord | undefined => ( {
|
|
660
812
|
...getRawEntityRecord( state, kind, name, recordId ),
|
|
661
813
|
...getEntityRecordEdits( state, kind, name, recordId ),
|
|
662
814
|
} ),
|
|
663
815
|
(
|
|
664
816
|
state: State,
|
|
665
|
-
kind:
|
|
666
|
-
name:
|
|
667
|
-
recordId:
|
|
817
|
+
kind: Kind,
|
|
818
|
+
name: Name,
|
|
819
|
+
recordId: GenericRecordKey,
|
|
668
820
|
query?: EntityQuery< any >
|
|
669
821
|
) => {
|
|
670
822
|
const context = query?.context ?? 'default';
|
|
@@ -703,9 +855,9 @@ export const getEditedEntityRecord = createSelector(
|
|
|
703
855
|
*/
|
|
704
856
|
export function isAutosavingEntityRecord(
|
|
705
857
|
state: State,
|
|
706
|
-
kind:
|
|
707
|
-
name:
|
|
708
|
-
recordId:
|
|
858
|
+
kind: Kind,
|
|
859
|
+
name: Name,
|
|
860
|
+
recordId: GenericRecordKey
|
|
709
861
|
): boolean {
|
|
710
862
|
const { pending, isAutosave } = get(
|
|
711
863
|
state.entities.records,
|
|
@@ -725,15 +877,15 @@ export function isAutosavingEntityRecord(
|
|
|
725
877
|
*
|
|
726
878
|
* @return Whether the entity record is saving or not.
|
|
727
879
|
*/
|
|
728
|
-
export function isSavingEntityRecord(
|
|
880
|
+
export function isSavingEntityRecord< K extends Kind, N extends Name >(
|
|
729
881
|
state: State,
|
|
730
|
-
kind:
|
|
731
|
-
name:
|
|
732
|
-
recordId:
|
|
882
|
+
kind: K,
|
|
883
|
+
name: N,
|
|
884
|
+
recordId: KeyOf< K, N >
|
|
733
885
|
): boolean {
|
|
734
886
|
return get(
|
|
735
887
|
state.entities.records,
|
|
736
|
-
[ kind, name, 'saving', recordId, 'pending' ],
|
|
888
|
+
[ kind, name, 'saving', recordId as GenericRecordKey, 'pending' ],
|
|
737
889
|
false
|
|
738
890
|
);
|
|
739
891
|
}
|
|
@@ -750,9 +902,9 @@ export function isSavingEntityRecord(
|
|
|
750
902
|
*/
|
|
751
903
|
export function isDeletingEntityRecord(
|
|
752
904
|
state: State,
|
|
753
|
-
kind:
|
|
754
|
-
name:
|
|
755
|
-
recordId:
|
|
905
|
+
kind: Kind,
|
|
906
|
+
name: Name,
|
|
907
|
+
recordId: GenericRecordKey
|
|
756
908
|
): boolean {
|
|
757
909
|
return get(
|
|
758
910
|
state.entities.records,
|
|
@@ -773,9 +925,9 @@ export function isDeletingEntityRecord(
|
|
|
773
925
|
*/
|
|
774
926
|
export function getLastEntitySaveError(
|
|
775
927
|
state: State,
|
|
776
|
-
kind:
|
|
777
|
-
name:
|
|
778
|
-
recordId:
|
|
928
|
+
kind: Kind,
|
|
929
|
+
name: Name,
|
|
930
|
+
recordId: GenericRecordKey
|
|
779
931
|
): any {
|
|
780
932
|
return get( state.entities.records, [
|
|
781
933
|
kind,
|
|
@@ -798,9 +950,9 @@ export function getLastEntitySaveError(
|
|
|
798
950
|
*/
|
|
799
951
|
export function getLastEntityDeleteError(
|
|
800
952
|
state: State,
|
|
801
|
-
kind:
|
|
802
|
-
name:
|
|
803
|
-
recordId:
|
|
953
|
+
kind: Kind,
|
|
954
|
+
name: Name,
|
|
955
|
+
recordId: GenericRecordKey
|
|
804
956
|
): any {
|
|
805
957
|
return get( state.entities.records, [
|
|
806
958
|
kind,
|
|
@@ -961,7 +1113,7 @@ export function canUser(
|
|
|
961
1113
|
state: State,
|
|
962
1114
|
action: string,
|
|
963
1115
|
resource: string,
|
|
964
|
-
id?:
|
|
1116
|
+
id?: GenericRecordKey
|
|
965
1117
|
): boolean | undefined {
|
|
966
1118
|
const key = compact( [ action, resource, id ] ).join( '/' );
|
|
967
1119
|
return get( state, [ 'userPermissions', key ] );
|
|
@@ -984,9 +1136,9 @@ export function canUser(
|
|
|
984
1136
|
*/
|
|
985
1137
|
export function canUserEditEntityRecord(
|
|
986
1138
|
state: State,
|
|
987
|
-
kind:
|
|
988
|
-
name:
|
|
989
|
-
recordId:
|
|
1139
|
+
kind: Kind,
|
|
1140
|
+
name: Name,
|
|
1141
|
+
recordId: GenericRecordKey
|
|
990
1142
|
): boolean | undefined {
|
|
991
1143
|
const entityConfig = getEntityConfig( state, kind, name );
|
|
992
1144
|
if ( ! entityConfig ) {
|
|
@@ -1012,7 +1164,7 @@ export function canUserEditEntityRecord(
|
|
|
1012
1164
|
export function getAutosaves(
|
|
1013
1165
|
state: State,
|
|
1014
1166
|
postType: string,
|
|
1015
|
-
postId:
|
|
1167
|
+
postId: GenericRecordKey
|
|
1016
1168
|
): Array< any > | undefined {
|
|
1017
1169
|
return state.autosaves[ postId ];
|
|
1018
1170
|
}
|
|
@@ -1030,8 +1182,8 @@ export function getAutosaves(
|
|
|
1030
1182
|
export function getAutosave(
|
|
1031
1183
|
state: State,
|
|
1032
1184
|
postType: string,
|
|
1033
|
-
postId:
|
|
1034
|
-
authorId:
|
|
1185
|
+
postId: GenericRecordKey,
|
|
1186
|
+
authorId: GenericRecordKey
|
|
1035
1187
|
): EntityRecord | undefined {
|
|
1036
1188
|
if ( authorId === undefined ) {
|
|
1037
1189
|
return;
|
|
@@ -1051,16 +1203,17 @@ export function getAutosave(
|
|
|
1051
1203
|
* @return True if the REST request was completed. False otherwise.
|
|
1052
1204
|
*/
|
|
1053
1205
|
export const hasFetchedAutosaves = createRegistrySelector(
|
|
1054
|
-
( select ) =>
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1206
|
+
( select ) =>
|
|
1207
|
+
(
|
|
1208
|
+
state: State,
|
|
1209
|
+
postType: string,
|
|
1210
|
+
postId: GenericRecordKey
|
|
1211
|
+
): boolean => {
|
|
1212
|
+
return select( STORE_NAME ).hasFinishedResolution( 'getAutosaves', [
|
|
1213
|
+
postType,
|
|
1214
|
+
postId,
|
|
1215
|
+
] );
|
|
1216
|
+
}
|
|
1064
1217
|
);
|
|
1065
1218
|
|
|
1066
1219
|
/**
|