@strapi/utils 4.4.0-rc.0 → 4.5.0-alpha.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.
@@ -6,10 +6,22 @@
6
6
  * Converts the standard Strapi REST query params to a more usable format for querying
7
7
  * You can read more here: https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/rest-api.html#filters
8
8
  */
9
- const { has, isEmpty, isObject, isPlainObject, cloneDeep, get, mergeAll } = require('lodash/fp');
9
+ const {
10
+ has,
11
+ isEmpty,
12
+ isObject,
13
+ isPlainObject,
14
+ cloneDeep,
15
+ get,
16
+ mergeAll,
17
+ isNil,
18
+ toNumber,
19
+ isInteger,
20
+ } = require('lodash/fp');
10
21
  const _ = require('lodash');
11
22
  const parseType = require('./parse-type');
12
23
  const contentTypesUtils = require('./content-types');
24
+ const { PaginationError } = require('./errors');
13
25
 
14
26
  const { PUBLISHED_AT_ATTRIBUTE } = contentTypesUtils.constants;
15
27
 
@@ -389,6 +401,80 @@ const convertPublicationStateParams = (type, params = {}, query = {}) => {
389
401
  }
390
402
  };
391
403
 
404
+ const transformParamsToQuery = (uid, params) => {
405
+ // NOTE: can be a CT, a Compo or nothing in the case of polymorphism (DZ & morph relations)
406
+ const schema = strapi.getModel(uid);
407
+
408
+ const query = {};
409
+
410
+ const { _q, sort, filters, fields, populate, page, pageSize, start, limit } = params;
411
+
412
+ if (!isNil(_q)) {
413
+ query._q = _q;
414
+ }
415
+
416
+ if (!isNil(sort)) {
417
+ query.orderBy = convertSortQueryParams(sort);
418
+ }
419
+
420
+ if (!isNil(filters)) {
421
+ query.where = convertFiltersQueryParams(filters, schema);
422
+ }
423
+
424
+ if (!isNil(fields)) {
425
+ query.select = convertFieldsQueryParams(fields);
426
+ }
427
+
428
+ if (!isNil(populate)) {
429
+ query.populate = convertPopulateQueryParams(populate, schema);
430
+ }
431
+
432
+ const isPagePagination = !isNil(page) || !isNil(pageSize);
433
+ const isOffsetPagination = !isNil(start) || !isNil(limit);
434
+
435
+ if (isPagePagination && isOffsetPagination) {
436
+ throw new PaginationError(
437
+ 'Invalid pagination attributes. You cannot use page and offset pagination in the same query'
438
+ );
439
+ }
440
+
441
+ if (!isNil(page)) {
442
+ const pageVal = toNumber(page);
443
+
444
+ if (!isInteger(pageVal) || pageVal <= 0) {
445
+ throw new PaginationError(
446
+ `Invalid 'page' parameter. Expected an integer > 0, received: ${page}`
447
+ );
448
+ }
449
+
450
+ query.page = pageVal;
451
+ }
452
+
453
+ if (!isNil(pageSize)) {
454
+ const pageSizeVal = toNumber(pageSize);
455
+
456
+ if (!isInteger(pageSizeVal) || pageSizeVal <= 0) {
457
+ throw new PaginationError(
458
+ `Invalid 'pageSize' parameter. Expected an integer > 0, received: ${page}`
459
+ );
460
+ }
461
+
462
+ query.pageSize = pageSizeVal;
463
+ }
464
+
465
+ if (!isNil(start)) {
466
+ query.offset = convertStartQueryParams(start);
467
+ }
468
+
469
+ if (!isNil(limit)) {
470
+ query.limit = convertLimitQueryParams(limit);
471
+ }
472
+
473
+ convertPublicationStateParams(schema, params, query);
474
+
475
+ return query;
476
+ };
477
+
392
478
  module.exports = {
393
479
  convertSortQueryParams,
394
480
  convertStartQueryParams,
@@ -397,4 +483,5 @@ module.exports = {
397
483
  convertFiltersQueryParams,
398
484
  convertFieldsQueryParams,
399
485
  convertPublicationStateParams,
486
+ transformParamsToQuery,
400
487
  };
package/lib/hooks.js CHANGED
@@ -2,8 +2,17 @@
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
+
5
13
  /**
6
14
  * Create a default Strapi hook
15
+ * @return {Hook}
7
16
  */
8
17
  const createHook = () => {
9
18
  const state = {
@@ -36,6 +45,7 @@ const createHook = () => {
36
45
  /**
37
46
  * Create an async series hook.
38
47
  * Upon execution, it will execute every handler in order with the same context
48
+ * @return {Hook}
39
49
  */
40
50
  const createAsyncSeriesHook = () => ({
41
51
  ...createHook(),
@@ -50,6 +60,7 @@ const createAsyncSeriesHook = () => ({
50
60
  /**
51
61
  * Create an async series waterfall hook.
52
62
  * 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}
53
64
  */
54
65
  const createAsyncSeriesWaterfallHook = () => ({
55
66
  ...createHook(),
@@ -68,6 +79,7 @@ const createAsyncSeriesWaterfallHook = () => ({
68
79
  /**
69
80
  * Create an async parallel hook.
70
81
  * Upon execution, it will execute every registered handler in band.
82
+ * @return {Hook}
71
83
  */
72
84
  const createAsyncParallelHook = () => ({
73
85
  ...createHook(),
@@ -79,24 +91,6 @@ const createAsyncParallelHook = () => ({
79
91
  },
80
92
  });
81
93
 
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
-
100
94
  module.exports = {
101
95
  // Internal utils
102
96
  internals: {
@@ -106,5 +100,4 @@ module.exports = {
106
100
  createAsyncSeriesHook,
107
101
  createAsyncSeriesWaterfallHook,
108
102
  createAsyncParallelHook,
109
- createAsyncBailHook,
110
103
  };
package/lib/index.js CHANGED
@@ -38,6 +38,7 @@ const pagination = require('./pagination');
38
38
  const sanitize = require('./sanitize');
39
39
  const traverseEntity = require('./traverse-entity');
40
40
  const pipeAsync = require('./pipe-async');
41
+ const convertQueryParams = require('./convert-query-params');
41
42
 
42
43
  module.exports = {
43
44
  yup,
@@ -79,4 +80,5 @@ module.exports = {
79
80
  errors,
80
81
  validateYupSchema,
81
82
  validateYupSchemaSync,
83
+ convertQueryParams,
82
84
  };
@@ -25,9 +25,25 @@ const createProviderHooksMap = () => ({
25
25
  });
26
26
 
27
27
  /**
28
- * A Provider factory
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
29
44
  * @param {Object} [options] - The factory options
30
45
  * @param {boolean = true} options.throwOnDuplicates - Specify the wanted behaviour when encountering a duplicate key on register
46
+ * @return {Provider}
31
47
  */
32
48
  const providerFactory = (options = {}) => {
33
49
  const { throwOnDuplicates = true } = options;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/utils",
3
- "version": "4.4.0-rc.0",
3
+ "version": "4.5.0-alpha.0",
4
4
  "description": "Shared utilities for the Strapi packages",
5
5
  "keywords": [
6
6
  "strapi",
@@ -45,5 +45,5 @@
45
45
  "node": ">=14.19.1 <=18.x.x",
46
46
  "npm": ">=6.0.0"
47
47
  },
48
- "gitHead": "57635b60c9a7815830734d85fe76df3ce8ed5898"
48
+ "gitHead": "c9a98c4dbcf3c4f2a449f8d96e7cbe4cd9b1e0f5"
49
49
  }