@wordpress/core-data 7.42.0 → 7.43.2-next.v.202604091042.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 (147) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/build/entities.cjs +28 -20
  3. package/build/entities.cjs.map +2 -2
  4. package/build/hooks/index.cjs +3 -3
  5. package/build/hooks/index.cjs.map +1 -1
  6. package/build/hooks/use-entity-record.cjs +4 -4
  7. package/build/hooks/use-entity-record.cjs.map +2 -2
  8. package/build/hooks/use-entity-records.cjs +3 -3
  9. package/build/hooks/use-entity-records.cjs.map +2 -2
  10. package/build/hooks/use-query-select.cjs +2 -2
  11. package/build/hooks/use-query-select.cjs.map +2 -2
  12. package/build/hooks/use-resource-permissions.cjs +4 -4
  13. package/build/hooks/use-resource-permissions.cjs.map +2 -2
  14. package/build/private-actions.cjs +10 -0
  15. package/build/private-actions.cjs.map +2 -2
  16. package/build/private-selectors.cjs +20 -3
  17. package/build/private-selectors.cjs.map +2 -2
  18. package/build/queried-data/get-query-parts.cjs +8 -7
  19. package/build/queried-data/get-query-parts.cjs.map +2 -2
  20. package/build/queried-data/reducer.cjs +15 -9
  21. package/build/queried-data/reducer.cjs.map +2 -2
  22. package/build/queried-data/selectors.cjs +23 -22
  23. package/build/queried-data/selectors.cjs.map +2 -2
  24. package/build/reducer.cjs +16 -3
  25. package/build/reducer.cjs.map +2 -2
  26. package/build/resolvers.cjs +22 -14
  27. package/build/resolvers.cjs.map +2 -2
  28. package/build/selectors.cjs +20 -10
  29. package/build/selectors.cjs.map +2 -2
  30. package/build/utils/crdt-blocks.cjs +170 -31
  31. package/build/utils/crdt-blocks.cjs.map +2 -2
  32. package/build/utils/crdt-text.cjs +52 -0
  33. package/build/utils/crdt-text.cjs.map +7 -0
  34. package/build/utils/crdt.cjs +13 -0
  35. package/build/utils/crdt.cjs.map +2 -2
  36. package/build/utils/index.cjs +0 -3
  37. package/build/utils/index.cjs.map +2 -2
  38. package/build-module/entities.mjs +29 -20
  39. package/build-module/entities.mjs.map +2 -2
  40. package/build-module/hooks/index.mjs +6 -6
  41. package/build-module/hooks/index.mjs.map +2 -2
  42. package/build-module/hooks/use-entity-record.mjs +3 -3
  43. package/build-module/hooks/use-entity-record.mjs.map +2 -2
  44. package/build-module/hooks/use-entity-records.mjs +2 -2
  45. package/build-module/hooks/use-entity-records.mjs.map +2 -2
  46. package/build-module/hooks/use-query-select.mjs +1 -1
  47. package/build-module/hooks/use-query-select.mjs.map +1 -1
  48. package/build-module/hooks/use-resource-permissions.mjs +3 -3
  49. package/build-module/hooks/use-resource-permissions.mjs.map +2 -2
  50. package/build-module/private-actions.mjs +9 -0
  51. package/build-module/private-actions.mjs.map +2 -2
  52. package/build-module/private-selectors.mjs +19 -3
  53. package/build-module/private-selectors.mjs.map +2 -2
  54. package/build-module/queried-data/get-query-parts.mjs +8 -7
  55. package/build-module/queried-data/get-query-parts.mjs.map +2 -2
  56. package/build-module/queried-data/reducer.mjs +15 -9
  57. package/build-module/queried-data/reducer.mjs.map +2 -2
  58. package/build-module/queried-data/selectors.mjs +23 -22
  59. package/build-module/queried-data/selectors.mjs.map +2 -2
  60. package/build-module/reducer.mjs +14 -2
  61. package/build-module/reducer.mjs.map +2 -2
  62. package/build-module/resolvers.mjs +20 -13
  63. package/build-module/resolvers.mjs.map +2 -2
  64. package/build-module/selectors.mjs +20 -11
  65. package/build-module/selectors.mjs.map +2 -2
  66. package/build-module/utils/crdt-blocks.mjs +169 -31
  67. package/build-module/utils/crdt-blocks.mjs.map +2 -2
  68. package/build-module/utils/crdt-text.mjs +26 -0
  69. package/build-module/utils/crdt-text.mjs.map +7 -0
  70. package/build-module/utils/crdt.mjs +13 -0
  71. package/build-module/utils/crdt.mjs.map +2 -2
  72. package/build-module/utils/index.mjs +8 -10
  73. package/build-module/utils/index.mjs.map +2 -2
  74. package/build-types/entities.d.ts +51 -32
  75. package/build-types/entities.d.ts.map +1 -1
  76. package/build-types/hooks/index.d.ts +3 -3
  77. package/build-types/hooks/index.d.ts.map +1 -1
  78. package/build-types/hooks/use-entity-record.d.ts +1 -1
  79. package/build-types/hooks/use-entity-record.d.ts.map +1 -1
  80. package/build-types/hooks/use-entity-records.d.ts +1 -1
  81. package/build-types/hooks/use-entity-records.d.ts.map +1 -1
  82. package/build-types/hooks/use-resource-permissions.d.ts +1 -1
  83. package/build-types/hooks/use-resource-permissions.d.ts.map +1 -1
  84. package/build-types/index.d.ts.map +1 -1
  85. package/build-types/private-actions.d.ts +10 -0
  86. package/build-types/private-actions.d.ts.map +1 -1
  87. package/build-types/private-selectors.d.ts +11 -4
  88. package/build-types/private-selectors.d.ts.map +1 -1
  89. package/build-types/queried-data/get-query-parts.d.ts +11 -19
  90. package/build-types/queried-data/get-query-parts.d.ts.map +1 -1
  91. package/build-types/queried-data/reducer.d.ts +11 -5
  92. package/build-types/queried-data/reducer.d.ts.map +1 -1
  93. package/build-types/queried-data/selectors.d.ts +5 -3
  94. package/build-types/queried-data/selectors.d.ts.map +1 -1
  95. package/build-types/reducer.d.ts +11 -0
  96. package/build-types/reducer.d.ts.map +1 -1
  97. package/build-types/resolvers.d.ts +3 -0
  98. package/build-types/resolvers.d.ts.map +1 -1
  99. package/build-types/selectors.d.ts +1 -0
  100. package/build-types/selectors.d.ts.map +1 -1
  101. package/build-types/utils/crdt-blocks.d.ts +11 -0
  102. package/build-types/utils/crdt-blocks.d.ts.map +1 -1
  103. package/build-types/utils/crdt-text.d.ts +16 -0
  104. package/build-types/utils/crdt-text.d.ts.map +1 -0
  105. package/build-types/utils/crdt.d.ts +7 -0
  106. package/build-types/utils/crdt.d.ts.map +1 -1
  107. package/build-types/utils/index.d.ts +0 -1
  108. package/package.json +18 -18
  109. package/src/entities.js +16 -8
  110. package/src/hooks/index.ts +3 -3
  111. package/src/hooks/test/use-entity-records.js +1 -1
  112. package/src/hooks/use-entity-record.ts +1 -1
  113. package/src/hooks/use-entity-records.ts +1 -1
  114. package/src/hooks/use-query-select.ts +1 -1
  115. package/src/hooks/use-resource-permissions.ts +1 -1
  116. package/src/private-actions.js +18 -0
  117. package/src/private-selectors.ts +37 -4
  118. package/src/queried-data/get-query-parts.js +14 -20
  119. package/src/queried-data/reducer.js +28 -15
  120. package/src/queried-data/selectors.js +34 -38
  121. package/src/queried-data/test/get-query-parts.js +11 -11
  122. package/src/queried-data/test/reducer.js +78 -8
  123. package/src/queried-data/test/selectors.js +52 -30
  124. package/src/reducer.js +20 -0
  125. package/src/resolvers.js +29 -13
  126. package/src/selectors.ts +28 -21
  127. package/src/utils/crdt-blocks.ts +348 -60
  128. package/src/utils/crdt-text.ts +43 -0
  129. package/src/utils/crdt.ts +25 -0
  130. package/src/utils/index.js +0 -1
  131. package/src/utils/test/crdt-blocks.ts +838 -6
  132. package/src/utils/test/crdt.ts +147 -1
  133. package/build/hooks/memoize.cjs +0 -38
  134. package/build/hooks/memoize.cjs.map +0 -7
  135. package/build/utils/is-raw-attribute.cjs +0 -29
  136. package/build/utils/is-raw-attribute.cjs.map +0 -7
  137. package/build-module/hooks/memoize.mjs +0 -7
  138. package/build-module/hooks/memoize.mjs.map +0 -7
  139. package/build-module/utils/is-raw-attribute.mjs +0 -8
  140. package/build-module/utils/is-raw-attribute.mjs.map +0 -7
  141. package/build-types/hooks/memoize.d.ts +0 -3
  142. package/build-types/hooks/memoize.d.ts.map +0 -1
  143. package/build-types/utils/is-raw-attribute.d.ts +0 -10
  144. package/build-types/utils/is-raw-attribute.d.ts.map +0 -1
  145. package/src/hooks/memoize.js +0 -7
  146. package/src/utils/is-raw-attribute.js +0 -11
  147. package/src/utils/test/is-raw-attribute.js +0 -22
