@wordpress/core-data 4.0.1 → 4.0.5
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/README.md +13 -7
- package/build/actions.js +178 -122
- package/build/actions.js.map +1 -1
- package/build/batch/default-processor.js +58 -27
- package/build/batch/default-processor.js.map +1 -1
- package/build/entities.js +70 -23
- package/build/entities.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/index.js +9 -17
- package/build/index.js.map +1 -1
- package/build/locks/actions.js +17 -77
- package/build/locks/actions.js.map +1 -1
- package/build/locks/engine.js +77 -0
- package/build/locks/engine.js.map +1 -0
- package/build/locks/reducer.js +1 -5
- package/build/locks/reducer.js.map +1 -1
- package/build/locks/selectors.js +6 -6
- package/build/locks/selectors.js.map +1 -1
- package/build/queried-data/get-query-parts.js +9 -4
- package/build/queried-data/get-query-parts.js.map +1 -1
- package/build/queried-data/selectors.js +3 -9
- package/build/queried-data/selectors.js.map +1 -1
- package/build/reducer.js +17 -22
- package/build/reducer.js.map +1 -1
- package/build/resolvers.js +151 -97
- package/build/resolvers.js.map +1 -1
- package/build/selectors.js +79 -14
- package/build/selectors.js.map +1 -1
- package/build/utils/forward-resolver.js +23 -0
- package/build/utils/forward-resolver.js.map +1 -0
- package/build/utils/index.js +11 -3
- package/build/utils/index.js.map +1 -1
- package/build/utils/is-raw-attribute.js +19 -0
- package/build/utils/is-raw-attribute.js.map +1 -0
- package/build-module/actions.js +155 -112
- package/build-module/actions.js.map +1 -1
- package/build-module/batch/default-processor.js +57 -27
- package/build-module/batch/default-processor.js.map +1 -1
- package/build-module/entities.js +65 -19
- package/build-module/entities.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/index.js +10 -14
- package/build-module/index.js.map +1 -1
- package/build-module/locks/actions.js +14 -68
- package/build-module/locks/actions.js.map +1 -1
- package/build-module/locks/engine.js +66 -0
- package/build-module/locks/engine.js.map +1 -0
- package/build-module/locks/reducer.js +1 -2
- package/build-module/locks/reducer.js.map +1 -1
- package/build-module/locks/selectors.js +4 -4
- package/build-module/locks/selectors.js.map +1 -1
- package/build-module/queried-data/get-query-parts.js +9 -4
- package/build-module/queried-data/get-query-parts.js.map +1 -1
- package/build-module/queried-data/selectors.js +3 -9
- package/build-module/queried-data/selectors.js.map +1 -1
- package/build-module/reducer.js +15 -19
- package/build-module/reducer.js.map +1 -1
- package/build-module/resolvers.js +123 -81
- package/build-module/resolvers.js.map +1 -1
- package/build-module/selectors.js +74 -13
- package/build-module/selectors.js.map +1 -1
- package/build-module/utils/forward-resolver.js +15 -0
- package/build-module/utils/forward-resolver.js.map +1 -0
- package/build-module/utils/index.js +2 -1
- package/build-module/utils/index.js.map +1 -1
- package/build-module/utils/is-raw-attribute.js +12 -0
- package/build-module/utils/is-raw-attribute.js.map +1 -0
- package/package.json +10 -11
- package/src/actions.js +163 -194
- package/src/batch/default-processor.js +57 -26
- package/src/batch/test/default-processor.js +53 -26
- package/src/entities.js +47 -19
- package/src/fetch/__experimental-fetch-url-data.js +1 -1
- package/src/index.js +7 -10
- package/src/locks/actions.js +10 -61
- package/src/locks/engine.js +43 -0
- package/src/locks/reducer.js +1 -3
- package/src/locks/selectors.js +4 -4
- package/src/locks/test/engine.js +135 -0
- package/src/locks/test/reducer.js +1 -1
- package/src/locks/test/selectors.js +105 -124
- package/src/queried-data/get-query-parts.js +11 -6
- package/src/queried-data/selectors.js +2 -9
- package/src/queried-data/test/get-query-parts.js +1 -1
- package/src/queried-data/test/selectors.js +1 -0
- package/src/reducer.js +14 -19
- package/src/resolvers.js +132 -120
- package/src/selectors.js +156 -44
- package/src/test/actions.js +330 -170
- package/src/test/entities.js +40 -26
- package/src/test/resolvers.js +270 -223
- package/src/test/selectors.js +127 -1
- package/src/utils/forward-resolver.js +14 -0
- package/src/utils/index.js +2 -1
- package/src/utils/is-raw-attribute.js +11 -0
- package/src/utils/test/is-raw-attribute.js +22 -0
- package/build/controls.js +0 -44
- package/build/controls.js.map +0 -1
- package/build/locks/index.js +0 -47
- package/build/locks/index.js.map +0 -1
- package/build/utils/if-not-resolved.js +0 -46
- package/build/utils/if-not-resolved.js.map +0 -1
- package/build-module/controls.js +0 -31
- package/build-module/controls.js.map +0 -1
- package/build-module/locks/index.js +0 -4
- package/build-module/locks/index.js.map +0 -1
- package/build-module/utils/if-not-resolved.js +0 -36
- package/build-module/utils/if-not-resolved.js.map +0 -1
- package/src/controls.js +0 -31
- package/src/locks/index.js +0 -3
- package/src/locks/test/actions.js +0 -307
- package/src/test/integration.js +0 -264
- package/src/utils/if-not-resolved.js +0 -40
- package/src/utils/test/if-not-resolved.js +0 -75
|
@@ -1,10 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { chunk } from 'lodash';
|
|
5
|
+
|
|
1
6
|
/**
|
|
2
7
|
* WordPress dependencies
|
|
3
8
|
*/
|
|
4
9
|
import apiFetch from '@wordpress/api-fetch';
|
|
5
10
|
|
|
6
11
|
/**
|
|
7
|
-
*
|
|
12
|
+
* Maximum number of requests to place in a single batch request. Obtained by
|
|
13
|
+
* sending a preflight OPTIONS request to /batch/v1/.
|
|
14
|
+
*
|
|
15
|
+
* @type {number?}
|
|
16
|
+
*/
|
|
17
|
+
let maxItems = null;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Default batch processor. Sends its input requests to /batch/v1.
|
|
8
21
|
*
|
|
9
22
|
* @param {Array} requests List of API requests to perform at once.
|
|
10
23
|
*
|
|
@@ -13,33 +26,51 @@ import apiFetch from '@wordpress/api-fetch';
|
|
|
13
26
|
* (if not ).
|
|
14
27
|
*/
|
|
15
28
|
export default async function defaultProcessor( requests ) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
path: request.path,
|
|
23
|
-
body: request.data, // Rename 'data' to 'body'.
|
|
24
|
-
method: request.method,
|
|
25
|
-
headers: request.headers,
|
|
26
|
-
} ) ),
|
|
27
|
-
},
|
|
28
|
-
} );
|
|
29
|
-
|
|
30
|
-
if ( batchResponse.failed ) {
|
|
31
|
-
return batchResponse.responses.map( ( response ) => ( {
|
|
32
|
-
error: response?.body,
|
|
33
|
-
} ) );
|
|
29
|
+
if ( maxItems === null ) {
|
|
30
|
+
const preflightResponse = await apiFetch( {
|
|
31
|
+
path: '/batch/v1',
|
|
32
|
+
method: 'OPTIONS',
|
|
33
|
+
} );
|
|
34
|
+
maxItems = preflightResponse.endpoints[ 0 ].args.requests.maxItems;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
const results = [];
|
|
38
|
+
|
|
39
|
+
for ( const batchRequests of chunk( requests, maxItems ) ) {
|
|
40
|
+
const batchResponse = await apiFetch( {
|
|
41
|
+
path: '/batch/v1',
|
|
42
|
+
method: 'POST',
|
|
43
|
+
data: {
|
|
44
|
+
validation: 'require-all-validate',
|
|
45
|
+
requests: batchRequests.map( ( request ) => ( {
|
|
46
|
+
path: request.path,
|
|
47
|
+
body: request.data, // Rename 'data' to 'body'.
|
|
48
|
+
method: request.method,
|
|
49
|
+
headers: request.headers,
|
|
50
|
+
} ) ),
|
|
51
|
+
},
|
|
52
|
+
} );
|
|
53
|
+
|
|
54
|
+
let batchResults;
|
|
55
|
+
|
|
56
|
+
if ( batchResponse.failed ) {
|
|
57
|
+
batchResults = batchResponse.responses.map( ( response ) => ( {
|
|
58
|
+
error: response?.body,
|
|
59
|
+
} ) );
|
|
40
60
|
} else {
|
|
41
|
-
|
|
61
|
+
batchResults = batchResponse.responses.map( ( response ) => {
|
|
62
|
+
const result = {};
|
|
63
|
+
if ( response.status >= 200 && response.status < 300 ) {
|
|
64
|
+
result.output = response.body;
|
|
65
|
+
} else {
|
|
66
|
+
result.error = response.body;
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
} );
|
|
42
70
|
}
|
|
43
|
-
|
|
44
|
-
|
|
71
|
+
|
|
72
|
+
results.push( ...batchResults );
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return results;
|
|
45
76
|
}
|
|
@@ -11,6 +11,18 @@ import defaultProcessor from '../default-processor';
|
|
|
11
11
|
jest.mock( '@wordpress/api-fetch' );
|
|
12
12
|
|
|
13
13
|
describe( 'defaultProcessor', () => {
|
|
14
|
+
const preflightResponse = {
|
|
15
|
+
endpoints: [
|
|
16
|
+
{
|
|
17
|
+
args: {
|
|
18
|
+
requests: {
|
|
19
|
+
maxItems: 25,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
};
|
|
25
|
+
|
|
14
26
|
const requests = [
|
|
15
27
|
{
|
|
16
28
|
path: '/v1/cricketers',
|
|
@@ -26,7 +38,12 @@ describe( 'defaultProcessor', () => {
|
|
|
26
38
|
},
|
|
27
39
|
];
|
|
28
40
|
|
|
29
|
-
const
|
|
41
|
+
const expectedPreflightOptions = {
|
|
42
|
+
path: '/batch/v1',
|
|
43
|
+
method: 'OPTIONS',
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const expectedBatchOptions = {
|
|
30
47
|
path: '/batch/v1',
|
|
31
48
|
method: 'POST',
|
|
32
49
|
data: {
|
|
@@ -49,21 +66,26 @@ describe( 'defaultProcessor', () => {
|
|
|
49
66
|
};
|
|
50
67
|
|
|
51
68
|
it( 'handles a successful request', async () => {
|
|
52
|
-
apiFetch.mockImplementation( async () =>
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
{
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
69
|
+
apiFetch.mockImplementation( async ( { method } ) =>
|
|
70
|
+
method === 'OPTIONS'
|
|
71
|
+
? preflightResponse
|
|
72
|
+
: {
|
|
73
|
+
failed: false,
|
|
74
|
+
responses: [
|
|
75
|
+
{
|
|
76
|
+
status: 200,
|
|
77
|
+
body: 'Lyon',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
status: 400,
|
|
81
|
+
body: 'Error!',
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
}
|
|
85
|
+
);
|
|
65
86
|
const results = await defaultProcessor( requests );
|
|
66
|
-
expect( apiFetch ).toHaveBeenCalledWith(
|
|
87
|
+
expect( apiFetch ).toHaveBeenCalledWith( expectedPreflightOptions );
|
|
88
|
+
expect( apiFetch ).toHaveBeenCalledWith( expectedBatchOptions );
|
|
67
89
|
expect( results ).toEqual( [
|
|
68
90
|
{ output: 'Lyon' },
|
|
69
91
|
{ error: 'Error!' },
|
|
@@ -71,18 +93,23 @@ describe( 'defaultProcessor', () => {
|
|
|
71
93
|
} );
|
|
72
94
|
|
|
73
95
|
it( 'handles a failed request', async () => {
|
|
74
|
-
apiFetch.mockImplementation( async () =>
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
96
|
+
apiFetch.mockImplementation( async ( { method } ) =>
|
|
97
|
+
method === 'OPTIONS'
|
|
98
|
+
? preflightResponse
|
|
99
|
+
: {
|
|
100
|
+
failed: true,
|
|
101
|
+
responses: [
|
|
102
|
+
null,
|
|
103
|
+
{
|
|
104
|
+
status: 400,
|
|
105
|
+
body: 'Error!',
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
}
|
|
109
|
+
);
|
|
84
110
|
const results = await defaultProcessor( requests );
|
|
85
|
-
expect( apiFetch ).toHaveBeenCalledWith(
|
|
111
|
+
expect( apiFetch ).toHaveBeenCalledWith( expectedPreflightOptions );
|
|
112
|
+
expect( apiFetch ).toHaveBeenCalledWith( expectedBatchOptions );
|
|
86
113
|
expect( results ).toEqual( [
|
|
87
114
|
{ error: undefined },
|
|
88
115
|
{ error: 'Error!' },
|
package/src/entities.js
CHANGED
|
@@ -6,24 +6,24 @@ import { upperFirst, camelCase, map, find, get, startCase } from 'lodash';
|
|
|
6
6
|
/**
|
|
7
7
|
* WordPress dependencies
|
|
8
8
|
*/
|
|
9
|
-
import
|
|
10
|
-
import { apiFetch } from '@wordpress/data-controls';
|
|
9
|
+
import apiFetch from '@wordpress/api-fetch';
|
|
11
10
|
import { __ } from '@wordpress/i18n';
|
|
12
11
|
|
|
13
12
|
/**
|
|
14
13
|
* Internal dependencies
|
|
15
14
|
*/
|
|
16
15
|
import { addEntities } from './actions';
|
|
17
|
-
import { STORE_NAME } from './name';
|
|
18
16
|
|
|
19
17
|
export const DEFAULT_ENTITY_KEY = 'id';
|
|
20
18
|
|
|
19
|
+
const POST_RAW_ATTRIBUTES = [ 'title', 'excerpt', 'content' ];
|
|
20
|
+
|
|
21
21
|
export const defaultEntities = [
|
|
22
22
|
{
|
|
23
23
|
label: __( 'Base' ),
|
|
24
24
|
name: '__unstableBase',
|
|
25
25
|
kind: 'root',
|
|
26
|
-
baseURL: '',
|
|
26
|
+
baseURL: '/',
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
29
|
label: __( 'Site' ),
|
|
@@ -41,6 +41,7 @@ export const defaultEntities = [
|
|
|
41
41
|
key: 'slug',
|
|
42
42
|
baseURL: '/wp/v2/types',
|
|
43
43
|
baseURLParams: { context: 'edit' },
|
|
44
|
+
rawAttributes: POST_RAW_ATTRIBUTES,
|
|
44
45
|
},
|
|
45
46
|
{
|
|
46
47
|
name: 'media',
|
|
@@ -115,6 +116,7 @@ export const defaultEntities = [
|
|
|
115
116
|
baseURLParams: { context: 'edit' },
|
|
116
117
|
plural: 'menuItems',
|
|
117
118
|
label: __( 'Menu Item' ),
|
|
119
|
+
rawAttributes: [ 'title', 'content' ],
|
|
118
120
|
},
|
|
119
121
|
{
|
|
120
122
|
name: 'menuLocation',
|
|
@@ -125,6 +127,33 @@ export const defaultEntities = [
|
|
|
125
127
|
label: __( 'Menu Location' ),
|
|
126
128
|
key: 'name',
|
|
127
129
|
},
|
|
130
|
+
{
|
|
131
|
+
name: 'navigationArea',
|
|
132
|
+
kind: 'root',
|
|
133
|
+
baseURL: '/__experimental/block-navigation-areas',
|
|
134
|
+
baseURLParams: { context: 'edit' },
|
|
135
|
+
plural: 'navigationAreas',
|
|
136
|
+
label: __( 'Navigation Area' ),
|
|
137
|
+
key: 'name',
|
|
138
|
+
getTitle: ( record ) => record?.description,
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
label: __( 'Global Styles' ),
|
|
142
|
+
name: 'globalStyles',
|
|
143
|
+
kind: 'root',
|
|
144
|
+
baseURL: '/wp/v2/global-styles',
|
|
145
|
+
baseURLParams: { context: 'edit' },
|
|
146
|
+
plural: 'globalStylesVariations', // should be different than name
|
|
147
|
+
getTitle: ( record ) => record?.title?.rendered || record?.title,
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
label: __( 'Themes' ),
|
|
151
|
+
name: 'theme',
|
|
152
|
+
kind: 'root',
|
|
153
|
+
baseURL: '/wp/v2/themes',
|
|
154
|
+
baseURLParams: { context: 'edit' },
|
|
155
|
+
key: 'stylesheet',
|
|
156
|
+
},
|
|
128
157
|
];
|
|
129
158
|
|
|
130
159
|
export const kinds = [
|
|
@@ -167,15 +196,16 @@ export const prePersistPostType = ( persistedRecord, edits ) => {
|
|
|
167
196
|
*
|
|
168
197
|
* @return {Promise} Entities promise
|
|
169
198
|
*/
|
|
170
|
-
function
|
|
171
|
-
const postTypes =
|
|
199
|
+
async function loadPostTypeEntities() {
|
|
200
|
+
const postTypes = await apiFetch( { path: '/wp/v2/types?context=edit' } );
|
|
172
201
|
return map( postTypes, ( postType, name ) => {
|
|
173
202
|
const isTemplate = [ 'wp_template', 'wp_template_part' ].includes(
|
|
174
203
|
name
|
|
175
204
|
);
|
|
205
|
+
const namespace = postType?.rest_namespace ?? 'wp/v2';
|
|
176
206
|
return {
|
|
177
207
|
kind: 'postType',
|
|
178
|
-
baseURL:
|
|
208
|
+
baseURL: `/${ namespace }/${ postType.rest_base }`,
|
|
179
209
|
baseURLParams: { context: 'edit' },
|
|
180
210
|
name,
|
|
181
211
|
label: postType.labels.singular_name,
|
|
@@ -184,6 +214,7 @@ function* loadPostTypeEntities() {
|
|
|
184
214
|
selection: true,
|
|
185
215
|
},
|
|
186
216
|
mergedEdits: { meta: true },
|
|
217
|
+
rawAttributes: POST_RAW_ATTRIBUTES,
|
|
187
218
|
getTitle: ( record ) =>
|
|
188
219
|
record?.title?.rendered ||
|
|
189
220
|
record?.title ||
|
|
@@ -199,14 +230,15 @@ function* loadPostTypeEntities() {
|
|
|
199
230
|
*
|
|
200
231
|
* @return {Promise} Entities promise
|
|
201
232
|
*/
|
|
202
|
-
function
|
|
203
|
-
const taxonomies =
|
|
233
|
+
async function loadTaxonomyEntities() {
|
|
234
|
+
const taxonomies = await apiFetch( {
|
|
204
235
|
path: '/wp/v2/taxonomies?context=edit',
|
|
205
236
|
} );
|
|
206
237
|
return map( taxonomies, ( taxonomy, name ) => {
|
|
238
|
+
const namespace = taxonomy?.rest_namespace ?? 'wp/v2';
|
|
207
239
|
return {
|
|
208
240
|
kind: 'taxonomy',
|
|
209
|
-
baseURL:
|
|
241
|
+
baseURL: `/${ namespace }/${ taxonomy.rest_base }`,
|
|
210
242
|
baseURLParams: { context: 'edit' },
|
|
211
243
|
name,
|
|
212
244
|
label: taxonomy.labels.singular_name,
|
|
@@ -248,12 +280,8 @@ export const getMethodName = (
|
|
|
248
280
|
*
|
|
249
281
|
* @return {Array} Entities
|
|
250
282
|
*/
|
|
251
|
-
export
|
|
252
|
-
let entities =
|
|
253
|
-
STORE_NAME,
|
|
254
|
-
'getEntitiesByKind',
|
|
255
|
-
kind
|
|
256
|
-
);
|
|
283
|
+
export const getKindEntities = ( kind ) => async ( { select, dispatch } ) => {
|
|
284
|
+
let entities = select.getEntitiesByKind( kind );
|
|
257
285
|
if ( entities && entities.length !== 0 ) {
|
|
258
286
|
return entities;
|
|
259
287
|
}
|
|
@@ -263,8 +291,8 @@ export function* getKindEntities( kind ) {
|
|
|
263
291
|
return [];
|
|
264
292
|
}
|
|
265
293
|
|
|
266
|
-
entities =
|
|
267
|
-
|
|
294
|
+
entities = await kindConfig.loadEntities();
|
|
295
|
+
dispatch( addEntities( entities ) );
|
|
268
296
|
|
|
269
297
|
return entities;
|
|
270
|
-
}
|
|
298
|
+
};
|
|
@@ -45,7 +45,7 @@ const CACHE = new Map();
|
|
|
45
45
|
* @return {Promise< WPRemoteUrlData[] >} Remote URL data.
|
|
46
46
|
*/
|
|
47
47
|
const fetchUrlData = async ( url, options = {} ) => {
|
|
48
|
-
const endpoint = '/
|
|
48
|
+
const endpoint = '/wp-block-editor/v1/url-details';
|
|
49
49
|
|
|
50
50
|
const args = {
|
|
51
51
|
url: prependHTTP( url ),
|
package/src/index.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
4
|
import { createReduxStore, register } from '@wordpress/data';
|
|
5
|
-
import { controls } from '@wordpress/data-controls';
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* Internal dependencies
|
|
@@ -11,9 +10,7 @@ import reducer from './reducer';
|
|
|
11
10
|
import * as selectors from './selectors';
|
|
12
11
|
import * as actions from './actions';
|
|
13
12
|
import * as resolvers from './resolvers';
|
|
14
|
-
import
|
|
15
|
-
import * as locksActions from './locks/actions';
|
|
16
|
-
import customControls from './controls';
|
|
13
|
+
import createLocksActions from './locks/actions';
|
|
17
14
|
import { defaultEntities, getMethodName } from './entities';
|
|
18
15
|
import { STORE_NAME } from './name';
|
|
19
16
|
|
|
@@ -57,13 +54,13 @@ const entityActions = defaultEntities.reduce( ( result, entity ) => {
|
|
|
57
54
|
return result;
|
|
58
55
|
}, {} );
|
|
59
56
|
|
|
60
|
-
const storeConfig = {
|
|
57
|
+
const storeConfig = () => ( {
|
|
61
58
|
reducer,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
selectors: { ...selectors, ...entitySelectors, ...locksSelectors },
|
|
59
|
+
actions: { ...actions, ...entityActions, ...createLocksActions() },
|
|
60
|
+
selectors: { ...selectors, ...entitySelectors },
|
|
65
61
|
resolvers: { ...resolvers, ...entityResolvers },
|
|
66
|
-
|
|
62
|
+
__experimentalUseThunks: true,
|
|
63
|
+
} );
|
|
67
64
|
|
|
68
65
|
/**
|
|
69
66
|
* Store definition for the code data namespace.
|
|
@@ -72,7 +69,7 @@ const storeConfig = {
|
|
|
72
69
|
*
|
|
73
70
|
* @type {Object}
|
|
74
71
|
*/
|
|
75
|
-
export const store = createReduxStore( STORE_NAME, storeConfig );
|
|
72
|
+
export const store = createReduxStore( STORE_NAME, storeConfig() );
|
|
76
73
|
|
|
77
74
|
register( store );
|
|
78
75
|
|
package/src/locks/actions.js
CHANGED
|
@@ -1,69 +1,18 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WordPress dependencies
|
|
3
|
-
*/
|
|
4
|
-
import { __unstableAwaitPromise } from '@wordpress/data-controls';
|
|
5
|
-
import { controls } from '@wordpress/data';
|
|
6
|
-
|
|
7
1
|
/**
|
|
8
2
|
* Internal dependencies
|
|
9
3
|
*/
|
|
10
|
-
import
|
|
4
|
+
import createLocks from './engine';
|
|
11
5
|
|
|
12
|
-
export function
|
|
13
|
-
const
|
|
14
|
-
exclusive,
|
|
15
|
-
} );
|
|
16
|
-
yield* __unstableProcessPendingLockRequests();
|
|
17
|
-
return yield __unstableAwaitPromise( promise );
|
|
18
|
-
}
|
|
6
|
+
export default function createLocksActions() {
|
|
7
|
+
const locks = createLocks();
|
|
19
8
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
notifyAcquired = resolve;
|
|
24
|
-
} );
|
|
25
|
-
yield {
|
|
26
|
-
type: 'ENQUEUE_LOCK_REQUEST',
|
|
27
|
-
request: { store, path, exclusive, notifyAcquired },
|
|
28
|
-
};
|
|
29
|
-
return promise;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function* __unstableReleaseStoreLock( lock ) {
|
|
33
|
-
yield {
|
|
34
|
-
type: 'RELEASE_LOCK',
|
|
35
|
-
lock,
|
|
36
|
-
};
|
|
37
|
-
yield* __unstableProcessPendingLockRequests();
|
|
38
|
-
}
|
|
9
|
+
function __unstableAcquireStoreLock( store, path, { exclusive } ) {
|
|
10
|
+
return () => locks.acquire( store, path, exclusive );
|
|
11
|
+
}
|
|
39
12
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
type: 'PROCESS_PENDING_LOCK_REQUESTS',
|
|
43
|
-
};
|
|
44
|
-
const lockRequests = yield controls.select(
|
|
45
|
-
STORE_NAME,
|
|
46
|
-
'__unstableGetPendingLockRequests'
|
|
47
|
-
);
|
|
48
|
-
for ( const request of lockRequests ) {
|
|
49
|
-
const { store, path, exclusive, notifyAcquired } = request;
|
|
50
|
-
const isAvailable = yield controls.select(
|
|
51
|
-
STORE_NAME,
|
|
52
|
-
'__unstableIsLockAvailable',
|
|
53
|
-
store,
|
|
54
|
-
path,
|
|
55
|
-
{
|
|
56
|
-
exclusive,
|
|
57
|
-
}
|
|
58
|
-
);
|
|
59
|
-
if ( isAvailable ) {
|
|
60
|
-
const lock = { store, path, exclusive };
|
|
61
|
-
yield {
|
|
62
|
-
type: 'GRANT_LOCK_REQUEST',
|
|
63
|
-
lock,
|
|
64
|
-
request,
|
|
65
|
-
};
|
|
66
|
-
notifyAcquired( lock );
|
|
67
|
-
}
|
|
13
|
+
function __unstableReleaseStoreLock( lock ) {
|
|
14
|
+
return () => locks.release( lock );
|
|
68
15
|
}
|
|
16
|
+
|
|
17
|
+
return { __unstableAcquireStoreLock, __unstableReleaseStoreLock };
|
|
69
18
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal dependencies
|
|
3
|
+
*/
|
|
4
|
+
import reducer from './reducer';
|
|
5
|
+
import { isLockAvailable, getPendingLockRequests } from './selectors';
|
|
6
|
+
|
|
7
|
+
export default function createLocks() {
|
|
8
|
+
let state = reducer( undefined, { type: '@@INIT' } );
|
|
9
|
+
|
|
10
|
+
function processPendingLockRequests() {
|
|
11
|
+
for ( const request of getPendingLockRequests( state ) ) {
|
|
12
|
+
const { store, path, exclusive, notifyAcquired } = request;
|
|
13
|
+
if ( isLockAvailable( state, store, path, { exclusive } ) ) {
|
|
14
|
+
const lock = { store, path, exclusive };
|
|
15
|
+
state = reducer( state, {
|
|
16
|
+
type: 'GRANT_LOCK_REQUEST',
|
|
17
|
+
lock,
|
|
18
|
+
request,
|
|
19
|
+
} );
|
|
20
|
+
notifyAcquired( lock );
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function acquire( store, path, exclusive ) {
|
|
26
|
+
return new Promise( ( resolve ) => {
|
|
27
|
+
state = reducer( state, {
|
|
28
|
+
type: 'ENQUEUE_LOCK_REQUEST',
|
|
29
|
+
request: { store, path, exclusive, notifyAcquired: resolve },
|
|
30
|
+
} );
|
|
31
|
+
processPendingLockRequests();
|
|
32
|
+
} );
|
|
33
|
+
}
|
|
34
|
+
function release( lock ) {
|
|
35
|
+
state = reducer( state, {
|
|
36
|
+
type: 'RELEASE_LOCK',
|
|
37
|
+
lock,
|
|
38
|
+
} );
|
|
39
|
+
processPendingLockRequests();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return { acquire, release };
|
|
43
|
+
}
|
package/src/locks/reducer.js
CHANGED
|
@@ -19,7 +19,7 @@ const DEFAULT_STATE = {
|
|
|
19
19
|
*
|
|
20
20
|
* @return {Object} Updated state.
|
|
21
21
|
*/
|
|
22
|
-
export function locks( state = DEFAULT_STATE, action ) {
|
|
22
|
+
export default function locks( state = DEFAULT_STATE, action ) {
|
|
23
23
|
switch ( action.type ) {
|
|
24
24
|
case 'ENQUEUE_LOCK_REQUEST': {
|
|
25
25
|
const { request } = action;
|
|
@@ -60,5 +60,3 @@ export function locks( state = DEFAULT_STATE, action ) {
|
|
|
60
60
|
|
|
61
61
|
return state;
|
|
62
62
|
}
|
|
63
|
-
|
|
64
|
-
export default locks;
|
package/src/locks/selectors.js
CHANGED
|
@@ -8,13 +8,13 @@ import {
|
|
|
8
8
|
getNode,
|
|
9
9
|
} from './utils';
|
|
10
10
|
|
|
11
|
-
export function
|
|
12
|
-
return state.
|
|
11
|
+
export function getPendingLockRequests( state ) {
|
|
12
|
+
return state.requests;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
export function
|
|
15
|
+
export function isLockAvailable( state, store, path, { exclusive } ) {
|
|
16
16
|
const storePath = [ store, ...path ];
|
|
17
|
-
const locks = state.
|
|
17
|
+
const locks = state.tree;
|
|
18
18
|
|
|
19
19
|
// Validate all parents and the node itself
|
|
20
20
|
for ( const node of iteratePath( locks, storePath ) ) {
|