@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.
Files changed (184) hide show
  1. package/dist/async.d.ts +10 -0
  2. package/dist/async.js +33 -0
  3. package/dist/async.js.map +1 -0
  4. package/dist/code-generator.d.ts +2 -0
  5. package/dist/code-generator.js +11 -0
  6. package/dist/code-generator.js.map +1 -0
  7. package/dist/config.d.ts +8 -0
  8. package/dist/config.js +79 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/content-types.d.ts +60 -0
  11. package/dist/content-types.js +151 -0
  12. package/dist/content-types.js.map +1 -0
  13. package/dist/convert-query-params.d.ts +75 -0
  14. package/dist/convert-query-params.js +476 -0
  15. package/dist/convert-query-params.js.map +1 -0
  16. package/dist/env-helper.d.ts +18 -0
  17. package/dist/env-helper.js +84 -0
  18. package/dist/env-helper.js.map +1 -0
  19. package/dist/errors.d.ts +37 -0
  20. package/dist/errors.js +100 -0
  21. package/dist/errors.js.map +1 -0
  22. package/dist/file.d.ts +16 -0
  23. package/dist/file.js +54 -0
  24. package/dist/file.js.map +1 -0
  25. package/dist/format-yup-error.d.ts +10 -0
  26. package/dist/format-yup-error.js +17 -0
  27. package/dist/format-yup-error.js.map +1 -0
  28. package/dist/hooks.d.ts +63 -0
  29. package/dist/hooks.js +89 -0
  30. package/dist/hooks.js.map +1 -0
  31. package/dist/import-default.d.ts +1 -0
  32. package/dist/import-default.js +9 -0
  33. package/dist/import-default.js.map +1 -0
  34. package/dist/index.d.ts +30 -0
  35. package/dist/index.js +99 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/object-formatting.d.ts +3 -0
  38. package/dist/object-formatting.js +14 -0
  39. package/dist/object-formatting.js.map +1 -0
  40. package/dist/operators.d.ts +2 -0
  41. package/dist/operators.js +70 -0
  42. package/dist/operators.js.map +1 -0
  43. package/dist/pagination.d.ts +14 -0
  44. package/dist/pagination.js +80 -0
  45. package/dist/pagination.js.map +1 -0
  46. package/dist/parse-multipart.d.ts +8 -0
  47. package/dist/parse-multipart.js +36 -0
  48. package/dist/parse-multipart.js.map +1 -0
  49. package/dist/parse-type.d.ts +21 -0
  50. package/dist/parse-type.js +108 -0
  51. package/dist/parse-type.js.map +1 -0
  52. package/dist/policy.d.ts +41 -0
  53. package/dist/policy.js +109 -0
  54. package/dist/policy.js.map +1 -0
  55. package/dist/print-value.d.ts +2 -0
  56. package/dist/print-value.js +50 -0
  57. package/dist/print-value.js.map +1 -0
  58. package/dist/provider-factory.d.ts +29 -0
  59. package/dist/provider-factory.js +80 -0
  60. package/dist/provider-factory.js.map +1 -0
  61. package/dist/relations.d.ts +10 -0
  62. package/dist/relations.js +23 -0
  63. package/dist/relations.js.map +1 -0
  64. package/dist/sanitize/index.d.ts +23 -0
  65. package/dist/sanitize/index.js +135 -0
  66. package/dist/sanitize/index.js.map +1 -0
  67. package/dist/sanitize/sanitizers.d.ts +10 -0
  68. package/dist/sanitize/sanitizers.js +114 -0
  69. package/dist/sanitize/sanitizers.js.map +1 -0
  70. package/dist/sanitize/visitors/allowed-fields.d.ts +3 -0
  71. package/{lib → dist}/sanitize/visitors/allowed-fields.js +17 -32
  72. package/dist/sanitize/visitors/allowed-fields.js.map +1 -0
  73. package/dist/sanitize/visitors/index.d.ts +7 -0
  74. package/dist/sanitize/visitors/index.js +21 -0
  75. package/dist/sanitize/visitors/index.js.map +1 -0
  76. package/dist/sanitize/visitors/remove-dynamic-zones.d.ts +3 -0
  77. package/dist/sanitize/visitors/remove-dynamic-zones.js +10 -0
  78. package/dist/sanitize/visitors/remove-dynamic-zones.js.map +1 -0
  79. package/dist/sanitize/visitors/remove-morph-to-relations.d.ts +3 -0
  80. package/dist/sanitize/visitors/remove-morph-to-relations.js +10 -0
  81. package/dist/sanitize/visitors/remove-morph-to-relations.js.map +1 -0
  82. package/dist/sanitize/visitors/remove-password.d.ts +3 -0
  83. package/dist/sanitize/visitors/remove-password.js +9 -0
  84. package/dist/sanitize/visitors/remove-password.js.map +1 -0
  85. package/dist/sanitize/visitors/remove-private.d.ts +3 -0
  86. package/dist/sanitize/visitors/remove-private.js +14 -0
  87. package/dist/sanitize/visitors/remove-private.js.map +1 -0
  88. package/dist/sanitize/visitors/remove-restricted-relations.d.ts +3 -0
  89. package/dist/sanitize/visitors/remove-restricted-relations.js +88 -0
  90. package/dist/sanitize/visitors/remove-restricted-relations.js.map +1 -0
  91. package/dist/sanitize/visitors/restricted-fields.d.ts +3 -0
  92. package/dist/sanitize/visitors/restricted-fields.js +25 -0
  93. package/dist/sanitize/visitors/restricted-fields.js.map +1 -0
  94. package/dist/set-creator-fields.d.ts +9 -0
  95. package/dist/set-creator-fields.js +39 -0
  96. package/dist/set-creator-fields.js.map +1 -0
  97. package/dist/string-formatting.d.ts +15 -0
  98. package/dist/string-formatting.js +85 -0
  99. package/dist/string-formatting.js.map +1 -0
  100. package/dist/template-configuration.d.ts +5 -0
  101. package/dist/template-configuration.js +30 -0
  102. package/dist/template-configuration.js.map +1 -0
  103. package/dist/template.d.ts +9 -0
  104. package/dist/template.js +20 -0
  105. package/dist/template.js.map +1 -0
  106. package/dist/traverse/factory.d.ts +78 -0
  107. package/dist/traverse/factory.js +127 -0
  108. package/dist/traverse/factory.js.map +1 -0
  109. package/dist/traverse/index.d.ts +5 -0
  110. package/dist/traverse/index.js +17 -0
  111. package/dist/traverse/index.js.map +1 -0
  112. package/dist/traverse/query-fields.d.ts +3 -0
  113. package/dist/traverse/query-fields.js +35 -0
  114. package/dist/traverse/query-fields.js.map +1 -0
  115. package/dist/traverse/query-filters.d.ts +3 -0
  116. package/dist/traverse/query-filters.js +75 -0
  117. package/dist/traverse/query-filters.js.map +1 -0
  118. package/dist/traverse/query-populate.d.ts +3 -0
  119. package/dist/traverse/query-populate.js +144 -0
  120. package/dist/traverse/query-populate.js.map +1 -0
  121. package/dist/traverse/query-sort.d.ts +3 -0
  122. package/dist/traverse/query-sort.js +116 -0
  123. package/dist/traverse/query-sort.js.map +1 -0
  124. package/dist/traverse-entity.d.ts +31 -0
  125. package/dist/traverse-entity.js +134 -0
  126. package/dist/traverse-entity.js.map +1 -0
  127. package/dist/types.d.ts +65 -0
  128. package/dist/types.js +3 -0
  129. package/dist/types.js.map +1 -0
  130. package/dist/validators.d.ts +13 -0
  131. package/dist/validators.js +120 -0
  132. package/dist/validators.js.map +1 -0
  133. package/dist/webhook.d.ts +5 -0
  134. package/dist/webhook.js +27 -0
  135. package/dist/webhook.js.map +1 -0
  136. package/package.json +19 -4
  137. package/.eslintignore +0 -3
  138. package/.eslintrc.js +0 -4
  139. package/index.d.ts +0 -5
  140. package/lib/async.d.ts +0 -21
  141. package/lib/async.js +0 -45
  142. package/lib/build-query.js +0 -208
  143. package/lib/code-generator.js +0 -13
  144. package/lib/config.js +0 -88
  145. package/lib/content-types.js +0 -196
  146. package/lib/convert-query-params.js +0 -586
  147. package/lib/env-helper.js +0 -98
  148. package/lib/errors.js +0 -113
  149. package/lib/file.js +0 -60
  150. package/lib/format-yup-error.js +0 -20
  151. package/lib/hooks.js +0 -110
  152. package/lib/import-default.js +0 -10
  153. package/lib/index.js +0 -99
  154. package/lib/object-formatting.js +0 -15
  155. package/lib/operators.js +0 -74
  156. package/lib/pagination.js +0 -99
  157. package/lib/parse-multipart.js +0 -44
  158. package/lib/parse-type.js +0 -100
  159. package/lib/policy.js +0 -129
  160. package/lib/print-value.js +0 -52
  161. package/lib/provider-factory.js +0 -116
  162. package/lib/relations.js +0 -31
  163. package/lib/sanitize/index.js +0 -143
  164. package/lib/sanitize/sanitizers.js +0 -163
  165. package/lib/sanitize/visitors/index.js +0 -11
  166. package/lib/sanitize/visitors/remove-dynamic-zones.js +0 -9
  167. package/lib/sanitize/visitors/remove-morph-to-relations.js +0 -9
  168. package/lib/sanitize/visitors/remove-password.js +0 -7
  169. package/lib/sanitize/visitors/remove-private.js +0 -15
  170. package/lib/sanitize/visitors/remove-restricted-relations.js +0 -81
  171. package/lib/sanitize/visitors/restricted-fields.js +0 -32
  172. package/lib/set-creator-fields.js +0 -17
  173. package/lib/string-formatting.js +0 -79
  174. package/lib/template-configuration.js +0 -32
  175. package/lib/template.js +0 -28
  176. package/lib/traverse/factory.js +0 -157
  177. package/lib/traverse/index.js +0 -16
  178. package/lib/traverse/query-fields.js +0 -39
  179. package/lib/traverse/query-filters.js +0 -97
  180. package/lib/traverse/query-populate.js +0 -191
  181. package/lib/traverse/query-sort.js +0 -171
  182. package/lib/traverse-entity.js +0 -166
  183. package/lib/validators.js +0 -120
  184. 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);
@@ -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);