@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
@@ -1,163 +0,0 @@
1
- 'use strict';
2
-
3
- const { curry, isEmpty, isNil, isArray, isObject } = require('lodash/fp');
4
-
5
- const { pipeAsync } = require('../async');
6
- const traverseEntity = require('../traverse-entity');
7
- const { isScalarAttribute } = require('../content-types');
8
-
9
- const {
10
- traverseQueryFilters,
11
- traverseQuerySort,
12
- traverseQueryPopulate,
13
- traverseQueryFields,
14
- } = require('../traverse');
15
-
16
- const {
17
- removePassword,
18
- removePrivate,
19
- removeDynamicZones,
20
- removeMorphToRelations,
21
- } = require('./visitors');
22
- const { isOperator } = require('../operators');
23
-
24
- const sanitizePasswords = (schema) => async (entity) => {
25
- return traverseEntity(removePassword, { schema }, entity);
26
- };
27
-
28
- const defaultSanitizeOutput = async (schema, entity) => {
29
- return traverseEntity(
30
- (...args) => {
31
- removePassword(...args);
32
- removePrivate(...args);
33
- },
34
- { schema },
35
- entity
36
- );
37
- };
38
-
39
- const defaultSanitizeFilters = curry((schema, filters) => {
40
- return pipeAsync(
41
- // Remove keys that are not attributes or valid operators
42
- traverseQueryFilters(
43
- ({ key, attribute }, { remove }) => {
44
- const isAttribute = !!attribute;
45
-
46
- if (!isAttribute && !isOperator(key) && key !== 'id') {
47
- remove(key);
48
- }
49
- },
50
- { schema }
51
- ),
52
- // Remove dynamic zones from filters
53
- traverseQueryFilters(removeDynamicZones, { schema }),
54
- // Remove morpTo relations from filters
55
- traverseQueryFilters(removeMorphToRelations, { schema }),
56
- // Remove passwords from filters
57
- traverseQueryFilters(removePassword, { schema }),
58
- // Remove private from filters
59
- traverseQueryFilters(removePrivate, { schema }),
60
- // Remove empty objects
61
- traverseQueryFilters(
62
- ({ key, value }, { remove }) => {
63
- if (isObject(value) && isEmpty(value)) {
64
- remove(key);
65
- }
66
- },
67
- { schema }
68
- )
69
- )(filters);
70
- });
71
-
72
- const defaultSanitizeSort = curry((schema, sort) => {
73
- return pipeAsync(
74
- // Remove non attribute keys
75
- traverseQuerySort(
76
- ({ key, attribute }, { remove }) => {
77
- // ID is not an attribute per se, so we need to make
78
- // an extra check to ensure we're not removing it
79
- if (key === 'id') {
80
- return;
81
- }
82
-
83
- if (!attribute) {
84
- remove(key);
85
- }
86
- },
87
- { schema }
88
- ),
89
- // Remove dynamic zones from sort
90
- traverseQuerySort(removeDynamicZones, { schema }),
91
- // Remove morpTo relations from sort
92
- traverseQuerySort(removeMorphToRelations, { schema }),
93
- // Remove private from sort
94
- traverseQuerySort(removePrivate, { schema }),
95
- // Remove passwords from filters
96
- traverseQuerySort(removePassword, { schema }),
97
- // Remove keys for empty non-scalar values
98
- traverseQuerySort(
99
- ({ key, attribute, value }, { remove }) => {
100
- if (!isScalarAttribute(attribute) && isEmpty(value)) {
101
- remove(key);
102
- }
103
- },
104
- { schema }
105
- )
106
- )(sort);
107
- });
108
-
109
- const defaultSanitizeFields = curry((schema, fields) => {
110
- return pipeAsync(
111
- // Only keep scalar attributes
112
- traverseQueryFields(
113
- ({ key, attribute }, { remove }) => {
114
- if (isNil(attribute) || !isScalarAttribute(attribute)) {
115
- remove(key);
116
- }
117
- },
118
- { schema }
119
- ),
120
- // Remove private fields
121
- traverseQueryFields(removePrivate, { schema }),
122
- // Remove password fields
123
- traverseQueryFields(removePassword, { schema }),
124
- // Remove nil values from fields array
125
- (value) => (isArray(value) ? value.filter((field) => !isNil(field)) : value)
126
- )(fields);
127
- });
128
-
129
- const defaultSanitizePopulate = curry((schema, populate) => {
130
- return pipeAsync(
131
- traverseQueryPopulate(
132
- async ({ key, value, schema, attribute }, { set }) => {
133
- if (attribute) {
134
- return;
135
- }
136
-
137
- if (key === 'sort') {
138
- set(key, await defaultSanitizeSort(schema, value));
139
- }
140
-
141
- if (key === 'filters') {
142
- set(key, await defaultSanitizeFilters(schema, value));
143
- }
144
-
145
- if (key === 'fields') {
146
- set(key, await defaultSanitizeFields(schema, value));
147
- }
148
- },
149
- { schema }
150
- ),
151
- // Remove private fields
152
- traverseQueryPopulate(removePrivate, { schema })
153
- )(populate);
154
- });
155
-
156
- module.exports = {
157
- sanitizePasswords,
158
- defaultSanitizeOutput,
159
- defaultSanitizeFilters,
160
- defaultSanitizeSort,
161
- defaultSanitizeFields,
162
- defaultSanitizePopulate,
163
- };
@@ -1,11 +0,0 @@
1
- 'use strict';
2
-
3
- module.exports = {
4
- removePassword: require('./remove-password'),
5
- removePrivate: require('./remove-private'),
6
- removeRestrictedRelations: require('./remove-restricted-relations'),
7
- removeMorphToRelations: require('./remove-morph-to-relations'),
8
- removeDynamicZones: require('./remove-dynamic-zones'),
9
- allowedFields: require('./allowed-fields'),
10
- restrictedFields: require('./restricted-fields'),
11
- };
@@ -1,9 +0,0 @@
1
- 'use strict';
2
-
3
- const { isDynamicZoneAttribute } = require('../../content-types');
4
-
5
- module.exports = ({ key, attribute }, { remove }) => {
6
- if (isDynamicZoneAttribute(attribute)) {
7
- remove(key);
8
- }
9
- };
@@ -1,9 +0,0 @@
1
- 'use strict';
2
-
3
- const { isMorphToRelationalAttribute } = require('../../content-types');
4
-
5
- module.exports = ({ key, attribute }, { remove }) => {
6
- if (isMorphToRelationalAttribute(attribute)) {
7
- remove(key);
8
- }
9
- };
@@ -1,7 +0,0 @@
1
- 'use strict';
2
-
3
- module.exports = ({ key, attribute }, { remove }) => {
4
- if (attribute?.type === 'password') {
5
- remove(key);
6
- }
7
- };
@@ -1,15 +0,0 @@
1
- 'use strict';
2
-
3
- const { isPrivateAttribute } = require('../../content-types');
4
-
5
- module.exports = ({ schema, key, attribute }, { remove }) => {
6
- if (!attribute) {
7
- return;
8
- }
9
-
10
- const isPrivate = attribute.private === true || isPrivateAttribute(schema, key);
11
-
12
- if (isPrivate) {
13
- remove(key);
14
- }
15
- };
@@ -1,81 +0,0 @@
1
- 'use strict';
2
-
3
- const ACTIONS_TO_VERIFY = ['find'];
4
-
5
- const { CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE } = require('../../content-types').constants;
6
-
7
- module.exports =
8
- (auth) =>
9
- async ({ data, key, attribute, schema }, { remove, set }) => {
10
- if (!attribute) {
11
- return;
12
- }
13
-
14
- const isRelation = attribute.type === 'relation';
15
-
16
- if (!isRelation) {
17
- return;
18
- }
19
-
20
- const handleMorphRelation = async () => {
21
- const newMorphValue = [];
22
-
23
- for (const element of data[key]) {
24
- const scopes = ACTIONS_TO_VERIFY.map((action) => `${element.__type}.${action}`);
25
- const isAllowed = await hasAccessToSomeScopes(scopes, auth);
26
-
27
- if (isAllowed) {
28
- newMorphValue.push(element);
29
- }
30
- }
31
-
32
- // If the new value is empty, remove the relation completely
33
- if (newMorphValue.length === 0) {
34
- remove(key);
35
- } else {
36
- set(key, newMorphValue);
37
- }
38
- };
39
-
40
- const handleRegularRelation = async () => {
41
- const scopes = ACTIONS_TO_VERIFY.map((action) => `${attribute.target}.${action}`);
42
-
43
- const isAllowed = await hasAccessToSomeScopes(scopes, auth);
44
-
45
- // If the authenticated user don't have access to any of the scopes, then remove the field
46
- if (!isAllowed) {
47
- remove(key);
48
- }
49
- };
50
-
51
- const isMorphRelation = attribute.relation.toLowerCase().startsWith('morph');
52
- const isCreatorRelation = [CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE].includes(key);
53
-
54
- // Polymorphic relations
55
- if (isMorphRelation) {
56
- await handleMorphRelation();
57
- return;
58
- }
59
-
60
- // Creator relations
61
- if (isCreatorRelation && schema.options.populateCreatorFields) {
62
- // do nothing
63
- return;
64
- }
65
-
66
- // Regular relations
67
- await handleRegularRelation();
68
- };
69
-
70
- const hasAccessToSomeScopes = async (scopes, auth) => {
71
- for (const scope of scopes) {
72
- try {
73
- await strapi.auth.verify(auth, { scope });
74
- return true;
75
- } catch {
76
- continue;
77
- }
78
- }
79
-
80
- return false;
81
- };
@@ -1,32 +0,0 @@
1
- 'use strict';
2
-
3
- const { isArray } = require('lodash/fp');
4
-
5
- module.exports =
6
- (restrictedFields = null) =>
7
- ({ key, path: { attribute: path } }, { remove }) => {
8
- // Remove all fields
9
- if (restrictedFields === null) {
10
- remove(key);
11
- return;
12
- }
13
-
14
- // Ignore invalid formats
15
- if (!isArray(restrictedFields)) {
16
- return;
17
- }
18
-
19
- // Remove if an exact match was found
20
- if (restrictedFields.includes(path)) {
21
- remove(key);
22
- return;
23
- }
24
-
25
- // Remove nested matches
26
- const isRestrictedNested = restrictedFields.some((allowedPath) =>
27
- path.startsWith(`${allowedPath}.`)
28
- );
29
- if (isRestrictedNested) {
30
- remove(key);
31
- }
32
- };
@@ -1,17 +0,0 @@
1
- 'use strict';
2
-
3
- const { assign, assoc } = require('lodash/fp');
4
- const { CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE } = require('./content-types').constants;
5
-
6
- module.exports =
7
- ({ user, isEdition = false }) =>
8
- (data) => {
9
- if (isEdition) {
10
- return assoc(UPDATED_BY_ATTRIBUTE, user.id, data);
11
- }
12
-
13
- return assign(data, {
14
- [CREATED_BY_ATTRIBUTE]: user.id,
15
- [UPDATED_BY_ATTRIBUTE]: user.id,
16
- });
17
- };
@@ -1,79 +0,0 @@
1
- 'use strict';
2
-
3
- const _ = require('lodash');
4
- const { trimChars, trimCharsEnd, trimCharsStart } = require('lodash/fp');
5
- const slugify = require('@sindresorhus/slugify');
6
- const { kebabCase } = require('lodash');
7
-
8
- const nameToSlug = (name, options = { separator: '-' }) => slugify(name, options);
9
-
10
- const nameToCollectionName = (name) => slugify(name, { separator: '_' });
11
-
12
- const toRegressedEnumValue = (value) =>
13
- slugify(value, {
14
- decamelize: false,
15
- lowercase: false,
16
- separator: '_',
17
- });
18
-
19
- const getCommonBeginning = (...strings) =>
20
- _.takeWhile(strings[0], (char, index) => strings.every((string) => string[index] === char)).join(
21
- ''
22
- );
23
-
24
- const getCommonPath = (...paths) => {
25
- const [segments, ...otherSegments] = paths.map((it) => _.split(it, '/'));
26
- return _.join(
27
- _.takeWhile(segments, (str, index) => otherSegments.every((it) => it[index] === str)),
28
- '/'
29
- );
30
- };
31
-
32
- const escapeQuery = (query, charsToEscape, escapeChar = '\\') => {
33
- return query
34
- .split('')
35
- .reduce(
36
- (escapedQuery, char) =>
37
- charsToEscape.includes(char)
38
- ? `${escapedQuery}${escapeChar}${char}`
39
- : `${escapedQuery}${char}`,
40
- ''
41
- );
42
- };
43
-
44
- const stringIncludes = (arr, val) => arr.map(String).includes(String(val));
45
- const stringEquals = (a, b) => String(a) === String(b);
46
- const isCamelCase = (value) => /^[a-z][a-zA-Z0-9]+$/.test(value);
47
- const isKebabCase = (value) => /^([a-z][a-z0-9]*)(-[a-z0-9]+)*$/.test(value);
48
- const startsWithANumber = (value) => /^[0-9]/.test(value);
49
-
50
- const joinBy = (joint, ...args) => {
51
- const trim = trimChars(joint);
52
- const trimEnd = trimCharsEnd(joint);
53
- const trimStart = trimCharsStart(joint);
54
-
55
- return args.reduce((url, path, index) => {
56
- if (args.length === 1) return path;
57
- if (index === 0) return trimEnd(path);
58
- if (index === args.length - 1) return url + joint + trimStart(path);
59
- return url + joint + trim(path);
60
- }, '');
61
- };
62
-
63
- const toKebabCase = (value) => kebabCase(value);
64
-
65
- module.exports = {
66
- nameToSlug,
67
- nameToCollectionName,
68
- getCommonBeginning,
69
- getCommonPath,
70
- escapeQuery,
71
- stringIncludes,
72
- stringEquals,
73
- isCamelCase,
74
- isKebabCase,
75
- toKebabCase,
76
- toRegressedEnumValue,
77
- startsWithANumber,
78
- joinBy,
79
- };
@@ -1,32 +0,0 @@
1
- 'use strict';
2
-
3
- const { isString, isPlainObject } = require('lodash');
4
-
5
- const regex = /\$\{[^()]*\}/g;
6
- const excludeConfigPaths = ['info.scripts'];
7
-
8
- /**
9
- * Allow dynamic config values through the native ES6 template string function.
10
- */
11
- const templateConfiguration = (obj, configPath = '') => {
12
- // Allow values which looks like such as an ES6 literal string without parenthesis inside (aka function call).
13
- // Exclude config with conflicting syntax (e.g. npm scripts).
14
- return Object.keys(obj).reduce((acc, key) => {
15
- if (isPlainObject(obj[key]) && !isString(obj[key])) {
16
- acc[key] = templateConfiguration(obj[key], `${configPath}.${key}`);
17
- } else if (
18
- isString(obj[key]) &&
19
- !excludeConfigPaths.includes(configPath.substr(1)) &&
20
- obj[key].match(regex) !== null
21
- ) {
22
- // eslint-disable-next-line prefer-template, no-eval
23
- acc[key] = eval('`' + obj[key] + '`');
24
- } else {
25
- acc[key] = obj[key];
26
- }
27
-
28
- return acc;
29
- }, {});
30
- };
31
-
32
- module.exports = templateConfiguration;
package/lib/template.js DELETED
@@ -1,28 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * Create a strict interpolation RegExp based on the given variables' name
5
- *
6
- * @param {string[]} allowedVariableNames - The list of allowed variables
7
- * @param {string} [flags] - The RegExp flags
8
- */
9
- const createStrictInterpolationRegExp = (allowedVariableNames, flags) => {
10
- const oneOfVariables = allowedVariableNames.join('|');
11
-
12
- // 1. We need to match the delimiters: <%= ... %>
13
- // 2. We accept any number of whitespaces characters before and/or after the variable name: \s* ... \s*
14
- // 3. We only accept values from the variable list as interpolation variables' name: : (${oneOfVariables})
15
- return new RegExp(`<%=\\s*(${oneOfVariables})\\s*%>`, flags);
16
- };
17
-
18
- /**
19
- * Create a loose interpolation RegExp to match as many groups as possible
20
- *
21
- * @param {string} [flags] - The RegExp flags
22
- */
23
- const createLooseInterpolationRegExp = (flags) => new RegExp(/<%=([\s\S]+?)%>/, flags);
24
-
25
- module.exports = {
26
- createStrictInterpolationRegExp,
27
- createLooseInterpolationRegExp,
28
- };
@@ -1,157 +0,0 @@
1
- 'use strict';
2
-
3
- const { isNil, pick } = require('lodash/fp');
4
-
5
- module.exports = () => {
6
- const state = {
7
- parsers: [],
8
- interceptors: [],
9
- ignore: [],
10
- handlers: {
11
- attributes: [],
12
- common: [],
13
- },
14
- };
15
-
16
- const traverse = async (visitor, options, data) => {
17
- const { path = { raw: null, attribute: null }, schema } = options ?? {};
18
-
19
- // interceptors
20
- for (const { predicate, handler } of state.interceptors) {
21
- if (predicate(data)) {
22
- return handler(visitor, options, data, { recurse: traverse });
23
- }
24
- }
25
-
26
- // parsers
27
- const parser = state.parsers.find((parser) => parser.predicate(data))?.parser;
28
- const utils = parser?.(data);
29
-
30
- // Return the data untouched if we don't know how to traverse it
31
- if (!utils) {
32
- return data;
33
- }
34
-
35
- // main loop
36
- let out = utils.transform(data);
37
- const keys = utils.keys(out);
38
-
39
- for (const key of keys) {
40
- const attribute =
41
- schema?.attributes?.[key] ??
42
- // FIX: Needed to not break existing behavior on the API.
43
- // It looks for the attribute in the DB metadata when the key is in snake_case
44
- schema?.attributes?.[strapi.db.metadata.get(schema?.uid).columnToAttribute[key]];
45
-
46
- const newPath = { ...path };
47
-
48
- newPath.raw = isNil(path.raw) ? key : `${path.raw}.${key}`;
49
-
50
- if (!isNil(attribute)) {
51
- newPath.attribute = isNil(path.attribute) ? key : `${path.attribute}.${key}`;
52
- }
53
-
54
- // visitors
55
-
56
- const visitorOptions = {
57
- key,
58
- value: utils.get(key, out),
59
- attribute,
60
- schema,
61
- path: newPath,
62
- data: out,
63
- };
64
-
65
- const transformUtils = {
66
- remove(key) {
67
- out = utils.remove(key, out);
68
- },
69
- set(key, value) {
70
- out = utils.set(key, value, out);
71
- },
72
- recurse: traverse,
73
- };
74
-
75
- await visitor(visitorOptions, pick(['remove', 'set'], transformUtils));
76
-
77
- const value = utils.get(key, out);
78
-
79
- const createContext = () => ({
80
- key,
81
- value,
82
- attribute,
83
- schema,
84
- path: newPath,
85
- data: out,
86
- visitor,
87
- });
88
-
89
- // ignore
90
- const ignoreCtx = createContext();
91
- const shouldIgnore = state.ignore.some((predicate) => predicate(ignoreCtx));
92
-
93
- if (shouldIgnore) {
94
- continue;
95
- }
96
-
97
- // handlers
98
- const handlers = [...state.handlers.common, ...state.handlers.attributes];
99
-
100
- for await (const handler of handlers) {
101
- const ctx = createContext();
102
- const pass = await handler.predicate(ctx);
103
-
104
- if (pass) {
105
- await handler.handler(ctx, pick(['recurse', 'set'], transformUtils));
106
- }
107
- }
108
- }
109
-
110
- return out;
111
- };
112
-
113
- return {
114
- traverse,
115
-
116
- intercept(predicate, handler) {
117
- state.interceptors.push({ predicate, handler });
118
- return this;
119
- },
120
-
121
- parse(predicate, parser) {
122
- state.parsers.push({ predicate, parser });
123
- return this;
124
- },
125
-
126
- ignore(predicate) {
127
- state.ignore.push(predicate);
128
- return this;
129
- },
130
-
131
- on(predicate, handler) {
132
- state.handlers.common.push({ predicate, handler });
133
- return this;
134
- },
135
-
136
- onAttribute(predicate, handler) {
137
- state.handlers.attributes.push({ predicate, handler });
138
- return this;
139
- },
140
-
141
- onRelation(handler) {
142
- return this.onAttribute(({ attribute }) => attribute?.type === 'relation', handler);
143
- },
144
-
145
- onMedia(handler) {
146
- return this.onAttribute(({ attribute }) => attribute?.type === 'media', handler);
147
- },
148
-
149
- onComponent(handler) {
150
- return this.onAttribute(({ attribute }) => attribute?.type === 'component', handler);
151
- },
152
-
153
- onDynamicZone(handler) {
154
- return this.onAttribute(({ attribute }) => attribute?.type === 'dynamiczone', handler);
155
- },
156
- };
157
- };
@@ -1,16 +0,0 @@
1
- 'use strict';
2
-
3
- const factory = require('./factory');
4
-
5
- const traverseQueryFilters = require('./query-filters');
6
- const traverseQuerySort = require('./query-sort');
7
- const traverseQueryPopulate = require('./query-populate');
8
- const traverseQueryFields = require('./query-fields');
9
-
10
- module.exports = {
11
- factory,
12
- traverseQueryFilters,
13
- traverseQuerySort,
14
- traverseQueryPopulate,
15
- traverseQueryFields,
16
- };