@strapi/utils 4.9.0 → 4.10.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/lib/async.js CHANGED
@@ -6,8 +6,9 @@ const { curry, curryN } = require('lodash/fp');
6
6
  function pipeAsync(...methods) {
7
7
  return async (data) => {
8
8
  let res = data;
9
- for (let i = 0; i < methods.length; i += 1) {
10
- res = await methods[i](res);
9
+
10
+ for (const method of methods) {
11
+ res = await method(res);
11
12
  }
12
13
 
13
14
  return res;
@@ -82,6 +82,7 @@ const isVisibleAttribute = (model, attributeName) => {
82
82
  return getVisibleAttributes(model).includes(attributeName);
83
83
  };
84
84
 
85
+ const getOptions = (model) => _.assign({ draftAndPublish: false }, _.get(model, 'options', {}));
85
86
  const hasDraftAndPublish = (model) => _.get(model, 'options.draftAndPublish', false) === true;
86
87
 
87
88
  const isDraft = (data, model) =>
@@ -178,6 +179,7 @@ module.exports = {
178
179
  getTimestamps,
179
180
  isVisibleAttribute,
180
181
  hasDraftAndPublish,
182
+ getOptions,
181
183
  isDraft,
182
184
  isSingleType,
183
185
  isCollectionType,
@@ -37,16 +37,12 @@ const createContentAPISanitizers = () => {
37
37
  return pipeAsync(...transforms)(data);
38
38
  };
39
39
 
40
- const sanitizeOutput = async (data, schema, { auth } = {}) => {
40
+ const sanitizeOuput = (data, schema, { auth } = {}) => {
41
41
  if (isArray(data)) {
42
- const res = new Array(data.length);
43
- for (let i = 0; i < data.length; i += 1) {
44
- res[i] = await sanitizeOutput(data[i], schema, { auth });
45
- }
46
- return res;
42
+ return Promise.all(data.map((entry) => sanitizeOuput(entry, schema, { auth })));
47
43
  }
48
44
 
49
- const transforms = [(data) => sanitizers.defaultSanitizeOutput(schema, data)];
45
+ const transforms = [sanitizers.defaultSanitizeOutput(schema)];
50
46
 
51
47
  if (auth) {
52
48
  transforms.push(traverseEntity(visitors.removeRestrictedRelations(auth), { schema }));
@@ -126,7 +122,7 @@ const createContentAPISanitizers = () => {
126
122
 
127
123
  return {
128
124
  input: sanitizeInput,
129
- output: sanitizeOutput,
125
+ output: sanitizeOuput,
130
126
  query: sanitizeQuery,
131
127
  filters: sanitizeFilters,
132
128
  sort: sanitizeSort,
@@ -20,20 +20,17 @@ const {
20
20
  removeMorphToRelations,
21
21
  } = require('./visitors');
22
22
 
23
- const sanitizePasswords = (schema) => async (entity) => {
23
+ const sanitizePasswords = curry((schema, entity) => {
24
24
  return traverseEntity(removePassword, { schema }, entity);
25
- };
25
+ });
26
26
 
27
- const defaultSanitizeOutput = async (schema, entity) => {
28
- return traverseEntity(
29
- (...args) => {
30
- removePassword(...args);
31
- removePrivate(...args);
32
- },
33
- { schema },
34
- entity
35
- );
36
- };
27
+ const sanitizePrivates = curry((schema, entity) => {
28
+ return traverseEntity(removePrivate, { schema }, entity);
29
+ });
30
+
31
+ const defaultSanitizeOutput = curry((schema, entity) => {
32
+ return pipeAsync(sanitizePrivates(schema), sanitizePasswords(schema))(entity);
33
+ });
37
34
 
38
35
  const defaultSanitizeFilters = curry((schema, filters) => {
39
36
  return pipeAsync(
@@ -143,6 +140,7 @@ const defaultSanitizePopulate = curry((schema, populate) => {
143
140
 
144
141
  module.exports = {
145
142
  sanitizePasswords,
143
+ sanitizePrivates,
146
144
  defaultSanitizeOutput,
147
145
  defaultSanitizeFilters,
148
146
  defaultSanitizeSort,
@@ -1,42 +1,6 @@
1
1
  'use strict';
2
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
- };
3
+ const { cloneDeep, isObject, isArray, isNil, curry } = require('lodash/fp');
40
4
 
41
5
  const traverseEntity = async (visitor, options, entity) => {
42
6
  const { path = { raw: null, attribute: null }, schema } = options;
@@ -47,13 +11,9 @@ const traverseEntity = async (visitor, options, entity) => {
47
11
  }
48
12
 
49
13
  // 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 });
14
+ const copy = cloneDeep(entity);
53
15
 
54
- const keys = Object.keys(copy);
55
- for (let i = 0; i < keys.length; i += 1) {
56
- const key = keys[i];
16
+ for (const key of Object.keys(copy)) {
57
17
  // Retrieve the attribute definition associated to the key from the schema
58
18
  const attribute = schema.attributes[key];
59
19
 
@@ -72,6 +32,7 @@ const traverseEntity = async (visitor, options, entity) => {
72
32
 
73
33
  // Visit the current attribute
74
34
  const visitorOptions = { data: copy, schema, key, value: copy[key], attribute, path: newPath };
35
+ const visitorUtils = createVisitorUtils({ data: copy });
75
36
 
76
37
  await visitor(visitorOptions, visitorUtils);
77
38
 
@@ -91,62 +52,58 @@ const traverseEntity = async (visitor, options, entity) => {
91
52
  if (isRelation) {
92
53
  const isMorphRelation = attribute.relation.toLowerCase().startsWith('morph');
93
54
 
94
- const method = isMorphRelation
95
- ? traverseMorphRelationTarget
96
- : traverseRelationTarget(strapi.getModel(attribute.target));
55
+ const traverseTarget = (entry) => {
56
+ // Handle polymorphic relationships
57
+ const targetSchemaUID = isMorphRelation ? entry.__type : attribute.target;
58
+ const targetSchema = strapi.getModel(targetSchemaUID);
97
59
 
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
- }
60
+ const traverseOptions = { schema: targetSchema, path: newPath };
107
61
 
108
- continue;
62
+ return traverseEntity(visitor, traverseOptions, entry);
63
+ };
64
+
65
+ // need to update copy
66
+ copy[key] = isArray(value)
67
+ ? await Promise.all(value.map(traverseTarget))
68
+ : await traverseTarget(value);
109
69
  }
110
70
 
111
71
  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
- }
72
+ const traverseTarget = (entry) => {
73
+ const targetSchemaUID = 'plugin::upload.file';
74
+ const targetSchema = strapi.getModel(targetSchemaUID);
122
75
 
123
- continue;
76
+ const traverseOptions = { schema: targetSchema, path: newPath };
77
+
78
+ return traverseEntity(visitor, traverseOptions, entry);
79
+ };
80
+
81
+ // need to update copy
82
+ copy[key] = isArray(value)
83
+ ? await Promise.all(value.map(traverseTarget))
84
+ : await traverseTarget(value);
124
85
  }
125
86
 
126
87
  if (isComponent) {
127
88
  const targetSchema = strapi.getModel(attribute.component);
89
+ const traverseOptions = { schema: targetSchema, path: newPath };
128
90
 
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
- }
91
+ const traverseComponent = (entry) => traverseEntity(visitor, traverseOptions, entry);
138
92
 
139
- continue;
93
+ copy[key] = isArray(value)
94
+ ? await Promise.all(value.map(traverseComponent))
95
+ : await traverseComponent(value);
140
96
  }
141
97
 
142
98
  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;
99
+ const visitDynamicZoneEntry = (entry) => {
100
+ const targetSchema = strapi.getModel(entry.__component);
101
+ const traverseOptions = { schema: targetSchema, path: newPath };
148
102
 
149
- continue;
103
+ return traverseEntity(visitor, traverseOptions, entry);
104
+ };
105
+
106
+ copy[key] = await Promise.all(value.map(visitDynamicZoneEntry));
150
107
  }
151
108
  }
152
109
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/utils",
3
- "version": "4.9.0",
3
+ "version": "4.10.0-beta.0",
4
4
  "description": "Shared utilities for the Strapi packages",
5
5
  "keywords": [
6
6
  "strapi",
@@ -32,9 +32,7 @@
32
32
  "lib": "./lib"
33
33
  },
34
34
  "scripts": {
35
- "test:unit": "jest",
36
- "test:unit:watch": "jest --watch",
37
- "lint": "eslint ."
35
+ "test:unit": "jest --verbose"
38
36
  },
39
37
  "dependencies": {
40
38
  "@sindresorhus/slugify": "1.1.0",
@@ -48,5 +46,5 @@
48
46
  "node": ">=14.19.1 <=18.x.x",
49
47
  "npm": ">=6.0.0"
50
48
  },
51
- "gitHead": "ffe3f4621ccc968ce56fda9a8317ec30d4bad205"
49
+ "gitHead": "1519ef0e56d27b738f24fc88223797651ad47aaf"
52
50
  }
package/.eslintignore DELETED
@@ -1,2 +0,0 @@
1
- node_modules/
2
- .eslintrc.js
package/.eslintrc.js DELETED
@@ -1,4 +0,0 @@
1
- module.exports = {
2
- root: true,
3
- extends: ['custom/back'],
4
- };