@strapi/utils 4.1.1 → 4.2.0-alpha.O
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.
|
@@ -124,7 +124,7 @@ class InvalidPopulateError extends Error {
|
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
// NOTE: we could support foo.* or foo.bar.* etc later on
|
|
127
|
-
const convertPopulateQueryParams = (populate, depth = 0) => {
|
|
127
|
+
const convertPopulateQueryParams = (populate, schema, depth = 0) => {
|
|
128
128
|
if (depth === 0 && populate === '*') {
|
|
129
129
|
return true;
|
|
130
130
|
}
|
|
@@ -147,18 +147,72 @@ const convertPopulateQueryParams = (populate, depth = 0) => {
|
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
if (_.isPlainObject(populate)) {
|
|
150
|
-
|
|
151
|
-
for (const key in populate) {
|
|
152
|
-
transformedPopulate[key] = convertNestedPopulate(populate[key]);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return transformedPopulate;
|
|
150
|
+
return convertPopulateObject(populate, schema);
|
|
156
151
|
}
|
|
157
152
|
|
|
158
153
|
throw new InvalidPopulateError();
|
|
159
154
|
};
|
|
160
155
|
|
|
161
|
-
const
|
|
156
|
+
const convertPopulateObject = (populate, schema) => {
|
|
157
|
+
if (!schema) {
|
|
158
|
+
return {};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const { attributes } = schema;
|
|
162
|
+
|
|
163
|
+
return Object.entries(populate).reduce((acc, [key, subPopulate]) => {
|
|
164
|
+
const attribute = attributes[key];
|
|
165
|
+
|
|
166
|
+
if (!attribute) {
|
|
167
|
+
return acc;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// FIXME: This is a temporary solution for dynamic zones that should be
|
|
171
|
+
// fixed when we'll implement a more accurate way to query them
|
|
172
|
+
if (attribute.type === 'dynamiczone') {
|
|
173
|
+
const generatedFakeDynamicZoneSchema = {
|
|
174
|
+
uid: `${schema.uid}.${key}`,
|
|
175
|
+
attributes: attribute.components
|
|
176
|
+
.sort()
|
|
177
|
+
.map(uid => strapi.getModel(uid).attributes)
|
|
178
|
+
.reduce((acc, componentAttributes) => ({ ...acc, ...componentAttributes }), {}),
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
return {
|
|
182
|
+
...acc,
|
|
183
|
+
[key]: convertNestedPopulate(subPopulate, generatedFakeDynamicZoneSchema),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// NOTE: Retrieve the target schema UID.
|
|
188
|
+
// Only handles basic relations, medias and component since it's not possible
|
|
189
|
+
// to populate with options for a dynamic zone or a polymorphic relation
|
|
190
|
+
let targetSchemaUID;
|
|
191
|
+
|
|
192
|
+
if (attribute.type === 'relation') {
|
|
193
|
+
targetSchemaUID = attribute.target;
|
|
194
|
+
} else if (attribute.type === 'component') {
|
|
195
|
+
targetSchemaUID = attribute.component;
|
|
196
|
+
} else if (attribute.type === 'media') {
|
|
197
|
+
targetSchemaUID = 'plugin::upload.file';
|
|
198
|
+
} else {
|
|
199
|
+
return acc;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const targetSchema = strapi.getModel(targetSchemaUID);
|
|
203
|
+
|
|
204
|
+
if (!targetSchema) {
|
|
205
|
+
return acc;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return {
|
|
209
|
+
...acc,
|
|
210
|
+
[key]: convertNestedPopulate(subPopulate, targetSchema),
|
|
211
|
+
};
|
|
212
|
+
}, {});
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
const convertNestedPopulate = (subPopulate, schema) => {
|
|
162
216
|
if (subPopulate === '*') {
|
|
163
217
|
return true;
|
|
164
218
|
}
|
|
@@ -181,7 +235,7 @@ const convertNestedPopulate = subPopulate => {
|
|
|
181
235
|
}
|
|
182
236
|
|
|
183
237
|
if (filters) {
|
|
184
|
-
query.where = convertFiltersQueryParams(filters);
|
|
238
|
+
query.where = convertFiltersQueryParams(filters, schema);
|
|
185
239
|
}
|
|
186
240
|
|
|
187
241
|
if (fields) {
|
|
@@ -189,7 +243,7 @@ const convertNestedPopulate = subPopulate => {
|
|
|
189
243
|
}
|
|
190
244
|
|
|
191
245
|
if (populate) {
|
|
192
|
-
query.populate = convertPopulateQueryParams(populate);
|
|
246
|
+
query.populate = convertPopulateQueryParams(populate, schema);
|
|
193
247
|
}
|
|
194
248
|
|
|
195
249
|
if (count) {
|
|
@@ -250,7 +304,7 @@ const convertAndSanitizeFilters = (filters, schema) => {
|
|
|
250
304
|
|
|
251
305
|
// Here, `key` can either be an operator or an attribute name
|
|
252
306
|
for (const [key, value] of Object.entries(filters)) {
|
|
253
|
-
const attribute = get(
|
|
307
|
+
const attribute = get(key, schema.attributes);
|
|
254
308
|
|
|
255
309
|
// Handle attributes
|
|
256
310
|
if (attribute) {
|
|
@@ -280,7 +334,7 @@ const convertAndSanitizeFilters = (filters, schema) => {
|
|
|
280
334
|
if (attribute.type === 'password') {
|
|
281
335
|
removeOperator(key);
|
|
282
336
|
} else {
|
|
283
|
-
filters[key] = convertAndSanitizeFilters(value);
|
|
337
|
+
filters[key] = convertAndSanitizeFilters(value, schema);
|
|
284
338
|
}
|
|
285
339
|
}
|
|
286
340
|
}
|
package/lib/index.js
CHANGED
|
@@ -19,6 +19,8 @@ const {
|
|
|
19
19
|
stringEquals,
|
|
20
20
|
isKebabCase,
|
|
21
21
|
isCamelCase,
|
|
22
|
+
toRegressedEnumValue,
|
|
23
|
+
startsWithANumber,
|
|
22
24
|
} = require('./string-formatting');
|
|
23
25
|
const { removeUndefined } = require('./object-formatting');
|
|
24
26
|
const { getConfigUrls, getAbsoluteAdminUrl, getAbsoluteServerUrl } = require('./config');
|
|
@@ -47,6 +49,8 @@ module.exports = {
|
|
|
47
49
|
traverseEntity,
|
|
48
50
|
parseType,
|
|
49
51
|
nameToSlug,
|
|
52
|
+
toRegressedEnumValue,
|
|
53
|
+
startsWithANumber,
|
|
50
54
|
nameToCollectionName,
|
|
51
55
|
getCommonBeginning,
|
|
52
56
|
getConfigUrls,
|
package/lib/string-formatting.js
CHANGED
|
@@ -6,6 +6,13 @@ const nameToSlug = (name, options = { separator: '-' }) => slugify(name, options
|
|
|
6
6
|
|
|
7
7
|
const nameToCollectionName = name => slugify(name, { separator: '_' });
|
|
8
8
|
|
|
9
|
+
const toRegressedEnumValue = value =>
|
|
10
|
+
slugify(value, {
|
|
11
|
+
decamelize: false,
|
|
12
|
+
lowercase: false,
|
|
13
|
+
separator: '_',
|
|
14
|
+
});
|
|
15
|
+
|
|
9
16
|
const getCommonBeginning = (...strings) =>
|
|
10
17
|
_.takeWhile(strings[0], (char, index) => strings.every(string => string[index] === char)).join(
|
|
11
18
|
''
|
|
@@ -35,6 +42,7 @@ const stringIncludes = (arr, val) => arr.map(String).includes(String(val));
|
|
|
35
42
|
const stringEquals = (a, b) => String(a) === String(b);
|
|
36
43
|
const isCamelCase = value => /^[a-z][a-zA-Z0-9]+$/.test(value);
|
|
37
44
|
const isKebabCase = value => /^([a-z][a-z0-9]*)(-[a-z0-9]+)*$/.test(value);
|
|
45
|
+
const startsWithANumber = value => /^[0-9]/.test(value);
|
|
38
46
|
|
|
39
47
|
module.exports = {
|
|
40
48
|
nameToSlug,
|
|
@@ -46,4 +54,6 @@ module.exports = {
|
|
|
46
54
|
stringEquals,
|
|
47
55
|
isCamelCase,
|
|
48
56
|
isKebabCase,
|
|
57
|
+
toRegressedEnumValue,
|
|
58
|
+
startsWithANumber,
|
|
49
59
|
};
|
package/lib/traverse-entity.js
CHANGED
|
@@ -41,6 +41,7 @@ const traverseEntity = async (visitor, options, entity) => {
|
|
|
41
41
|
const isRelation = attribute.type === 'relation';
|
|
42
42
|
const isComponent = attribute.type === 'component';
|
|
43
43
|
const isDynamicZone = attribute.type === 'dynamiczone';
|
|
44
|
+
const isMedia = attribute.type === 'media';
|
|
44
45
|
|
|
45
46
|
if (isRelation) {
|
|
46
47
|
const isMorphRelation = attribute.relation.toLowerCase().startsWith('morph');
|
|
@@ -61,6 +62,22 @@ const traverseEntity = async (visitor, options, entity) => {
|
|
|
61
62
|
: await traverseTarget(value);
|
|
62
63
|
}
|
|
63
64
|
|
|
65
|
+
if (isMedia) {
|
|
66
|
+
const traverseTarget = entry => {
|
|
67
|
+
const targetSchemaUID = 'plugin::upload.file';
|
|
68
|
+
const targetSchema = strapi.getModel(targetSchemaUID);
|
|
69
|
+
|
|
70
|
+
const traverseOptions = { schema: targetSchema, path: newPath };
|
|
71
|
+
|
|
72
|
+
return traverseEntity(visitor, traverseOptions, entry);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// need to update copy
|
|
76
|
+
copy[key] = isArray(value)
|
|
77
|
+
? await Promise.all(value.map(traverseTarget))
|
|
78
|
+
: await traverseTarget(value);
|
|
79
|
+
}
|
|
80
|
+
|
|
64
81
|
if (isComponent) {
|
|
65
82
|
const targetSchema = strapi.getModel(attribute.component);
|
|
66
83
|
const traverseOptions = { schema: targetSchema, path: newPath };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strapi/utils",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0-alpha.O",
|
|
4
4
|
"description": "Shared utilities for the Strapi packages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"strapi",
|
|
@@ -45,5 +45,5 @@
|
|
|
45
45
|
"node": ">=12.22.0 <=16.x.x",
|
|
46
46
|
"npm": ">=6.0.0"
|
|
47
47
|
},
|
|
48
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "0e1f1ae08565a5f2427753582f37645a43c00cb2"
|
|
49
49
|
}
|