@strapi/utils 4.11.3 → 4.12.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/async.d.ts +10 -0
- package/dist/async.js +33 -0
- package/dist/async.js.map +1 -0
- package/dist/code-generator.d.ts +2 -0
- package/dist/code-generator.js +11 -0
- package/dist/code-generator.js.map +1 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.js +79 -0
- package/dist/config.js.map +1 -0
- package/dist/content-types.d.ts +60 -0
- package/dist/content-types.js +151 -0
- package/dist/content-types.js.map +1 -0
- package/dist/convert-query-params.d.ts +75 -0
- package/dist/convert-query-params.js +476 -0
- package/dist/convert-query-params.js.map +1 -0
- package/dist/env-helper.d.ts +18 -0
- package/dist/env-helper.js +84 -0
- package/dist/env-helper.js.map +1 -0
- package/dist/errors.d.ts +37 -0
- package/dist/errors.js +100 -0
- package/dist/errors.js.map +1 -0
- package/dist/file.d.ts +16 -0
- package/dist/file.js +54 -0
- package/dist/file.js.map +1 -0
- package/dist/format-yup-error.d.ts +10 -0
- package/dist/format-yup-error.js +17 -0
- package/dist/format-yup-error.js.map +1 -0
- package/dist/hooks.d.ts +63 -0
- package/dist/hooks.js +89 -0
- package/dist/hooks.js.map +1 -0
- package/dist/import-default.d.ts +1 -0
- package/dist/import-default.js +9 -0
- package/dist/import-default.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +99 -0
- package/dist/index.js.map +1 -0
- package/dist/object-formatting.d.ts +3 -0
- package/dist/object-formatting.js +14 -0
- package/dist/object-formatting.js.map +1 -0
- package/dist/operators.d.ts +2 -0
- package/dist/operators.js +70 -0
- package/dist/operators.js.map +1 -0
- package/dist/pagination.d.ts +14 -0
- package/dist/pagination.js +80 -0
- package/dist/pagination.js.map +1 -0
- package/dist/parse-multipart.d.ts +8 -0
- package/dist/parse-multipart.js +36 -0
- package/dist/parse-multipart.js.map +1 -0
- package/dist/parse-type.d.ts +21 -0
- package/dist/parse-type.js +108 -0
- package/dist/parse-type.js.map +1 -0
- package/dist/policy.d.ts +41 -0
- package/dist/policy.js +109 -0
- package/dist/policy.js.map +1 -0
- package/dist/print-value.d.ts +2 -0
- package/dist/print-value.js +50 -0
- package/dist/print-value.js.map +1 -0
- package/dist/provider-factory.d.ts +29 -0
- package/dist/provider-factory.js +80 -0
- package/dist/provider-factory.js.map +1 -0
- package/dist/relations.d.ts +10 -0
- package/dist/relations.js +23 -0
- package/dist/relations.js.map +1 -0
- package/dist/sanitize/index.d.ts +23 -0
- package/dist/sanitize/index.js +135 -0
- package/dist/sanitize/index.js.map +1 -0
- package/dist/sanitize/sanitizers.d.ts +10 -0
- package/dist/sanitize/sanitizers.js +114 -0
- package/dist/sanitize/sanitizers.js.map +1 -0
- package/dist/sanitize/visitors/allowed-fields.d.ts +3 -0
- package/{lib → dist}/sanitize/visitors/allowed-fields.js +17 -32
- package/dist/sanitize/visitors/allowed-fields.js.map +1 -0
- package/dist/sanitize/visitors/index.d.ts +7 -0
- package/dist/sanitize/visitors/index.js +21 -0
- package/dist/sanitize/visitors/index.js.map +1 -0
- package/dist/sanitize/visitors/remove-dynamic-zones.d.ts +3 -0
- package/dist/sanitize/visitors/remove-dynamic-zones.js +10 -0
- package/dist/sanitize/visitors/remove-dynamic-zones.js.map +1 -0
- package/dist/sanitize/visitors/remove-morph-to-relations.d.ts +3 -0
- package/dist/sanitize/visitors/remove-morph-to-relations.js +10 -0
- package/dist/sanitize/visitors/remove-morph-to-relations.js.map +1 -0
- package/dist/sanitize/visitors/remove-password.d.ts +3 -0
- package/dist/sanitize/visitors/remove-password.js +9 -0
- package/dist/sanitize/visitors/remove-password.js.map +1 -0
- package/dist/sanitize/visitors/remove-private.d.ts +3 -0
- package/dist/sanitize/visitors/remove-private.js +14 -0
- package/dist/sanitize/visitors/remove-private.js.map +1 -0
- package/dist/sanitize/visitors/remove-restricted-relations.d.ts +3 -0
- package/dist/sanitize/visitors/remove-restricted-relations.js +88 -0
- package/dist/sanitize/visitors/remove-restricted-relations.js.map +1 -0
- package/dist/sanitize/visitors/restricted-fields.d.ts +3 -0
- package/dist/sanitize/visitors/restricted-fields.js +25 -0
- package/dist/sanitize/visitors/restricted-fields.js.map +1 -0
- package/dist/set-creator-fields.d.ts +9 -0
- package/dist/set-creator-fields.js +39 -0
- package/dist/set-creator-fields.js.map +1 -0
- package/dist/string-formatting.d.ts +15 -0
- package/dist/string-formatting.js +85 -0
- package/dist/string-formatting.js.map +1 -0
- package/dist/template-configuration.d.ts +5 -0
- package/dist/template-configuration.js +30 -0
- package/dist/template-configuration.js.map +1 -0
- package/dist/template.d.ts +9 -0
- package/dist/template.js +20 -0
- package/dist/template.js.map +1 -0
- package/dist/traverse/factory.d.ts +78 -0
- package/dist/traverse/factory.js +127 -0
- package/dist/traverse/factory.js.map +1 -0
- package/dist/traverse/index.d.ts +5 -0
- package/dist/traverse/index.js +17 -0
- package/dist/traverse/index.js.map +1 -0
- package/dist/traverse/query-fields.d.ts +3 -0
- package/dist/traverse/query-fields.js +35 -0
- package/dist/traverse/query-fields.js.map +1 -0
- package/dist/traverse/query-filters.d.ts +3 -0
- package/dist/traverse/query-filters.js +75 -0
- package/dist/traverse/query-filters.js.map +1 -0
- package/dist/traverse/query-populate.d.ts +3 -0
- package/dist/traverse/query-populate.js +144 -0
- package/dist/traverse/query-populate.js.map +1 -0
- package/dist/traverse/query-sort.d.ts +3 -0
- package/dist/traverse/query-sort.js +116 -0
- package/dist/traverse/query-sort.js.map +1 -0
- package/dist/traverse-entity.d.ts +31 -0
- package/dist/traverse-entity.js +134 -0
- package/dist/traverse-entity.js.map +1 -0
- package/dist/types.d.ts +65 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/validators.d.ts +13 -0
- package/dist/validators.js +120 -0
- package/dist/validators.js.map +1 -0
- package/dist/webhook.d.ts +5 -0
- package/dist/webhook.js +27 -0
- package/dist/webhook.js.map +1 -0
- package/package.json +19 -4
- package/.eslintignore +0 -3
- package/.eslintrc.js +0 -4
- package/index.d.ts +0 -5
- package/lib/async.d.ts +0 -21
- package/lib/async.js +0 -45
- package/lib/build-query.js +0 -208
- package/lib/code-generator.js +0 -13
- package/lib/config.js +0 -88
- package/lib/content-types.js +0 -196
- package/lib/convert-query-params.js +0 -586
- package/lib/env-helper.js +0 -98
- package/lib/errors.js +0 -113
- package/lib/file.js +0 -60
- package/lib/format-yup-error.js +0 -20
- package/lib/hooks.js +0 -110
- package/lib/import-default.js +0 -10
- package/lib/index.js +0 -99
- package/lib/object-formatting.js +0 -15
- package/lib/operators.js +0 -74
- package/lib/pagination.js +0 -99
- package/lib/parse-multipart.js +0 -44
- package/lib/parse-type.js +0 -100
- package/lib/policy.js +0 -129
- package/lib/print-value.js +0 -52
- package/lib/provider-factory.js +0 -116
- package/lib/relations.js +0 -31
- package/lib/sanitize/index.js +0 -143
- package/lib/sanitize/sanitizers.js +0 -163
- package/lib/sanitize/visitors/index.js +0 -11
- package/lib/sanitize/visitors/remove-dynamic-zones.js +0 -9
- package/lib/sanitize/visitors/remove-morph-to-relations.js +0 -9
- package/lib/sanitize/visitors/remove-password.js +0 -7
- package/lib/sanitize/visitors/remove-private.js +0 -15
- package/lib/sanitize/visitors/remove-restricted-relations.js +0 -81
- package/lib/sanitize/visitors/restricted-fields.js +0 -32
- package/lib/set-creator-fields.js +0 -17
- package/lib/string-formatting.js +0 -79
- package/lib/template-configuration.js +0 -32
- package/lib/template.js +0 -28
- package/lib/traverse/factory.js +0 -157
- package/lib/traverse/index.js +0 -16
- package/lib/traverse/query-fields.js +0 -39
- package/lib/traverse/query-filters.js +0 -97
- package/lib/traverse/query-populate.js +0 -191
- package/lib/traverse/query-sort.js +0 -171
- package/lib/traverse-entity.js +0 -166
- package/lib/validators.js +0 -120
- package/lib/webhook.js +0 -30
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { curry, isArray, isString, eq, trim, constant } = require('lodash/fp');
|
|
4
|
-
|
|
5
|
-
const traverseFactory = require('./factory');
|
|
6
|
-
|
|
7
|
-
const isStringArray = (value) => isArray(value) && value.every(isString);
|
|
8
|
-
|
|
9
|
-
const fields = traverseFactory()
|
|
10
|
-
// Interecept array of strings
|
|
11
|
-
.intercept(isStringArray, async (visitor, options, fields, { recurse }) => {
|
|
12
|
-
return Promise.all(fields.map((field) => recurse(visitor, options, field)));
|
|
13
|
-
})
|
|
14
|
-
// Return wildcards as is
|
|
15
|
-
.intercept(eq('*'), constant('*'))
|
|
16
|
-
// Parse string values
|
|
17
|
-
// Since we're parsing strings only, each value should be an attribute name (and it's value, undefined),
|
|
18
|
-
// thus it shouldn't be possible to set a new value, and get should return the whole data if key === data
|
|
19
|
-
.parse(isString, () => ({
|
|
20
|
-
transform: trim,
|
|
21
|
-
|
|
22
|
-
remove(key, data) {
|
|
23
|
-
return data === key ? undefined : data;
|
|
24
|
-
},
|
|
25
|
-
|
|
26
|
-
set(_key, _value, data) {
|
|
27
|
-
return data;
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
keys(data) {
|
|
31
|
-
return [data];
|
|
32
|
-
},
|
|
33
|
-
|
|
34
|
-
get(key, data) {
|
|
35
|
-
return key === data ? data : undefined;
|
|
36
|
-
},
|
|
37
|
-
}));
|
|
38
|
-
|
|
39
|
-
module.exports = curry(fields.traverse);
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { curry, isObject, isEmpty, isArray, isNil, cloneDeep } = require('lodash/fp');
|
|
4
|
-
|
|
5
|
-
const traverseFactory = require('./factory');
|
|
6
|
-
|
|
7
|
-
const filters = traverseFactory()
|
|
8
|
-
.intercept(
|
|
9
|
-
// Intercept filters arrays and apply the traversal to each one individually
|
|
10
|
-
isArray,
|
|
11
|
-
async (visitor, options, filters, { recurse }) => {
|
|
12
|
-
return Promise.all(
|
|
13
|
-
filters.map((filter, i) => {
|
|
14
|
-
// In filters, only operators such as $and, $in, $notIn or $or and implicit operators like [...]
|
|
15
|
-
// can have a value array, thus we can update the raw path but not the attribute one
|
|
16
|
-
const newPath = { ...options.path, raw: `${options.path.raw}[${i}]` };
|
|
17
|
-
|
|
18
|
-
return recurse(visitor, { ...options, path: newPath }, filter);
|
|
19
|
-
})
|
|
20
|
-
// todo: move that to the visitors
|
|
21
|
-
).then((res) => res.filter((val) => !(isObject(val) && isEmpty(val))));
|
|
22
|
-
}
|
|
23
|
-
)
|
|
24
|
-
.intercept(
|
|
25
|
-
// Ignore non object filters and return the value as-is
|
|
26
|
-
(filters) => !isObject(filters),
|
|
27
|
-
(_, __, filters) => {
|
|
28
|
-
return filters;
|
|
29
|
-
}
|
|
30
|
-
)
|
|
31
|
-
// Parse object values
|
|
32
|
-
.parse(
|
|
33
|
-
(value) => typeof value === 'object',
|
|
34
|
-
() => ({
|
|
35
|
-
transform: cloneDeep,
|
|
36
|
-
|
|
37
|
-
remove(key, data) {
|
|
38
|
-
const { [key]: ignored, ...rest } = data;
|
|
39
|
-
|
|
40
|
-
return rest;
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
set(key, value, data) {
|
|
44
|
-
return { ...data, [key]: value };
|
|
45
|
-
},
|
|
46
|
-
|
|
47
|
-
keys(data) {
|
|
48
|
-
return Object.keys(data);
|
|
49
|
-
},
|
|
50
|
-
|
|
51
|
-
get(key, data) {
|
|
52
|
-
return data[key];
|
|
53
|
-
},
|
|
54
|
-
})
|
|
55
|
-
)
|
|
56
|
-
// Ignore null or undefined values
|
|
57
|
-
.ignore(({ value }) => isNil(value))
|
|
58
|
-
// Recursion on operators (non attributes)
|
|
59
|
-
.on(
|
|
60
|
-
({ attribute }) => isNil(attribute),
|
|
61
|
-
async ({ key, visitor, path, value, schema }, { set, recurse }) => {
|
|
62
|
-
set(key, await recurse(visitor, { schema, path }, value));
|
|
63
|
-
}
|
|
64
|
-
)
|
|
65
|
-
// Handle relation recursion
|
|
66
|
-
.onRelation(async ({ key, attribute, visitor, path, value }, { set, recurse }) => {
|
|
67
|
-
const isMorphRelation = attribute.relation.toLowerCase().startsWith('morph');
|
|
68
|
-
|
|
69
|
-
if (isMorphRelation) {
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const targetSchemaUID = attribute.target;
|
|
74
|
-
const targetSchema = strapi.getModel(targetSchemaUID);
|
|
75
|
-
|
|
76
|
-
const newValue = await recurse(visitor, { schema: targetSchema, path }, value);
|
|
77
|
-
|
|
78
|
-
set(key, newValue);
|
|
79
|
-
})
|
|
80
|
-
.onComponent(async ({ key, attribute, visitor, path, value }, { set, recurse }) => {
|
|
81
|
-
const targetSchema = strapi.getModel(attribute.component);
|
|
82
|
-
|
|
83
|
-
const newValue = await recurse(visitor, { schema: targetSchema, path }, value);
|
|
84
|
-
|
|
85
|
-
set(key, newValue);
|
|
86
|
-
})
|
|
87
|
-
// Handle media recursion
|
|
88
|
-
.onMedia(async ({ key, visitor, path, value }, { set, recurse }) => {
|
|
89
|
-
const targetSchemaUID = 'plugin::upload.file';
|
|
90
|
-
const targetSchema = strapi.getModel(targetSchemaUID);
|
|
91
|
-
|
|
92
|
-
const newValue = await recurse(visitor, { schema: targetSchema, path }, value);
|
|
93
|
-
|
|
94
|
-
set(key, newValue);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
module.exports = curry(filters.traverse);
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const {
|
|
4
|
-
curry,
|
|
5
|
-
isString,
|
|
6
|
-
isArray,
|
|
7
|
-
eq,
|
|
8
|
-
constant,
|
|
9
|
-
split,
|
|
10
|
-
isObject,
|
|
11
|
-
trim,
|
|
12
|
-
isNil,
|
|
13
|
-
cloneDeep,
|
|
14
|
-
join,
|
|
15
|
-
first,
|
|
16
|
-
} = require('lodash/fp');
|
|
17
|
-
|
|
18
|
-
const traverseFactory = require('./factory');
|
|
19
|
-
|
|
20
|
-
const isKeyword =
|
|
21
|
-
(keyword) =>
|
|
22
|
-
({ key, attribute }) => {
|
|
23
|
-
return !attribute && keyword === key;
|
|
24
|
-
};
|
|
25
|
-
const isStringArray = (value) => isArray(value) && value.every(isString);
|
|
26
|
-
|
|
27
|
-
const populate = traverseFactory()
|
|
28
|
-
// Array of strings ['foo', 'foo.bar'] => map(recurse), then filter out empty items
|
|
29
|
-
.intercept(isStringArray, async (visitor, options, populate, { recurse }) => {
|
|
30
|
-
return Promise.all(populate.map((nestedPopulate) => recurse(visitor, options, nestedPopulate)));
|
|
31
|
-
})
|
|
32
|
-
// Return wildcards as is
|
|
33
|
-
.intercept(eq('*'), constant('*'))
|
|
34
|
-
// Parse string values
|
|
35
|
-
.parse(isString, () => {
|
|
36
|
-
const tokenize = split('.');
|
|
37
|
-
const recompose = join('.');
|
|
38
|
-
|
|
39
|
-
return {
|
|
40
|
-
transform: trim,
|
|
41
|
-
|
|
42
|
-
remove(key, data) {
|
|
43
|
-
const [root] = tokenize(data);
|
|
44
|
-
|
|
45
|
-
return root === key ? undefined : data;
|
|
46
|
-
},
|
|
47
|
-
|
|
48
|
-
set(key, value, data) {
|
|
49
|
-
const [root] = tokenize(data);
|
|
50
|
-
|
|
51
|
-
if (root !== key) {
|
|
52
|
-
return data;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return isNil(value) ? root : `${root}.${value}`;
|
|
56
|
-
},
|
|
57
|
-
|
|
58
|
-
keys(data) {
|
|
59
|
-
return [first(tokenize(data))];
|
|
60
|
-
},
|
|
61
|
-
|
|
62
|
-
get(key, data) {
|
|
63
|
-
const [root, ...rest] = tokenize(data);
|
|
64
|
-
|
|
65
|
-
return key === root ? recompose(rest) : undefined;
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
})
|
|
69
|
-
// Parse object values
|
|
70
|
-
.parse(isObject, () => ({
|
|
71
|
-
transform: cloneDeep,
|
|
72
|
-
|
|
73
|
-
remove(key, data) {
|
|
74
|
-
const { [key]: ignored, ...rest } = data;
|
|
75
|
-
|
|
76
|
-
return rest;
|
|
77
|
-
},
|
|
78
|
-
|
|
79
|
-
set(key, value, data) {
|
|
80
|
-
return { ...data, [key]: value };
|
|
81
|
-
},
|
|
82
|
-
|
|
83
|
-
keys(data) {
|
|
84
|
-
return Object.keys(data);
|
|
85
|
-
},
|
|
86
|
-
|
|
87
|
-
get(key, data) {
|
|
88
|
-
return data[key];
|
|
89
|
-
},
|
|
90
|
-
}))
|
|
91
|
-
.ignore(({ key, attribute }) => {
|
|
92
|
-
return ['sort', 'filters', 'fields'].includes(key) && !attribute;
|
|
93
|
-
})
|
|
94
|
-
.on(
|
|
95
|
-
// Handle recursion on populate."populate"
|
|
96
|
-
isKeyword('populate'),
|
|
97
|
-
async ({ key, visitor, path, value, schema }, { set, recurse }) => {
|
|
98
|
-
const newValue = await recurse(visitor, { schema, path }, value);
|
|
99
|
-
|
|
100
|
-
set(key, newValue);
|
|
101
|
-
}
|
|
102
|
-
)
|
|
103
|
-
.on(isKeyword('on'), async ({ key, visitor, path, value }, { set, recurse }) => {
|
|
104
|
-
const newOn = {};
|
|
105
|
-
|
|
106
|
-
for (const [uid, subPopulate] of Object.entries(value)) {
|
|
107
|
-
const model = strapi.getModel(uid);
|
|
108
|
-
const newPath = { ...path, raw: `${path.raw}[${uid}]` };
|
|
109
|
-
|
|
110
|
-
const newSubPopulate = await recurse(visitor, { schema: model, path: newPath }, subPopulate);
|
|
111
|
-
|
|
112
|
-
newOn[uid] = newSubPopulate;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
set(key, newOn);
|
|
116
|
-
})
|
|
117
|
-
// Handle populate on relation
|
|
118
|
-
.onRelation(async ({ key, value, attribute, visitor, path, schema }, { set, recurse }) => {
|
|
119
|
-
const isMorphRelation = attribute.relation.toLowerCase().startsWith('morph');
|
|
120
|
-
|
|
121
|
-
if (isMorphRelation) {
|
|
122
|
-
// Don't traverse values that cannot be parsed
|
|
123
|
-
if (!isObject(value) || !isObject(value?.on)) {
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// If there is a populate fragment defined, traverse it
|
|
128
|
-
const newValue = await recurse(visitor, { schema, path }, { on: value.on });
|
|
129
|
-
|
|
130
|
-
set(key, { on: newValue });
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const targetSchemaUID = attribute.target;
|
|
134
|
-
const targetSchema = strapi.getModel(targetSchemaUID);
|
|
135
|
-
|
|
136
|
-
const newValue = await recurse(visitor, { schema: targetSchema, path }, value);
|
|
137
|
-
|
|
138
|
-
set(key, newValue);
|
|
139
|
-
})
|
|
140
|
-
// Handle populate on media
|
|
141
|
-
.onMedia(async ({ key, path, visitor, value }, { recurse, set }) => {
|
|
142
|
-
const targetSchemaUID = 'plugin::upload.file';
|
|
143
|
-
const targetSchema = strapi.getModel(targetSchemaUID);
|
|
144
|
-
|
|
145
|
-
const newValue = await recurse(visitor, { schema: targetSchema, path }, value);
|
|
146
|
-
|
|
147
|
-
set(key, newValue);
|
|
148
|
-
})
|
|
149
|
-
// Handle populate on components
|
|
150
|
-
.onComponent(async ({ key, value, visitor, path, attribute }, { recurse, set }) => {
|
|
151
|
-
const targetSchema = strapi.getModel(attribute.component);
|
|
152
|
-
|
|
153
|
-
const newValue = await recurse(visitor, { schema: targetSchema, path }, value);
|
|
154
|
-
|
|
155
|
-
set(key, newValue);
|
|
156
|
-
})
|
|
157
|
-
// Handle populate on dynamic zones
|
|
158
|
-
.onDynamicZone(async ({ key, value, attribute, schema, visitor, path }, { set, recurse }) => {
|
|
159
|
-
if (isObject(value)) {
|
|
160
|
-
const { components } = attribute;
|
|
161
|
-
const { on, ...properties } = value;
|
|
162
|
-
|
|
163
|
-
const newValue = {};
|
|
164
|
-
|
|
165
|
-
// Handle legacy DZ params
|
|
166
|
-
let newProperties = properties;
|
|
167
|
-
|
|
168
|
-
for (const componentUID of components) {
|
|
169
|
-
const componentSchema = strapi.getModel(componentUID);
|
|
170
|
-
newProperties = await recurse(visitor, { schema: componentSchema, path }, newProperties);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
Object.assign(newValue, newProperties);
|
|
174
|
-
|
|
175
|
-
// Handle new morph fragment syntax
|
|
176
|
-
if (on) {
|
|
177
|
-
const newOn = await recurse(visitor, { schema, path }, { on });
|
|
178
|
-
|
|
179
|
-
// Recompose both syntaxes
|
|
180
|
-
Object.assign(newValue, newOn);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
set(key, newValue);
|
|
184
|
-
} else {
|
|
185
|
-
const newValue = await recurse(visitor, { schema, path }, value);
|
|
186
|
-
|
|
187
|
-
set(key, newValue);
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
module.exports = curry(populate.traverse);
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const {
|
|
4
|
-
curry,
|
|
5
|
-
isString,
|
|
6
|
-
isObject,
|
|
7
|
-
map,
|
|
8
|
-
trim,
|
|
9
|
-
split,
|
|
10
|
-
isEmpty,
|
|
11
|
-
flatten,
|
|
12
|
-
pipe,
|
|
13
|
-
isNil,
|
|
14
|
-
first,
|
|
15
|
-
cloneDeep,
|
|
16
|
-
} = require('lodash/fp');
|
|
17
|
-
|
|
18
|
-
const traverseFactory = require('./factory');
|
|
19
|
-
|
|
20
|
-
const ORDERS = { asc: 'asc', desc: 'desc' };
|
|
21
|
-
const ORDER_VALUES = Object.values(ORDERS);
|
|
22
|
-
|
|
23
|
-
const isSortOrder = (value) => ORDER_VALUES.includes(value.toLowerCase());
|
|
24
|
-
const isStringArray = (value) => Array.isArray(value) && value.every(isString);
|
|
25
|
-
const isObjectArray = (value) => Array.isArray(value) && value.every(isObject);
|
|
26
|
-
const isNestedSorts = (value) => isString(value) && value.split(',').length > 1;
|
|
27
|
-
|
|
28
|
-
const sort = traverseFactory()
|
|
29
|
-
.intercept(
|
|
30
|
-
// String with chained sorts (foo,bar,foobar) => split, map(recurse), then recompose
|
|
31
|
-
isNestedSorts,
|
|
32
|
-
async (visitor, options, sort, { recurse }) => {
|
|
33
|
-
return Promise.all(
|
|
34
|
-
sort
|
|
35
|
-
.split(',')
|
|
36
|
-
.map(trim)
|
|
37
|
-
.map((nestedSort) => recurse(visitor, options, nestedSort))
|
|
38
|
-
).then((res) => res.filter((part) => !isEmpty(part)).join(','));
|
|
39
|
-
}
|
|
40
|
-
)
|
|
41
|
-
.intercept(
|
|
42
|
-
// Array of strings ['foo', 'foo,bar'] => map(recurse), then filter out empty items
|
|
43
|
-
isStringArray,
|
|
44
|
-
async (visitor, options, sort, { recurse }) => {
|
|
45
|
-
return Promise.all(sort.map((nestedSort) => recurse(visitor, options, nestedSort))).then(
|
|
46
|
-
(res) => res.filter((nestedSort) => !isEmpty(nestedSort))
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
)
|
|
50
|
-
.intercept(
|
|
51
|
-
// Array of objects [{ foo: 'asc' }, { bar: 'desc', baz: 'asc' }] => map(recurse), then filter out empty items
|
|
52
|
-
isObjectArray,
|
|
53
|
-
async (visitor, options, sort, { recurse }) => {
|
|
54
|
-
return Promise.all(sort.map((nestedSort) => recurse(visitor, options, nestedSort))).then(
|
|
55
|
-
(res) => res.filter((nestedSort) => !isEmpty(nestedSort))
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
)
|
|
59
|
-
// Parse string values
|
|
60
|
-
.parse(
|
|
61
|
-
(sort) => typeof sort === 'string',
|
|
62
|
-
() => {
|
|
63
|
-
const tokenize = pipe(split('.'), map(split(':')), flatten);
|
|
64
|
-
const recompose = (parts) => {
|
|
65
|
-
if (parts.length === 0) {
|
|
66
|
-
return undefined;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return parts.reduce((acc, part) => {
|
|
70
|
-
if (isEmpty(part)) {
|
|
71
|
-
return acc;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (acc === '') {
|
|
75
|
-
return part;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return isSortOrder(part) ? `${acc}:${part}` : `${acc}.${part}`;
|
|
79
|
-
}, '');
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
return {
|
|
83
|
-
transform: trim,
|
|
84
|
-
|
|
85
|
-
remove(key, data) {
|
|
86
|
-
const [root] = tokenize(data);
|
|
87
|
-
|
|
88
|
-
return root === key ? undefined : data;
|
|
89
|
-
},
|
|
90
|
-
|
|
91
|
-
set(key, value, data) {
|
|
92
|
-
const [root] = tokenize(data);
|
|
93
|
-
|
|
94
|
-
if (root !== key) {
|
|
95
|
-
return data;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return isNil(value) ? root : `${root}.${value}`;
|
|
99
|
-
},
|
|
100
|
-
|
|
101
|
-
keys(data) {
|
|
102
|
-
return [first(tokenize(data))];
|
|
103
|
-
},
|
|
104
|
-
|
|
105
|
-
get(key, data) {
|
|
106
|
-
const [root, ...rest] = tokenize(data);
|
|
107
|
-
|
|
108
|
-
return key === root ? recompose(rest) : undefined;
|
|
109
|
-
},
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
)
|
|
113
|
-
// Parse object values
|
|
114
|
-
.parse(
|
|
115
|
-
(value) => typeof value === 'object',
|
|
116
|
-
() => ({
|
|
117
|
-
transform: cloneDeep,
|
|
118
|
-
|
|
119
|
-
remove(key, data) {
|
|
120
|
-
const { [key]: ignored, ...rest } = data;
|
|
121
|
-
|
|
122
|
-
return rest;
|
|
123
|
-
},
|
|
124
|
-
|
|
125
|
-
set(key, value, data) {
|
|
126
|
-
return { ...data, [key]: value };
|
|
127
|
-
},
|
|
128
|
-
|
|
129
|
-
keys(data) {
|
|
130
|
-
return Object.keys(data);
|
|
131
|
-
},
|
|
132
|
-
|
|
133
|
-
get(key, data) {
|
|
134
|
-
return data[key];
|
|
135
|
-
},
|
|
136
|
-
})
|
|
137
|
-
)
|
|
138
|
-
// Handle deep sort on relation
|
|
139
|
-
.onRelation(async ({ key, value, attribute, visitor, path }, { set, recurse }) => {
|
|
140
|
-
const isMorphRelation = attribute.relation.toLowerCase().startsWith('morph');
|
|
141
|
-
|
|
142
|
-
if (isMorphRelation) {
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const targetSchemaUID = attribute.target;
|
|
147
|
-
const targetSchema = strapi.getModel(targetSchemaUID);
|
|
148
|
-
|
|
149
|
-
const newValue = await recurse(visitor, { schema: targetSchema, path }, value);
|
|
150
|
-
|
|
151
|
-
set(key, newValue);
|
|
152
|
-
})
|
|
153
|
-
// Handle deep sort on media
|
|
154
|
-
.onMedia(async ({ key, path, visitor, value }, { recurse, set }) => {
|
|
155
|
-
const targetSchemaUID = 'plugin::upload.file';
|
|
156
|
-
const targetSchema = strapi.getModel(targetSchemaUID);
|
|
157
|
-
|
|
158
|
-
const newValue = await recurse(visitor, { schema: targetSchema, path }, value);
|
|
159
|
-
|
|
160
|
-
set(key, newValue);
|
|
161
|
-
})
|
|
162
|
-
// Handle deep sort on components
|
|
163
|
-
.onComponent(async ({ key, value, visitor, path, attribute }, { recurse, set }) => {
|
|
164
|
-
const targetSchema = strapi.getModel(attribute.component);
|
|
165
|
-
|
|
166
|
-
const newValue = await recurse(visitor, { schema: targetSchema, path }, value);
|
|
167
|
-
|
|
168
|
-
set(key, newValue);
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
module.exports = curry(sort.traverse);
|
package/lib/traverse-entity.js
DELETED
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { clone, isObject, isArray, isNil, curry } = require('lodash/fp');
|
|
4
|
-
|
|
5
|
-
const traverseMorphRelationTarget = async (visitor, path, entry) => {
|
|
6
|
-
const targetSchema = strapi.getModel(entry.__type);
|
|
7
|
-
|
|
8
|
-
const traverseOptions = { schema: targetSchema, path };
|
|
9
|
-
|
|
10
|
-
return traverseEntity(visitor, traverseOptions, entry);
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
const traverseRelationTarget = (schema) => async (visitor, path, entry) => {
|
|
14
|
-
const traverseOptions = { schema, path };
|
|
15
|
-
|
|
16
|
-
return traverseEntity(visitor, traverseOptions, entry);
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const traverseMediaTarget = async (visitor, path, entry) => {
|
|
20
|
-
const targetSchemaUID = 'plugin::upload.file';
|
|
21
|
-
const targetSchema = strapi.getModel(targetSchemaUID);
|
|
22
|
-
|
|
23
|
-
const traverseOptions = { schema: targetSchema, path };
|
|
24
|
-
|
|
25
|
-
return traverseEntity(visitor, traverseOptions, entry);
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const traverseComponent = async (visitor, path, schema, entry) => {
|
|
29
|
-
const traverseOptions = { schema, path };
|
|
30
|
-
|
|
31
|
-
return traverseEntity(visitor, traverseOptions, entry);
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const visitDynamicZoneEntry = async (visitor, path, entry) => {
|
|
35
|
-
const targetSchema = strapi.getModel(entry.__component);
|
|
36
|
-
const traverseOptions = { schema: targetSchema, path };
|
|
37
|
-
|
|
38
|
-
return traverseEntity(visitor, traverseOptions, entry);
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const traverseEntity = async (visitor, options, entity) => {
|
|
42
|
-
const { path = { raw: null, attribute: null }, schema } = options;
|
|
43
|
-
|
|
44
|
-
// End recursion
|
|
45
|
-
if (!isObject(entity) || isNil(schema)) {
|
|
46
|
-
return entity;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Don't mutate the original entity object
|
|
50
|
-
// only clone at 1st level as the next level will get clone when traversed
|
|
51
|
-
const copy = clone(entity);
|
|
52
|
-
const visitorUtils = createVisitorUtils({ data: copy });
|
|
53
|
-
|
|
54
|
-
const keys = Object.keys(copy);
|
|
55
|
-
for (let i = 0; i < keys.length; i += 1) {
|
|
56
|
-
const key = keys[i];
|
|
57
|
-
// Retrieve the attribute definition associated to the key from the schema
|
|
58
|
-
const attribute = schema.attributes[key];
|
|
59
|
-
|
|
60
|
-
// If the attribute doesn't exist within the schema, ignore it
|
|
61
|
-
if (isNil(attribute)) {
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const newPath = { ...path };
|
|
66
|
-
|
|
67
|
-
newPath.raw = isNil(path.raw) ? key : `${path.raw}.${key}`;
|
|
68
|
-
|
|
69
|
-
if (!isNil(attribute)) {
|
|
70
|
-
newPath.attribute = isNil(path.attribute) ? key : `${path.attribute}.${key}`;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Visit the current attribute
|
|
74
|
-
const visitorOptions = { data: copy, schema, key, value: copy[key], attribute, path: newPath };
|
|
75
|
-
|
|
76
|
-
await visitor(visitorOptions, visitorUtils);
|
|
77
|
-
|
|
78
|
-
// Extract the value for the current key (after calling the visitor)
|
|
79
|
-
const value = copy[key];
|
|
80
|
-
|
|
81
|
-
// Ignore Nil values
|
|
82
|
-
if (isNil(value)) {
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const isRelation = attribute.type === 'relation';
|
|
87
|
-
const isComponent = attribute.type === 'component';
|
|
88
|
-
const isDynamicZone = attribute.type === 'dynamiczone';
|
|
89
|
-
const isMedia = attribute.type === 'media';
|
|
90
|
-
|
|
91
|
-
if (isRelation) {
|
|
92
|
-
const isMorphRelation = attribute.relation.toLowerCase().startsWith('morph');
|
|
93
|
-
|
|
94
|
-
const method = isMorphRelation
|
|
95
|
-
? traverseMorphRelationTarget
|
|
96
|
-
: traverseRelationTarget(strapi.getModel(attribute.target));
|
|
97
|
-
|
|
98
|
-
if (isArray(value)) {
|
|
99
|
-
const res = new Array(value.length);
|
|
100
|
-
for (let i = 0; i < value.length; i += 1) {
|
|
101
|
-
res[i] = await method(visitor, newPath, value[i]);
|
|
102
|
-
}
|
|
103
|
-
copy[key] = res;
|
|
104
|
-
} else {
|
|
105
|
-
copy[key] = await method(visitor, newPath, value);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
continue;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (isMedia) {
|
|
112
|
-
// need to update copy
|
|
113
|
-
if (isArray(value)) {
|
|
114
|
-
const res = new Array(value.length);
|
|
115
|
-
for (let i = 0; i < value.length; i += 1) {
|
|
116
|
-
res[i] = await traverseMediaTarget(visitor, newPath, value[i]);
|
|
117
|
-
}
|
|
118
|
-
copy[key] = res;
|
|
119
|
-
} else {
|
|
120
|
-
copy[key] = await traverseMediaTarget(visitor, newPath, value);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
continue;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (isComponent) {
|
|
127
|
-
const targetSchema = strapi.getModel(attribute.component);
|
|
128
|
-
|
|
129
|
-
if (isArray(value)) {
|
|
130
|
-
const res = new Array(value.length);
|
|
131
|
-
for (let i = 0; i < value.length; i += 1) {
|
|
132
|
-
res[i] = await traverseComponent(visitor, newPath, targetSchema, value[i]);
|
|
133
|
-
}
|
|
134
|
-
copy[key] = res;
|
|
135
|
-
} else {
|
|
136
|
-
copy[key] = await traverseComponent(visitor, newPath, targetSchema, value);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
continue;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (isDynamicZone && isArray(value)) {
|
|
143
|
-
const res = new Array(value.length);
|
|
144
|
-
for (let i = 0; i < value.length; i += 1) {
|
|
145
|
-
res[i] = await visitDynamicZoneEntry(visitor, newPath, value[i]);
|
|
146
|
-
}
|
|
147
|
-
copy[key] = res;
|
|
148
|
-
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
return copy;
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
const createVisitorUtils = ({ data }) => ({
|
|
157
|
-
remove(key) {
|
|
158
|
-
delete data[key];
|
|
159
|
-
},
|
|
160
|
-
|
|
161
|
-
set(key, value) {
|
|
162
|
-
data[key] = value;
|
|
163
|
-
},
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
module.exports = curry(traverseEntity);
|