@wordpress/core-data 4.14.1-next.d6164808d3.0 → 5.0.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.
Files changed (197) hide show
  1. package/CHANGELOG.md +7 -1
  2. package/README.md +73 -61
  3. package/build/entities.js +31 -46
  4. package/build/entities.js.map +1 -1
  5. package/build/hooks/use-entity-record.js +4 -2
  6. package/build/hooks/use-entity-record.js.map +1 -1
  7. package/build/hooks/use-entity-records.js +2 -0
  8. package/build/hooks/use-entity-records.js.map +1 -1
  9. package/build/hooks/use-query-select.js +5 -2
  10. package/build/hooks/use-query-select.js.map +1 -1
  11. package/build/hooks/use-resource-permissions.js +22 -6
  12. package/build/hooks/use-resource-permissions.js.map +1 -1
  13. package/build/index.js +0 -2
  14. package/build/index.js.map +1 -1
  15. package/build/resolvers.js +45 -21
  16. package/build/resolvers.js.map +1 -1
  17. package/build/selectors.js +9 -46
  18. package/build/selectors.js.map +1 -1
  19. package/build-module/entities.js +31 -46
  20. package/build-module/entities.js.map +1 -1
  21. package/build-module/hooks/use-entity-record.js +4 -2
  22. package/build-module/hooks/use-entity-record.js.map +1 -1
  23. package/build-module/hooks/use-entity-records.js +2 -0
  24. package/build-module/hooks/use-entity-records.js.map +1 -1
  25. package/build-module/hooks/use-query-select.js +4 -1
  26. package/build-module/hooks/use-query-select.js.map +1 -1
  27. package/build-module/hooks/use-resource-permissions.js +22 -6
  28. package/build-module/hooks/use-resource-permissions.js.map +1 -1
  29. package/build-module/index.js +0 -2
  30. package/build-module/index.js.map +1 -1
  31. package/build-module/resolvers.js +45 -21
  32. package/build-module/resolvers.js.map +1 -1
  33. package/build-module/selectors.js +7 -44
  34. package/build-module/selectors.js.map +1 -1
  35. package/build-types/actions.d.ts +188 -0
  36. package/build-types/actions.d.ts.map +1 -0
  37. package/build-types/batch/create-batch.d.ts +71 -0
  38. package/build-types/batch/create-batch.d.ts.map +1 -0
  39. package/build-types/batch/default-processor.d.ts +11 -0
  40. package/build-types/batch/default-processor.d.ts.map +1 -0
  41. package/build-types/batch/index.d.ts +3 -0
  42. package/build-types/batch/index.d.ts.map +1 -0
  43. package/build-types/entities.d.ts +128 -0
  44. package/build-types/entities.d.ts.map +1 -0
  45. package/build-types/entity-provider.d.ts +68 -0
  46. package/build-types/entity-provider.d.ts.map +1 -0
  47. package/build-types/entity-types/attachment.d.ts +121 -0
  48. package/build-types/entity-types/attachment.d.ts.map +1 -0
  49. package/build-types/entity-types/base-entity-records.d.ts +37 -0
  50. package/build-types/entity-types/base-entity-records.d.ts.map +1 -0
  51. package/build-types/entity-types/comment.d.ts +82 -0
  52. package/build-types/entity-types/comment.d.ts.map +1 -0
  53. package/build-types/entity-types/helpers.d.ts +123 -0
  54. package/build-types/entity-types/helpers.d.ts.map +1 -0
  55. package/build-types/entity-types/index.d.ts +64 -0
  56. package/build-types/entity-types/index.d.ts.map +1 -0
  57. package/build-types/entity-types/menu-location.d.ts +25 -0
  58. package/build-types/entity-types/menu-location.d.ts.map +1 -0
  59. package/build-types/entity-types/nav-menu-item.d.ts +88 -0
  60. package/build-types/entity-types/nav-menu-item.d.ts.map +1 -0
  61. package/build-types/entity-types/nav-menu.d.ts +45 -0
  62. package/build-types/entity-types/nav-menu.d.ts.map +1 -0
  63. package/build-types/entity-types/page.d.ts +120 -0
  64. package/build-types/entity-types/page.d.ts.map +1 -0
  65. package/build-types/entity-types/plugin.d.ts +62 -0
  66. package/build-types/entity-types/plugin.d.ts.map +1 -0
  67. package/build-types/entity-types/post.d.ts +128 -0
  68. package/build-types/entity-types/post.d.ts.map +1 -0
  69. package/build-types/entity-types/settings.d.ts +89 -0
  70. package/build-types/entity-types/settings.d.ts.map +1 -0
  71. package/build-types/entity-types/sidebar.d.ts +55 -0
  72. package/build-types/entity-types/sidebar.d.ts.map +1 -0
  73. package/build-types/entity-types/taxonomy.d.ts +83 -0
  74. package/build-types/entity-types/taxonomy.d.ts.map +1 -0
  75. package/build-types/entity-types/theme.d.ts +206 -0
  76. package/build-types/entity-types/theme.d.ts.map +1 -0
  77. package/build-types/entity-types/type.d.ts +71 -0
  78. package/build-types/entity-types/type.d.ts.map +1 -0
  79. package/build-types/entity-types/user.d.ts +93 -0
  80. package/build-types/entity-types/user.d.ts.map +1 -0
  81. package/build-types/entity-types/widget-type.d.ts +33 -0
  82. package/build-types/entity-types/widget-type.d.ts.map +1 -0
  83. package/build-types/entity-types/widget.d.ts +59 -0
  84. package/build-types/entity-types/widget.d.ts.map +1 -0
  85. package/build-types/entity-types/wp-template-part.d.ts +80 -0
  86. package/build-types/entity-types/wp-template-part.d.ts.map +1 -0
  87. package/build-types/entity-types/wp-template.d.ts +80 -0
  88. package/build-types/entity-types/wp-template.d.ts.map +1 -0
  89. package/build-types/fetch/__experimental-fetch-link-suggestions.d.ts +139 -0
  90. package/build-types/fetch/__experimental-fetch-link-suggestions.d.ts.map +1 -0
  91. package/build-types/fetch/__experimental-fetch-url-data.d.ts +35 -0
  92. package/build-types/fetch/__experimental-fetch-url-data.d.ts.map +1 -0
  93. package/build-types/fetch/index.d.ts +3 -0
  94. package/build-types/fetch/index.d.ts.map +1 -0
  95. package/build-types/hooks/constants.d.ts +7 -0
  96. package/build-types/hooks/constants.d.ts.map +1 -0
  97. package/build-types/hooks/index.d.ts +4 -0
  98. package/build-types/hooks/index.d.ts.map +1 -0
  99. package/build-types/hooks/memoize.d.ts +3 -0
  100. package/build-types/hooks/memoize.d.ts.map +1 -0
  101. package/build-types/hooks/use-entity-record.d.ts +124 -0
  102. package/build-types/hooks/use-entity-record.d.ts.map +1 -0
  103. package/build-types/hooks/use-entity-records.d.ts +49 -0
  104. package/build-types/hooks/use-entity-records.d.ts.map +1 -0
  105. package/build-types/hooks/use-query-select.d.ts +46 -0
  106. package/build-types/hooks/use-query-select.d.ts.map +1 -0
  107. package/build-types/hooks/use-resource-permissions.d.ts +99 -0
  108. package/build-types/hooks/use-resource-permissions.d.ts.map +1 -0
  109. package/build-types/index.d.ts +131 -0
  110. package/build-types/index.d.ts.map +1 -0
  111. package/build-types/locks/actions.d.ts +7 -0
  112. package/build-types/locks/actions.d.ts.map +1 -0
  113. package/build-types/locks/engine.d.ts +5 -0
  114. package/build-types/locks/engine.d.ts.map +1 -0
  115. package/build-types/locks/reducer.d.ts +10 -0
  116. package/build-types/locks/reducer.d.ts.map +1 -0
  117. package/build-types/locks/selectors.d.ts +5 -0
  118. package/build-types/locks/selectors.d.ts.map +1 -0
  119. package/build-types/locks/utils.d.ts +8 -0
  120. package/build-types/locks/utils.d.ts.map +1 -0
  121. package/build-types/name.d.ts +8 -0
  122. package/build-types/name.d.ts.map +1 -0
  123. package/build-types/queried-data/actions.d.ts +32 -0
  124. package/build-types/queried-data/actions.d.ts.map +1 -0
  125. package/build-types/queried-data/get-query-parts.d.ts +60 -0
  126. package/build-types/queried-data/get-query-parts.d.ts.map +1 -0
  127. package/build-types/queried-data/index.d.ts +4 -0
  128. package/build-types/queried-data/index.d.ts.map +1 -0
  129. package/build-types/queried-data/reducer.d.ts +54 -0
  130. package/build-types/queried-data/reducer.d.ts.map +1 -0
  131. package/build-types/queried-data/selectors.d.ts +16 -0
  132. package/build-types/queried-data/selectors.d.ts.map +1 -0
  133. package/build-types/reducer.d.ts +156 -0
  134. package/build-types/reducer.d.ts.map +1 -0
  135. package/build-types/resolvers.d.ts +75 -0
  136. package/build-types/resolvers.d.ts.map +1 -0
  137. package/build-types/selectors.d.ts +524 -0
  138. package/build-types/selectors.d.ts.map +1 -0
  139. package/build-types/types.d.ts +4 -0
  140. package/build-types/types.d.ts.map +1 -0
  141. package/build-types/utils/conservative-map-item.d.ts +12 -0
  142. package/build-types/utils/conservative-map-item.d.ts.map +1 -0
  143. package/build-types/utils/forward-resolver.d.ts +10 -0
  144. package/build-types/utils/forward-resolver.d.ts.map +1 -0
  145. package/build-types/utils/get-normalized-comma-separable.d.ts +12 -0
  146. package/build-types/utils/get-normalized-comma-separable.d.ts.map +1 -0
  147. package/build-types/utils/if-matching-action.d.ts +14 -0
  148. package/build-types/utils/if-matching-action.d.ts.map +1 -0
  149. package/build-types/utils/index.d.ts +9 -0
  150. package/build-types/utils/index.d.ts.map +1 -0
  151. package/build-types/utils/is-raw-attribute.d.ts +10 -0
  152. package/build-types/utils/is-raw-attribute.d.ts.map +1 -0
  153. package/build-types/utils/on-sub-key.d.ts +4 -0
  154. package/build-types/utils/on-sub-key.d.ts.map +1 -0
  155. package/build-types/utils/replace-action.d.ts +13 -0
  156. package/build-types/utils/replace-action.d.ts.map +1 -0
  157. package/build-types/utils/with-weak-map-cache.d.ts +12 -0
  158. package/build-types/utils/with-weak-map-cache.d.ts.map +1 -0
  159. package/package.json +12 -11
  160. package/src/entities.js +325 -0
  161. package/src/entity-types/attachment.ts +3 -4
  162. package/src/entity-types/comment.ts +3 -4
  163. package/src/entity-types/index.ts +31 -88
  164. package/src/entity-types/menu-location.ts +3 -4
  165. package/src/entity-types/nav-menu-item.ts +3 -4
  166. package/src/entity-types/nav-menu.ts +3 -3
  167. package/src/entity-types/page.ts +3 -3
  168. package/src/entity-types/plugin.ts +3 -3
  169. package/src/entity-types/post.ts +3 -3
  170. package/src/entity-types/settings.ts +3 -3
  171. package/src/entity-types/sidebar.ts +3 -4
  172. package/src/entity-types/taxonomy.ts +3 -4
  173. package/src/entity-types/theme.ts +3 -3
  174. package/src/entity-types/type.ts +3 -3
  175. package/src/entity-types/user.ts +3 -3
  176. package/src/entity-types/widget-type.ts +3 -4
  177. package/src/entity-types/widget.ts +3 -3
  178. package/src/entity-types/wp-template-part.ts +3 -4
  179. package/src/entity-types/wp-template.ts +3 -4
  180. package/src/hooks/test/use-entity-record.js +41 -1
  181. package/src/hooks/test/use-resource-permissions.js +4 -0
  182. package/src/hooks/use-entity-record.ts +12 -2
  183. package/src/hooks/use-entity-records.ts +2 -0
  184. package/src/hooks/use-query-select.ts +4 -1
  185. package/src/hooks/use-resource-permissions.ts +28 -6
  186. package/src/index.js +0 -2
  187. package/src/resolvers.js +46 -23
  188. package/src/selectors.ts +202 -341
  189. package/src/test/resolvers.js +118 -4
  190. package/tsconfig.json +21 -0
  191. package/tsconfig.tsbuildinfo +1 -0
  192. package/build/entity-types/entities.js +0 -6
  193. package/build/entity-types/entities.js.map +0 -1
  194. package/build-module/entity-types/entities.js +0 -2
  195. package/build-module/entity-types/entities.js.map +0 -1
  196. package/src/entities.ts +0 -550
  197. package/src/entity-types/entities.ts +0 -130
