@strapi/utils 4.0.0-next.10 → 4.0.0-next.14
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/build-query.js +1 -1
- package/lib/content-types.js +5 -5
- package/lib/convert-query-params.js +10 -19
- package/lib/hooks.js +4 -2
- package/lib/index.js +3 -2
- package/lib/pagination.js +87 -0
- package/lib/policy.js +15 -0
- package/lib/sanitize-entity.js +24 -25
- package/package.json +5 -9
package/lib/build-query.js
CHANGED
|
@@ -60,7 +60,7 @@ const getAssociationFromFieldKey = ({ model, field }) => {
|
|
|
60
60
|
const castInput = ({ type, value, operator }) => {
|
|
61
61
|
return Array.isArray(value)
|
|
62
62
|
? value.map(val => castValue({ type, operator, value: val }))
|
|
63
|
-
: castValue({ type, operator, value
|
|
63
|
+
: castValue({ type, operator, value });
|
|
64
64
|
};
|
|
65
65
|
|
|
66
66
|
/**
|
package/lib/content-types.js
CHANGED
|
@@ -6,12 +6,12 @@ const SINGLE_TYPE = 'singleType';
|
|
|
6
6
|
const COLLECTION_TYPE = 'collectionType';
|
|
7
7
|
|
|
8
8
|
const ID_ATTRIBUTE = 'id';
|
|
9
|
-
const PUBLISHED_AT_ATTRIBUTE = '
|
|
10
|
-
const CREATED_BY_ATTRIBUTE = '
|
|
11
|
-
const UPDATED_BY_ATTRIBUTE = '
|
|
9
|
+
const PUBLISHED_AT_ATTRIBUTE = 'publishedAt';
|
|
10
|
+
const CREATED_BY_ATTRIBUTE = 'createdBy';
|
|
11
|
+
const UPDATED_BY_ATTRIBUTE = 'updatedBy';
|
|
12
12
|
|
|
13
|
-
const CREATED_AT_ATTRIBUTE = '
|
|
14
|
-
const UPDATED_AT_ATTRIBUTE = '
|
|
13
|
+
const CREATED_AT_ATTRIBUTE = 'createdAt';
|
|
14
|
+
const UPDATED_AT_ATTRIBUTE = 'updatedAt';
|
|
15
15
|
|
|
16
16
|
const DP_PUB_STATE_LIVE = 'live';
|
|
17
17
|
const DP_PUB_STATE_PREVIEW = 'preview';
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
const _ = require('lodash');
|
|
9
|
+
const parseType = require('./parse-type');
|
|
9
10
|
|
|
10
11
|
const QUERY_OPERATORS = ['_where', '_or', '_and'];
|
|
11
12
|
|
|
@@ -29,6 +30,10 @@ const validateOrder = order => {
|
|
|
29
30
|
}
|
|
30
31
|
};
|
|
31
32
|
|
|
33
|
+
const convertCountQueryParams = countQuery => {
|
|
34
|
+
return parseType({ type: 'boolean', value: countQuery });
|
|
35
|
+
};
|
|
36
|
+
|
|
32
37
|
/**
|
|
33
38
|
* Sort query parser
|
|
34
39
|
* @param {string} sortQuery - ex: id:asc,price:desc
|
|
@@ -161,7 +166,7 @@ const convertNestedPopulate = subPopulate => {
|
|
|
161
166
|
}
|
|
162
167
|
|
|
163
168
|
// TODO: We will need to consider a way to add limitation / pagination
|
|
164
|
-
const { sort, filters, fields, populate } = subPopulate;
|
|
169
|
+
const { sort, filters, fields, populate, count } = subPopulate;
|
|
165
170
|
|
|
166
171
|
const query = {};
|
|
167
172
|
|
|
@@ -181,6 +186,10 @@ const convertNestedPopulate = subPopulate => {
|
|
|
181
186
|
query.populate = convertPopulateQueryParams(populate);
|
|
182
187
|
}
|
|
183
188
|
|
|
189
|
+
if (count) {
|
|
190
|
+
query.count = convertCountQueryParams(count);
|
|
191
|
+
}
|
|
192
|
+
|
|
184
193
|
return query;
|
|
185
194
|
};
|
|
186
195
|
|
|
@@ -206,23 +215,6 @@ const convertFieldsQueryParams = (fields, depth = 0) => {
|
|
|
206
215
|
// NOTE: We could validate the parameters are on existing / non private attributes
|
|
207
216
|
const convertFiltersQueryParams = filters => filters;
|
|
208
217
|
|
|
209
|
-
// TODO: migrate
|
|
210
|
-
const VALID_REST_OPERATORS = [
|
|
211
|
-
'eq',
|
|
212
|
-
'ne',
|
|
213
|
-
'in',
|
|
214
|
-
'nin',
|
|
215
|
-
'contains',
|
|
216
|
-
'ncontains',
|
|
217
|
-
'containss',
|
|
218
|
-
'ncontainss',
|
|
219
|
-
'lt',
|
|
220
|
-
'lte',
|
|
221
|
-
'gt',
|
|
222
|
-
'gte',
|
|
223
|
-
'null',
|
|
224
|
-
];
|
|
225
|
-
|
|
226
218
|
module.exports = {
|
|
227
219
|
convertSortQueryParams,
|
|
228
220
|
convertStartQueryParams,
|
|
@@ -230,6 +222,5 @@ module.exports = {
|
|
|
230
222
|
convertPopulateQueryParams,
|
|
231
223
|
convertFiltersQueryParams,
|
|
232
224
|
convertFieldsQueryParams,
|
|
233
|
-
VALID_REST_OPERATORS,
|
|
234
225
|
QUERY_OPERATORS,
|
|
235
226
|
};
|
package/lib/hooks.js
CHANGED
|
@@ -24,12 +24,14 @@ const createHook = () => {
|
|
|
24
24
|
return state.handlers;
|
|
25
25
|
},
|
|
26
26
|
|
|
27
|
-
register
|
|
27
|
+
register(handler) {
|
|
28
28
|
state.handlers.push(handler);
|
|
29
|
+
return this;
|
|
29
30
|
},
|
|
30
31
|
|
|
31
|
-
delete
|
|
32
|
+
delete(handler) {
|
|
32
33
|
state.handlers = remove(eq(handler), state.handlers);
|
|
34
|
+
return this;
|
|
33
35
|
},
|
|
34
36
|
|
|
35
37
|
call() {
|
package/lib/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Export shared utilities
|
|
5
5
|
*/
|
|
6
6
|
const { buildQuery, hasDeepFilters } = require('./build-query');
|
|
7
|
-
const {
|
|
7
|
+
const { QUERY_OPERATORS } = require('./convert-query-params');
|
|
8
8
|
const parseMultipartData = require('./parse-multipart');
|
|
9
9
|
const sanitizeEntity = require('./sanitize-entity');
|
|
10
10
|
const parseType = require('./parse-type');
|
|
@@ -31,13 +31,13 @@ const relations = require('./relations');
|
|
|
31
31
|
const setCreatorFields = require('./set-creator-fields');
|
|
32
32
|
const hooks = require('./hooks');
|
|
33
33
|
const providerFactory = require('./provider-factory');
|
|
34
|
+
const pagination = require('./pagination');
|
|
34
35
|
|
|
35
36
|
module.exports = {
|
|
36
37
|
yup,
|
|
37
38
|
formatYupErrors,
|
|
38
39
|
policy,
|
|
39
40
|
templateConfiguration,
|
|
40
|
-
VALID_REST_OPERATORS,
|
|
41
41
|
QUERY_OPERATORS,
|
|
42
42
|
buildQuery,
|
|
43
43
|
hasDeepFilters,
|
|
@@ -64,4 +64,5 @@ module.exports = {
|
|
|
64
64
|
setCreatorFields,
|
|
65
65
|
hooks,
|
|
66
66
|
providerFactory,
|
|
67
|
+
pagination,
|
|
67
68
|
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { merge, pipe, omit, isNil } = require('lodash/fp');
|
|
4
|
+
|
|
5
|
+
const STRAPI_DEFAULTS = {
|
|
6
|
+
offset: {
|
|
7
|
+
start: 0,
|
|
8
|
+
limit: 10,
|
|
9
|
+
},
|
|
10
|
+
page: {
|
|
11
|
+
page: 1,
|
|
12
|
+
pageSize: 10,
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const paginationAttributes = ['start', 'limit', 'page', 'pageSize'];
|
|
17
|
+
|
|
18
|
+
const withMaxLimit = (limit, maxLimit = -1) => {
|
|
19
|
+
if (maxLimit === -1 || limit < maxLimit) {
|
|
20
|
+
return limit;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return maxLimit;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Ensure minimum page & pageSize values (page >= 1, pageSize >= 0, start >= 0, limit >= 0)
|
|
27
|
+
const ensureMinValues = ({ start, limit }) => ({
|
|
28
|
+
start: Math.max(start, 0),
|
|
29
|
+
limit: Math.max(limit, 1),
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const ensureMaxValues = (maxLimit = -1) => ({ start, limit }) => ({
|
|
33
|
+
start,
|
|
34
|
+
limit: withMaxLimit(limit, maxLimit),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const withDefaultPagination = (args, { defaults = {}, maxLimit = -1 } = {}) => {
|
|
38
|
+
const defaultValues = merge(STRAPI_DEFAULTS, defaults);
|
|
39
|
+
|
|
40
|
+
const usePagePagination = !isNil(args.page) || !isNil(args.pageSize);
|
|
41
|
+
const useOffsetPagination = !isNil(args.start) || !isNil(args.limit);
|
|
42
|
+
|
|
43
|
+
const ensureValidValues = pipe(
|
|
44
|
+
ensureMinValues,
|
|
45
|
+
ensureMaxValues(maxLimit)
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
// If there is no pagination attribute, don't modify the payload
|
|
49
|
+
if (!usePagePagination && !useOffsetPagination) {
|
|
50
|
+
return merge(args, ensureValidValues(defaultValues.offset));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// If there is page & offset pagination attributes, throw an error
|
|
54
|
+
if (usePagePagination && useOffsetPagination) {
|
|
55
|
+
throw new Error('Cannot use both page & offset pagination in the same query');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const pagination = {};
|
|
59
|
+
|
|
60
|
+
// Start / Limit
|
|
61
|
+
if (useOffsetPagination) {
|
|
62
|
+
const { start, limit } = merge(defaultValues.offset, args);
|
|
63
|
+
|
|
64
|
+
Object.assign(pagination, { start, limit });
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Page / PageSize
|
|
68
|
+
if (usePagePagination) {
|
|
69
|
+
const { page, pageSize } = merge(defaultValues.page, args);
|
|
70
|
+
|
|
71
|
+
Object.assign(pagination, {
|
|
72
|
+
start: (page - 1) * pageSize,
|
|
73
|
+
limit: pageSize,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const replacePaginationAttributes = pipe(
|
|
78
|
+
// Remove pagination attributes
|
|
79
|
+
omit(paginationAttributes),
|
|
80
|
+
// Merge the object with the new pagination + ensure minimum & maximum values
|
|
81
|
+
merge(ensureValidValues(pagination))
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
return replacePaginationAttributes(args);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
module.exports = { withDefaultPagination };
|
package/lib/policy.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
'use strict';
|
|
5
5
|
|
|
6
6
|
const _ = require('lodash');
|
|
7
|
+
const { eq } = require('lodash/fp');
|
|
7
8
|
|
|
8
9
|
const PLUGIN_PREFIX = 'plugin::';
|
|
9
10
|
const API_PREFIX = 'api::';
|
|
@@ -105,9 +106,23 @@ const createPolicyFactory = (factoryCallback, options) => {
|
|
|
105
106
|
};
|
|
106
107
|
};
|
|
107
108
|
|
|
109
|
+
const createPolicyContext = (type, ctx) => {
|
|
110
|
+
return Object.assign(
|
|
111
|
+
{
|
|
112
|
+
is: eq(type),
|
|
113
|
+
|
|
114
|
+
get type() {
|
|
115
|
+
return type;
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
ctx
|
|
119
|
+
);
|
|
120
|
+
};
|
|
121
|
+
|
|
108
122
|
module.exports = {
|
|
109
123
|
get,
|
|
110
124
|
globalPolicy,
|
|
111
125
|
bodyPolicy,
|
|
112
126
|
createPolicyFactory,
|
|
127
|
+
createPolicyContext,
|
|
113
128
|
};
|
package/lib/sanitize-entity.js
CHANGED
|
@@ -48,8 +48,10 @@ const sanitizeEntity = (dataSource, options) => {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
// Relations
|
|
51
|
-
const
|
|
52
|
-
if (
|
|
51
|
+
const isRelation = attribute && ['relation', 'component'].includes(attribute.type);
|
|
52
|
+
if (isRelation) {
|
|
53
|
+
const relation = attribute && (attribute.target || attribute.component);
|
|
54
|
+
|
|
53
55
|
if (_.isNil(value)) {
|
|
54
56
|
return { ...acc, [key]: value };
|
|
55
57
|
}
|
|
@@ -69,23 +71,18 @@ const sanitizeEntity = (dataSource, options) => {
|
|
|
69
71
|
};
|
|
70
72
|
|
|
71
73
|
let sanitizeFn;
|
|
72
|
-
if (relation
|
|
74
|
+
if (attribute.relation && attribute.relation.toLowerCase().includes('morph')) {
|
|
73
75
|
sanitizeFn = entity => {
|
|
74
|
-
if (_.isNil(entity) || !_.has(entity, '
|
|
76
|
+
if (_.isNil(entity) || !_.has(entity, '__type')) {
|
|
75
77
|
return entity;
|
|
76
78
|
}
|
|
77
79
|
|
|
78
|
-
return sanitizeEntity(entity, {
|
|
79
|
-
model: strapi.getModel(entity.__contentType),
|
|
80
|
-
...baseOptions,
|
|
81
|
-
});
|
|
80
|
+
return sanitizeEntity(entity, { model: strapi.getModel(entity.__type), ...baseOptions });
|
|
82
81
|
};
|
|
83
82
|
} else {
|
|
84
|
-
sanitizeFn = entity =>
|
|
85
|
-
sanitizeEntity(entity, {
|
|
86
|
-
|
|
87
|
-
...baseOptions,
|
|
88
|
-
});
|
|
83
|
+
sanitizeFn = entity => {
|
|
84
|
+
return sanitizeEntity(entity, { model: strapi.getModel(relation), ...baseOptions });
|
|
85
|
+
};
|
|
89
86
|
}
|
|
90
87
|
|
|
91
88
|
const nextVal = Array.isArray(value) ? value.map(sanitizeFn) : sanitizeFn(value);
|
|
@@ -131,18 +128,20 @@ const getAllowedFields = ({ includeFields, model, isOutput }) => {
|
|
|
131
128
|
|
|
132
129
|
const nonVisibleWritableAttributes = _.intersection(writableAttributes, nonVisibleAttributes);
|
|
133
130
|
|
|
134
|
-
return _.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
131
|
+
return _.uniq(
|
|
132
|
+
_.concat(
|
|
133
|
+
includeFields || [],
|
|
134
|
+
...(isOutput
|
|
135
|
+
? [
|
|
136
|
+
STATIC_FIELDS,
|
|
137
|
+
CREATED_AT_ATTRIBUTE,
|
|
138
|
+
UPDATED_AT_ATTRIBUTE,
|
|
139
|
+
COMPONENT_FIELDS,
|
|
140
|
+
...nonWritableAttributes,
|
|
141
|
+
...nonVisibleAttributes,
|
|
142
|
+
]
|
|
143
|
+
: [STATIC_FIELDS, COMPONENT_FIELDS, ...nonVisibleWritableAttributes])
|
|
144
|
+
)
|
|
146
145
|
);
|
|
147
146
|
};
|
|
148
147
|
|
package/package.json
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strapi/utils",
|
|
3
|
-
"version": "4.0.0-next.
|
|
3
|
+
"version": "4.0.0-next.14",
|
|
4
4
|
"description": "Shared utilities for the Strapi packages",
|
|
5
5
|
"homepage": "https://strapi.io",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"strapi",
|
|
8
|
-
"
|
|
9
|
-
"utils",
|
|
10
|
-
"winston"
|
|
8
|
+
"utils"
|
|
11
9
|
],
|
|
12
10
|
"directories": {
|
|
13
11
|
"lib": "./lib"
|
|
@@ -15,11 +13,9 @@
|
|
|
15
13
|
"main": "./lib",
|
|
16
14
|
"dependencies": {
|
|
17
15
|
"@sindresorhus/slugify": "1.1.0",
|
|
18
|
-
"date-fns": "
|
|
16
|
+
"date-fns": "2.24.0",
|
|
19
17
|
"lodash": "4.17.21",
|
|
20
|
-
"
|
|
21
|
-
"pluralize": "^8.0.0",
|
|
22
|
-
"yup": "^0.32.9"
|
|
18
|
+
"yup": "0.32.9"
|
|
23
19
|
},
|
|
24
20
|
"author": {
|
|
25
21
|
"email": "hi@strapi.io",
|
|
@@ -45,5 +41,5 @@
|
|
|
45
41
|
"npm": ">=6.0.0"
|
|
46
42
|
},
|
|
47
43
|
"license": "SEE LICENSE IN LICENSE",
|
|
48
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "9b2bc8ed5d39e6b7c3a1b0767b73028b5292467b"
|
|
49
45
|
}
|