@strapi/utils 4.11.3 → 4.12.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.
Files changed (184) hide show
  1. package/dist/async.d.ts +10 -0
  2. package/dist/async.js +33 -0
  3. package/dist/async.js.map +1 -0
  4. package/dist/code-generator.d.ts +2 -0
  5. package/dist/code-generator.js +11 -0
  6. package/dist/code-generator.js.map +1 -0
  7. package/dist/config.d.ts +8 -0
  8. package/dist/config.js +79 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/content-types.d.ts +60 -0
  11. package/dist/content-types.js +151 -0
  12. package/dist/content-types.js.map +1 -0
  13. package/dist/convert-query-params.d.ts +75 -0
  14. package/dist/convert-query-params.js +476 -0
  15. package/dist/convert-query-params.js.map +1 -0
  16. package/dist/env-helper.d.ts +18 -0
  17. package/dist/env-helper.js +84 -0
  18. package/dist/env-helper.js.map +1 -0
  19. package/dist/errors.d.ts +37 -0
  20. package/dist/errors.js +100 -0
  21. package/dist/errors.js.map +1 -0
  22. package/dist/file.d.ts +16 -0
  23. package/dist/file.js +54 -0
  24. package/dist/file.js.map +1 -0
  25. package/dist/format-yup-error.d.ts +10 -0
  26. package/dist/format-yup-error.js +17 -0
  27. package/dist/format-yup-error.js.map +1 -0
  28. package/dist/hooks.d.ts +63 -0
  29. package/dist/hooks.js +89 -0
  30. package/dist/hooks.js.map +1 -0
  31. package/dist/import-default.d.ts +1 -0
  32. package/dist/import-default.js +9 -0
  33. package/dist/import-default.js.map +1 -0
  34. package/dist/index.d.ts +30 -0
  35. package/dist/index.js +99 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/object-formatting.d.ts +3 -0
  38. package/dist/object-formatting.js +14 -0
  39. package/dist/object-formatting.js.map +1 -0
  40. package/dist/operators.d.ts +2 -0
  41. package/dist/operators.js +70 -0
  42. package/dist/operators.js.map +1 -0
  43. package/dist/pagination.d.ts +14 -0
  44. package/dist/pagination.js +80 -0
  45. package/dist/pagination.js.map +1 -0
  46. package/dist/parse-multipart.d.ts +8 -0
  47. package/dist/parse-multipart.js +36 -0
  48. package/dist/parse-multipart.js.map +1 -0
  49. package/dist/parse-type.d.ts +21 -0
  50. package/dist/parse-type.js +108 -0
  51. package/dist/parse-type.js.map +1 -0
  52. package/dist/policy.d.ts +41 -0
  53. package/dist/policy.js +109 -0
  54. package/dist/policy.js.map +1 -0
  55. package/dist/print-value.d.ts +2 -0
  56. package/dist/print-value.js +50 -0
  57. package/dist/print-value.js.map +1 -0
  58. package/dist/provider-factory.d.ts +29 -0
  59. package/dist/provider-factory.js +80 -0
  60. package/dist/provider-factory.js.map +1 -0
  61. package/dist/relations.d.ts +10 -0
  62. package/dist/relations.js +23 -0
  63. package/dist/relations.js.map +1 -0
  64. package/dist/sanitize/index.d.ts +23 -0
  65. package/dist/sanitize/index.js +135 -0
  66. package/dist/sanitize/index.js.map +1 -0
  67. package/dist/sanitize/sanitizers.d.ts +10 -0
  68. package/dist/sanitize/sanitizers.js +114 -0
  69. package/dist/sanitize/sanitizers.js.map +1 -0
  70. package/dist/sanitize/visitors/allowed-fields.d.ts +3 -0
  71. package/{lib → dist}/sanitize/visitors/allowed-fields.js +17 -32
  72. package/dist/sanitize/visitors/allowed-fields.js.map +1 -0
  73. package/dist/sanitize/visitors/index.d.ts +7 -0
  74. package/dist/sanitize/visitors/index.js +21 -0
  75. package/dist/sanitize/visitors/index.js.map +1 -0
  76. package/dist/sanitize/visitors/remove-dynamic-zones.d.ts +3 -0
  77. package/dist/sanitize/visitors/remove-dynamic-zones.js +10 -0
  78. package/dist/sanitize/visitors/remove-dynamic-zones.js.map +1 -0
  79. package/dist/sanitize/visitors/remove-morph-to-relations.d.ts +3 -0
  80. package/dist/sanitize/visitors/remove-morph-to-relations.js +10 -0
  81. package/dist/sanitize/visitors/remove-morph-to-relations.js.map +1 -0
  82. package/dist/sanitize/visitors/remove-password.d.ts +3 -0
  83. package/dist/sanitize/visitors/remove-password.js +9 -0
  84. package/dist/sanitize/visitors/remove-password.js.map +1 -0
  85. package/dist/sanitize/visitors/remove-private.d.ts +3 -0
  86. package/dist/sanitize/visitors/remove-private.js +14 -0
  87. package/dist/sanitize/visitors/remove-private.js.map +1 -0
  88. package/dist/sanitize/visitors/remove-restricted-relations.d.ts +3 -0
  89. package/dist/sanitize/visitors/remove-restricted-relations.js +88 -0
  90. package/dist/sanitize/visitors/remove-restricted-relations.js.map +1 -0
  91. package/dist/sanitize/visitors/restricted-fields.d.ts +3 -0
  92. package/dist/sanitize/visitors/restricted-fields.js +25 -0
  93. package/dist/sanitize/visitors/restricted-fields.js.map +1 -0
  94. package/dist/set-creator-fields.d.ts +9 -0
  95. package/dist/set-creator-fields.js +39 -0
  96. package/dist/set-creator-fields.js.map +1 -0
  97. package/dist/string-formatting.d.ts +15 -0
  98. package/dist/string-formatting.js +85 -0
  99. package/dist/string-formatting.js.map +1 -0
  100. package/dist/template-configuration.d.ts +5 -0
  101. package/dist/template-configuration.js +30 -0
  102. package/dist/template-configuration.js.map +1 -0
  103. package/dist/template.d.ts +9 -0
  104. package/dist/template.js +20 -0
  105. package/dist/template.js.map +1 -0
  106. package/dist/traverse/factory.d.ts +78 -0
  107. package/dist/traverse/factory.js +127 -0
  108. package/dist/traverse/factory.js.map +1 -0
  109. package/dist/traverse/index.d.ts +5 -0
  110. package/dist/traverse/index.js +17 -0
  111. package/dist/traverse/index.js.map +1 -0
  112. package/dist/traverse/query-fields.d.ts +3 -0
  113. package/dist/traverse/query-fields.js +35 -0
  114. package/dist/traverse/query-fields.js.map +1 -0
  115. package/dist/traverse/query-filters.d.ts +3 -0
  116. package/dist/traverse/query-filters.js +75 -0
  117. package/dist/traverse/query-filters.js.map +1 -0
  118. package/dist/traverse/query-populate.d.ts +3 -0
  119. package/dist/traverse/query-populate.js +144 -0
  120. package/dist/traverse/query-populate.js.map +1 -0
  121. package/dist/traverse/query-sort.d.ts +3 -0
  122. package/dist/traverse/query-sort.js +116 -0
  123. package/dist/traverse/query-sort.js.map +1 -0
  124. package/dist/traverse-entity.d.ts +31 -0
  125. package/dist/traverse-entity.js +134 -0
  126. package/dist/traverse-entity.js.map +1 -0
  127. package/dist/types.d.ts +65 -0
  128. package/dist/types.js +3 -0
  129. package/dist/types.js.map +1 -0
  130. package/dist/validators.d.ts +13 -0
  131. package/dist/validators.js +120 -0
  132. package/dist/validators.js.map +1 -0
  133. package/dist/webhook.d.ts +5 -0
  134. package/dist/webhook.js +27 -0
  135. package/dist/webhook.js.map +1 -0
  136. package/package.json +19 -4
  137. package/.eslintignore +0 -3
  138. package/.eslintrc.js +0 -4
  139. package/index.d.ts +0 -5
  140. package/lib/async.d.ts +0 -21
  141. package/lib/async.js +0 -45
  142. package/lib/build-query.js +0 -208
  143. package/lib/code-generator.js +0 -13
  144. package/lib/config.js +0 -88
  145. package/lib/content-types.js +0 -196
  146. package/lib/convert-query-params.js +0 -586
  147. package/lib/env-helper.js +0 -98
  148. package/lib/errors.js +0 -113
  149. package/lib/file.js +0 -60
  150. package/lib/format-yup-error.js +0 -20
  151. package/lib/hooks.js +0 -110
  152. package/lib/import-default.js +0 -10
  153. package/lib/index.js +0 -99
  154. package/lib/object-formatting.js +0 -15
  155. package/lib/operators.js +0 -74
  156. package/lib/pagination.js +0 -99
  157. package/lib/parse-multipart.js +0 -44
  158. package/lib/parse-type.js +0 -100
  159. package/lib/policy.js +0 -129
  160. package/lib/print-value.js +0 -52
  161. package/lib/provider-factory.js +0 -116
  162. package/lib/relations.js +0 -31
  163. package/lib/sanitize/index.js +0 -143
  164. package/lib/sanitize/sanitizers.js +0 -163
  165. package/lib/sanitize/visitors/index.js +0 -11
  166. package/lib/sanitize/visitors/remove-dynamic-zones.js +0 -9
  167. package/lib/sanitize/visitors/remove-morph-to-relations.js +0 -9
  168. package/lib/sanitize/visitors/remove-password.js +0 -7
  169. package/lib/sanitize/visitors/remove-private.js +0 -15
  170. package/lib/sanitize/visitors/remove-restricted-relations.js +0 -81
  171. package/lib/sanitize/visitors/restricted-fields.js +0 -32
  172. package/lib/set-creator-fields.js +0 -17
  173. package/lib/string-formatting.js +0 -79
  174. package/lib/template-configuration.js +0 -32
  175. package/lib/template.js +0 -28
  176. package/lib/traverse/factory.js +0 -157
  177. package/lib/traverse/index.js +0 -16
  178. package/lib/traverse/query-fields.js +0 -39
  179. package/lib/traverse/query-filters.js +0 -97
  180. package/lib/traverse/query-populate.js +0 -191
  181. package/lib/traverse/query-sort.js +0 -171
  182. package/lib/traverse-entity.js +0 -166
  183. package/lib/validators.js +0 -120
  184. package/lib/webhook.js +0 -30