@@ -9,7 +9,6 @@ import type {
9
9
  } from './helpers';
10
10
 
11
11
  import type { BaseEntityRecords as _BaseEntityRecords } from './base-entity-records';
12
- import type { DefaultContextOf } from './index';
13
12
 
14
13
  declare module './base-entity-records' {
15
14
  export namespace BaseEntityRecords {
@@ -94,5 +93,6 @@ declare module './base-entity-records' {
94
93
  }
95
94
  }
96
95
 
97
- export type Settings< C extends Context = DefaultContextOf< 'root', 'site' > > =
98
- OmitNevers< _BaseEntityRecords.Settings< C > >;
96
+ export type Settings< C extends Context = 'view' > = OmitNevers<
97
+ _BaseEntityRecords.Settings< C >
98
+ >;
@@ -4,7 +4,6 @@
4
4
  import type { Context, OmitNevers } from './helpers';
5
5
 
6
6
  import type { BaseEntityRecords as _BaseEntityRecords } from './base-entity-records';
7
- import type { DefaultContextOf } from './index';
8
7
 
9
8
  declare module './base-entity-records' {
10
9
  export namespace BaseEntityRecords {
@@ -55,6 +54,6 @@ declare module './base-entity-records' {
55
54
 
56
55
  type SidebarStatus = 'active' | 'inactive';
57
56
 
58
- export type Sidebar<
59
- C extends Context = DefaultContextOf< 'root', 'sidebar' >
60
- > = OmitNevers< _BaseEntityRecords.Sidebar< C > >;
57
+ export type Sidebar< C extends Context = 'edit' > = OmitNevers<
58
+ _BaseEntityRecords.Sidebar< C >
59
+ >;
@@ -4,7 +4,6 @@
4
4
  import type { Context, ContextualField, OmitNevers } from './helpers';
5
5
 
6
6
  import type { BaseEntityRecords as _BaseEntityRecords } from './base-entity-records';
7
- import type { DefaultContextOf } from './index';
8
7
 
9
8
  declare module './base-entity-records' {
10
9
  export namespace BaseEntityRecords {
@@ -88,6 +87,6 @@ declare module './base-entity-records' {
88
87
  }
89
88
  }
90
89
 
91
- export type Taxonomy<
92
- C extends Context = DefaultContextOf< 'postType', 'taxonomy' >
93
- > = OmitNevers< _BaseEntityRecords.Taxonomy< C > >;
90
+ export type Taxonomy< C extends Context = 'edit' > = OmitNevers<
91
+ _BaseEntityRecords.Taxonomy< C >
92
+ >;
@@ -4,7 +4,6 @@
4
4
  import type { Context, PostFormat, RenderedText, OmitNevers } from './helpers';
5
5
 
6
6
  import type { BaseEntityRecords as _BaseEntityRecords } from './base-entity-records';
7
- import type { DefaultContextOf } from './index';
8
7
 
9
8
  declare module './base-entity-records' {
10
9
  export namespace BaseEntityRecords {
@@ -222,5 +221,6 @@ declare module './base-entity-records' {
222
221
  }
223
222
  }
224
223
 
225
- export type Theme< C extends Context = DefaultContextOf< 'root', 'theme' > > =
226
- OmitNevers< _BaseEntityRecords.Theme< C > >;
224
+ export type Theme< C extends Context = 'edit' > = OmitNevers<
225
+ _BaseEntityRecords.Theme< C >
226
+ >;
@@ -4,7 +4,6 @@
4
4
  import type { Context, ContextualField, OmitNevers } from './helpers';
5
5
 
6
6
  import type { BaseEntityRecords as _BaseEntityRecords } from './base-entity-records';
7
- import type { DefaultContextOf } from './index';
8
7
 
9
8
  declare module './base-entity-records' {
10
9
  export namespace BaseEntityRecords {
@@ -76,5 +75,6 @@ declare module './base-entity-records' {
76
75
  }
77
76
  }
78
77
 
79
- export type Type< C extends Context = DefaultContextOf< 'root', 'postType' > > =
80
- OmitNevers< _BaseEntityRecords.Type< C > >;
78
+ export type Type< C extends Context = 'edit' > = OmitNevers<
79
+ _BaseEntityRecords.Type< C >
80
+ >;
@@ -9,7 +9,6 @@ import type {
9
9
  } from './helpers';
10
10
 
11
11
  import type { BaseEntityRecords as _BaseEntityRecords } from './base-entity-records';
12
- import type { DefaultContextOf } from './index';
13
12
 
14
13
  declare module './base-entity-records' {
15
14
  export namespace BaseEntityRecords {
@@ -110,5 +109,6 @@ declare module './base-entity-records' {
110
109
  }
111
110
  }
112
111
 
113
- export type User< C extends Context = DefaultContextOf< 'root', 'user' > > =
114
- OmitNevers< _BaseEntityRecords.User< C > >;
112
+ export type User< C extends Context = 'edit' > = OmitNevers<
113
+ _BaseEntityRecords.User< C >
114
+ >;
@@ -4,7 +4,6 @@
4
4
  import type { Context, OmitNevers } from './helpers';
5
5
 
6
6
  import type { BaseEntityRecords as _BaseEntityRecords } from './base-entity-records';
7
- import type { DefaultContextOf } from './index';
8
7
 
9
8
  declare module './base-entity-records' {
10
9
  export namespace BaseEntityRecords {
@@ -33,6 +32,6 @@ declare module './base-entity-records' {
33
32
  }
34
33
  }
35
34
 
36
- export type WidgetType<
37
- C extends Context = DefaultContextOf< 'root', 'widgetType' >
38
- > = OmitNevers< _BaseEntityRecords.WidgetType< C > >;
35
+ export type WidgetType< C extends Context = 'edit' > = OmitNevers<
36
+ _BaseEntityRecords.WidgetType< C >
37
+ >;
@@ -4,7 +4,6 @@
4
4
  import type { Context, ContextualField, OmitNevers } from './helpers';
5
5
 
6
6
  import type { BaseEntityRecords as _BaseEntityRecords } from './base-entity-records';
7
- import type { DefaultContextOf } from './index';
8
7
 
9
8
  declare module './base-entity-records' {
10
9
  export namespace BaseEntityRecords {
@@ -60,5 +59,6 @@ declare module './base-entity-records' {
60
59
  }
61
60
  }
62
61
 
63
- export type Widget< C extends Context = DefaultContextOf< 'root', 'widget' > > =
64
- OmitNevers< _BaseEntityRecords.Widget< C > >;
62
+ export type Widget< C extends Context = 'edit' > = OmitNevers<
63
+ _BaseEntityRecords.Widget< C >
64
+ >;
@@ -10,7 +10,6 @@ import type {
10
10
  } from './helpers';
11
11
 
12
12
  import type { BaseEntityRecords as _BaseEntityRecords } from './base-entity-records';
13
- import type { DefaultContextOf } from './index';
14
13
 
15
14
  declare module './base-entity-records' {
16
15
  export namespace BaseEntityRecords {
@@ -90,6 +89,6 @@ declare module './base-entity-records' {
90
89
  }
91
90
  }
92
91
 
93
- export type WpTemplatePart<
94
- C extends Context = DefaultContextOf< 'postType', 'wp_template_part' >
95
- > = OmitNevers< _BaseEntityRecords.WpTemplatePart< C > >;
92
+ export type WpTemplatePart< C extends Context = 'edit' > = OmitNevers<
93
+ _BaseEntityRecords.WpTemplatePart< C >
94
+ >;
@@ -10,7 +10,6 @@ import type {
10
10
  } from './helpers';
11
11
 
12
12
  import type { BaseEntityRecords as _BaseEntityRecords } from './base-entity-records';
13
- import type { DefaultContextOf } from './index';
14
13
 
15
14
  declare module './base-entity-records' {
16
15
  export namespace BaseEntityRecords {
@@ -90,6 +89,6 @@ declare module './base-entity-records' {
90
89
  }
91
90
  }
92
91
 
93
- export type WpTemplate<
94
- C extends Context = DefaultContextOf< 'postType', 'wp_template' >
95
- > = OmitNevers< _BaseEntityRecords.WpTemplate< C > >;
92
+ export type WpTemplate< C extends Context = 'edit' > = OmitNevers<
93
+ _BaseEntityRecords.WpTemplate< C >
94
+ >;
@@ -71,7 +71,38 @@ describe( 'useEntityRecord', () => {
71
71
 
72
72
  expect( data ).toEqual( {
73
73
  edit: expect.any( Function ),
74
- editedRecord: {},
74
+ editedRecord: { hello: 'world', id: 1 },
75
+ hasEdits: false,
76
+ record: { hello: 'world', id: 1 },
77
+ save: expect.any( Function ),
78
+ hasResolved: true,
79
+ isResolving: false,
80
+ status: 'SUCCESS',
81
+ } );
82
+ } );
83
+
84
+ it( 'applies edits to the entity record', async () => {
85
+ // Provide response
86
+ triggerFetch.mockImplementation( () => TEST_RECORD );
87
+
88
+ let widget;
89
+ const TestComponent = () => {
90
+ widget = useEntityRecord( 'root', 'widget', 1 );
91
+ return <div />;
92
+ };
93
+ render(
94
+ <RegistryProvider value={ registry }>
95
+ <TestComponent />
96
+ </RegistryProvider>
97
+ );
98
+
99
+ await act( async () => {
100
+ jest.advanceTimersByTime( 1 );
101
+ } );
102
+
103
+ expect( widget ).toEqual( {
104
+ edit: expect.any( Function ),
105
+ editedRecord: { hello: 'world', id: 1 },
75
106
  hasEdits: false,
76
107
  record: { hello: 'world', id: 1 },
77
108
  save: expect.any( Function ),
@@ -79,5 +110,14 @@ describe( 'useEntityRecord', () => {
79
110
  isResolving: false,
80
111
  status: 'SUCCESS',
81
112
  } );
113
+
114
+ await act( async () => {
115
+ widget.edit( { hello: 'foo' } );
116
+ jest.advanceTimersByTime( 1 );
117
+ } );
118
+
119
+ expect( widget.hasEdits ).toEqual( true );
120
+ expect( widget.record ).toEqual( { hello: 'world', id: 1 } );
121
+ expect( widget.editedRecord ).toEqual( { hello: 'foo', id: 1 } );
82
122
  } );
83
123
  } );
@@ -55,6 +55,7 @@ describe( 'useResourcePermissions', () => {
55
55
  isResolving: false,
56
56
  hasResolved: false,
57
57
  canCreate: false,
58
+ canRead: false,
58
59
  } );
59
60
 
60
61
  // Required to make sure no updates happen outside of act()
@@ -67,6 +68,7 @@ describe( 'useResourcePermissions', () => {
67
68
  isResolving: false,
68
69
  hasResolved: true,
69
70
  canCreate: true,
71
+ canRead: false,
70
72
  } );
71
73
  } );
72
74
 
@@ -86,6 +88,7 @@ describe( 'useResourcePermissions', () => {
86
88
  isResolving: false,
87
89
  hasResolved: false,
88
90
  canCreate: false,
91
+ canRead: false,
89
92
  canUpdate: false,
90
93
  canDelete: false,
91
94
  } );
@@ -100,6 +103,7 @@ describe( 'useResourcePermissions', () => {
100
103
  isResolving: false,
101
104
  hasResolved: true,
102
105
  canCreate: true,
106
+ canRead: false,
103
107
  canUpdate: false,
104
108
  canDelete: false,
105
109
  } );
@@ -56,6 +56,8 @@ export interface Options {
56
56
  /**
57
57
  * Resolves the specified entity record.
58
58
  *
59
+ * @since 6.1.0 Introduced in WordPress core.
60
+ *
59
61
  * @param kind Kind of the entity, e.g. `root` or a `postType`. See rootEntitiesConfig in ../entities.ts for a list of available kinds.
60
62
  * @param name Name of the entity, e.g. `plugin` or a `post`. See rootEntitiesConfig in ../entities.ts for a list of available names.
61
63
  * @param recordId ID of the requested entity record.
@@ -163,8 +165,16 @@ export default function useEntityRecord< RecordType >(
163
165
 
164
166
  const { editedRecord, hasEdits } = useSelect(
165
167
  ( select ) => ( {
166
- editedRecord: select( coreStore ).getEditedEntityRecord(),
167
- hasEdits: select( coreStore ).hasEditsForEntityRecord(),
168
+ editedRecord: select( coreStore ).getEditedEntityRecord(
169
+ kind,
170
+ name,
171
+ recordId
172
+ ),
173
+ hasEdits: select( coreStore ).hasEditsForEntityRecord(
174
+ kind,
175
+ name,
176
+ recordId
177
+ ),
168
178
  } ),
169
179
  [ kind, name, recordId ]
170
180
  );
@@ -24,6 +24,8 @@ const EMPTY_ARRAY = [];
24
24
  /**
25
25
  * Resolves the specified entity records.
26
26
  *
27
+ * @since 6.1.0 Introduced in WordPress core.
28
+ *
27
29
  * @param kind Kind of the entity, e.g. `root` or a `postType`. See rootEntitiesConfig in ../entities.ts for a list of available kinds.
28
30
  * @param name Name of the entity, e.g. `plugin` or a `post`. See rootEntitiesConfig in ../entities.ts for a list of available names.
29
31
  * @param queryArgs Optional HTTP query description for how to fetch the data, passed to the requested API endpoint.
@@ -35,6 +35,9 @@ interface QuerySelectResponse< Data > {
35
35
  * Like useSelect, but the selectors return objects containing
36
36
  * both the original data AND the resolution info.
37
37
  *
38
+ * @since 6.1.0 Introduced in WordPress core.
39
+ * @private
40
+ *
38
41
  * @param {Function} mapQuerySelect see useSelect
39
42
  * @param {Array} deps see useSelect
40
43
  *
@@ -71,7 +74,7 @@ interface QuerySelectResponse< Data > {
71
74
  *
72
75
  * @return {QuerySelectResponse} Queried data.
73
76
  */
74
- export default function __experimentalUseQuerySelect( mapQuerySelect, deps ) {
77
+ export default function useQuerySelect( mapQuerySelect, deps ) {
75
78
  return useSelect( ( select, registry ) => {
76
79
  const resolve = ( store ) => enrichSelectors( select( store ) );
77
80
  return mapQuerySelect( resolve, registry );
@@ -44,6 +44,8 @@ type ResourcePermissionsResolution< IdType > = [
44
44
  /**
45
45
  * Resolves resource permissions.
46
46
  *
47
+ * @since 6.1.0 Introduced in WordPress core.
48
+ *
47
49
  * @param resource The resource in question, e.g. media.
48
50
  * @param id ID of a specific resource entry, if needed, e.g. 10.
49
51
  *
@@ -116,20 +118,39 @@ export default function useResourcePermissions< IdType = void >(
116
118
  const { canUser } = resolve( coreStore );
117
119
  const create = canUser( 'create', resource );
118
120
  if ( ! id ) {
121
+ const read = canUser( 'read', resource );
122
+
123
+ const isResolving = create.isResolving || read.isResolving;
124
+ const hasResolved = create.hasResolved && read.hasResolved;
125
+ let status = Status.Idle;
126
+ if ( isResolving ) {
127
+ status = Status.Resolving;
128
+ } else if ( hasResolved ) {
129
+ status = Status.Success;
130
+ }
131
+
119
132
  return {
120
- status: create.status,
121
- isResolving: create.isResolving,
122
- hasResolved: create.hasResolved,
133
+ status,
134
+ isResolving,
135
+ hasResolved,
123
136
  canCreate: create.hasResolved && create.data,
137
+ canRead: read.hasResolved && read.data,
124
138
  };
125
139
  }
126
140
 
141
+ const read = canUser( 'read', resource, id );
127
142
  const update = canUser( 'update', resource, id );
128
143
  const _delete = canUser( 'delete', resource, id );
129
144
  const isResolving =
130
- create.isResolving || update.isResolving || _delete.isResolving;
145
+ read.isResolving ||
146
+ create.isResolving ||
147
+ update.isResolving ||
148
+ _delete.isResolving;
131
149
  const hasResolved =
132
- create.hasResolved && update.hasResolved && _delete.hasResolved;
150
+ read.hasResolved &&
151
+ create.hasResolved &&
152
+ update.hasResolved &&
153
+ _delete.hasResolved;
133
154
 
134
155
  let status = Status.Idle;
135
156
  if ( isResolving ) {
@@ -141,6 +162,7 @@ export default function useResourcePermissions< IdType = void >(
141
162
  status,
142
163
  isResolving,
143
164
  hasResolved,
165
+ canRead: hasResolved && read.data,
144
166
  canCreate: hasResolved && create.data,
145
167
  canUpdate: hasResolved && update.data,
146
168
  canDelete: hasResolved && _delete.data,
@@ -152,7 +174,7 @@ export default function useResourcePermissions< IdType = void >(
152
174
 
153
175
  export function __experimentalUseResourcePermissions(
154
176
  resource: string,
155
- id?: IdType
177
+ id?: unknown
156
178
  ) {
157
179
  deprecated( `wp.data.__experimentalUseResourcePermissions`, {
158
180
  alternative: 'wp.data.useResourcePermissions',
package/src/index.js CHANGED
@@ -60,8 +60,6 @@ const storeConfig = () => ( {
60
60
  * Store definition for the code data namespace.
61
61
  *
62
62
  * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore
63
- *
64
- * @type {Object}
65
63
  */
66
64
  export const store = createReduxStore( STORE_NAME, storeConfig() );
67
65
 
package/src/resolvers.js CHANGED
@@ -273,34 +273,42 @@ export const getEmbedPreview =
273
273
  * Checks whether the current user can perform the given action on the given
274
274
  * REST resource.
275
275
  *
276
- * @param {string} action Action to check. One of: 'create', 'read', 'update',
277
- * 'delete'.
278
- * @param {string} resource REST resource to check, e.g. 'media' or 'posts'.
279
- * @param {?string} id ID of the rest resource to check.
276
+ * @param {string} requestedAction Action to check. One of: 'create', 'read', 'update',
277
+ * 'delete'.
278
+ * @param {string} resource REST resource to check, e.g. 'media' or 'posts'.
279
+ * @param {?string} id ID of the rest resource to check.
280
280
  */
281
281
  export const canUser =
282
- ( action, resource, id ) =>
283
- async ( { dispatch } ) => {
284
- const methods = {
285
- create: 'POST',
286
- read: 'GET',
287
- update: 'PUT',
288
- delete: 'DELETE',
289
- };
282
+ ( requestedAction, resource, id ) =>
283
+ async ( { dispatch, registry } ) => {
284
+ const { hasStartedResolution } = registry.select( STORE_NAME );
285
+
286
+ const resourcePath = id ? `${ resource }/${ id }` : resource;
287
+ const retrievedActions = [ 'create', 'read', 'update', 'delete' ];
290
288
 
291
- const method = methods[ action ];
292
- if ( ! method ) {
293
- throw new Error( `'${ action }' is not a valid action.` );
289
+ if ( ! retrievedActions.includes( requestedAction ) ) {
290
+ throw new Error( `'${ requestedAction }' is not a valid action.` );
294
291
  }
295
292
 
296
- const path = id
297
- ? `/wp/v2/${ resource }/${ id }`
298
- : `/wp/v2/${ resource }`;
293
+ // Prevent resolving the same resource twice.
294
+ for ( const relatedAction of retrievedActions ) {
295
+ if ( relatedAction === requestedAction ) {
296
+ continue;
297
+ }
298
+ const isAlreadyResolving = hasStartedResolution( 'canUser', [
299
+ relatedAction,
300
+ resource,
301
+ id,
302
+ ] );
303
+ if ( isAlreadyResolving ) {
304
+ return;
305
+ }
306
+ }
299
307
 
300
308
  let response;
301
309
  try {
302
310
  response = await apiFetch( {
303
- path,
311
+ path: `/wp/v2/${ resourcePath }`,
304
312
  method: 'OPTIONS',
305
313
  parse: false,
306
314
  } );
@@ -314,10 +322,25 @@ export const canUser =
314
322
  // return the expected result in the native version. Instead, API requests
315
323
  // only return the result, without including response properties like the headers.
316
324
  const allowHeader = response.headers?.get( 'allow' );
317
- const key = [ action, resource, id ].filter( Boolean ).join( '/' );
318
- const isAllowed =
319
- allowHeader?.includes?.( method ) || allowHeader?.allow === method;
320
- dispatch.receiveUserPermission( key, isAllowed );
325
+ const allowedMethods = allowHeader?.allow || allowHeader || '';
326
+
327
+ const permissions = {};
328
+ const methods = {
329
+ create: 'POST',
330
+ read: 'GET',
331
+ update: 'PUT',
332
+ delete: 'DELETE',
333
+ };
334
+ for ( const [ actionName, methodName ] of Object.entries( methods ) ) {
335
+ permissions[ actionName ] = allowedMethods.includes( methodName );
336
+ }
337
+
338
+ for ( const action of retrievedActions ) {
339
+ dispatch.receiveUserPermission(
340
+ `${ action }/${ resourcePath }`,
341
+ permissions[ action ]
342
+ );
343
+ }
321
344
  };
322
345
 
323
346
  /**