@@ -26,12 +26,15 @@ const queriedItemsCacheByState = new WeakMap();
26
26
  /**
27
27
  * Returns items for a given query, or null if the items are not known.
28
28
  *
29
- * @param {Object} state State object.
30
- * @param {?Object} query Optional query.
29
+ * @param {Object} state State object.
30
+ * @param {?Object} query Optional query.
31
+ * @param {?Object} options Optional pagination options.
32
+ * @param {boolean} options.supportsPagination Whether the entity supports pagination. Default true.
31
33
  *
32
34
  * @return {?Array} Query items.
33
35
  */
34
- function getQueriedItemsUncached( state, query ) {
36
+ function getQueriedItemsUncached( state, query, options = {} ) {
37
+ const { supportsPagination = true } = options;
35
38
  const {
36
39
  stableKey,
37
40
  page,
@@ -47,31 +50,20 @@ function getQueriedItemsUncached( state, query ) {
47
50
  return null;
48
51
  }
49
52
 
50
- const startOffset = perPage === -1 ? 0 : ( page - 1 ) * perPage;
51
- const endOffset =
52
- perPage === -1
53
- ? itemIds.length
54
- : Math.min( startOffset + perPage, itemIds.length );
53
+ const isPaginated = supportsPagination && perPage !== -1;
54
+ const startOffset = isPaginated ? queryOffset ?? ( page - 1 ) * perPage : 0;
55
+ const endOffset = isPaginated
56
+ ? Math.min( startOffset + perPage, itemIds.length )
57
+ : itemIds.length;
55
58
 
56
59
  // If the requested page range exceeds the stored itemIds, the data for
57
60
  // this specific pagination window may not have been fetched yet. Return
58
61
  // null unless totalItems confirms we already have all available items.
59
- if ( perPage !== -1 && itemIds.length < startOffset + perPage ) {
62
+ if ( isPaginated && itemIds.length < startOffset + perPage ) {
60
63
  const totalItems =
61
64
  state.queries[ context ][ stableKey ].meta?.totalItems;
62
- if ( Number.isFinite( totalItems ) ) {
63
- // For offset-based queries, totalItems (from X-WP-Total)
64
- // reflects the global count of all matching items, not the
65
- // count remaining after the offset. The number of items
66
- // available for this query is (totalItems - offset), so a
67
- // partial last page is expected and valid.
68
- const effectiveTotal =
69
- queryOffset !== undefined
70
- ? totalItems - queryOffset
71
- : totalItems;
72
- if ( itemIds.length < effectiveTotal ) {
73
- return null;
74
- }
65
+ if ( Number.isFinite( totalItems ) && itemIds.length < totalItems ) {
66
+ return null;
75
67
  }
76
68
  }
77
69
 
@@ -128,27 +120,31 @@ function getQueriedItemsUncached( state, query ) {
128
120
  *
129
121
  * `getQueriedItems( state, {} ) !== getQueriedItems( state, {} )`
130
122
  *
131
- * @param {Object} state State object.
132
- * @param {?Object} query Optional query.
123
+ * @param {Object} state State object.
124
+ * @param {?Object} query Optional query.
125
+ * @param {?Object} options Optional pagination options.
126
+ * @param {boolean} options.supportsPagination Whether the entity supports pagination. Default true.
133
127
  *
134
128
  * @return {?Array} Query items.
135
129
  */
136
- export const getQueriedItems = createSelector( ( state, query = {} ) => {
137
- let queriedItemsCache = queriedItemsCacheByState.get( state );
138
- if ( queriedItemsCache ) {
139
- const queriedItems = queriedItemsCache.get( query );
140
- if ( queriedItems !== undefined ) {
141
- return queriedItems;
130
+ export const getQueriedItems = createSelector(
131
+ ( state, query = {}, options = {} ) => {
132
+ let queriedItemsCache = queriedItemsCacheByState.get( state );
133
+ if ( queriedItemsCache ) {
134
+ const queriedItems = queriedItemsCache.get( query );
135
+ if ( queriedItems !== undefined ) {
136
+ return queriedItems;
137
+ }
138
+ } else {
139
+ queriedItemsCache = new EquivalentKeyMap();
140
+ queriedItemsCacheByState.set( state, queriedItemsCache );
142
141
  }
143
- } else {
144
- queriedItemsCache = new EquivalentKeyMap();
145
- queriedItemsCacheByState.set( state, queriedItemsCache );
146
- }
147
142
 
148
- const items = getQueriedItemsUncached( state, query );
149
- queriedItemsCache.set( query, items );
150
- return items;
151
- } );
143
+ const items = getQueriedItemsUncached( state, query, options );
144
+ queriedItemsCache.set( query, items );
145
+ return items;
146
+ }
147
+ );
152
148
 
153
149
  export function getQueriedTotalItems( state, query = {} ) {
154
150
  const { stableKey, context } = getQueryParts( query );
@@ -11,7 +11,7 @@ describe( 'getQueryParts', () => {
11
11
  context: 'default',
12
12
  page: 2,
13
13
  perPage: 2,
14
- offset: undefined,
14
+ offset: null,
15
15
  stableKey: '',
16
16
  fields: null,
17
17
  include: null,
@@ -29,7 +29,7 @@ describe( 'getQueryParts', () => {
29
29
  context: 'default',
30
30
  page: 1,
31
31
  perPage: 10,
32
- offset: undefined,
32
+ offset: null,
33
33
  stableKey: 'include=1',
34
34
  fields: null,
35
35
  include: [ 1 ],
@@ -45,7 +45,7 @@ describe( 'getQueryParts', () => {
45
45
  context: 'default',
46
46
  page: 1,
47
47
  perPage: 10,
48
- offset: undefined,
48
+ offset: null,
49
49
  stableKey: '%3F=%26&b=2',
50
50
  fields: null,
51
51
  include: null,
@@ -59,7 +59,7 @@ describe( 'getQueryParts', () => {
59
59
  context: 'default',
60
60
  page: 1,
61
61
  perPage: 10,
62
- offset: undefined,
62
+ offset: null,
63
63
  stableKey: 'a%5B0%5D=1&a%5B1%5D=2',
64
64
  fields: null,
65
65
  include: null,
@@ -75,7 +75,7 @@ describe( 'getQueryParts', () => {
75
75
  context: 'default',
76
76
  page: 1,
77
77
  perPage: 10,
78
- offset: undefined,
78
+ offset: null,
79
79
  stableKey: 'b=2',
80
80
  fields: null,
81
81
  include: null,
@@ -89,7 +89,7 @@ describe( 'getQueryParts', () => {
89
89
  context: 'default',
90
90
  page: 1,
91
91
  perPage: -1,
92
- offset: undefined,
92
+ offset: null,
93
93
  stableKey: 'b=2',
94
94
  fields: null,
95
95
  include: null,
@@ -103,7 +103,7 @@ describe( 'getQueryParts', () => {
103
103
  context: 'default',
104
104
  page: 1,
105
105
  perPage: 10,
106
- offset: undefined,
106
+ offset: null,
107
107
  stableKey: '_fields=id%2Ctitle',
108
108
  fields: [ 'id', 'title' ],
109
109
  include: null,
@@ -116,7 +116,7 @@ describe( 'getQueryParts', () => {
116
116
  expect( parts ).toEqual( {
117
117
  page: 1,
118
118
  perPage: 10,
119
- offset: undefined,
119
+ offset: null,
120
120
  stableKey: '',
121
121
  include: null,
122
122
  fields: null,
@@ -124,7 +124,7 @@ describe( 'getQueryParts', () => {
124
124
  } );
125
125
  } );
126
126
 
127
- it( 'extracts offset and includes it in stableKey', () => {
127
+ it( 'extracts offset and excludes it from stableKey', () => {
128
128
  const parts = getQueryParts( {
129
129
  per_page: 50,
130
130
  offset: 100,
@@ -135,7 +135,7 @@ describe( 'getQueryParts', () => {
135
135
  page: 1,
136
136
  perPage: 50,
137
137
  offset: 100,
138
- stableKey: 'offset=100',
138
+ stableKey: '',
139
139
  fields: null,
140
140
  include: null,
141
141
  } );
@@ -147,6 +147,6 @@ describe( 'getQueryParts', () => {
147
147
  offset: 'abc',
148
148
  } );
149
149
 
150
- expect( parts.offset ).toBeUndefined();
150
+ expect( parts.offset ).toBeNull();
151
151
  } );
152
152
  } );
@@ -11,7 +11,10 @@ import { removeItems } from '../actions';
11
11
 
12
12
  describe( 'getMergedItemIds', () => {
13
13
  it( 'should receive a page', () => {
14
- const result = getMergedItemIds( [], [ 4, 5, 6 ], 2, 3 );
14
+ const result = getMergedItemIds( [], [ 4, 5, 6 ], {
15
+ page: 2,
16
+ perPage: 3,
17
+ } );
15
18
 
16
19
  expect( result ).toEqual( [
17
20
  undefined,
@@ -32,46 +35,68 @@ describe( 'getMergedItemIds', () => {
32
35
  5,
33
36
  6,
34
37
  ] );
35
- const result = getMergedItemIds( original, [ 1, 2, 3 ], 1, 3 );
38
+ const result = getMergedItemIds( original, [ 1, 2, 3 ], {
39
+ page: 1,
40
+ perPage: 3,
41
+ } );
36
42
 
37
43
  expect( result ).toEqual( [ 1, 2, 3, 4, 5, 6 ] );
38
44
  } );
39
45
 
40
46
  it( 'should replace with new page', () => {
41
47
  const original = deepFreeze( [ 1, 2, 3, 4, 5, 6 ] );
42
- const result = getMergedItemIds( original, [ 'replaced', 5, 6 ], 2, 3 );
48
+ const result = getMergedItemIds( original, [ 'replaced', 5, 6 ], {
49
+ page: 2,
50
+ perPage: 3,
51
+ } );
43
52
 
44
53
  expect( result ).toEqual( [ 1, 2, 3, 'replaced', 5, 6 ] );
45
54
  } );
46
55
 
47
56
  it( 'should append a new partial page', () => {
48
57
  const original = deepFreeze( [ 1, 2, 3, 4, 5, 6 ] );
49
- const result = getMergedItemIds( original, [ 7 ], 3, 3 );
58
+ const result = getMergedItemIds( original, [ 7 ], {
59
+ page: 3,
60
+ perPage: 3,
61
+ } );
50
62
 
51
63
  expect( result ).toEqual( [ 1, 2, 3, 4, 5, 6, 7 ] );
52
64
  } );
53
65
 
54
66
  it( 'should return a copy of nextItemIds if it represents all ids (single id removed) (page=1 and perPage=-1)', () => {
55
67
  const original = deepFreeze( [ 1, 2, 3 ] );
56
- const result = getMergedItemIds( original, [ 1, 3 ], 1, -1 );
68
+ const result = getMergedItemIds( original, [ 1, 3 ], {
69
+ page: 1,
70
+ perPage: -1,
71
+ } );
57
72
 
58
73
  expect( result ).toEqual( [ 1, 3 ] );
59
74
  } );
60
75
 
61
76
  it( 'should return a copy of nextItemIds if it represents all ids (single id removed and another one added) (page=1 and perPage=-1)', () => {
62
77
  const original = deepFreeze( [ 1, 2, 3 ] );
63
- const result = getMergedItemIds( original, [ 1, 3, 4 ], 1, -1 );
78
+ const result = getMergedItemIds( original, [ 1, 3, 4 ], {
79
+ page: 1,
80
+ perPage: -1,
81
+ } );
64
82
 
65
83
  expect( result ).toEqual( [ 1, 3, 4 ] );
66
84
  } );
85
+
67
86
  it( 'should update a page properly if less items are provided than previously stored', () => {
68
87
  let original = deepFreeze( [ 1, 2, 3 ] );
69
- let result = getMergedItemIds( original, [ 1, 2 ], 1, 3 );
88
+ let result = getMergedItemIds( original, [ 1, 2 ], {
89
+ page: 1,
90
+ perPage: 3,
91
+ } );
70
92
 
71
93
  expect( result ).toEqual( [ 1, 2 ] );
72
94
 
73
95
  original = deepFreeze( [ 1, 2, 3, 4, 5, 6 ] );
74
- result = getMergedItemIds( original, [ 9 ], 2, 2 );
96
+ result = getMergedItemIds( original, [ 9 ], {
97
+ page: 2,
98
+ perPage: 2,
99
+ } );
75
100
 
76
101
  expect( result ).toEqual( [ 1, 2, 9, undefined, 5, 6 ] );
77
102
  } );
@@ -197,6 +222,51 @@ describe( 'reducer', () => {
197
222
  } );
198
223
  } );
199
224
 
225
+ it( 'receives a sparse subset of items at given offsets', () => {
226
+ const original = deepFreeze( {
227
+ items: { default: {} },
228
+ queries: {},
229
+ itemIsComplete: { default: {} },
230
+ } );
231
+ const state = [
232
+ {
233
+ type: 'RECEIVE_ITEMS',
234
+ query: { offset: 1, per_page: 2 },
235
+ items: [
236
+ { id: 2, name: 'def' },
237
+ { id: 3, name: 'ghi' },
238
+ ],
239
+ },
240
+ {
241
+ type: 'RECEIVE_ITEMS',
242
+ query: { offset: 4, per_page: 2 },
243
+ items: [
244
+ { id: 5, name: 'mno' },
245
+ { id: 6, name: 'pqr' },
246
+ ],
247
+ },
248
+ ].reduce( reducer, original );
249
+
250
+ expect( state ).toEqual( {
251
+ items: {
252
+ default: {
253
+ 2: { id: 2, name: 'def' },
254
+ 3: { id: 3, name: 'ghi' },
255
+ 5: { id: 5, name: 'mno' },
256
+ 6: { id: 6, name: 'pqr' },
257
+ },
258
+ },
259
+ itemIsComplete: {
260
+ default: { 2: true, 3: true, 5: true, 6: true },
261
+ },
262
+ queries: {
263
+ default: {
264
+ '': { itemIds: [ undefined, 2, 3, undefined, 5, 6 ] },
265
+ },
266
+ },
267
+ } );
268
+ } );
269
+
200
270
  it( 'deletes an item', () => {
201
271
  const kind = 'root';
202
272
  const name = 'menu';
@@ -2,6 +2,7 @@
2
2
  * Internal dependencies
3
3
  */
4
4
  import { getQueriedItems } from '../selectors';
5
+ import { getMergedItemIds } from '../reducer';
5
6
 
6
7
  describe( 'getQueriedItems', () => {
7
8
  it( 'should return null if requesting but no item IDs', () => {
@@ -261,7 +262,11 @@ describe( 'getQueriedItems', () => {
261
262
  },
262
263
  };
263
264
 
264
- const result = getQueriedItems( state, { per_page: 3 } );
265
+ const result = getQueriedItems(
266
+ state,
267
+ { per_page: 3 },
268
+ { supportsPagination: true }
269
+ );
265
270
  expect( result ).toBe( null );
266
271
  } );
267
272
 
@@ -284,18 +289,22 @@ describe( 'getQueriedItems', () => {
284
289
  },
285
290
  queries: {
286
291
  default: {
287
- 'offset=100': {
288
- itemIds: [ 101, 102, 103 ],
292
+ '': {
293
+ itemIds: getMergedItemIds( [], [ 101, 102, 103 ], {
294
+ offset: 100,
295
+ perPage: 50,
296
+ } ),
289
297
  meta: { totalItems: 103 },
290
298
  },
291
299
  },
292
300
  },
293
301
  };
294
302
 
295
- const result = getQueriedItems( state, {
296
- per_page: 50,
297
- offset: 100,
298
- } );
303
+ const result = getQueriedItems(
304
+ state,
305
+ { per_page: 50, offset: 100 },
306
+ { supportsPagination: true }
307
+ );
299
308
  expect( result ).toEqual( [ { id: 101 }, { id: 102 }, { id: 103 } ] );
300
309
  } );
301
310
 
@@ -314,18 +323,22 @@ describe( 'getQueriedItems', () => {
314
323
  },
315
324
  queries: {
316
325
  default: {
317
- 'offset=50': {
318
- itemIds: [ 51, 52 ],
326
+ '': {
327
+ itemIds: getMergedItemIds( [], [ 51, 52 ], {
328
+ offset: 50,
329
+ perPage: 50,
330
+ } ),
319
331
  meta: { totalItems: 200 },
320
332
  },
321
333
  },
322
334
  },
323
335
  };
324
336
 
325
- const result = getQueriedItems( state, {
326
- per_page: 50,
327
- offset: 50,
328
- } );
337
+ const result = getQueriedItems(
338
+ state,
339
+ { per_page: 50, offset: 50 },
340
+ { supportsPagination: true }
341
+ );
329
342
  expect( result ).toBe( null );
330
343
  } );
331
344
 
@@ -348,18 +361,22 @@ describe( 'getQueriedItems', () => {
348
361
  },
349
362
  queries: {
350
363
  default: {
351
- 'offset=3': {
352
- itemIds: [ 4, 5, 6, 7, 8 ],
364
+ '': {
365
+ itemIds: getMergedItemIds( [], [ 4, 5, 6, 7, 8 ], {
366
+ offset: 3,
367
+ perPage: 10,
368
+ } ),
353
369
  meta: { totalItems: 50 },
354
370
  },
355
371
  },
356
372
  },
357
373
  };
358
374
 
359
- const result = getQueriedItems( state, {
360
- per_page: 10,
361
- offset: 3,
362
- } );
375
+ const result = getQueriedItems(
376
+ state,
377
+ { per_page: 10, offset: 3 },
378
+ { supportsPagination: true }
379
+ );
363
380
  expect( result ).toBe( null );
364
381
  } );
365
382
 
@@ -379,7 +396,7 @@ describe( 'getQueriedItems', () => {
379
396
  },
380
397
  queries: {
381
398
  default: {
382
- 'offset=0': {
399
+ '': {
383
400
  itemIds: [ 1, 2 ],
384
401
  meta: { totalItems: 5 },
385
402
  },
@@ -388,10 +405,11 @@ describe( 'getQueriedItems', () => {
388
405
  };
389
406
 
390
407
  // 2 items stored, but 5 total exist — should return null.
391
- const result = getQueriedItems( state, {
392
- per_page: 3,
393
- offset: 0,
394
- } );
408
+ const result = getQueriedItems(
409
+ state,
410
+ { per_page: 3, offset: 0 },
411
+ { supportsPagination: true }
412
+ );
395
413
  expect( result ).toBe( null );
396
414
  } );
397
415
 
@@ -408,18 +426,22 @@ describe( 'getQueriedItems', () => {
408
426
  },
409
427
  queries: {
410
428
  default: {
411
- 'offset=84': {
412
- itemIds: [],
429
+ '': {
430
+ itemIds: getMergedItemIds( [], [], {
431
+ offset: 84,
432
+ perPage: 7,
433
+ } ),
413
434
  meta: { totalItems: 84 },
414
435
  },
415
436
  },
416
437
  },
417
438
  };
418
439
 
419
- const result = getQueriedItems( state, {
420
- per_page: 7,
421
- offset: 84,
422
- } );
440
+ const result = getQueriedItems(
441
+ state,
442
+ { per_page: 7, offset: 84 },
443
+ { supportsPagination: true }
444
+ );
423
445
  expect( result ).toEqual( [] );
424
446
  } );
425
447
  } );
package/src/reducer.js CHANGED
@@ -721,6 +721,25 @@ export function collaborationSupported( state = true, action ) {
721
721
  return state;
722
722
  }
723
723
 
724
+ /**
725
+ * Reducer managing view configs, keyed by `kind/name`.
726
+ *
727
+ * @param {Object} state Current state.
728
+ * @param {Object} action Dispatched action.
729
+ *
730
+ * @return {Object} Updated state.
731
+ */
732
+ export function viewConfigs( state = {}, action ) {
733
+ switch ( action.type ) {
734
+ case 'RECEIVE_VIEW_CONFIG':
735
+ return {
736
+ ...state,
737
+ [ `${ action.kind }/${ action.name }` ]: action.config,
738
+ };
739
+ }
740
+ return state;
741
+ }
742
+
724
743
  export default combineReducers( {
725
744
  users,
726
745
  currentTheme,
@@ -745,4 +764,5 @@ export default combineReducers( {
745
764
  editorAssets,
746
765
  syncConnectionStatuses,
747
766
  collaborationSupported,
767
+ viewConfigs,
748
768
  } );
package/src/resolvers.js CHANGED
@@ -578,7 +578,7 @@ export const getEntityRecords =
578
578
 
579
579
  dispatch.__unstableReleaseStoreLock( lock );
580
580
  } );
581
- } catch ( e ) {
581
+ } catch {
582
582
  dispatch.__unstableReleaseStoreLock( lock );
583
583
  }
584
584
  };
@@ -635,7 +635,7 @@ export const getEmbedPreview =
635
635
  path: addQueryArgs( '/oembed/1.0/proxy', { url } ),
636
636
  } );
637
637
  dispatch.receiveEmbedPreview( url, embedProxyResponse );
638
- } catch ( error ) {
638
+ } catch {
639
639
  // Embed API 404s if the URL cannot be embedded, so we have to catch the error from the apiRequest here.
640
640
  dispatch.receiveEmbedPreview( url, false );
641
641
  }
@@ -706,7 +706,7 @@ export const canUser =
706
706
  method: 'OPTIONS',
707
707
  parse: false,
708
708
  } );
709
- } catch ( error ) {
709
+ } catch {
710
710
  // Do nothing if our OPTIONS request comes back with an API error (4xx or
711
711
  // 5xx). The previously determined isAllowed value will remain in the store.
712
712
  return;
@@ -991,11 +991,12 @@ export const getDefaultTemplateId =
991
991
  const id = window?.__experimentalTemplateActivate
992
992
  ? template?.wp_id || template?.id
993
993
  : template?.id;
994
- // Endpoint may return an empty object if no template is found.
995
- if ( id ) {
996
- template.id = id;
997
- registry.batch( () => {
998
- dispatch.receiveDefaultTemplateId( query, id );
994
+
995
+ registry.batch( () => {
996
+ dispatch.receiveDefaultTemplateId( query, id || '' );
997
+ // Endpoint may return an empty object if no template is found.
998
+ if ( id ) {
999
+ template.id = id;
999
1000
  dispatch.receiveEntityRecords(
1000
1001
  'postType',
1001
1002
  template.type,
@@ -1007,8 +1008,8 @@ export const getDefaultTemplateId =
1007
1008
  template.type,
1008
1009
  id,
1009
1010
  ] );
1010
- } );
1011
- }
1011
+ }
1012
+ } );
1012
1013
  };
1013
1014
 
1014
1015
  getDefaultTemplateId.shouldInvalidate = ( action ) => {
@@ -1076,7 +1077,7 @@ export const getRevisions =
1076
1077
  entityConfig.supportsPagination && query.per_page !== -1;
1077
1078
  try {
1078
1079
  response = await apiFetch( { path, parse: ! isPaginated } );
1079
- } catch ( error ) {
1080
+ } catch {
1080
1081
  // Do nothing if our request comes back with an API error.
1081
1082
  return;
1082
1083
  }
@@ -1219,7 +1220,7 @@ export const getRevision =
1219
1220
  let record;
1220
1221
  try {
1221
1222
  record = await apiFetch( { path } );
1222
- } catch ( error ) {
1223
+ } catch {
1223
1224
  // Do nothing if our request comes back with an API error.
1224
1225
  return;
1225
1226
  }
@@ -1256,7 +1257,7 @@ export const getRegisteredPostMeta =
1256
1257
  path: `${ restNamespace }/${ restBase }/?context=edit`,
1257
1258
  method: 'OPTIONS',
1258
1259
  } );
1259
- } catch ( error ) {
1260
+ } catch {
1260
1261
  // Do nothing if the request comes back with an API error.
1261
1262
  return;
1262
1263
  }
@@ -1320,3 +1321,18 @@ export const getEditorAssets =
1320
1321
  } );
1321
1322
  dispatch.receiveEditorAssets( assets );
1322
1323
  };
1324
+
1325
+ /**
1326
+ * Requests view config for a given entity type from the REST API.
1327
+ *
1328
+ * @param {string} kind Entity kind.
1329
+ * @param {string} name Entity name.
1330
+ */
1331
+ export const getViewConfig =
1332
+ ( kind, name ) =>
1333
+ async ( { dispatch } ) => {
1334
+ const config = await apiFetch( {
1335
+ path: addQueryArgs( '/wp/v2/view-config', { kind, name } ),
1336
+ } );
1337
+ dispatch.receiveViewConfig( kind, name, config );
1338
+ };