@wordpress/core-data 4.2.0 → 4.4.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 +8 -0
- package/README.md +68 -11
- package/build/actions.js +61 -41
- package/build/actions.js.map +1 -1
- package/build/batch/default-processor.js +1 -1
- package/build/batch/default-processor.js.map +1 -1
- package/build/entities.js +36 -23
- package/build/entities.js.map +1 -1
- package/build/entity-provider.js +46 -44
- package/build/entity-provider.js.map +1 -1
- package/build/entity-types/{base-entity-types.js → base-entity-records.js} +9 -9
- package/build/entity-types/base-entity-records.js.map +1 -0
- package/build/fetch/__experimental-fetch-link-suggestions.js +48 -11
- package/build/fetch/__experimental-fetch-link-suggestions.js.map +1 -1
- package/build/fetch/__experimental-fetch-url-data.js +1 -1
- package/build/fetch/__experimental-fetch-url-data.js.map +1 -1
- package/build/hooks/use-entity-record.js +15 -5
- package/build/hooks/use-entity-record.js.map +1 -1
- package/build/hooks/use-entity-records.js +14 -2
- package/build/hooks/use-entity-records.js.map +1 -1
- package/build/hooks/use-query-select.js.map +1 -1
- package/build/index.js +9 -21
- package/build/index.js.map +1 -1
- package/build/queried-data/actions.js +4 -4
- package/build/queried-data/actions.js.map +1 -1
- package/build/queried-data/get-query-parts.js +7 -3
- package/build/queried-data/get-query-parts.js.map +1 -1
- package/build/queried-data/reducer.js +8 -6
- package/build/queried-data/reducer.js.map +1 -1
- package/build/reducer.js +77 -25
- package/build/reducer.js.map +1 -1
- package/build/resolvers.js +48 -24
- package/build/resolvers.js.map +1 -1
- package/build/selectors.js +122 -55
- package/build/selectors.js.map +1 -1
- package/build/types.js +6 -0
- package/build/types.js.map +1 -0
- package/build/utils/conservative-map-item.js +1 -1
- package/build/utils/conservative-map-item.js.map +1 -1
- package/build/utils/if-matching-action.js +4 -2
- package/build/utils/if-matching-action.js.map +1 -1
- package/build/utils/is-raw-attribute.js +1 -1
- package/build/utils/is-raw-attribute.js.map +1 -1
- package/build/utils/on-sub-key.js +3 -1
- package/build/utils/on-sub-key.js.map +1 -1
- package/build/utils/replace-action.js +4 -2
- package/build/utils/replace-action.js.map +1 -1
- package/build-module/actions.js +62 -42
- package/build-module/actions.js.map +1 -1
- package/build-module/batch/default-processor.js +1 -1
- package/build-module/batch/default-processor.js.map +1 -1
- package/build-module/entities.js +32 -19
- package/build-module/entities.js.map +1 -1
- package/build-module/entity-provider.js +47 -45
- package/build-module/entity-provider.js.map +1 -1
- package/build-module/entity-types/{base-entity-types.js → base-entity-records.js} +7 -7
- package/build-module/entity-types/base-entity-records.js.map +1 -0
- package/build-module/fetch/__experimental-fetch-link-suggestions.js +48 -11
- package/build-module/fetch/__experimental-fetch-link-suggestions.js.map +1 -1
- package/build-module/fetch/__experimental-fetch-url-data.js +1 -1
- package/build-module/fetch/__experimental-fetch-url-data.js.map +1 -1
- package/build-module/hooks/use-entity-record.js +15 -5
- package/build-module/hooks/use-entity-record.js.map +1 -1
- package/build-module/hooks/use-entity-records.js +14 -2
- package/build-module/hooks/use-entity-records.js.map +1 -1
- package/build-module/hooks/use-query-select.js.map +1 -1
- package/build-module/index.js +10 -22
- package/build-module/index.js.map +1 -1
- package/build-module/queried-data/actions.js +4 -4
- package/build-module/queried-data/actions.js.map +1 -1
- package/build-module/queried-data/get-query-parts.js +7 -3
- package/build-module/queried-data/get-query-parts.js.map +1 -1
- package/build-module/queried-data/reducer.js +8 -6
- package/build-module/queried-data/reducer.js.map +1 -1
- package/build-module/reducer.js +75 -26
- package/build-module/reducer.js.map +1 -1
- package/build-module/resolvers.js +42 -24
- package/build-module/resolvers.js.map +1 -1
- package/build-module/selectors.js +114 -55
- package/build-module/selectors.js.map +1 -1
- package/build-module/types.js +2 -0
- package/build-module/types.js.map +1 -0
- package/build-module/utils/conservative-map-item.js +1 -1
- package/build-module/utils/conservative-map-item.js.map +1 -1
- package/build-module/utils/if-matching-action.js +4 -2
- package/build-module/utils/if-matching-action.js.map +1 -1
- package/build-module/utils/is-raw-attribute.js +1 -1
- package/build-module/utils/is-raw-attribute.js.map +1 -1
- package/build-module/utils/on-sub-key.js +3 -1
- package/build-module/utils/on-sub-key.js.map +1 -1
- package/build-module/utils/replace-action.js +4 -2
- package/build-module/utils/replace-action.js.map +1 -1
- package/package.json +11 -11
- package/src/actions.js +62 -42
- package/src/batch/default-processor.js +1 -0
- package/src/{entities.js → entities.ts} +50 -21
- package/src/entity-provider.js +50 -44
- package/src/entity-types/attachment.ts +5 -5
- package/src/entity-types/{base-entity-types.ts → base-entity-records.ts} +5 -5
- package/src/entity-types/comment.ts +5 -5
- package/src/entity-types/helpers.ts +1 -1
- package/src/entity-types/index.ts +4 -4
- package/src/entity-types/menu-location.ts +5 -5
- package/src/entity-types/nav-menu-item.ts +10 -5
- package/src/entity-types/nav-menu.ts +5 -5
- package/src/entity-types/navigation-area.ts +5 -5
- package/src/entity-types/page.ts +5 -5
- package/src/entity-types/plugin.ts +10 -5
- package/src/entity-types/post.ts +5 -5
- package/src/entity-types/settings.ts +10 -5
- package/src/entity-types/sidebar.ts +6 -7
- package/src/entity-types/taxonomy.ts +5 -5
- package/src/entity-types/theme.ts +5 -5
- package/src/entity-types/type.ts +5 -5
- package/src/entity-types/user.ts +10 -5
- package/src/entity-types/widget-type.ts +5 -5
- package/src/entity-types/widget.ts +5 -5
- package/src/entity-types/wp-template-part.ts +5 -5
- package/src/entity-types/wp-template.ts +5 -5
- package/src/fetch/__experimental-fetch-link-suggestions.js +56 -20
- package/src/fetch/__experimental-fetch-url-data.js +1 -0
- package/src/fetch/test/__experimental-fetch-link-suggestions.js +39 -1
- package/src/hooks/use-entity-record.ts +19 -8
- package/src/hooks/use-entity-records.ts +23 -6
- package/src/hooks/use-query-select.ts +12 -7
- package/src/index.js +10 -15
- package/src/locks/test/selectors.js +4 -4
- package/src/queried-data/actions.js +4 -4
- package/src/queried-data/get-query-parts.js +5 -5
- package/src/queried-data/reducer.js +6 -6
- package/src/reducer.js +67 -24
- package/src/resolvers.js +39 -30
- package/src/{selectors.js → selectors.ts} +118 -57
- package/src/test/actions.js +138 -33
- package/src/test/entities.js +11 -11
- package/src/test/reducer.js +4 -4
- package/src/test/resolvers.js +5 -5
- package/src/test/selectors.js +22 -22
- package/src/types.ts +3 -0
- package/src/utils/conservative-map-item.js +1 -1
- package/src/utils/if-matching-action.js +4 -2
- package/src/utils/is-raw-attribute.js +1 -1
- package/src/utils/on-sub-key.js +3 -1
- package/src/utils/replace-action.js +4 -2
- package/src/utils/test/is-raw-attribute.js +4 -4
- package/build/entity-types/base-entity-types.js.map +0 -1
- package/build-module/entity-types/base-entity-types.js.map +0 -1
package/src/entity-types/type.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Internal dependencies
|
|
3
3
|
*/
|
|
4
|
-
import { Context, ContextualField, OmitNevers } from './helpers';
|
|
4
|
+
import type { Context, ContextualField, OmitNevers } from './helpers';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import type { BaseEntityRecords as _BaseEntityRecords } from './base-entity-records';
|
|
7
7
|
|
|
8
|
-
declare module './base-entity-
|
|
9
|
-
export namespace
|
|
8
|
+
declare module './base-entity-records' {
|
|
9
|
+
export namespace BaseEntityRecords {
|
|
10
10
|
export interface Type< C extends Context > {
|
|
11
11
|
/**
|
|
12
12
|
* All capabilities used by the post type.
|
|
@@ -76,5 +76,5 @@ declare module './base-entity-types' {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
export type Type< C extends Context > = OmitNevers<
|
|
79
|
-
|
|
79
|
+
_BaseEntityRecords.Type< C >
|
|
80
80
|
>;
|
package/src/entity-types/user.ts
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Internal dependencies
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import type {
|
|
5
|
+
AvatarUrls,
|
|
6
|
+
Context,
|
|
7
|
+
ContextualField,
|
|
8
|
+
OmitNevers,
|
|
9
|
+
} from './helpers';
|
|
5
10
|
|
|
6
|
-
import {
|
|
11
|
+
import type { BaseEntityRecords as _BaseEntityRecords } from './base-entity-records';
|
|
7
12
|
|
|
8
|
-
declare module './base-entity-
|
|
9
|
-
export namespace
|
|
13
|
+
declare module './base-entity-records' {
|
|
14
|
+
export namespace BaseEntityRecords {
|
|
10
15
|
export interface User< C extends Context > {
|
|
11
16
|
/**
|
|
12
17
|
* Unique identifier for the user.
|
|
@@ -105,5 +110,5 @@ declare module './base-entity-types' {
|
|
|
105
110
|
}
|
|
106
111
|
|
|
107
112
|
export type User< C extends Context > = OmitNevers<
|
|
108
|
-
|
|
113
|
+
_BaseEntityRecords.User< C >
|
|
109
114
|
>;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Internal dependencies
|
|
3
3
|
*/
|
|
4
|
-
import { Context, OmitNevers } from './helpers';
|
|
4
|
+
import type { Context, OmitNevers } from './helpers';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import type { BaseEntityRecords as _BaseEntityRecords } from './base-entity-records';
|
|
7
7
|
|
|
8
|
-
declare module './base-entity-
|
|
9
|
-
export namespace
|
|
8
|
+
declare module './base-entity-records' {
|
|
9
|
+
export namespace BaseEntityRecords {
|
|
10
10
|
export interface WidgetType< C extends Context > {
|
|
11
11
|
/**
|
|
12
12
|
* Unique slug identifying the widget type.
|
|
@@ -33,5 +33,5 @@ declare module './base-entity-types' {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
export type WidgetType< C extends Context > = OmitNevers<
|
|
36
|
-
|
|
36
|
+
_BaseEntityRecords.WidgetType< C >
|
|
37
37
|
>;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Internal dependencies
|
|
3
3
|
*/
|
|
4
|
-
import { Context, ContextualField, OmitNevers } from './helpers';
|
|
4
|
+
import type { Context, ContextualField, OmitNevers } from './helpers';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import type { BaseEntityRecords as _BaseEntityRecords } from './base-entity-records';
|
|
7
7
|
|
|
8
|
-
declare module './base-entity-
|
|
9
|
-
export namespace
|
|
8
|
+
declare module './base-entity-records' {
|
|
9
|
+
export namespace BaseEntityRecords {
|
|
10
10
|
export interface Widget< C extends Context > {
|
|
11
11
|
/**
|
|
12
12
|
* Unique identifier for the widget.
|
|
@@ -60,5 +60,5 @@ declare module './base-entity-types' {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
export type Widget< C extends Context > = OmitNevers<
|
|
63
|
-
|
|
63
|
+
_BaseEntityRecords.Widget< C >
|
|
64
64
|
>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Internal dependencies
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import type {
|
|
5
5
|
Context,
|
|
6
6
|
PostStatus,
|
|
7
7
|
RenderedText,
|
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
ContextualField,
|
|
10
10
|
} from './helpers';
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import type { BaseEntityRecords as _BaseEntityRecords } from './base-entity-records';
|
|
13
13
|
|
|
14
|
-
declare module './base-entity-
|
|
15
|
-
export namespace
|
|
14
|
+
declare module './base-entity-records' {
|
|
15
|
+
export namespace BaseEntityRecords {
|
|
16
16
|
export interface WpTemplatePart< C extends Context > {
|
|
17
17
|
/**
|
|
18
18
|
* ID of template.
|
|
@@ -90,5 +90,5 @@ declare module './base-entity-types' {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
export type WpTemplatePart< C extends Context > = OmitNevers<
|
|
93
|
-
|
|
93
|
+
_BaseEntityRecords.WpTemplatePart< C >
|
|
94
94
|
>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Internal dependencies
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import type {
|
|
5
5
|
Context,
|
|
6
6
|
PostStatus,
|
|
7
7
|
RenderedText,
|
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
ContextualField,
|
|
10
10
|
} from './helpers';
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import type { BaseEntityRecords as _BaseEntityRecords } from './base-entity-records';
|
|
13
13
|
|
|
14
|
-
declare module './base-entity-
|
|
15
|
-
export namespace
|
|
14
|
+
declare module './base-entity-records' {
|
|
15
|
+
export namespace BaseEntityRecords {
|
|
16
16
|
export interface WpTemplate< C extends Context > {
|
|
17
17
|
/**
|
|
18
18
|
* ID of template.
|
|
@@ -90,5 +90,5 @@ declare module './base-entity-types' {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
export type WpTemplate< C extends Context > = OmitNevers<
|
|
93
|
-
|
|
93
|
+
_BaseEntityRecords.WpTemplate< C >
|
|
94
94
|
>;
|
|
@@ -9,7 +9,7 @@ import { __ } from '@wordpress/i18n';
|
|
|
9
9
|
/**
|
|
10
10
|
* Filters the search by type
|
|
11
11
|
*
|
|
12
|
-
* @typedef { 'post' | 'term' | 'post-format' } WPLinkSearchType
|
|
12
|
+
* @typedef { 'attachment' | 'post' | 'term' | 'post-format' } WPLinkSearchType
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -38,6 +38,17 @@ import { __ } from '@wordpress/i18n';
|
|
|
38
38
|
* @property {WPKind} [kind] Link kind of post-type or taxonomy
|
|
39
39
|
*/
|
|
40
40
|
|
|
41
|
+
/**
|
|
42
|
+
* @typedef WPLinkSearchResultAugments
|
|
43
|
+
*
|
|
44
|
+
* @property {{kind: WPKind}} [meta] Contains kind information.
|
|
45
|
+
* @property {WPKind} [subtype] Optional subtype if it exists.
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @typedef {WPLinkSearchResult & WPLinkSearchResultAugments} WPLinkSearchResultAugmented
|
|
50
|
+
*/
|
|
51
|
+
|
|
41
52
|
/**
|
|
42
53
|
* @typedef WPEditorSettings
|
|
43
54
|
*
|
|
@@ -82,6 +93,7 @@ const fetchLinkSuggestions = async (
|
|
|
82
93
|
|
|
83
94
|
const { disablePostFormats = false } = settings;
|
|
84
95
|
|
|
96
|
+
/** @type {Promise<WPLinkSearchResult>[]} */
|
|
85
97
|
const queries = [];
|
|
86
98
|
|
|
87
99
|
if ( ! type || type === 'post' ) {
|
|
@@ -126,7 +138,7 @@ const fetchLinkSuggestions = async (
|
|
|
126
138
|
};
|
|
127
139
|
} );
|
|
128
140
|
} )
|
|
129
|
-
.catch( () => [] )
|
|
141
|
+
.catch( () => [] ) // Fail by returning no results.
|
|
130
142
|
);
|
|
131
143
|
}
|
|
132
144
|
|
|
@@ -149,14 +161,36 @@ const fetchLinkSuggestions = async (
|
|
|
149
161
|
};
|
|
150
162
|
} );
|
|
151
163
|
} )
|
|
152
|
-
.catch( () => [] )
|
|
164
|
+
.catch( () => [] ) // Fail by returning no results.
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if ( ! type || type === 'attachment' ) {
|
|
169
|
+
queries.push(
|
|
170
|
+
apiFetch( {
|
|
171
|
+
path: addQueryArgs( '/wp/v2/media', {
|
|
172
|
+
search,
|
|
173
|
+
page,
|
|
174
|
+
per_page: perPage,
|
|
175
|
+
} ),
|
|
176
|
+
} )
|
|
177
|
+
.then( ( results ) => {
|
|
178
|
+
return results.map( ( result ) => {
|
|
179
|
+
return {
|
|
180
|
+
...result,
|
|
181
|
+
meta: { kind: 'media' },
|
|
182
|
+
};
|
|
183
|
+
} );
|
|
184
|
+
} )
|
|
185
|
+
.catch( () => [] ) // Fail by returning no results.
|
|
153
186
|
);
|
|
154
187
|
}
|
|
155
188
|
|
|
156
189
|
return Promise.all( queries ).then( ( results ) => {
|
|
157
190
|
return results
|
|
158
191
|
.reduce(
|
|
159
|
-
(
|
|
192
|
+
( /** @type {WPLinkSearchResult[]} */ accumulator, current ) =>
|
|
193
|
+
accumulator.concat( current ), // Flatten list.
|
|
160
194
|
[]
|
|
161
195
|
)
|
|
162
196
|
.filter(
|
|
@@ -168,22 +202,24 @@ const fetchLinkSuggestions = async (
|
|
|
168
202
|
}
|
|
169
203
|
)
|
|
170
204
|
.slice( 0, perPage )
|
|
171
|
-
.map(
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
205
|
+
.map( ( /** @type {WPLinkSearchResultAugmented} */ result ) => {
|
|
206
|
+
const isMedia = result.type === 'attachment';
|
|
207
|
+
|
|
208
|
+
return {
|
|
209
|
+
id: result.id,
|
|
210
|
+
// @ts-ignore fix when we make this a TS file
|
|
211
|
+
url: isMedia ? result.source_url : result.url,
|
|
212
|
+
title:
|
|
213
|
+
decodeEntities(
|
|
214
|
+
isMedia
|
|
215
|
+
? // @ts-ignore fix when we make this a TS file
|
|
216
|
+
result.title.rendered
|
|
217
|
+
: result.title || ''
|
|
218
|
+
) || __( '(no title)' ),
|
|
219
|
+
type: result.subtype || result.type,
|
|
220
|
+
kind: result?.meta?.kind,
|
|
221
|
+
};
|
|
222
|
+
} );
|
|
187
223
|
} );
|
|
188
224
|
};
|
|
189
225
|
|
|
@@ -70,6 +70,18 @@ jest.mock( '@wordpress/api-fetch', () =>
|
|
|
70
70
|
subtype: 'page',
|
|
71
71
|
},
|
|
72
72
|
] );
|
|
73
|
+
case '/wp/v2/media?search=&per_page=20':
|
|
74
|
+
return Promise.resolve( [
|
|
75
|
+
{
|
|
76
|
+
id: 54,
|
|
77
|
+
title: {
|
|
78
|
+
rendered: 'Some Test Media Title',
|
|
79
|
+
},
|
|
80
|
+
type: 'attachment',
|
|
81
|
+
source_url:
|
|
82
|
+
'http://localhost:8888/wp-content/uploads/2022/03/test-pdf.pdf',
|
|
83
|
+
},
|
|
84
|
+
] );
|
|
73
85
|
default:
|
|
74
86
|
return Promise.resolve( [
|
|
75
87
|
{
|
|
@@ -154,7 +166,25 @@ describe( 'fetchLinkSuggestions', () => {
|
|
|
154
166
|
{ disablePostFormats: true }
|
|
155
167
|
).then( ( suggestions ) => expect( suggestions ).toEqual( [] ) );
|
|
156
168
|
} );
|
|
157
|
-
|
|
169
|
+
|
|
170
|
+
it( 'filters suggestions by attachment', () => {
|
|
171
|
+
return fetchLinkSuggestions( '', {
|
|
172
|
+
type: 'attachment',
|
|
173
|
+
} ).then( ( suggestions ) =>
|
|
174
|
+
expect( suggestions ).toEqual( [
|
|
175
|
+
{
|
|
176
|
+
id: 54,
|
|
177
|
+
title: 'Some Test Media Title',
|
|
178
|
+
url:
|
|
179
|
+
'http://localhost:8888/wp-content/uploads/2022/03/test-pdf.pdf',
|
|
180
|
+
type: 'attachment',
|
|
181
|
+
kind: 'media',
|
|
182
|
+
},
|
|
183
|
+
] )
|
|
184
|
+
);
|
|
185
|
+
} );
|
|
186
|
+
|
|
187
|
+
it( 'returns suggestions from post, term, post-format and media', () => {
|
|
158
188
|
return fetchLinkSuggestions( '', {} ).then( ( suggestions ) =>
|
|
159
189
|
expect( suggestions ).toEqual( [
|
|
160
190
|
{
|
|
@@ -192,6 +222,14 @@ describe( 'fetchLinkSuggestions', () => {
|
|
|
192
222
|
type: 'post-format',
|
|
193
223
|
kind: 'taxonomy',
|
|
194
224
|
},
|
|
225
|
+
{
|
|
226
|
+
id: 54,
|
|
227
|
+
title: 'Some Test Media Title',
|
|
228
|
+
url:
|
|
229
|
+
'http://localhost:8888/wp-content/uploads/2022/03/test-pdf.pdf',
|
|
230
|
+
type: 'attachment',
|
|
231
|
+
kind: 'media',
|
|
232
|
+
},
|
|
195
233
|
] )
|
|
196
234
|
);
|
|
197
235
|
} );
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import useQuerySelect from './use-query-select';
|
|
5
5
|
import { store as coreStore } from '../';
|
|
6
|
-
import { Status } from './constants';
|
|
6
|
+
import type { Status } from './constants';
|
|
7
7
|
|
|
8
8
|
interface EntityRecordResolution< RecordType > {
|
|
9
9
|
/** The requested entity record */
|
|
@@ -23,13 +23,18 @@ interface EntityRecordResolution< RecordType > {
|
|
|
23
23
|
status: Status;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
interface Options {
|
|
27
|
+
enabled: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
26
30
|
/**
|
|
27
31
|
* Resolves the specified entity record.
|
|
28
32
|
*
|
|
29
|
-
* @param kind
|
|
30
|
-
* @param name
|
|
31
|
-
* @param recordId
|
|
32
|
-
*
|
|
33
|
+
* @param kind Kind of the requested entity.
|
|
34
|
+
* @param name Name of the requested entity.
|
|
35
|
+
* @param recordId Record ID of the requested entity.
|
|
36
|
+
* @param options Hook options.
|
|
37
|
+
* @param [options.enabled=true] Whether to run the query or short-circuit and return null. Defaults to true.
|
|
33
38
|
* @example
|
|
34
39
|
* ```js
|
|
35
40
|
* import { useEntityRecord } from '@wordpress/core-data';
|
|
@@ -58,11 +63,17 @@ interface EntityRecordResolution< RecordType > {
|
|
|
58
63
|
export default function __experimentalUseEntityRecord< RecordType >(
|
|
59
64
|
kind: string,
|
|
60
65
|
name: string,
|
|
61
|
-
recordId: string | number
|
|
66
|
+
recordId: string | number,
|
|
67
|
+
options: Options = { enabled: true }
|
|
62
68
|
): EntityRecordResolution< RecordType > {
|
|
63
69
|
const { data: record, ...rest } = useQuerySelect(
|
|
64
|
-
( query ) =>
|
|
65
|
-
|
|
70
|
+
( query ) => {
|
|
71
|
+
if ( ! options.enabled ) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
return query( coreStore ).getEntityRecord( kind, name, recordId );
|
|
75
|
+
},
|
|
76
|
+
[ kind, name, recordId, options.enabled ]
|
|
66
77
|
);
|
|
67
78
|
|
|
68
79
|
return {
|
|
@@ -8,7 +8,7 @@ import { addQueryArgs } from '@wordpress/url';
|
|
|
8
8
|
*/
|
|
9
9
|
import useQuerySelect from './use-query-select';
|
|
10
10
|
import { store as coreStore } from '../';
|
|
11
|
-
import { Status } from './constants';
|
|
11
|
+
import type { Status } from './constants';
|
|
12
12
|
|
|
13
13
|
interface EntityRecordsResolution< RecordType > {
|
|
14
14
|
/** The requested entity record */
|
|
@@ -28,12 +28,22 @@ interface EntityRecordsResolution< RecordType > {
|
|
|
28
28
|
status: Status;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
interface Options {
|
|
32
|
+
/**
|
|
33
|
+
* Whether to run the query or short-circuit and return null.
|
|
34
|
+
*
|
|
35
|
+
* @default true
|
|
36
|
+
*/
|
|
37
|
+
enabled: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
31
40
|
/**
|
|
32
41
|
* Resolves the specified entity records.
|
|
33
42
|
*
|
|
34
43
|
* @param kind Kind of the requested entities.
|
|
35
44
|
* @param name Name of the requested entities.
|
|
36
45
|
* @param queryArgs HTTP query for the requested entities.
|
|
46
|
+
* @param options Hook options.
|
|
37
47
|
* @example
|
|
38
48
|
* ```js
|
|
39
49
|
* import { useEntityRecord } from '@wordpress/core-data';
|
|
@@ -62,13 +72,14 @@ interface EntityRecordsResolution< RecordType > {
|
|
|
62
72
|
* application, the list of records and the resolution details will be retrieved from
|
|
63
73
|
* the store state using `getEntityRecords()`, or resolved if missing.
|
|
64
74
|
*
|
|
65
|
-
* @return
|
|
75
|
+
* @return Entity records data.
|
|
66
76
|
* @template RecordType
|
|
67
77
|
*/
|
|
68
78
|
export default function __experimentalUseEntityRecords< RecordType >(
|
|
69
79
|
kind: string,
|
|
70
80
|
name: string,
|
|
71
|
-
queryArgs: unknown = {}
|
|
81
|
+
queryArgs: Record< string, unknown > = {},
|
|
82
|
+
options: Options = { enabled: true }
|
|
72
83
|
): EntityRecordsResolution< RecordType > {
|
|
73
84
|
// Serialize queryArgs to a string that can be safely used as a React dep.
|
|
74
85
|
// We can't just pass queryArgs as one of the deps, because if it is passed
|
|
@@ -77,9 +88,15 @@ export default function __experimentalUseEntityRecords< RecordType >(
|
|
|
77
88
|
const queryAsString = addQueryArgs( '', queryArgs );
|
|
78
89
|
|
|
79
90
|
const { data: records, ...rest } = useQuerySelect(
|
|
80
|
-
( query ) =>
|
|
81
|
-
|
|
82
|
-
|
|
91
|
+
( query ) => {
|
|
92
|
+
if ( ! options.enabled ) {
|
|
93
|
+
return {
|
|
94
|
+
data: [],
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
return query( coreStore ).getEntityRecords( kind, name, queryArgs );
|
|
98
|
+
},
|
|
99
|
+
[ kind, name, queryAsString, options.enabled ]
|
|
83
100
|
);
|
|
84
101
|
|
|
85
102
|
return {
|
|
@@ -17,9 +17,9 @@ export const META_SELECTORS = [
|
|
|
17
17
|
'getCachedResolvers',
|
|
18
18
|
];
|
|
19
19
|
|
|
20
|
-
interface QuerySelectResponse {
|
|
20
|
+
interface QuerySelectResponse< Data > {
|
|
21
21
|
/** the requested selector return value */
|
|
22
|
-
data:
|
|
22
|
+
data: Data;
|
|
23
23
|
|
|
24
24
|
/** is the record still being resolved? Via the `getIsResolving` meta-selector */
|
|
25
25
|
isResolving: boolean;
|
|
@@ -78,9 +78,14 @@ export default function __experimentalUseQuerySelect( mapQuerySelect, deps ) {
|
|
|
78
78
|
}, deps );
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
type QuerySelector = ( ...args ) => QuerySelectResponse;
|
|
82
81
|
interface EnrichedSelectors {
|
|
83
|
-
|
|
82
|
+
< Selectors extends Record< string, ( ...args: any[] ) => any > >(
|
|
83
|
+
selectors: Selectors
|
|
84
|
+
): {
|
|
85
|
+
[ Selector in keyof Selectors ]: (
|
|
86
|
+
...args: Parameters< Selectors[ Selector ] >
|
|
87
|
+
) => QuerySelectResponse< ReturnType< Selectors[ Selector ] > >;
|
|
88
|
+
};
|
|
84
89
|
}
|
|
85
90
|
|
|
86
91
|
/**
|
|
@@ -90,14 +95,14 @@ interface EnrichedSelectors {
|
|
|
90
95
|
* @param {Object} selectors Selectors to enrich
|
|
91
96
|
* @return {EnrichedSelectors} Enriched selectors
|
|
92
97
|
*/
|
|
93
|
-
const enrichSelectors = memoize( ( selectors ) => {
|
|
98
|
+
const enrichSelectors = memoize( ( ( selectors ) => {
|
|
94
99
|
const resolvers = {};
|
|
95
100
|
for ( const selectorName in selectors ) {
|
|
96
101
|
if ( META_SELECTORS.includes( selectorName ) ) {
|
|
97
102
|
continue;
|
|
98
103
|
}
|
|
99
104
|
Object.defineProperty( resolvers, selectorName, {
|
|
100
|
-
get: () => ( ...args ) => {
|
|
105
|
+
get: () => ( ...args: unknown[] ) => {
|
|
101
106
|
const { getIsResolving, hasFinishedResolution } = selectors;
|
|
102
107
|
const isResolving = !! getIsResolving( selectorName, args );
|
|
103
108
|
const hasResolved =
|
|
@@ -128,4 +133,4 @@ const enrichSelectors = memoize( ( selectors ) => {
|
|
|
128
133
|
} );
|
|
129
134
|
}
|
|
130
135
|
return resolvers;
|
|
131
|
-
} );
|
|
136
|
+
} ) as EnrichedSelectors );
|
package/src/index.js
CHANGED
|
@@ -11,41 +11,36 @@ import * as selectors from './selectors';
|
|
|
11
11
|
import * as actions from './actions';
|
|
12
12
|
import * as resolvers from './resolvers';
|
|
13
13
|
import createLocksActions from './locks/actions';
|
|
14
|
-
import {
|
|
14
|
+
import { rootEntitiesConfig, getMethodName } from './entities';
|
|
15
15
|
import { STORE_NAME } from './name';
|
|
16
16
|
|
|
17
17
|
// The entity selectors/resolvers and actions are shortcuts to their generic equivalents
|
|
18
|
-
// (getEntityRecord, getEntityRecords, updateEntityRecord,
|
|
19
|
-
// Instead of getEntityRecord, the consumer could use more user-
|
|
18
|
+
// (getEntityRecord, getEntityRecords, updateEntityRecord, updateEntityRecords)
|
|
19
|
+
// Instead of getEntityRecord, the consumer could use more user-friendly named selector: getPostType, getTaxonomy...
|
|
20
20
|
// The "kind" and the "name" of the entity are combined to generate these shortcuts.
|
|
21
21
|
|
|
22
|
-
const entitySelectors =
|
|
22
|
+
const entitySelectors = rootEntitiesConfig.reduce( ( result, entity ) => {
|
|
23
23
|
const { kind, name } = entity;
|
|
24
24
|
result[ getMethodName( kind, name ) ] = ( state, key, query ) =>
|
|
25
25
|
selectors.getEntityRecord( state, kind, name, key, query );
|
|
26
|
-
result[ getMethodName( kind, name, 'get', true ) ] = ( state,
|
|
27
|
-
selectors.getEntityRecords( state, kind, name,
|
|
26
|
+
result[ getMethodName( kind, name, 'get', true ) ] = ( state, query ) =>
|
|
27
|
+
selectors.getEntityRecords( state, kind, name, query );
|
|
28
28
|
return result;
|
|
29
29
|
}, {} );
|
|
30
30
|
|
|
31
|
-
const entityResolvers =
|
|
31
|
+
const entityResolvers = rootEntitiesConfig.reduce( ( result, entity ) => {
|
|
32
32
|
const { kind, name } = entity;
|
|
33
33
|
result[ getMethodName( kind, name ) ] = ( key, query ) =>
|
|
34
34
|
resolvers.getEntityRecord( kind, name, key, query );
|
|
35
35
|
const pluralMethodName = getMethodName( kind, name, 'get', true );
|
|
36
36
|
result[ pluralMethodName ] = ( ...args ) =>
|
|
37
37
|
resolvers.getEntityRecords( kind, name, ...args );
|
|
38
|
-
result[ pluralMethodName ].shouldInvalidate = ( action
|
|
39
|
-
resolvers.getEntityRecords.shouldInvalidate(
|
|
40
|
-
action,
|
|
41
|
-
kind,
|
|
42
|
-
name,
|
|
43
|
-
...args
|
|
44
|
-
);
|
|
38
|
+
result[ pluralMethodName ].shouldInvalidate = ( action ) =>
|
|
39
|
+
resolvers.getEntityRecords.shouldInvalidate( action, kind, name );
|
|
45
40
|
return result;
|
|
46
41
|
}, {} );
|
|
47
42
|
|
|
48
|
-
const entityActions =
|
|
43
|
+
const entityActions = rootEntitiesConfig.reduce( ( result, entity ) => {
|
|
49
44
|
const { kind, name } = entity;
|
|
50
45
|
result[ getMethodName( kind, name, 'save' ) ] = ( key ) =>
|
|
51
46
|
actions.saveEntityRecord( kind, name, key );
|
|
@@ -116,7 +116,7 @@ describe( 'isLockAvailable', () => {
|
|
|
116
116
|
store: 'core',
|
|
117
117
|
path: [
|
|
118
118
|
'entities',
|
|
119
|
-
'
|
|
119
|
+
'records',
|
|
120
120
|
'postType',
|
|
121
121
|
'post',
|
|
122
122
|
16,
|
|
@@ -163,7 +163,7 @@ describe( 'isLockAvailable', () => {
|
|
|
163
163
|
entities: {
|
|
164
164
|
locks: [],
|
|
165
165
|
children: {
|
|
166
|
-
|
|
166
|
+
records: {
|
|
167
167
|
locks: [],
|
|
168
168
|
children: {
|
|
169
169
|
postType: {
|
|
@@ -178,7 +178,7 @@ describe( 'isLockAvailable', () => {
|
|
|
178
178
|
path: [
|
|
179
179
|
'core',
|
|
180
180
|
'entities',
|
|
181
|
-
'
|
|
181
|
+
'records',
|
|
182
182
|
'postType',
|
|
183
183
|
'book',
|
|
184
184
|
67,
|
|
@@ -205,7 +205,7 @@ describe( 'isLockAvailable', () => {
|
|
|
205
205
|
isLockAvailable(
|
|
206
206
|
deepFreeze( subState ),
|
|
207
207
|
'core',
|
|
208
|
-
[ 'entities', '
|
|
208
|
+
[ 'entities', 'records', 'postType', 'book', 67 ],
|
|
209
209
|
{ exclusive: false }
|
|
210
210
|
)
|
|
211
211
|
).toBe( false );
|
|
@@ -23,10 +23,10 @@ export function receiveItems( items, edits ) {
|
|
|
23
23
|
* Returns an action object used in signalling that entity records have been
|
|
24
24
|
* deleted and they need to be removed from entities state.
|
|
25
25
|
*
|
|
26
|
-
* @param {string}
|
|
27
|
-
* @param {string}
|
|
28
|
-
* @param {Array|number} records Record IDs of the removed entities.
|
|
29
|
-
* @param {boolean}
|
|
26
|
+
* @param {string} kind Kind of the removed entities.
|
|
27
|
+
* @param {string} name Name of the removed entities.
|
|
28
|
+
* @param {Array|number|string} records Record IDs of the removed entities.
|
|
29
|
+
* @param {boolean} invalidateCache Controls whether we want to invalidate the cache.
|
|
30
30
|
* @return {Object} Action object.
|
|
31
31
|
*/
|
|
32
32
|
export function removeItems( kind, name, records, invalidateCache = false ) {
|
|
@@ -70,19 +70,19 @@ export function getQueryParts( query ) {
|
|
|
70
70
|
// While in theory, we could exclude "_fields" from the stableKey
|
|
71
71
|
// because two request with different fields have the same results
|
|
72
72
|
// We're not able to ensure that because the server can decide to omit
|
|
73
|
-
// fields from the response even if we
|
|
73
|
+
// fields from the response even if we explicitly asked for it.
|
|
74
74
|
// Example: Asking for titles in posts without title support.
|
|
75
75
|
if ( key === '_fields' ) {
|
|
76
|
-
parts.fields = getNormalizedCommaSeparable( value );
|
|
76
|
+
parts.fields = getNormalizedCommaSeparable( value ) ?? [];
|
|
77
77
|
// Make sure to normalize value for `stableKey`
|
|
78
78
|
value = parts.fields.join();
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
// Two requests with different include values cannot have same results.
|
|
82
82
|
if ( key === 'include' ) {
|
|
83
|
-
parts.include =
|
|
84
|
-
|
|
85
|
-
);
|
|
83
|
+
parts.include = (
|
|
84
|
+
getNormalizedCommaSeparable( value ) ?? []
|
|
85
|
+
).map( Number );
|
|
86
86
|
// Normalize value for `stableKey`.
|
|
87
87
|
value = parts.include.join();
|
|
88
88
|
}
|