@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.
@@ -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: value });
63
+ : castValue({ type, operator, value });
64
64
  };
65
65
 
66
66
  /**
@@ -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 = 'published_at';
10
- const CREATED_BY_ATTRIBUTE = 'created_by';
11
- const UPDATED_BY_ATTRIBUTE = 'updated_by';
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 = 'created_at';
14
- const UPDATED_AT_ATTRIBUTE = 'updated_at';
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: handler => {
27
+ register(handler) {
28
28
  state.handlers.push(handler);
29
+ return this;
29
30
  },
30
31
 
31
- delete: handler => {
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 { VALID_REST_OPERATORS, QUERY_OPERATORS } = require('./convert-query-params');
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
  };
@@ -48,8 +48,10 @@ const sanitizeEntity = (dataSource, options) => {
48
48
  }
49
49
 
50
50
  // Relations
51
- const relation = attribute && (attribute.model || attribute.collection || attribute.component);
52
- if (relation) {
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, '__contentType')) {
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
- model: strapi.getModel(relation, attribute.plugin),
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 _.concat(
135
- includeFields || [],
136
- ...(isOutput
137
- ? [
138
- STATIC_FIELDS,
139
- CREATED_AT_ATTRIBUTE,
140
- UPDATED_AT_ATTRIBUTE,
141
- COMPONENT_FIELDS,
142
- ...nonWritableAttributes,
143
- ...nonVisibleAttributes,
144
- ]
145
- : [STATIC_FIELDS, COMPONENT_FIELDS, ...nonVisibleWritableAttributes])
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.10",
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
- "utilities",
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": "^2.19.0",
16
+ "date-fns": "2.24.0",
19
17
  "lodash": "4.17.21",
20
- "pino": "^4.7.1",
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": "9c81dbea7f82b6618caed76628c873627ebbc26f"
44
+ "gitHead": "9b2bc8ed5d39e6b7c3a1b0767b73028b5292467b"
49
45
  }