package/lib/parse-type.js DELETED
@@ -1,100 +0,0 @@
1
- 'use strict';
2
-
3
- const _ = require('lodash');
4
- const dates = require('date-fns');
5
-
6
- const timeRegex = /^(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]{1,3})?$/;
7
-
8
- const parseTime = (value) => {
9
- if (dates.isDate(value)) return dates.format(value, 'HH:mm:ss.SSS');
10
-
11
- if (typeof value !== 'string') {
12
- throw new Error(`Expected a string, got a ${typeof value}`);
13
- }
14
- const result = value.match(timeRegex);
15
-
16
- if (result === null) {
17
- throw new Error('Invalid time format, expected HH:mm:ss.SSS');
18
- }
19
-
20
- const [, hours, minutes, seconds, fraction = '.000'] = result;
21
- const fractionPart = _.padEnd(fraction.slice(1), 3, '0');
22
-
23
- return `${hours}:${minutes}:${seconds}.${fractionPart}`;
24
- };
25
-
26
- const parseDate = (value) => {
27
- if (dates.isDate(value)) return dates.format(value, 'yyyy-MM-dd');
28
- try {
29
- const date = dates.parseISO(value);
30
-
31
- if (dates.isValid(date)) return dates.format(date, 'yyyy-MM-dd');
32
-
33
- throw new Error(`Invalid format, expected an ISO compatible date`);
34
- } catch (error) {
35
- throw new Error(`Invalid format, expected an ISO compatible date`);
36
- }
37
- };
38
-
39
- const parseDateTimeOrTimestamp = (value) => {
40
- if (dates.isDate(value)) return value;
41
- try {
42
- const date = dates.parseISO(value);
43
- if (dates.isValid(date)) return date;
44
-
45
- const milliUnixDate = dates.parse(value, 'T', new Date());
46
- if (dates.isValid(milliUnixDate)) return milliUnixDate;
47
-
48
- throw new Error(`Invalid format, expected a timestamp or an ISO date`);
49
- } catch (error) {
50
- throw new Error(`Invalid format, expected a timestamp or an ISO date`);
51
- }
52
- };
53
-
54
- /**
55
- * Cast basic values based on attribute type
56
- * @param {Object} options - Options
57
- * @param {string} options.type - type of the atribute
58
- * @param {*} options.value - value tu cast
59
- */
60
- const parseType = ({ type, value, forceCast = false }) => {
61
- switch (type) {
62
- case 'boolean': {
63
- if (typeof value === 'boolean') return value;
64
-
65
- if (['true', 't', '1', 1].includes(value)) {
66
- return true;
67
- }
68
-
69
- if (['false', 'f', '0', 0].includes(value)) {
70
- return false;
71
- }
72
-
73
- if (forceCast) {
74
- return Boolean(value);
75
- }
76
-
77
- throw new Error('Invalid boolean input. Expected "t","1","true","false","0","f"');
78
- }
79
- case 'integer':
80
- case 'biginteger':
81
- case 'float':
82
- case 'decimal': {
83
- return _.toNumber(value);
84
- }
85
- case 'time': {
86
- return parseTime(value);
87
- }
88
- case 'date': {
89
- return parseDate(value);
90
- }
91
- case 'timestamp':
92
- case 'datetime': {
93
- return parseDateTimeOrTimestamp(value);
94
- }
95
- default:
96
- return value;
97
- }
98
- };
99
-
100
- module.exports = parseType;
package/lib/policy.js DELETED
@@ -1,129 +0,0 @@
1
- /**
2
- * Policies util
3
- */
4
-
5
- 'use strict';
6
-
7
- const _ = require('lodash');
8
- const { eq } = require('lodash/fp');
9
-
10
- const PLUGIN_PREFIX = 'plugin::';
11
- const API_PREFIX = 'api::';
12
-
13
- const parsePolicy = (policy) => {
14
- if (typeof policy === 'string') {
15
- return { policyName: policy, config: {} };
16
- }
17
-
18
- const { name, config } = policy;
19
- return { policyName: name, config };
20
- };
21
-
22
- const searchLocalPolicy = (policyName, { pluginName, apiName }) => {
23
- if (pluginName) {
24
- return strapi.policy(`${PLUGIN_PREFIX}${pluginName}.${policyName}`);
25
- }
26
-
27
- if (apiName) {
28
- return strapi.policy(`${API_PREFIX}${apiName}.${policyName}`);
29
- }
30
- };
31
-
32
- const globalPolicy = ({ method, endpoint, controller, action, plugin }) => {
33
- return async (ctx, next) => {
34
- ctx.request.route = {
35
- endpoint: `${method} ${endpoint}`,
36
- controller: _.toLower(controller),
37
- action: _.toLower(action),
38
- verb: _.toLower(method),
39
- plugin,
40
- };
41
-
42
- await next();
43
- };
44
- };
45
-
46
- const resolvePolicies = (config, { pluginName, apiName } = {}) => {
47
- return config.map((policyConfig) => {
48
- return {
49
- handler: getPolicy(policyConfig, { pluginName, apiName }),
50
- config: policyConfig.config || {},
51
- };
52
- });
53
- };
54
-
55
- const findPolicy = (name, { pluginName, apiName } = {}) => {
56
- const resolvedPolicy = strapi.policy(name);
57
-
58
- if (resolvedPolicy !== undefined) {
59
- return resolvedPolicy;
60
- }
61
-
62
- const localPolicy = searchLocalPolicy(name, { pluginName, apiName });
63
-
64
- if (localPolicy !== undefined) {
65
- return localPolicy;
66
- }
67
-
68
- throw new Error(`Could not find policy "${name}"`);
69
- };
70
-
71
- const getPolicy = (policyConfig, { pluginName, apiName } = {}) => {
72
- if (typeof policyConfig === 'function') {
73
- return policyConfig;
74
- }
75
-
76
- const { policyName, config } = parsePolicy(policyConfig);
77
-
78
- const policy = findPolicy(policyName, { pluginName, apiName });
79
-
80
- if (typeof policy === 'function') {
81
- return policy;
82
- }
83
-
84
- if (policy.validator) {
85
- policy.validator(config);
86
- }
87
-
88
- return policy.handler;
89
- };
90
-
91
- const createPolicy = (options) => {
92
- const { name = 'unnamed', validator, handler } = options;
93
-
94
- const wrappedValidator = (config) => {
95
- if (validator) {
96
- try {
97
- validator(config);
98
- } catch (e) {
99
- throw new Error(`Invalid config passed to "${name}" policy.`);
100
- }
101
- }
102
- };
103
-
104
- return {
105
- name,
106
- validator: wrappedValidator,
107
- handler,
108
- };
109
- };
110
-
111
- const createPolicyContext = (type, ctx) => {
112
- return Object.assign(
113
- {
114
- is: eq(type),
115
- get type() {
116
- return type;
117
- },
118
- },
119
- ctx
120
- );
121
- };
122
-
123
- module.exports = {
124
- get: getPolicy,
125
- resolve: resolvePolicies,
126
- globalPolicy,
127
- createPolicy,
128
- createPolicyContext,
129
- };
@@ -1,52 +0,0 @@
1
- 'use strict';
2
-
3
- // Code copied from the yup library (https://github.com/jquense/yup)
4
- // https://github.com/jquense/yup/blob/2778b88bdacd5260d593c6468793da2e77daf21f/src/util/printValue.ts
5
-
6
- const { toString } = Object.prototype;
7
- const errorToString = Error.prototype.toString;
8
- const regExpToString = RegExp.prototype.toString;
9
- const symbolToString = typeof Symbol !== 'undefined' ? Symbol.prototype.toString : () => '';
10
-
11
- const SYMBOL_REGEXP = /^Symbol\((.*)\)(.*)$/;
12
-
13
- function printNumber(val) {
14
- // eslint-disable-next-line eqeqeq
15
- if (val != +val) return 'NaN';
16
- const isNegativeZero = val === 0 && 1 / val < 0;
17
- return isNegativeZero ? '-0' : `${val}`;
18
- }
19
-
20
- function printSimpleValue(val, quoteStrings = false) {
21
- if (val == null || val === true || val === false) return `${val}`;
22
-
23
- const typeOf = typeof val;
24
- if (typeOf === 'number') return printNumber(val);
25
- if (typeOf === 'string') return quoteStrings ? `"${val}"` : val;
26
- if (typeOf === 'function') return `[Function ${val.name || 'anonymous'}]`;
27
- if (typeOf === 'symbol') return symbolToString.call(val).replace(SYMBOL_REGEXP, 'Symbol($1)');
28
-
29
- const tag = toString.call(val).slice(8, -1);
30
- if (tag === 'Date') return Number.isNaN(val.getTime()) ? `${val}` : val.toISOString(val);
31
- if (tag === 'Error' || val instanceof Error) return `[${errorToString.call(val)}]`;
32
- if (tag === 'RegExp') return regExpToString.call(val);
33
-
34
- return null;
35
- }
36
-
37
- function printValue(value, quoteStrings) {
38
- const result = printSimpleValue(value, quoteStrings);
39
- if (result !== null) return result;
40
-
41
- return JSON.stringify(
42
- value,
43
- function replacer(key, value) {
44
- const result = printSimpleValue(this[key], quoteStrings);
45
- if (result !== null) return result;
46
- return value;
47
- },
48
- 2
49
- );
50
- }
51
-
52
- module.exports = printValue;
@@ -1,116 +0,0 @@
1
- 'use strict';
2
-
3
- const { cloneDeep } = require('lodash/fp');
4
- const { createAsyncSeriesHook, createAsyncParallelHook } = require('./hooks');
5
-
6
- /**
7
- * @typedef ProviderHooksMap
8
- * @property willRegister
9
- * @property didRegister
10
- * @property willDelete
11
- * @property didDelete
12
- */
13
-
14
- /**
15
- * Creates a new object containing various hooks used by the providers
16
- * @return {ProviderHooksMap}
17
- */
18
- const createProviderHooksMap = () => ({
19
- // Register events
20
- willRegister: createAsyncSeriesHook(),
21
- didRegister: createAsyncParallelHook(),
22
- // Delete events
23
- willDelete: createAsyncParallelHook(),
24
- didDelete: createAsyncParallelHook(),
25
- });
26
-
27
- /**
28
- * A Provider factory
29
- * @param {Object} [options] - The factory options
30
- * @param {boolean = true} options.throwOnDuplicates - Specify the wanted behaviour when encountering a duplicate key on register
31
- */
32
- const providerFactory = (options = {}) => {
33
- const { throwOnDuplicates = true } = options;
34
-
35
- const state = {
36
- hooks: createProviderHooksMap(),
37
- registry: new Map(),
38
- };
39
-
40
- return {
41
- hooks: state.hooks,
42
-
43
- async register(key, item) {
44
- if (throwOnDuplicates && this.has(key)) {
45
- throw new Error(`Duplicated item key: ${key}`);
46
- }
47
-
48
- await state.hooks.willRegister.call({ key, value: item });
49
-
50
- state.registry.set(key, item);
51
-
52
- await state.hooks.didRegister.call({ key, value: cloneDeep(item) });
53
-
54
- return this;
55
- },
56
-
57
- async delete(key) {
58
- if (this.has(key)) {
59
- const item = this.get(key);
60
-
61
- await state.hooks.willDelete.call({ key, value: cloneDeep(item) });
62
-
63
- state.registry.delete(key);
64
-
65
- await state.hooks.didDelete.call({ key, value: cloneDeep(item) });
66
- }
67
-
68
- return this;
69
- },
70
-
71
- get(key) {
72
- return state.registry.get(key);
73
- },
74
-
75
- getWhere(filters = {}) {
76
- const items = this.values();
77
- const filtersEntries = Object.entries(filters);
78
-
79
- if (filtersEntries.length === 0) {
80
- return items;
81
- }
82
-
83
- return items.filter((item) => {
84
- return filtersEntries.every(([key, value]) => item[key] === value);
85
- });
86
- },
87
-
88
- values() {
89
- return Array.from(state.registry.values());
90
- },
91
-
92
- keys() {
93
- return Array.from(state.registry.keys());
94
- },
95
-
96
- has(key) {
97
- return state.registry.has(key);
98
- },
99
-
100
- size() {
101
- return state.registry.size;
102
- },
103
-
104
- async clear() {
105
- const keys = this.keys();
106
-
107
- for (const key of keys) {
108
- await this.delete(key);
109
- }
110
-
111
- return this;
112
- },
113
- };
114
- };
115
-
116
- module.exports = providerFactory;
package/lib/relations.js DELETED
@@ -1,31 +0,0 @@
1
- 'use strict';
2
-
3
- const { isRelationalAttribute } = require('./content-types');
4
-
5
- const MANY_RELATIONS = ['oneToMany', 'manyToMany'];
6
-
7
- const getRelationalFields = (contentType) => {
8
- return Object.keys(contentType.attributes).filter((attributeName) => {
9
- return contentType.attributes[attributeName].type === 'relation';
10
- });
11
- };
12
-
13
- const isOneToAny = (attribute) =>
14
- isRelationalAttribute(attribute) && ['oneToOne', 'oneToMany'].includes(attribute.relation);
15
- const isManyToAny = (attribute) =>
16
- isRelationalAttribute(attribute) && ['manyToMany', 'manyToOne'].includes(attribute.relation);
17
- const isAnyToOne = (attribute) =>
18
- isRelationalAttribute(attribute) && ['oneToOne', 'manyToOne'].includes(attribute.relation);
19
- const isAnyToMany = (attribute) =>
20
- isRelationalAttribute(attribute) && ['oneToMany', 'manyToMany'].includes(attribute.relation);
21
-
22
- module.exports = {
23
- getRelationalFields,
24
- isOneToAny,
25
- isManyToAny,
26
- isAnyToOne,
27
- isAnyToMany,
28
- constants: {
29
- MANY_RELATIONS,
30
- },
31
- };
@@ -1,143 +0,0 @@
1
- 'use strict';
2
-
3
- const { isArray, cloneDeep } = require('lodash/fp');
4
-
5
- const { getNonWritableAttributes } = require('../content-types');
6
- const { pipeAsync } = require('../async');
7
-
8
- const visitors = require('./visitors');
9
- const sanitizers = require('./sanitizers');
10
- const traverseEntity = require('../traverse-entity');
11
-
12
- const { traverseQueryFilters, traverseQuerySort, traverseQueryPopulate } = require('../traverse');
13
-
14
- const createContentAPISanitizers = () => {
15
- const sanitizeInput = (data, schema, { auth } = {}) => {
16
- if (isArray(data)) {
17
- return Promise.all(data.map((entry) => sanitizeInput(entry, schema, { auth })));
18
- }
19
-
20
- const nonWritableAttributes = getNonWritableAttributes(schema);
21
-
22
- const transforms = [
23
- // Remove non writable attributes
24
- traverseEntity(visitors.restrictedFields(nonWritableAttributes), { schema }),
25
- ];
26
-
27
- if (auth) {
28
- // Remove restricted relations
29
- transforms.push(traverseEntity(visitors.removeRestrictedRelations(auth), { schema }));
30
- }
31
-
32
- // Apply sanitizers from registry if exists
33
- strapi.sanitizers
34
- .get('content-api.input')
35
- .forEach((sanitizer) => transforms.push(sanitizer(schema)));
36
-
37
- return pipeAsync(...transforms)(data);
38
- };
39
-
40
- const sanitizeOutput = async (data, schema, { auth } = {}) => {
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;
47
- }
48
-
49
- const transforms = [(data) => sanitizers.defaultSanitizeOutput(schema, data)];
50
-
51
- if (auth) {
52
- transforms.push(traverseEntity(visitors.removeRestrictedRelations(auth), { schema }));
53
- }
54
-
55
- // Apply sanitizers from registry if exists
56
- strapi.sanitizers
57
- .get('content-api.output')
58
- .forEach((sanitizer) => transforms.push(sanitizer(schema)));
59
-
60
- return pipeAsync(...transforms)(data);
61
- };
62
-
63
- const sanitizeQuery = async (query, schema, { auth } = {}) => {
64
- const { filters, sort, fields, populate } = query;
65
-
66
- const sanitizedQuery = cloneDeep(query);
67
-
68
- if (filters) {
69
- Object.assign(sanitizedQuery, { filters: await sanitizeFilters(filters, schema, { auth }) });
70
- }
71
-
72
- if (sort) {
73
- Object.assign(sanitizedQuery, { sort: await sanitizeSort(sort, schema, { auth }) });
74
- }
75
-
76
- if (fields) {
77
- Object.assign(sanitizedQuery, { fields: await sanitizeFields(fields, schema) });
78
- }
79
-
80
- if (populate) {
81
- Object.assign(sanitizedQuery, { populate: await sanitizePopulate(populate, schema) });
82
- }
83
-
84
- return sanitizedQuery;
85
- };
86
-
87
- const sanitizeFilters = (filters, schema, { auth } = {}) => {
88
- if (isArray(filters)) {
89
- return Promise.all(filters.map((filter) => sanitizeFilters(filter, schema, { auth })));
90
- }
91
-
92
- const transforms = [sanitizers.defaultSanitizeFilters(schema)];
93
-
94
- if (auth) {
95
- transforms.push(traverseQueryFilters(visitors.removeRestrictedRelations(auth), { schema }));
96
- }
97
-
98
- return pipeAsync(...transforms)(filters);
99
- };
100
-
101
- const sanitizeSort = (sort, schema, { auth } = {}) => {
102
- const transforms = [sanitizers.defaultSanitizeSort(schema)];
103
-
104
- if (auth) {
105
- transforms.push(traverseQuerySort(visitors.removeRestrictedRelations(auth), { schema }));
106
- }
107
-
108
- return pipeAsync(...transforms)(sort);
109
- };
110
-
111
- const sanitizeFields = (fields, schema) => {
112
- const transforms = [sanitizers.defaultSanitizeFields(schema)];
113
-
114
- return pipeAsync(...transforms)(fields);
115
- };
116
-
117
- const sanitizePopulate = (populate, schema, { auth } = {}) => {
118
- const transforms = [sanitizers.defaultSanitizePopulate(schema)];
119
-
120
- if (auth) {
121
- transforms.push(traverseQueryPopulate(visitors.removeRestrictedRelations(auth), { schema }));
122
- }
123
-
124
- return pipeAsync(...transforms)(populate);
125
- };
126
-
127
- return {
128
- input: sanitizeInput,
129
- output: sanitizeOutput,
130
- query: sanitizeQuery,
131
- filters: sanitizeFilters,
132
- sort: sanitizeSort,
133
- fields: sanitizeFields,
134
- populate: sanitizePopulate,
135
- };
136
- };
137
-
138
- module.exports = {
139
- contentAPI: createContentAPISanitizers(),
140
-
141
- sanitizers,
142
- visitors,
143
- };