@strapi/utils 4.4.0-alpha.0 → 4.4.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.
@@ -21,7 +21,7 @@ const getAssociationFromFieldKey = ({ model, field }) => {
21
21
  let association;
22
22
  let attribute;
23
23
 
24
- for (let i = 0; i < fieldParts.length; i++) {
24
+ for (let i = 0; i < fieldParts.length; i += 1) {
25
25
  const part = fieldParts[i];
26
26
  attribute = part;
27
27
 
@@ -106,6 +106,20 @@ const isPrivateAttribute = (model = {}, attributeName) => {
106
106
  const isScalarAttribute = (attribute) => {
107
107
  return !['media', 'component', 'relation', 'dynamiczone'].includes(attribute.type);
108
108
  };
109
+ const isMediaAttribute = (attribute) => attribute.type === 'media';
110
+ const isRelationalAttribute = (attribute) => attribute.type === 'relation';
111
+ const isComponentAttribute = (attribute) => ['component', 'dynamiczone'].includes(attribute.type);
112
+
113
+ const getComponentAttributes = (schema) => {
114
+ return _.reduce(
115
+ schema.attributes,
116
+ (acc, attr, attrName) => {
117
+ if (isComponentAttribute(attr)) acc.push(attrName);
118
+ return acc;
119
+ },
120
+ []
121
+ );
122
+ };
109
123
 
110
124
  const getScalarAttributes = (schema) => {
111
125
  return _.reduce(
@@ -118,10 +132,6 @@ const getScalarAttributes = (schema) => {
118
132
  );
119
133
  };
120
134
 
121
- const isMediaAttribute = (attribute) => attribute.type === 'media';
122
- const isRelationalAttribute = (attribute) => attribute.type === 'relation';
123
- const isComponentAttribute = (attribute) => ['component', 'dynamiczone'].includes(attribute.type);
124
-
125
135
  /**
126
136
  * Checks if an attribute is of type `type`
127
137
  * @param {object} attribute
@@ -152,6 +162,7 @@ module.exports = {
152
162
  isPrivateAttribute,
153
163
  constants,
154
164
  getNonWritableAttributes,
165
+ getComponentAttributes,
155
166
  getScalarAttributes,
156
167
  getWritableAttributes,
157
168
  isWritableAttribute,
@@ -174,7 +174,13 @@ const convertPopulateObject = (populate, schema) => {
174
174
  if (attribute.type === 'dynamiczone') {
175
175
  const populates = attribute.components
176
176
  .map((uid) => strapi.getModel(uid))
177
- .map((schema) => convertNestedPopulate(subPopulate, schema));
177
+ .map((schema) => convertNestedPopulate(subPopulate, schema))
178
+ .map((populate) => (populate === true ? {} : populate)) // cast boolean to empty object to avoid merging issues
179
+ .filter((populate) => populate !== false);
180
+
181
+ if (isEmpty(populates)) {
182
+ return acc;
183
+ }
178
184
 
179
185
  return {
180
186
  ...acc,
@@ -203,16 +209,22 @@ const convertPopulateObject = (populate, schema) => {
203
209
  return acc;
204
210
  }
205
211
 
212
+ const populateObject = convertNestedPopulate(subPopulate, targetSchema);
213
+
214
+ if (!populateObject) {
215
+ return acc;
216
+ }
217
+
206
218
  return {
207
219
  ...acc,
208
- [key]: convertNestedPopulate(subPopulate, targetSchema),
220
+ [key]: populateObject,
209
221
  };
210
222
  }, {});
211
223
  };
212
224
 
213
225
  const convertNestedPopulate = (subPopulate, schema) => {
214
- if (subPopulate === '*') {
215
- return true;
226
+ if (_.isString(subPopulate)) {
227
+ return parseType({ type: 'boolean', value: subPopulate, forceCast: true });
216
228
  }
217
229
 
218
230
  if (_.isBoolean(subPopulate)) {
package/lib/hooks.js CHANGED
@@ -2,17 +2,8 @@
2
2
 
3
3
  const { eq, remove, cloneDeep } = require('lodash/fp');
4
4
 
5
- /**
6
- * @typedef Hook
7
- * @property {Array<Function>} _handlers - A registry of handler used by the hook
8
- * @property {function(Function):Hook} register - Register a new handler into the hook's registry
9
- * @property {function(Function):Hook} delete- Delete the given handler from the hook's registry
10
- * @property {Function} call - Not implemented by default, can be replaced by any implementation.
11
- */
12
-
13
5
  /**
14
6
  * Create a default Strapi hook
15
- * @return {Hook}
16
7
  */
17
8
  const createHook = () => {
18
9
  const state = {
@@ -45,7 +36,6 @@ const createHook = () => {
45
36
  /**
46
37
  * Create an async series hook.
47
38
  * Upon execution, it will execute every handler in order with the same context
48
- * @return {Hook}
49
39
  */
50
40
  const createAsyncSeriesHook = () => ({
51
41
  ...createHook(),
@@ -60,7 +50,6 @@ const createAsyncSeriesHook = () => ({
60
50
  /**
61
51
  * Create an async series waterfall hook.
62
52
  * Upon execution, it will execute every handler in order and pass the return value of the last handler to the next one
63
- * @return {Hook}
64
53
  */
65
54
  const createAsyncSeriesWaterfallHook = () => ({
66
55
  ...createHook(),
@@ -79,7 +68,6 @@ const createAsyncSeriesWaterfallHook = () => ({
79
68
  /**
80
69
  * Create an async parallel hook.
81
70
  * Upon execution, it will execute every registered handler in band.
82
- * @return {Hook}
83
71
  */
84
72
  const createAsyncParallelHook = () => ({
85
73
  ...createHook(),
@@ -91,6 +79,24 @@ const createAsyncParallelHook = () => ({
91
79
  },
92
80
  });
93
81
 
82
+ /**
83
+ * Create an async parallel hook.
84
+ * Upon execution, it will execute every registered handler in serie and return the first result found.
85
+ */
86
+ const createAsyncBailHook = () => ({
87
+ ...createHook(),
88
+
89
+ async call(context) {
90
+ for (const handler of this.getHandlers()) {
91
+ const result = await handler(context);
92
+
93
+ if (result !== undefined) {
94
+ return result;
95
+ }
96
+ }
97
+ },
98
+ });
99
+
94
100
  module.exports = {
95
101
  // Internal utils
96
102
  internals: {
@@ -100,4 +106,5 @@ module.exports = {
100
106
  createAsyncSeriesHook,
101
107
  createAsyncSeriesWaterfallHook,
102
108
  createAsyncParallelHook,
109
+ createAsyncBailHook,
103
110
  };
@@ -11,6 +11,7 @@ const symbolToString = typeof Symbol !== 'undefined' ? Symbol.prototype.toString
11
11
  const SYMBOL_REGEXP = /^Symbol\((.*)\)(.*)$/;
12
12
 
13
13
  function printNumber(val) {
14
+ // eslint-disable-next-line eqeqeq
14
15
  if (val != +val) return 'NaN';
15
16
  const isNegativeZero = val === 0 && 1 / val < 0;
16
17
  return isNegativeZero ? '-0' : `${val}`;
@@ -25,25 +25,9 @@ const createProviderHooksMap = () => ({
25
25
  });
26
26
 
27
27
  /**
28
- * A customizable item provider enhanced with register/delete hooks
29
- * @typedef {Object} Provider
30
- * @property hooks
31
- * @property register
32
- * @property delete
33
- * @property get
34
- * @property getWhere
35
- * @property values
36
- * @property keys
37
- * @property has
38
- * @property size
39
- * @property clear
40
- */
41
-
42
- /**
43
- * A {@link Provider} factory
28
+ * A Provider factory
44
29
  * @param {Object} [options] - The factory options
45
30
  * @param {boolean = true} options.throwOnDuplicates - Specify the wanted behaviour when encountering a duplicate key on register
46
- * @return {Provider}
47
31
  */
48
32
  const providerFactory = (options = {}) => {
49
33
  const { throwOnDuplicates = true } = options;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/utils",
3
- "version": "4.4.0-alpha.0",
3
+ "version": "4.4.0-beta.0",
4
4
  "description": "Shared utilities for the Strapi packages",
5
5
  "keywords": [
6
6
  "strapi",
@@ -42,8 +42,8 @@
42
42
  "yup": "0.32.9"
43
43
  },
44
44
  "engines": {
45
- "node": ">=14.19.1 <=16.x.x",
45
+ "node": ">=14.19.1 <=18.x.x",
46
46
  "npm": ">=6.0.0"
47
47
  },
48
- "gitHead": "fc78298ae4f9b247d636beda568734d5f8ed7b3e"
48
+ "gitHead": "cae16f7f259fa4473a55e8fea57839cda98f34ae"
49
49
  }