@wordpress/data 9.4.0 → 9.5.1
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 +2 -0
- package/build/components/use-dispatch/use-dispatch-with-map.js +2 -6
- package/build/components/use-dispatch/use-dispatch-with-map.js.map +1 -1
- package/build/components/use-select/index.js +1 -1
- package/build/components/use-select/index.js.map +1 -1
- package/build/components/with-dispatch/index.js +3 -5
- package/build/components/with-dispatch/index.js.map +1 -1
- package/build/components/with-registry/index.js +2 -6
- package/build/components/with-registry/index.js.map +1 -1
- package/build/components/with-select/index.js +3 -3
- package/build/components/with-select/index.js.map +1 -1
- package/build/controls.js +18 -37
- package/build/controls.js.map +1 -1
- package/build/factory.js +2 -4
- package/build/factory.js.map +1 -1
- package/build/{private-apis.js → lock-unlock.js} +1 -1
- package/build/lock-unlock.js.map +1 -0
- package/build/redux-store/index.js +140 -204
- package/build/redux-store/index.js.map +1 -1
- package/build/redux-store/metadata/reducer.js +2 -8
- package/build/redux-store/metadata/reducer.js.map +1 -1
- package/build/redux-store/metadata/selectors.js +5 -15
- package/build/redux-store/metadata/selectors.js.map +1 -1
- package/build/redux-store/metadata/utils.js +1 -3
- package/build/redux-store/metadata/utils.js.map +1 -1
- package/build/registry.js +14 -24
- package/build/registry.js.map +1 -1
- package/build/resolvers-cache-middleware.js +3 -6
- package/build/resolvers-cache-middleware.js.map +1 -1
- package/build/store/index.js +2 -10
- package/build/store/index.js.map +1 -1
- package/build-module/components/use-dispatch/use-dispatch-with-map.js +2 -6
- package/build-module/components/use-dispatch/use-dispatch-with-map.js.map +1 -1
- package/build-module/components/use-select/index.js +1 -1
- package/build-module/components/use-select/index.js.map +1 -1
- package/build-module/components/with-dispatch/index.js +3 -2
- package/build-module/components/with-dispatch/index.js.map +1 -1
- package/build-module/components/with-registry/index.js +2 -3
- package/build-module/components/with-registry/index.js.map +1 -1
- package/build-module/components/with-select/index.js +3 -2
- package/build-module/components/with-select/index.js.map +1 -1
- package/build-module/controls.js +18 -37
- package/build-module/controls.js.map +1 -1
- package/build-module/factory.js +2 -4
- package/build-module/factory.js.map +1 -1
- package/build-module/{private-apis.js → lock-unlock.js} +1 -1
- package/build-module/lock-unlock.js.map +1 -0
- package/build-module/redux-store/index.js +138 -202
- package/build-module/redux-store/index.js.map +1 -1
- package/build-module/redux-store/metadata/reducer.js +2 -8
- package/build-module/redux-store/metadata/reducer.js.map +1 -1
- package/build-module/redux-store/metadata/selectors.js +5 -15
- package/build-module/redux-store/metadata/selectors.js.map +1 -1
- package/build-module/redux-store/metadata/utils.js +1 -3
- package/build-module/redux-store/metadata/utils.js.map +1 -1
- package/build-module/registry.js +9 -19
- package/build-module/registry.js.map +1 -1
- package/build-module/resolvers-cache-middleware.js +3 -6
- package/build-module/resolvers-cache-middleware.js.map +1 -1
- package/build-module/store/index.js +2 -10
- package/build-module/store/index.js.map +1 -1
- package/build-types/{private-apis.d.ts → lock-unlock.d.ts} +1 -1
- package/build-types/lock-unlock.d.ts.map +1 -0
- package/build-types/redux-store/index.d.ts.map +1 -1
- package/package.json +9 -9
- package/src/factory.js +1 -1
- package/src/redux-store/index.js +170 -224
- package/src/registry.js +1 -1
- package/src/test/privateAPIs.js +118 -11
- package/tsconfig.tsbuildinfo +1 -1
- package/build/private-apis.js.map +0 -1
- package/build-module/private-apis.js.map +0 -1
- package/build-types/private-apis.d.ts.map +0 -1
- /package/src/{private-apis.js → lock-unlock.js} +0 -0
package/src/redux-store/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import { compose } from '@wordpress/compose';
|
|
|
15
15
|
* Internal dependencies
|
|
16
16
|
*/
|
|
17
17
|
import { builtinControls } from '../controls';
|
|
18
|
-
import { lock } from '../
|
|
18
|
+
import { lock } from '../lock-unlock';
|
|
19
19
|
import promise from '../promise-middleware';
|
|
20
20
|
import createResolversCacheMiddleware from '../resolvers-cache-middleware';
|
|
21
21
|
import createThunkMiddleware from './thunk-middleware';
|
|
@@ -54,12 +54,11 @@ const trimUndefinedValues = ( array ) => {
|
|
|
54
54
|
* @return {Array} Transformed object.
|
|
55
55
|
*/
|
|
56
56
|
const mapValues = ( obj, callback ) =>
|
|
57
|
-
Object.
|
|
58
|
-
(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
{}
|
|
57
|
+
Object.fromEntries(
|
|
58
|
+
Object.entries( obj ?? {} ).map( ( [ key, value ] ) => [
|
|
59
|
+
key,
|
|
60
|
+
callback( value, key ),
|
|
61
|
+
] )
|
|
63
62
|
);
|
|
64
63
|
|
|
65
64
|
// Convert Map objects to plain objects
|
|
@@ -102,6 +101,21 @@ function createResolversCache() {
|
|
|
102
101
|
};
|
|
103
102
|
}
|
|
104
103
|
|
|
104
|
+
function createBindingCache( bind ) {
|
|
105
|
+
const cache = new WeakMap();
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
get( item ) {
|
|
109
|
+
let boundItem = cache.get( item );
|
|
110
|
+
if ( ! boundItem ) {
|
|
111
|
+
boundItem = bind( item );
|
|
112
|
+
cache.set( item, boundItem );
|
|
113
|
+
}
|
|
114
|
+
return boundItem;
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
105
119
|
/**
|
|
106
120
|
* Creates a data store descriptor for the provided Redux store configuration containing
|
|
107
121
|
* properties describing reducer, actions, selectors, controls and resolvers.
|
|
@@ -148,17 +162,10 @@ export default function createReduxStore( key, options ) {
|
|
|
148
162
|
const thunkArgs = {
|
|
149
163
|
registry,
|
|
150
164
|
get dispatch() {
|
|
151
|
-
return
|
|
152
|
-
( action ) => store.dispatch( action ),
|
|
153
|
-
getActions()
|
|
154
|
-
);
|
|
165
|
+
return thunkActions;
|
|
155
166
|
},
|
|
156
167
|
get select() {
|
|
157
|
-
return
|
|
158
|
-
( selector ) =>
|
|
159
|
-
selector( store.__unstableOriginalGetState() ),
|
|
160
|
-
getSelectors()
|
|
161
|
-
);
|
|
168
|
+
return thunkSelectors;
|
|
162
169
|
},
|
|
163
170
|
get resolveSelect() {
|
|
164
171
|
return getResolveSelectors();
|
|
@@ -176,77 +183,94 @@ export default function createReduxStore( key, options ) {
|
|
|
176
183
|
lock( store, privateRegistrationFunctions );
|
|
177
184
|
const resolversCache = createResolversCache();
|
|
178
185
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
...options.actions,
|
|
184
|
-
},
|
|
185
|
-
store
|
|
186
|
-
);
|
|
187
|
-
lock(
|
|
188
|
-
actions,
|
|
189
|
-
new Proxy( privateActions, {
|
|
190
|
-
get: ( target, prop ) => {
|
|
191
|
-
return (
|
|
192
|
-
mapActions( privateActions, store )[ prop ] ||
|
|
193
|
-
actions[ prop ]
|
|
194
|
-
);
|
|
195
|
-
},
|
|
196
|
-
} )
|
|
197
|
-
);
|
|
186
|
+
function bindAction( action ) {
|
|
187
|
+
return ( ...args ) =>
|
|
188
|
+
Promise.resolve( store.dispatch( action( ...args ) ) );
|
|
189
|
+
}
|
|
198
190
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
( selector ) =>
|
|
204
|
-
( state, ...args ) =>
|
|
205
|
-
selector( state.metadata, ...args )
|
|
206
|
-
),
|
|
207
|
-
...mapValues( options.selectors, ( selector ) => {
|
|
208
|
-
if ( selector.isRegistrySelector ) {
|
|
209
|
-
selector.registry = registry;
|
|
210
|
-
}
|
|
191
|
+
const actions = {
|
|
192
|
+
...mapValues( metadataActions, bindAction ),
|
|
193
|
+
...mapValues( options.actions, bindAction ),
|
|
194
|
+
};
|
|
211
195
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
196
|
+
const boundPrivateActions = createBindingCache( bindAction );
|
|
197
|
+
const allActions = new Proxy( () => {}, {
|
|
198
|
+
get: ( target, prop ) => {
|
|
199
|
+
const privateAction = privateActions[ prop ];
|
|
200
|
+
return privateAction
|
|
201
|
+
? boundPrivateActions.get( privateAction )
|
|
202
|
+
: actions[ prop ];
|
|
215
203
|
},
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
)
|
|
204
|
+
} );
|
|
205
|
+
|
|
206
|
+
const thunkActions = new Proxy( allActions, {
|
|
207
|
+
apply: ( target, thisArg, [ action ] ) =>
|
|
208
|
+
store.dispatch( action ),
|
|
209
|
+
} );
|
|
210
|
+
|
|
211
|
+
lock( actions, allActions );
|
|
212
|
+
|
|
213
|
+
function bindSelector( selector ) {
|
|
214
|
+
if ( selector.isRegistrySelector ) {
|
|
215
|
+
selector.registry = registry;
|
|
216
|
+
}
|
|
217
|
+
const boundSelector = ( ...args ) => {
|
|
218
|
+
const state = store.__unstableOriginalGetState();
|
|
219
|
+
return selector( state.root, ...args );
|
|
220
|
+
};
|
|
221
|
+
boundSelector.hasResolver = false;
|
|
222
|
+
return boundSelector;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function bindMetadataSelector( selector ) {
|
|
226
|
+
const boundSelector = ( ...args ) => {
|
|
227
|
+
const state = store.__unstableOriginalGetState();
|
|
228
|
+
return selector( state.metadata, ...args );
|
|
229
|
+
};
|
|
230
|
+
boundSelector.hasResolver = false;
|
|
231
|
+
return boundSelector;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
let selectors = {
|
|
235
|
+
...mapValues( metadataSelectors, bindMetadataSelector ),
|
|
236
|
+
...mapValues( options.selectors, bindSelector ),
|
|
237
|
+
};
|
|
238
238
|
|
|
239
|
+
let resolvers;
|
|
239
240
|
if ( options.resolvers ) {
|
|
240
|
-
|
|
241
|
-
|
|
241
|
+
resolvers = mapResolvers( options.resolvers );
|
|
242
|
+
selectors = mapSelectorsWithResolvers(
|
|
242
243
|
selectors,
|
|
244
|
+
resolvers,
|
|
243
245
|
store,
|
|
244
246
|
resolversCache
|
|
245
247
|
);
|
|
246
|
-
resolvers = result.resolvers;
|
|
247
|
-
selectors = result.selectors;
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
+
const boundPrivateSelectors = createBindingCache( bindSelector );
|
|
251
|
+
|
|
252
|
+
// Pre-bind the private selectors that have been registered by the time of
|
|
253
|
+
// instantiation, so that registry selectors are bound to the registry.
|
|
254
|
+
for ( const privateSelector of Object.values( privateSelectors ) ) {
|
|
255
|
+
boundPrivateSelectors.get( privateSelector );
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const allSelectors = new Proxy( () => {}, {
|
|
259
|
+
get: ( target, prop ) => {
|
|
260
|
+
const privateSelector = privateSelectors[ prop ];
|
|
261
|
+
return privateSelector
|
|
262
|
+
? boundPrivateSelectors.get( privateSelector )
|
|
263
|
+
: selectors[ prop ];
|
|
264
|
+
},
|
|
265
|
+
} );
|
|
266
|
+
|
|
267
|
+
const thunkSelectors = new Proxy( allSelectors, {
|
|
268
|
+
apply: ( target, thisArg, [ selector ] ) =>
|
|
269
|
+
selector( store.__unstableOriginalGetState() ),
|
|
270
|
+
} );
|
|
271
|
+
|
|
272
|
+
lock( selectors, allSelectors );
|
|
273
|
+
|
|
250
274
|
const resolveSelectors = mapResolveSelectors( selectors, store );
|
|
251
275
|
const suspendSelectors = mapSuspendSelectors( selectors, store );
|
|
252
276
|
|
|
@@ -360,59 +384,6 @@ function instantiateReduxStore( key, options, registry, thunkArgs ) {
|
|
|
360
384
|
);
|
|
361
385
|
}
|
|
362
386
|
|
|
363
|
-
/**
|
|
364
|
-
* Maps selectors to a store.
|
|
365
|
-
*
|
|
366
|
-
* @param {Object} selectors Selectors to register. Keys will be used as the
|
|
367
|
-
* public facing API. Selectors will get passed the
|
|
368
|
-
* state as first argument.
|
|
369
|
-
* @param {Object} store The store to which the selectors should be mapped.
|
|
370
|
-
* @return {Object} Selectors mapped to the provided store.
|
|
371
|
-
*/
|
|
372
|
-
function mapSelectors( selectors, store ) {
|
|
373
|
-
const createStateSelector = ( registrySelector ) => {
|
|
374
|
-
const selector = function runSelector() {
|
|
375
|
-
// This function is an optimized implementation of:
|
|
376
|
-
//
|
|
377
|
-
// selector( store.getState(), ...arguments )
|
|
378
|
-
//
|
|
379
|
-
// Where the above would incur an `Array#concat` in its application,
|
|
380
|
-
// the logic here instead efficiently constructs an arguments array via
|
|
381
|
-
// direct assignment.
|
|
382
|
-
const argsLength = arguments.length;
|
|
383
|
-
const args = new Array( argsLength + 1 );
|
|
384
|
-
args[ 0 ] = store.__unstableOriginalGetState();
|
|
385
|
-
for ( let i = 0; i < argsLength; i++ ) {
|
|
386
|
-
args[ i + 1 ] = arguments[ i ];
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
return registrySelector( ...args );
|
|
390
|
-
};
|
|
391
|
-
selector.hasResolver = false;
|
|
392
|
-
return selector;
|
|
393
|
-
};
|
|
394
|
-
|
|
395
|
-
return mapValues( selectors, createStateSelector );
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
/**
|
|
399
|
-
* Maps actions to dispatch from a given store.
|
|
400
|
-
*
|
|
401
|
-
* @param {Object} actions Actions to register.
|
|
402
|
-
* @param {Object} store The redux store to which the actions should be mapped.
|
|
403
|
-
*
|
|
404
|
-
* @return {Object} Actions mapped to the redux store provided.
|
|
405
|
-
*/
|
|
406
|
-
function mapActions( actions, store ) {
|
|
407
|
-
const createBoundAction =
|
|
408
|
-
( action ) =>
|
|
409
|
-
( ...args ) => {
|
|
410
|
-
return Promise.resolve( store.dispatch( action( ...args ) ) );
|
|
411
|
-
};
|
|
412
|
-
|
|
413
|
-
return mapValues( actions, createBoundAction );
|
|
414
|
-
}
|
|
415
|
-
|
|
416
387
|
/**
|
|
417
388
|
* Maps selectors to functions that return a resolution promise for them
|
|
418
389
|
*
|
|
@@ -519,20 +490,13 @@ function mapSuspendSelectors( selectors, store ) {
|
|
|
519
490
|
}
|
|
520
491
|
|
|
521
492
|
/**
|
|
522
|
-
*
|
|
523
|
-
*
|
|
524
|
-
* used in ensuring that the data needs for the selector are satisfied.
|
|
493
|
+
* Convert resolvers to a normalized form, an object with `fulfill` method and
|
|
494
|
+
* optional methods like `isFulfilled`.
|
|
525
495
|
*
|
|
526
|
-
* @param {Object} resolvers
|
|
527
|
-
* @param {Object} selectors The current selectors to be modified.
|
|
528
|
-
* @param {Object} store The redux store to which the resolvers should be mapped.
|
|
529
|
-
* @param {Object} resolversCache Resolvers Cache.
|
|
496
|
+
* @param {Object} resolvers Resolver to convert
|
|
530
497
|
*/
|
|
531
|
-
function mapResolvers( resolvers
|
|
532
|
-
|
|
533
|
-
// cases, an object with a `fullfill` method and other optional methods like `isFulfilled`.
|
|
534
|
-
// Here we normalize the `resolver` function to an object with `fulfill` method.
|
|
535
|
-
const mappedResolvers = mapValues( resolvers, ( resolver ) => {
|
|
498
|
+
function mapResolvers( resolvers ) {
|
|
499
|
+
return mapValues( resolvers, ( resolver ) => {
|
|
536
500
|
if ( resolver.fulfill ) {
|
|
537
501
|
return resolver;
|
|
538
502
|
}
|
|
@@ -542,99 +506,81 @@ function mapResolvers( resolvers, selectors, store, resolversCache ) {
|
|
|
542
506
|
fulfill: resolver, // Add the fulfill method.
|
|
543
507
|
};
|
|
544
508
|
} );
|
|
509
|
+
}
|
|
545
510
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
511
|
+
/**
|
|
512
|
+
* Returns resolvers with matched selectors for a given namespace.
|
|
513
|
+
* Resolvers are side effects invoked once per argument set of a given selector call,
|
|
514
|
+
* used in ensuring that the data needs for the selector are satisfied.
|
|
515
|
+
*
|
|
516
|
+
* @param {Object} selectors The current selectors to be modified.
|
|
517
|
+
* @param {Object} resolvers Resolvers to register.
|
|
518
|
+
* @param {Object} store The redux store to which the resolvers should be mapped.
|
|
519
|
+
* @param {Object} resolversCache Resolvers Cache.
|
|
520
|
+
*/
|
|
521
|
+
function mapSelectorsWithResolvers(
|
|
522
|
+
selectors,
|
|
523
|
+
resolvers,
|
|
524
|
+
store,
|
|
525
|
+
resolversCache
|
|
526
|
+
) {
|
|
527
|
+
function fulfillSelector( resolver, selectorName, args ) {
|
|
528
|
+
const state = store.getState();
|
|
529
|
+
|
|
530
|
+
if (
|
|
531
|
+
resolversCache.isRunning( selectorName, args ) ||
|
|
532
|
+
( typeof resolver.isFulfilled === 'function' &&
|
|
533
|
+
resolver.isFulfilled( state, ...args ) )
|
|
534
|
+
) {
|
|
535
|
+
return;
|
|
551
536
|
}
|
|
552
537
|
|
|
553
|
-
const
|
|
554
|
-
async function fulfillSelector() {
|
|
555
|
-
const state = store.getState();
|
|
556
|
-
|
|
557
|
-
if (
|
|
558
|
-
resolversCache.isRunning( selectorName, args ) ||
|
|
559
|
-
( typeof resolver.isFulfilled === 'function' &&
|
|
560
|
-
resolver.isFulfilled( state, ...args ) )
|
|
561
|
-
) {
|
|
562
|
-
return;
|
|
563
|
-
}
|
|
538
|
+
const { metadata } = store.__unstableOriginalGetState();
|
|
564
539
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
return;
|
|
575
|
-
}
|
|
540
|
+
if (
|
|
541
|
+
metadataSelectors.hasStartedResolution(
|
|
542
|
+
metadata,
|
|
543
|
+
selectorName,
|
|
544
|
+
args
|
|
545
|
+
)
|
|
546
|
+
) {
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
576
549
|
|
|
577
|
-
|
|
550
|
+
resolversCache.markAsRunning( selectorName, args );
|
|
578
551
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
);
|
|
597
|
-
} catch ( error ) {
|
|
598
|
-
store.dispatch(
|
|
599
|
-
metadataActions.failResolution(
|
|
600
|
-
selectorName,
|
|
601
|
-
args,
|
|
602
|
-
error
|
|
603
|
-
)
|
|
604
|
-
);
|
|
605
|
-
}
|
|
606
|
-
} );
|
|
552
|
+
setTimeout( async () => {
|
|
553
|
+
resolversCache.clear( selectorName, args );
|
|
554
|
+
store.dispatch(
|
|
555
|
+
metadataActions.startResolution( selectorName, args )
|
|
556
|
+
);
|
|
557
|
+
try {
|
|
558
|
+
const action = resolver.fulfill( ...args );
|
|
559
|
+
if ( action ) {
|
|
560
|
+
await store.dispatch( action );
|
|
561
|
+
}
|
|
562
|
+
store.dispatch(
|
|
563
|
+
metadataActions.finishResolution( selectorName, args )
|
|
564
|
+
);
|
|
565
|
+
} catch ( error ) {
|
|
566
|
+
store.dispatch(
|
|
567
|
+
metadataActions.failResolution( selectorName, args, error )
|
|
568
|
+
);
|
|
607
569
|
}
|
|
570
|
+
}, 0 );
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
return mapValues( selectors, ( selector, selectorName ) => {
|
|
574
|
+
const resolver = resolvers[ selectorName ];
|
|
575
|
+
if ( ! resolver ) {
|
|
576
|
+
return selector;
|
|
577
|
+
}
|
|
608
578
|
|
|
609
|
-
|
|
579
|
+
const selectorResolver = ( ...args ) => {
|
|
580
|
+
fulfillSelector( resolver, selectorName, args );
|
|
610
581
|
return selector( ...args );
|
|
611
582
|
};
|
|
612
583
|
selectorResolver.hasResolver = true;
|
|
613
584
|
return selectorResolver;
|
|
614
|
-
};
|
|
615
|
-
|
|
616
|
-
return {
|
|
617
|
-
resolvers: mappedResolvers,
|
|
618
|
-
selectors: mapValues( selectors, mapSelector ),
|
|
619
|
-
};
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
/**
|
|
623
|
-
* Calls a resolver given arguments
|
|
624
|
-
*
|
|
625
|
-
* @param {Object} store Store reference, for fulfilling via resolvers
|
|
626
|
-
* @param {Object} resolvers Store Resolvers
|
|
627
|
-
* @param {string} selectorName Selector name to fulfill.
|
|
628
|
-
* @param {Array} args Selector Arguments.
|
|
629
|
-
*/
|
|
630
|
-
async function fulfillResolver( store, resolvers, selectorName, ...args ) {
|
|
631
|
-
const resolver = resolvers[ selectorName ];
|
|
632
|
-
if ( ! resolver ) {
|
|
633
|
-
return;
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
const action = resolver.fulfill( ...args );
|
|
637
|
-
if ( action ) {
|
|
638
|
-
await store.dispatch( action );
|
|
639
|
-
}
|
|
585
|
+
} );
|
|
640
586
|
}
|
package/src/registry.js
CHANGED
|
@@ -9,7 +9,7 @@ import deprecated from '@wordpress/deprecated';
|
|
|
9
9
|
import createReduxStore from './redux-store';
|
|
10
10
|
import coreDataStore from './store';
|
|
11
11
|
import { createEmitter } from './utils/emitter';
|
|
12
|
-
import { lock, unlock } from './
|
|
12
|
+
import { lock, unlock } from './lock-unlock';
|
|
13
13
|
|
|
14
14
|
/** @typedef {import('./types').StoreDescriptor} StoreDescriptor */
|
|
15
15
|
|
package/src/test/privateAPIs.js
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { createRegistry } from '../registry';
|
|
5
5
|
import createReduxStore from '../redux-store';
|
|
6
|
-
import { unlock } from '../
|
|
6
|
+
import { unlock } from '../lock-unlock';
|
|
7
|
+
import { createRegistrySelector } from '../factory';
|
|
7
8
|
|
|
8
9
|
describe( 'Private data APIs', () => {
|
|
9
10
|
let registry;
|
|
@@ -32,23 +33,19 @@ describe( 'Private data APIs', () => {
|
|
|
32
33
|
getState: ( state ) => state,
|
|
33
34
|
},
|
|
34
35
|
actions: { setPublicPrice },
|
|
35
|
-
reducer: ( state, action ) => {
|
|
36
|
-
if ( action
|
|
36
|
+
reducer: ( state = { price: 1000, secretDiscount: 800 }, action ) => {
|
|
37
|
+
if ( action.type === 'SET_PRIVATE_PRICE' ) {
|
|
37
38
|
return {
|
|
38
39
|
...state,
|
|
39
|
-
secretDiscount: action
|
|
40
|
+
secretDiscount: action.price,
|
|
40
41
|
};
|
|
41
|
-
} else if ( action
|
|
42
|
+
} else if ( action.type === 'SET_PUBLIC_PRICE' ) {
|
|
42
43
|
return {
|
|
43
44
|
...state,
|
|
44
|
-
price: action
|
|
45
|
+
price: action.price,
|
|
45
46
|
};
|
|
46
47
|
}
|
|
47
|
-
return
|
|
48
|
-
price: 1000,
|
|
49
|
-
secretDiscount: 800,
|
|
50
|
-
...( state || {} ),
|
|
51
|
-
};
|
|
48
|
+
return state;
|
|
52
49
|
},
|
|
53
50
|
};
|
|
54
51
|
function createStore() {
|
|
@@ -96,6 +93,37 @@ describe( 'Private data APIs', () => {
|
|
|
96
93
|
);
|
|
97
94
|
} );
|
|
98
95
|
|
|
96
|
+
it( 'should support combination of private selectors and resolvers', async () => {
|
|
97
|
+
const testStore = createReduxStore( 'test', {
|
|
98
|
+
reducer: ( state = {}, action ) => {
|
|
99
|
+
if ( action.type === 'RECEIVE' ) {
|
|
100
|
+
return { ...state, [ action.key ]: action.value };
|
|
101
|
+
}
|
|
102
|
+
return state;
|
|
103
|
+
},
|
|
104
|
+
selectors: {
|
|
105
|
+
get: ( state, key ) => state[ key ],
|
|
106
|
+
},
|
|
107
|
+
resolvers: {
|
|
108
|
+
get:
|
|
109
|
+
( key ) =>
|
|
110
|
+
async ( { dispatch } ) => {
|
|
111
|
+
const value = await ( 'resolved-' + key );
|
|
112
|
+
dispatch( { type: 'RECEIVE', key, value } );
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
} );
|
|
116
|
+
unlock( testStore ).registerPrivateSelectors( {
|
|
117
|
+
peek: ( state, key ) => state[ key ],
|
|
118
|
+
} );
|
|
119
|
+
registry.register( testStore );
|
|
120
|
+
|
|
121
|
+
await registry.resolveSelect( testStore ).get( 'x' );
|
|
122
|
+
expect( unlock( registry.select( testStore ) ).peek( 'x' ) ).toBe(
|
|
123
|
+
'resolved-x'
|
|
124
|
+
);
|
|
125
|
+
} );
|
|
126
|
+
|
|
99
127
|
it( 'should give private selectors access to the state', () => {
|
|
100
128
|
const groceryStore = createStore();
|
|
101
129
|
unlock( groceryStore ).registerPrivateSelectors( {
|
|
@@ -116,6 +144,16 @@ describe( 'Private data APIs', () => {
|
|
|
116
144
|
expect( unlockedSelectors.getPublicPrice() ).toEqual( 1000 );
|
|
117
145
|
} );
|
|
118
146
|
|
|
147
|
+
it( 'should return stable references to selectors', () => {
|
|
148
|
+
const groceryStore = createStore();
|
|
149
|
+
unlock( groceryStore ).registerPrivateSelectors( {
|
|
150
|
+
getSecretDiscount,
|
|
151
|
+
} );
|
|
152
|
+
const select = unlock( registry.select( groceryStore ) );
|
|
153
|
+
expect( select.getPublicPrice ).toBe( select.getPublicPrice );
|
|
154
|
+
expect( select.getSecretDiscount ).toBe( select.getSecretDiscount );
|
|
155
|
+
} );
|
|
156
|
+
|
|
119
157
|
it( 'should support registerStore', () => {
|
|
120
158
|
const groceryStore = registry.registerStore(
|
|
121
159
|
storeName,
|
|
@@ -164,6 +202,42 @@ describe( 'Private data APIs', () => {
|
|
|
164
202
|
);
|
|
165
203
|
expect( subPrivateSelectors.getSecretDiscount() ).toEqual( 800 );
|
|
166
204
|
} );
|
|
205
|
+
|
|
206
|
+
it( 'should support private registry selectors', () => {
|
|
207
|
+
const groceryStore = createStore();
|
|
208
|
+
const otherStore = createReduxStore( 'other', {
|
|
209
|
+
reducer: ( state = {} ) => state,
|
|
210
|
+
} );
|
|
211
|
+
unlock( otherStore ).registerPrivateSelectors( {
|
|
212
|
+
getPrice: createRegistrySelector(
|
|
213
|
+
( select ) => () => select( groceryStore ).getPublicPrice()
|
|
214
|
+
),
|
|
215
|
+
} );
|
|
216
|
+
registry.register( otherStore );
|
|
217
|
+
const privateSelectors = unlock( registry.select( otherStore ) );
|
|
218
|
+
expect( privateSelectors.getPrice() ).toEqual( 1000 );
|
|
219
|
+
} );
|
|
220
|
+
|
|
221
|
+
it( 'should support calling a private registry selector from a public selector', () => {
|
|
222
|
+
const groceryStore = createStore();
|
|
223
|
+
const getPriceWithShipping = createRegistrySelector(
|
|
224
|
+
( select ) => () => select( groceryStore ).getPublicPrice() + 5
|
|
225
|
+
);
|
|
226
|
+
const store = createReduxStore( 'a', {
|
|
227
|
+
reducer: ( state = {} ) => state,
|
|
228
|
+
selectors: {
|
|
229
|
+
getPriceWithShippingAndTax: ( state ) =>
|
|
230
|
+
getPriceWithShipping( state ) * 1.1,
|
|
231
|
+
},
|
|
232
|
+
} );
|
|
233
|
+
unlock( store ).registerPrivateSelectors( {
|
|
234
|
+
getPriceWithShipping,
|
|
235
|
+
} );
|
|
236
|
+
registry.register( store );
|
|
237
|
+
expect(
|
|
238
|
+
registry.select( store ).getPriceWithShippingAndTax()
|
|
239
|
+
).toEqual( 1105.5 );
|
|
240
|
+
} );
|
|
167
241
|
} );
|
|
168
242
|
|
|
169
243
|
describe( 'private actions', () => {
|
|
@@ -232,6 +306,16 @@ describe( 'Private data APIs', () => {
|
|
|
232
306
|
).toEqual( 400 );
|
|
233
307
|
} );
|
|
234
308
|
|
|
309
|
+
it( 'should return stable references to actions', () => {
|
|
310
|
+
const groceryStore = createStore();
|
|
311
|
+
unlock( groceryStore ).registerPrivateActions( {
|
|
312
|
+
setSecretDiscount,
|
|
313
|
+
} );
|
|
314
|
+
const disp = unlock( registry.dispatch( groceryStore ) );
|
|
315
|
+
expect( disp.setPublicPrice ).toBe( disp.setPublicPrice );
|
|
316
|
+
expect( disp.setSecretDiscount ).toBe( disp.setSecretDiscount );
|
|
317
|
+
} );
|
|
318
|
+
|
|
235
319
|
it( 'should dispatch public actions on the unlocked store', () => {
|
|
236
320
|
const groceryStore = createStore();
|
|
237
321
|
unlock( groceryStore ).registerPrivateActions( {
|
|
@@ -263,6 +347,29 @@ describe( 'Private data APIs', () => {
|
|
|
263
347
|
).toEqual( 100 );
|
|
264
348
|
} );
|
|
265
349
|
|
|
350
|
+
it( 'should expose unlocked private selectors and actions to thunks', () => {
|
|
351
|
+
const groceryStore = createStore();
|
|
352
|
+
unlock( groceryStore ).registerPrivateSelectors( {
|
|
353
|
+
getSecretDiscount,
|
|
354
|
+
} );
|
|
355
|
+
unlock( groceryStore ).registerPrivateActions( {
|
|
356
|
+
setSecretDiscount,
|
|
357
|
+
doubleSecretDiscount() {
|
|
358
|
+
return ( { dispatch, select } ) => {
|
|
359
|
+
dispatch.setSecretDiscount(
|
|
360
|
+
select.getSecretDiscount() * 2
|
|
361
|
+
);
|
|
362
|
+
};
|
|
363
|
+
},
|
|
364
|
+
} );
|
|
365
|
+
const privateActions = unlock( registry.dispatch( groceryStore ) );
|
|
366
|
+
privateActions.setSecretDiscount( 100 );
|
|
367
|
+
privateActions.doubleSecretDiscount();
|
|
368
|
+
expect(
|
|
369
|
+
unlock( registry.select( groceryStore ) ).getSecretDiscount()
|
|
370
|
+
).toEqual( 200 );
|
|
371
|
+
} );
|
|
372
|
+
|
|
266
373
|
it( 'should support registerStore', () => {
|
|
267
374
|
const groceryStore = registry.registerStore(
|
|
268
375
|
storeName,
|