@wordpress/core-data 6.16.0 → 6.17.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/actions.js +69 -134
- package/build/actions.js.map +1 -1
- package/build/batch/create-batch.js +0 -22
- package/build/batch/create-batch.js.map +1 -1
- package/build/batch/default-processor.js +3 -15
- package/build/batch/default-processor.js.map +1 -1
- package/build/batch/index.js +0 -3
- package/build/batch/index.js.map +1 -1
- package/build/entities.js +109 -36
- package/build/entities.js.map +1 -1
- package/build/entity-provider.js +34 -53
- package/build/entity-provider.js.map +1 -1
- package/build/entity-types/attachment.js.map +1 -1
- package/build/entity-types/base-entity-records.js +0 -3
- package/build/entity-types/base-entity-records.js.map +1 -1
- package/build/entity-types/comment.js.map +1 -1
- package/build/entity-types/helpers.js.map +1 -1
- package/build/entity-types/index.js.map +1 -1
- package/build/entity-types/menu-location.js.map +1 -1
- package/build/entity-types/nav-menu-item.js.map +1 -1
- package/build/entity-types/nav-menu.js.map +1 -1
- package/build/entity-types/page.js.map +1 -1
- package/build/entity-types/plugin.js.map +1 -1
- package/build/entity-types/post.js.map +1 -1
- package/build/entity-types/settings.js.map +1 -1
- package/build/entity-types/sidebar.js.map +1 -1
- package/build/entity-types/taxonomy.js.map +1 -1
- package/build/entity-types/theme.js.map +1 -1
- package/build/entity-types/type.js.map +1 -1
- package/build/entity-types/user.js.map +1 -1
- package/build/entity-types/widget-type.js.map +1 -1
- package/build/entity-types/widget.js.map +1 -1
- package/build/entity-types/wp-template-part.js.map +1 -1
- package/build/entity-types/wp-template.js.map +1 -1
- package/build/fetch/__experimental-fetch-link-suggestions.js +14 -20
- package/build/fetch/__experimental-fetch-link-suggestions.js.map +1 -1
- package/build/fetch/__experimental-fetch-url-data.js +4 -13
- package/build/fetch/__experimental-fetch-url-data.js.map +1 -1
- package/build/fetch/index.js +0 -3
- package/build/fetch/index.js.map +1 -1
- package/build/hooks/constants.js +4 -5
- package/build/hooks/constants.js.map +1 -1
- package/build/hooks/index.js +0 -5
- package/build/hooks/index.js.map +1 -1
- package/build/hooks/memoize.js +0 -3
- package/build/hooks/memoize.js.map +1 -1
- package/build/hooks/use-entity-record.js +0 -9
- package/build/hooks/use-entity-record.js.map +1 -1
- package/build/hooks/use-entity-records.js +2 -9
- package/build/hooks/use-entity-records.js.map +1 -1
- package/build/hooks/use-query-select.js +1 -13
- package/build/hooks/use-query-select.js.map +1 -1
- package/build/hooks/use-resource-permissions.js +0 -15
- package/build/hooks/use-resource-permissions.js.map +1 -1
- package/build/index.js +9 -41
- package/build/index.js.map +1 -1
- package/build/locks/actions.js +1 -6
- package/build/locks/actions.js.map +1 -1
- package/build/locks/engine.js +1 -9
- package/build/locks/engine.js.map +1 -1
- package/build/locks/reducer.js +8 -9
- package/build/locks/reducer.js.map +1 -1
- package/build/locks/selectors.js +8 -11
- package/build/locks/selectors.js.map +1 -1
- package/build/locks/utils.js +4 -19
- package/build/locks/utils.js.map +1 -1
- package/build/name.js +0 -1
- package/build/name.js.map +1 -1
- package/build/private-apis.js +1 -2
- package/build/private-apis.js.map +1 -1
- package/build/private-selectors.js +2 -5
- package/build/private-selectors.js.map +1 -1
- package/build/queried-data/actions.js +4 -6
- package/build/queried-data/actions.js.map +1 -1
- package/build/queried-data/get-query-parts.js +11 -24
- package/build/queried-data/get-query-parts.js.map +1 -1
- package/build/queried-data/index.js +0 -6
- package/build/queried-data/index.js.map +1 -1
- package/build/queried-data/reducer.js +33 -51
- package/build/queried-data/reducer.js.map +1 -1
- package/build/queried-data/selectors.js +4 -25
- package/build/queried-data/selectors.js.map +1 -1
- package/build/reducer.js +76 -128
- package/build/reducer.js.map +1 -1
- package/build/resolvers.js +91 -133
- package/build/resolvers.js.map +1 -1
- package/build/selectors.js +51 -145
- package/build/selectors.js.map +1 -1
- package/build/sync.js +19 -0
- package/build/sync.js.map +1 -0
- package/build/types.js.map +1 -1
- package/build/utils/conservative-map-item.js +3 -10
- package/build/utils/conservative-map-item.js.map +1 -1
- package/build/utils/forward-resolver.js +0 -2
- package/build/utils/forward-resolver.js.map +1 -1
- package/build/utils/get-normalized-comma-separable.js +0 -3
- package/build/utils/get-normalized-comma-separable.js.map +1 -1
- package/build/utils/if-matching-action.js +0 -3
- package/build/utils/if-matching-action.js.map +1 -1
- package/build/utils/index.js +0 -10
- package/build/utils/index.js.map +1 -1
- package/build/utils/is-raw-attribute.js +0 -1
- package/build/utils/is-raw-attribute.js.map +1 -1
- package/build/utils/on-sub-key.js +5 -9
- package/build/utils/on-sub-key.js.map +1 -1
- package/build/utils/replace-action.js +0 -2
- package/build/utils/replace-action.js.map +1 -1
- package/build/utils/set-nested-value.js +0 -4
- package/build/utils/set-nested-value.js.map +1 -1
- package/build/utils/with-weak-map-cache.js +3 -6
- package/build/utils/with-weak-map-cache.js.map +1 -1
- package/build-module/actions.js +72 -95
- package/build-module/actions.js.map +1 -1
- package/build-module/batch/create-batch.js +1 -20
- package/build-module/batch/create-batch.js.map +1 -1
- package/build-module/batch/default-processor.js +4 -13
- package/build-module/batch/default-processor.js.map +1 -1
- package/build-module/batch/index.js.map +1 -1
- package/build-module/entities.js +109 -25
- package/build-module/entities.js.map +1 -1
- package/build-module/entity-provider.js +35 -45
- package/build-module/entity-provider.js.map +1 -1
- package/build-module/entity-types/attachment.js.map +1 -1
- package/build-module/entity-types/base-entity-records.js +0 -2
- package/build-module/entity-types/base-entity-records.js.map +1 -1
- package/build-module/entity-types/comment.js.map +1 -1
- package/build-module/entity-types/helpers.js.map +1 -1
- package/build-module/entity-types/index.js.map +1 -1
- package/build-module/entity-types/menu-location.js.map +1 -1
- package/build-module/entity-types/nav-menu-item.js.map +1 -1
- package/build-module/entity-types/nav-menu.js.map +1 -1
- package/build-module/entity-types/page.js.map +1 -1
- package/build-module/entity-types/plugin.js.map +1 -1
- package/build-module/entity-types/post.js.map +1 -1
- package/build-module/entity-types/settings.js.map +1 -1
- package/build-module/entity-types/sidebar.js.map +1 -1
- package/build-module/entity-types/taxonomy.js.map +1 -1
- package/build-module/entity-types/theme.js.map +1 -1
- package/build-module/entity-types/type.js.map +1 -1
- package/build-module/entity-types/user.js.map +1 -1
- package/build-module/entity-types/widget-type.js.map +1 -1
- package/build-module/entity-types/widget.js.map +1 -1
- package/build-module/entity-types/wp-template-part.js.map +1 -1
- package/build-module/entity-types/wp-template.js.map +1 -1
- package/build-module/fetch/__experimental-fetch-link-suggestions.js +15 -15
- package/build-module/fetch/__experimental-fetch-link-suggestions.js.map +1 -1
- package/build-module/fetch/__experimental-fetch-url-data.js +5 -10
- package/build-module/fetch/__experimental-fetch-url-data.js.map +1 -1
- package/build-module/fetch/index.js.map +1 -1
- package/build-module/hooks/constants.js +3 -4
- package/build-module/hooks/constants.js.map +1 -1
- package/build-module/hooks/index.js.map +1 -1
- package/build-module/hooks/memoize.js +2 -1
- package/build-module/hooks/memoize.js.map +1 -1
- package/build-module/hooks/use-entity-record.js +1 -3
- package/build-module/hooks/use-entity-record.js.map +1 -1
- package/build-module/hooks/use-entity-records.js +2 -3
- package/build-module/hooks/use-entity-records.js.map +1 -1
- package/build-module/hooks/use-query-select.js +1 -9
- package/build-module/hooks/use-query-select.js.map +1 -1
- package/build-module/hooks/use-resource-permissions.js +1 -10
- package/build-module/hooks/use-resource-permissions.js.map +1 -1
- package/build-module/index.js +11 -19
- package/build-module/index.js.map +1 -1
- package/build-module/locks/actions.js +0 -3
- package/build-module/locks/actions.js.map +1 -1
- package/build-module/locks/engine.js +0 -5
- package/build-module/locks/engine.js.map +1 -1
- package/build-module/locks/reducer.js +7 -7
- package/build-module/locks/reducer.js.map +1 -1
- package/build-module/locks/selectors.js +7 -8
- package/build-module/locks/selectors.js.map +1 -1
- package/build-module/locks/utils.js +4 -14
- package/build-module/locks/utils.js.map +1 -1
- package/build-module/name.js.map +1 -1
- package/build-module/private-apis.js.map +1 -1
- package/build-module/private-selectors.js +2 -2
- package/build-module/private-selectors.js.map +1 -1
- package/build-module/queried-data/actions.js +4 -3
- package/build-module/queried-data/actions.js.map +1 -1
- package/build-module/queried-data/get-query-parts.js +13 -21
- package/build-module/queried-data/get-query-parts.js.map +1 -1
- package/build-module/queried-data/index.js.map +1 -1
- package/build-module/queried-data/reducer.js +33 -42
- package/build-module/queried-data/reducer.js.map +1 -1
- package/build-module/queried-data/selectors.js +6 -21
- package/build-module/queried-data/selectors.js.map +1 -1
- package/build-module/reducer.js +79 -104
- package/build-module/reducer.js.map +1 -1
- package/build-module/resolvers.js +94 -96
- package/build-module/resolvers.js.map +1 -1
- package/build-module/selectors.js +56 -92
- package/build-module/selectors.js.map +1 -1
- package/build-module/sync.js +12 -0
- package/build-module/sync.js.map +1 -0
- package/build-module/types.js.map +1 -1
- package/build-module/utils/conservative-map-item.js +4 -8
- package/build-module/utils/conservative-map-item.js.map +1 -1
- package/build-module/utils/forward-resolver.js +0 -1
- package/build-module/utils/forward-resolver.js.map +1 -1
- package/build-module/utils/get-normalized-comma-separable.js +0 -2
- package/build-module/utils/get-normalized-comma-separable.js.map +1 -1
- package/build-module/utils/if-matching-action.js +0 -2
- package/build-module/utils/if-matching-action.js.map +1 -1
- package/build-module/utils/index.js.map +1 -1
- package/build-module/utils/is-raw-attribute.js.map +1 -1
- package/build-module/utils/on-sub-key.js +5 -7
- package/build-module/utils/on-sub-key.js.map +1 -1
- package/build-module/utils/replace-action.js +0 -1
- package/build-module/utils/replace-action.js.map +1 -1
- package/build-module/utils/set-nested-value.js +0 -3
- package/build-module/utils/set-nested-value.js.map +1 -1
- package/build-module/utils/with-weak-map-cache.js +3 -5
- package/build-module/utils/with-weak-map-cache.js.map +1 -1
- package/build-types/actions.d.ts.map +1 -1
- package/build-types/entities.d.ts +53 -0
- package/build-types/entities.d.ts.map +1 -1
- package/build-types/entity-provider.d.ts +1 -1
- package/build-types/entity-provider.d.ts.map +1 -1
- package/build-types/hooks/memoize.d.ts +1 -1
- package/build-types/hooks/memoize.d.ts.map +1 -1
- package/build-types/index.d.ts +3 -3
- package/build-types/index.d.ts.map +1 -1
- package/build-types/resolvers.d.ts.map +1 -1
- package/build-types/sync.d.ts +2 -0
- package/build-types/sync.d.ts.map +1 -0
- package/package.json +17 -15
- package/src/actions.js +24 -14
- package/src/entities.js +91 -0
- package/src/entity-provider.js +11 -2
- package/src/resolvers.js +89 -41
- package/src/sync.js +18 -0
- package/src/test/entity-provider.js +272 -0
- package/tsconfig.json +1 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -2,26 +2,27 @@
|
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
4
|
import { camelCase } from 'change-case';
|
|
5
|
+
|
|
5
6
|
/**
|
|
6
7
|
* WordPress dependencies
|
|
7
8
|
*/
|
|
8
|
-
|
|
9
9
|
import { addQueryArgs } from '@wordpress/url';
|
|
10
10
|
import apiFetch from '@wordpress/api-fetch';
|
|
11
|
+
|
|
11
12
|
/**
|
|
12
13
|
* Internal dependencies
|
|
13
14
|
*/
|
|
14
|
-
|
|
15
15
|
import { STORE_NAME } from './name';
|
|
16
16
|
import { getOrLoadEntitiesConfig, DEFAULT_ENTITY_KEY } from './entities';
|
|
17
17
|
import { forwardResolver, getNormalizedCommaSeparable } from './utils';
|
|
18
|
+
import { getSyncProvider } from './sync';
|
|
19
|
+
|
|
18
20
|
/**
|
|
19
21
|
* Requests authors from the REST API.
|
|
20
22
|
*
|
|
21
23
|
* @param {Object|undefined} query Optional object of query parameters to
|
|
22
24
|
* include with request.
|
|
23
25
|
*/
|
|
24
|
-
|
|
25
26
|
export const getAuthors = query => async ({
|
|
26
27
|
dispatch
|
|
27
28
|
}) => {
|
|
@@ -31,10 +32,10 @@ export const getAuthors = query => async ({
|
|
|
31
32
|
});
|
|
32
33
|
dispatch.receiveUserQuery(path, users);
|
|
33
34
|
};
|
|
35
|
+
|
|
34
36
|
/**
|
|
35
37
|
* Requests the current user from the REST API.
|
|
36
38
|
*/
|
|
37
|
-
|
|
38
39
|
export const getCurrentUser = () => async ({
|
|
39
40
|
dispatch
|
|
40
41
|
}) => {
|
|
@@ -43,6 +44,7 @@ export const getCurrentUser = () => async ({
|
|
|
43
44
|
});
|
|
44
45
|
dispatch.receiveCurrentUser(currentUser);
|
|
45
46
|
};
|
|
47
|
+
|
|
46
48
|
/**
|
|
47
49
|
* Requests an entity's record from the REST API.
|
|
48
50
|
*
|
|
@@ -53,74 +55,98 @@ export const getCurrentUser = () => async ({
|
|
|
53
55
|
* include with request. If requesting specific
|
|
54
56
|
* fields, fields must always include the ID.
|
|
55
57
|
*/
|
|
56
|
-
|
|
57
58
|
export const getEntityRecord = (kind, name, key = '', query) => async ({
|
|
58
59
|
select,
|
|
59
60
|
dispatch
|
|
60
61
|
}) => {
|
|
61
62
|
const configs = await dispatch(getOrLoadEntitiesConfig(kind));
|
|
62
63
|
const entityConfig = configs.find(config => config.name === name && config.kind === kind);
|
|
63
|
-
|
|
64
64
|
if (!entityConfig || entityConfig?.__experimentalNoFetch) {
|
|
65
65
|
return;
|
|
66
66
|
}
|
|
67
|
-
|
|
68
67
|
const lock = await dispatch.__unstableAcquireStoreLock(STORE_NAME, ['entities', 'records', kind, name, key], {
|
|
69
68
|
exclusive: false
|
|
70
69
|
});
|
|
71
|
-
|
|
72
70
|
try {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
// additional query modifications in the condition below, since those
|
|
83
|
-
// modifications are relevant to how the data is tracked in state, and not
|
|
84
|
-
// for how the request is made to the REST API.
|
|
85
|
-
// eslint-disable-next-line @wordpress/no-unused-vars-before-return
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const path = addQueryArgs(entityConfig.baseURL + (key ? '/' + key : ''), { ...entityConfig.baseURLParams,
|
|
89
|
-
...query
|
|
90
|
-
});
|
|
71
|
+
// Entity supports configs,
|
|
72
|
+
// use the sync algorithm instead of the old fetch behavior.
|
|
73
|
+
if (window.__experimentalEnableSync && entityConfig.syncConfig && !query) {
|
|
74
|
+
const objectId = entityConfig.getSyncObjectId(key);
|
|
75
|
+
|
|
76
|
+
// Loads the persisted document.
|
|
77
|
+
await getSyncProvider().bootstrap(entityConfig.syncObjectType, objectId, record => {
|
|
78
|
+
dispatch.receiveEntityRecords(kind, name, record, query);
|
|
79
|
+
});
|
|
91
80
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
81
|
+
// Boostraps the edited document as well (and load from peers).
|
|
82
|
+
await getSyncProvider().bootstrap(entityConfig.syncObjectType + '--edit', objectId, record => {
|
|
83
|
+
dispatch({
|
|
84
|
+
type: 'EDIT_ENTITY_RECORD',
|
|
85
|
+
kind,
|
|
86
|
+
name,
|
|
87
|
+
recordId: key,
|
|
88
|
+
edits: record,
|
|
89
|
+
meta: {
|
|
90
|
+
undo: undefined
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
} else {
|
|
95
|
+
if (query !== undefined && query._fields) {
|
|
96
|
+
// If requesting specific fields, items and query association to said
|
|
97
|
+
// records are stored by ID reference. Thus, fields must always include
|
|
98
|
+
// the ID.
|
|
99
|
+
query = {
|
|
100
|
+
...query,
|
|
101
|
+
_fields: [...new Set([...(getNormalizedCommaSeparable(query._fields) || []), entityConfig.key || DEFAULT_ENTITY_KEY])].join()
|
|
102
|
+
};
|
|
103
|
+
}
|
|
98
104
|
|
|
99
|
-
|
|
105
|
+
// Disable reason: While true that an early return could leave `path`
|
|
106
|
+
// unused, it's important that path is derived using the query prior to
|
|
107
|
+
// additional query modifications in the condition below, since those
|
|
108
|
+
// modifications are relevant to how the data is tracked in state, and not
|
|
109
|
+
// for how the request is made to the REST API.
|
|
100
110
|
|
|
101
|
-
|
|
102
|
-
|
|
111
|
+
// eslint-disable-next-line @wordpress/no-unused-vars-before-return
|
|
112
|
+
const path = addQueryArgs(entityConfig.baseURL + (key ? '/' + key : ''), {
|
|
113
|
+
...entityConfig.baseURLParams,
|
|
114
|
+
...query
|
|
115
|
+
});
|
|
116
|
+
if (query !== undefined) {
|
|
117
|
+
query = {
|
|
118
|
+
...query,
|
|
119
|
+
include: [key]
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// The resolution cache won't consider query as reusable based on the
|
|
123
|
+
// fields, so it's tested here, prior to initiating the REST request,
|
|
124
|
+
// and without causing `getEntityRecords` resolution to occur.
|
|
125
|
+
const hasRecords = select.hasEntityRecords(kind, name, query);
|
|
126
|
+
if (hasRecords) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
103
129
|
}
|
|
130
|
+
const record = await apiFetch({
|
|
131
|
+
path
|
|
132
|
+
});
|
|
133
|
+
dispatch.receiveEntityRecords(kind, name, record, query);
|
|
104
134
|
}
|
|
105
|
-
|
|
106
|
-
const record = await apiFetch({
|
|
107
|
-
path
|
|
108
|
-
});
|
|
109
|
-
dispatch.receiveEntityRecords(kind, name, record, query);
|
|
110
135
|
} finally {
|
|
111
136
|
dispatch.__unstableReleaseStoreLock(lock);
|
|
112
137
|
}
|
|
113
138
|
};
|
|
139
|
+
|
|
114
140
|
/**
|
|
115
141
|
* Requests an entity's record from the REST API.
|
|
116
142
|
*/
|
|
117
|
-
|
|
118
143
|
export const getRawEntityRecord = forwardResolver('getEntityRecord');
|
|
144
|
+
|
|
119
145
|
/**
|
|
120
146
|
* Requests an entity's record from the REST API.
|
|
121
147
|
*/
|
|
122
|
-
|
|
123
148
|
export const getEditedEntityRecord = forwardResolver('getEntityRecord');
|
|
149
|
+
|
|
124
150
|
/**
|
|
125
151
|
* Requests the entity's records from the REST API.
|
|
126
152
|
*
|
|
@@ -129,40 +155,37 @@ export const getEditedEntityRecord = forwardResolver('getEntityRecord');
|
|
|
129
155
|
* @param {Object?} query Query Object. If requesting specific fields, fields
|
|
130
156
|
* must always include the ID.
|
|
131
157
|
*/
|
|
132
|
-
|
|
133
158
|
export const getEntityRecords = (kind, name, query = {}) => async ({
|
|
134
159
|
dispatch
|
|
135
160
|
}) => {
|
|
136
161
|
const configs = await dispatch(getOrLoadEntitiesConfig(kind));
|
|
137
162
|
const entityConfig = configs.find(config => config.name === name && config.kind === kind);
|
|
138
|
-
|
|
139
163
|
if (!entityConfig || entityConfig?.__experimentalNoFetch) {
|
|
140
164
|
return;
|
|
141
165
|
}
|
|
142
|
-
|
|
143
166
|
const lock = await dispatch.__unstableAcquireStoreLock(STORE_NAME, ['entities', 'records', kind, name], {
|
|
144
167
|
exclusive: false
|
|
145
168
|
});
|
|
146
|
-
|
|
147
169
|
try {
|
|
148
170
|
if (query._fields) {
|
|
149
171
|
// If requesting specific fields, items and query association to said
|
|
150
172
|
// records are stored by ID reference. Thus, fields must always include
|
|
151
173
|
// the ID.
|
|
152
|
-
query = {
|
|
174
|
+
query = {
|
|
175
|
+
...query,
|
|
153
176
|
_fields: [...new Set([...(getNormalizedCommaSeparable(query._fields) || []), entityConfig.key || DEFAULT_ENTITY_KEY])].join()
|
|
154
177
|
};
|
|
155
178
|
}
|
|
156
|
-
|
|
157
|
-
|
|
179
|
+
const path = addQueryArgs(entityConfig.baseURL, {
|
|
180
|
+
...entityConfig.baseURLParams,
|
|
158
181
|
...query
|
|
159
182
|
});
|
|
160
183
|
let records = Object.values(await apiFetch({
|
|
161
184
|
path
|
|
162
|
-
}));
|
|
185
|
+
}));
|
|
186
|
+
// If we request fields but the result doesn't contain the fields,
|
|
163
187
|
// explicitly set these fields as "undefined"
|
|
164
188
|
// that way we consider the query "fullfilled".
|
|
165
|
-
|
|
166
189
|
if (query._fields) {
|
|
167
190
|
records = records.map(record => {
|
|
168
191
|
query._fields.split(',').forEach(field => {
|
|
@@ -170,15 +193,14 @@ export const getEntityRecords = (kind, name, query = {}) => async ({
|
|
|
170
193
|
record[field] = undefined;
|
|
171
194
|
}
|
|
172
195
|
});
|
|
173
|
-
|
|
174
196
|
return record;
|
|
175
197
|
});
|
|
176
198
|
}
|
|
199
|
+
dispatch.receiveEntityRecords(kind, name, records, query);
|
|
177
200
|
|
|
178
|
-
|
|
201
|
+
// When requesting all fields, the list of results can be used to
|
|
179
202
|
// resolve the `getEntityRecord` selector in addition to `getEntityRecords`.
|
|
180
203
|
// See https://github.com/WordPress/gutenberg/pull/26575
|
|
181
|
-
|
|
182
204
|
if (!query?._fields && !query.context) {
|
|
183
205
|
const key = entityConfig.key || DEFAULT_ENTITY_KEY;
|
|
184
206
|
const resolutionsArgs = records.filter(record => record[key]).map(record => [kind, name, record[key]]);
|
|
@@ -197,15 +219,13 @@ export const getEntityRecords = (kind, name, query = {}) => async ({
|
|
|
197
219
|
dispatch.__unstableReleaseStoreLock(lock);
|
|
198
220
|
}
|
|
199
221
|
};
|
|
200
|
-
|
|
201
222
|
getEntityRecords.shouldInvalidate = (action, kind, name) => {
|
|
202
223
|
return (action.type === 'RECEIVE_ITEMS' || action.type === 'REMOVE_ITEMS') && action.invalidateCache && kind === action.kind && name === action.name;
|
|
203
224
|
};
|
|
225
|
+
|
|
204
226
|
/**
|
|
205
227
|
* Requests the current theme.
|
|
206
228
|
*/
|
|
207
|
-
|
|
208
|
-
|
|
209
229
|
export const getCurrentTheme = () => async ({
|
|
210
230
|
dispatch,
|
|
211
231
|
resolveSelect
|
|
@@ -215,17 +235,17 @@ export const getCurrentTheme = () => async ({
|
|
|
215
235
|
});
|
|
216
236
|
dispatch.receiveCurrentTheme(activeThemes[0]);
|
|
217
237
|
};
|
|
238
|
+
|
|
218
239
|
/**
|
|
219
240
|
* Requests theme supports data from the index.
|
|
220
241
|
*/
|
|
221
|
-
|
|
222
242
|
export const getThemeSupports = forwardResolver('getCurrentTheme');
|
|
243
|
+
|
|
223
244
|
/**
|
|
224
245
|
* Requests a preview from the from the Embed API.
|
|
225
246
|
*
|
|
226
247
|
* @param {string} url URL to get the preview for.
|
|
227
248
|
*/
|
|
228
|
-
|
|
229
249
|
export const getEmbedPreview = url => async ({
|
|
230
250
|
dispatch
|
|
231
251
|
}) => {
|
|
@@ -241,6 +261,7 @@ export const getEmbedPreview = url => async ({
|
|
|
241
261
|
dispatch.receiveEmbedPreview(url, false);
|
|
242
262
|
}
|
|
243
263
|
};
|
|
264
|
+
|
|
244
265
|
/**
|
|
245
266
|
* Checks whether the current user can perform the given action on the given
|
|
246
267
|
* REST resource.
|
|
@@ -250,7 +271,6 @@ export const getEmbedPreview = url => async ({
|
|
|
250
271
|
* @param {string} resource REST resource to check, e.g. 'media' or 'posts'.
|
|
251
272
|
* @param {?string} id ID of the rest resource to check.
|
|
252
273
|
*/
|
|
253
|
-
|
|
254
274
|
export const canUser = (requestedAction, resource, id) => async ({
|
|
255
275
|
dispatch,
|
|
256
276
|
registry
|
|
@@ -260,26 +280,21 @@ export const canUser = (requestedAction, resource, id) => async ({
|
|
|
260
280
|
} = registry.select(STORE_NAME);
|
|
261
281
|
const resourcePath = id ? `${resource}/${id}` : resource;
|
|
262
282
|
const retrievedActions = ['create', 'read', 'update', 'delete'];
|
|
263
|
-
|
|
264
283
|
if (!retrievedActions.includes(requestedAction)) {
|
|
265
284
|
throw new Error(`'${requestedAction}' is not a valid action.`);
|
|
266
|
-
}
|
|
267
|
-
|
|
285
|
+
}
|
|
268
286
|
|
|
287
|
+
// Prevent resolving the same resource twice.
|
|
269
288
|
for (const relatedAction of retrievedActions) {
|
|
270
289
|
if (relatedAction === requestedAction) {
|
|
271
290
|
continue;
|
|
272
291
|
}
|
|
273
|
-
|
|
274
292
|
const isAlreadyResolving = hasStartedResolution('canUser', [relatedAction, resource, id]);
|
|
275
|
-
|
|
276
293
|
if (isAlreadyResolving) {
|
|
277
294
|
return;
|
|
278
295
|
}
|
|
279
296
|
}
|
|
280
|
-
|
|
281
297
|
let response;
|
|
282
|
-
|
|
283
298
|
try {
|
|
284
299
|
response = await apiFetch({
|
|
285
300
|
path: `/wp/v2/${resourcePath}`,
|
|
@@ -290,11 +305,11 @@ export const canUser = (requestedAction, resource, id) => async ({
|
|
|
290
305
|
// Do nothing if our OPTIONS request comes back with an API error (4xx or
|
|
291
306
|
// 5xx). The previously determined isAllowed value will remain in the store.
|
|
292
307
|
return;
|
|
293
|
-
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Optional chaining operator is used here because the API requests don't
|
|
294
311
|
// return the expected result in the native version. Instead, API requests
|
|
295
312
|
// only return the result, without including response properties like the headers.
|
|
296
|
-
|
|
297
|
-
|
|
298
313
|
const allowHeader = response.headers?.get('allow');
|
|
299
314
|
const allowedMethods = allowHeader?.allow || allowHeader || '';
|
|
300
315
|
const permissions = {};
|
|
@@ -304,15 +319,14 @@ export const canUser = (requestedAction, resource, id) => async ({
|
|
|
304
319
|
update: 'PUT',
|
|
305
320
|
delete: 'DELETE'
|
|
306
321
|
};
|
|
307
|
-
|
|
308
322
|
for (const [actionName, methodName] of Object.entries(methods)) {
|
|
309
323
|
permissions[actionName] = allowedMethods.includes(methodName);
|
|
310
324
|
}
|
|
311
|
-
|
|
312
325
|
for (const action of retrievedActions) {
|
|
313
326
|
dispatch.receiveUserPermission(`${action}/${resourcePath}`, permissions[action]);
|
|
314
327
|
}
|
|
315
328
|
};
|
|
329
|
+
|
|
316
330
|
/**
|
|
317
331
|
* Checks whether the current user can perform the given action on the given
|
|
318
332
|
* REST resource.
|
|
@@ -321,27 +335,24 @@ export const canUser = (requestedAction, resource, id) => async ({
|
|
|
321
335
|
* @param {string} name Entity name.
|
|
322
336
|
* @param {string} recordId Record's id.
|
|
323
337
|
*/
|
|
324
|
-
|
|
325
338
|
export const canUserEditEntityRecord = (kind, name, recordId) => async ({
|
|
326
339
|
dispatch
|
|
327
340
|
}) => {
|
|
328
341
|
const configs = await dispatch(getOrLoadEntitiesConfig(kind));
|
|
329
342
|
const entityConfig = configs.find(config => config.name === name && config.kind === kind);
|
|
330
|
-
|
|
331
343
|
if (!entityConfig) {
|
|
332
344
|
return;
|
|
333
345
|
}
|
|
334
|
-
|
|
335
346
|
const resource = entityConfig.__unstable_rest_base;
|
|
336
347
|
await dispatch(canUser('update', resource, recordId));
|
|
337
348
|
};
|
|
349
|
+
|
|
338
350
|
/**
|
|
339
351
|
* Request autosave data from the REST API.
|
|
340
352
|
*
|
|
341
353
|
* @param {string} postType The type of the parent post.
|
|
342
354
|
* @param {number} postId The id of the parent post.
|
|
343
355
|
*/
|
|
344
|
-
|
|
345
356
|
export const getAutosaves = (postType, postId) => async ({
|
|
346
357
|
dispatch,
|
|
347
358
|
resolveSelect
|
|
@@ -353,11 +364,11 @@ export const getAutosaves = (postType, postId) => async ({
|
|
|
353
364
|
const autosaves = await apiFetch({
|
|
354
365
|
path: `/${restNamespace}/${restBase}/${postId}/autosaves?context=edit`
|
|
355
366
|
});
|
|
356
|
-
|
|
357
367
|
if (autosaves && autosaves.length) {
|
|
358
368
|
dispatch.receiveAutosaves(postId, autosaves);
|
|
359
369
|
}
|
|
360
370
|
};
|
|
371
|
+
|
|
361
372
|
/**
|
|
362
373
|
* Request autosave data from the REST API.
|
|
363
374
|
*
|
|
@@ -367,24 +378,22 @@ export const getAutosaves = (postType, postId) => async ({
|
|
|
367
378
|
* @param {string} postType The type of the parent post.
|
|
368
379
|
* @param {number} postId The id of the parent post.
|
|
369
380
|
*/
|
|
370
|
-
|
|
371
381
|
export const getAutosave = (postType, postId) => async ({
|
|
372
382
|
resolveSelect
|
|
373
383
|
}) => {
|
|
374
384
|
await resolveSelect.getAutosaves(postType, postId);
|
|
375
385
|
};
|
|
386
|
+
|
|
376
387
|
/**
|
|
377
388
|
* Retrieve the frontend template used for a given link.
|
|
378
389
|
*
|
|
379
390
|
* @param {string} link Link.
|
|
380
391
|
*/
|
|
381
|
-
|
|
382
392
|
export const __experimentalGetTemplateForLink = link => async ({
|
|
383
393
|
dispatch,
|
|
384
394
|
resolveSelect
|
|
385
395
|
}) => {
|
|
386
396
|
let template;
|
|
387
|
-
|
|
388
397
|
try {
|
|
389
398
|
// This is NOT calling a REST endpoint but rather ends up with a response from
|
|
390
399
|
// an Ajax function which has a different shape from a WP_REST_Response.
|
|
@@ -395,26 +404,22 @@ export const __experimentalGetTemplateForLink = link => async ({
|
|
|
395
404
|
}).then(({
|
|
396
405
|
data
|
|
397
406
|
}) => data);
|
|
398
|
-
} catch (e) {
|
|
407
|
+
} catch (e) {
|
|
408
|
+
// For non-FSE themes, it is possible that this request returns an error.
|
|
399
409
|
}
|
|
400
|
-
|
|
401
410
|
if (!template) {
|
|
402
411
|
return;
|
|
403
412
|
}
|
|
404
|
-
|
|
405
413
|
const record = await resolveSelect.getEntityRecord('postType', 'wp_template', template.id);
|
|
406
|
-
|
|
407
414
|
if (record) {
|
|
408
415
|
dispatch.receiveEntityRecords('postType', 'wp_template', [record], {
|
|
409
416
|
'find-template': link
|
|
410
417
|
});
|
|
411
418
|
}
|
|
412
419
|
};
|
|
413
|
-
|
|
414
420
|
__experimentalGetTemplateForLink.shouldInvalidate = action => {
|
|
415
421
|
return (action.type === 'RECEIVE_ITEMS' || action.type === 'REMOVE_ITEMS') && action.invalidateCache && action.kind === 'postType' && action.name === 'wp_template';
|
|
416
422
|
};
|
|
417
|
-
|
|
418
423
|
export const __experimentalGetCurrentGlobalStylesId = () => async ({
|
|
419
424
|
dispatch,
|
|
420
425
|
resolveSelect
|
|
@@ -423,12 +428,10 @@ export const __experimentalGetCurrentGlobalStylesId = () => async ({
|
|
|
423
428
|
status: 'active'
|
|
424
429
|
});
|
|
425
430
|
const globalStylesURL = activeThemes?.[0]?._links?.['wp:user-global-styles']?.[0]?.href;
|
|
426
|
-
|
|
427
431
|
if (globalStylesURL) {
|
|
428
432
|
const globalStylesObject = await apiFetch({
|
|
429
433
|
url: globalStylesURL
|
|
430
434
|
});
|
|
431
|
-
|
|
432
435
|
dispatch.__experimentalReceiveCurrentGlobalStylesId(globalStylesObject.id);
|
|
433
436
|
}
|
|
434
437
|
};
|
|
@@ -440,7 +443,6 @@ export const __experimentalGetCurrentThemeBaseGlobalStyles = () => async ({
|
|
|
440
443
|
const themeGlobalStyles = await apiFetch({
|
|
441
444
|
path: `/wp/v2/global-styles/themes/${currentTheme.stylesheet}`
|
|
442
445
|
});
|
|
443
|
-
|
|
444
446
|
dispatch.__experimentalReceiveThemeBaseGlobalStyles(currentTheme.stylesheet, themeGlobalStyles);
|
|
445
447
|
};
|
|
446
448
|
export const __experimentalGetCurrentThemeGlobalStylesVariations = () => async ({
|
|
@@ -451,13 +453,12 @@ export const __experimentalGetCurrentThemeGlobalStylesVariations = () => async (
|
|
|
451
453
|
const variations = await apiFetch({
|
|
452
454
|
path: `/wp/v2/global-styles/themes/${currentTheme.stylesheet}/variations`
|
|
453
455
|
});
|
|
454
|
-
|
|
455
456
|
dispatch.__experimentalReceiveThemeGlobalStyleVariations(currentTheme.stylesheet, variations);
|
|
456
457
|
};
|
|
458
|
+
|
|
457
459
|
/**
|
|
458
460
|
* Fetches and returns the revisions of the current global styles theme.
|
|
459
461
|
*/
|
|
460
|
-
|
|
461
462
|
export const getCurrentThemeGlobalStylesRevisions = () => async ({
|
|
462
463
|
resolveSelect,
|
|
463
464
|
dispatch
|
|
@@ -465,7 +466,6 @@ export const getCurrentThemeGlobalStylesRevisions = () => async ({
|
|
|
465
466
|
const globalStylesId = await resolveSelect.__experimentalGetCurrentGlobalStylesId();
|
|
466
467
|
const record = globalStylesId ? await resolveSelect.getEntityRecord('root', 'globalStyles', globalStylesId) : undefined;
|
|
467
468
|
const revisionsURL = record?._links?.['version-history']?.[0]?.href;
|
|
468
|
-
|
|
469
469
|
if (revisionsURL) {
|
|
470
470
|
const resetRevisions = await apiFetch({
|
|
471
471
|
url: revisionsURL
|
|
@@ -474,11 +474,9 @@ export const getCurrentThemeGlobalStylesRevisions = () => async ({
|
|
|
474
474
|
dispatch.receiveThemeGlobalStyleRevisions(globalStylesId, revisions);
|
|
475
475
|
}
|
|
476
476
|
};
|
|
477
|
-
|
|
478
477
|
getCurrentThemeGlobalStylesRevisions.shouldInvalidate = action => {
|
|
479
478
|
return action.type === 'SAVE_ENTITY_RECORD_FINISH' && action.kind === 'root' && !action.error && action.name === 'globalStyles';
|
|
480
479
|
};
|
|
481
|
-
|
|
482
480
|
export const getBlockPatterns = () => async ({
|
|
483
481
|
dispatch
|
|
484
482
|
}) => {
|
|
@@ -513,15 +511,15 @@ export const getNavigationFallbackId = () => async ({
|
|
|
513
511
|
});
|
|
514
512
|
const record = fallback?._embedded?.self;
|
|
515
513
|
dispatch.receiveNavigationFallbackId(fallback?.id);
|
|
516
|
-
|
|
517
514
|
if (record) {
|
|
518
515
|
// If the fallback is already in the store, don't invalidate navigation queries.
|
|
519
516
|
// Otherwise, invalidate the cache for the scenario where there were no Navigation
|
|
520
517
|
// posts in the state and the fallback created one.
|
|
521
518
|
const existingFallbackEntityRecord = select.getEntityRecord('postType', 'wp_navigation', fallback?.id);
|
|
522
519
|
const invalidateNavigationQueries = !existingFallbackEntityRecord;
|
|
523
|
-
dispatch.receiveEntityRecords('postType', 'wp_navigation', record, undefined, invalidateNavigationQueries);
|
|
520
|
+
dispatch.receiveEntityRecords('postType', 'wp_navigation', record, undefined, invalidateNavigationQueries);
|
|
524
521
|
|
|
522
|
+
// Resolve to avoid further network requests.
|
|
525
523
|
dispatch.finishResolution('getEntityRecord', ['postType', 'wp_navigation', fallback?.id]);
|
|
526
524
|
}
|
|
527
525
|
};
|