@strapi/utils 4.20.5 → 5.0.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.
Files changed (60) hide show
  1. package/dist/async.d.ts +9 -6
  2. package/dist/async.d.ts.map +1 -1
  3. package/dist/content-types.d.ts +2 -4
  4. package/dist/content-types.d.ts.map +1 -1
  5. package/dist/convert-query-params.d.ts +11 -8
  6. package/dist/convert-query-params.d.ts.map +1 -1
  7. package/dist/env-helper.d.ts +3 -1
  8. package/dist/env-helper.d.ts.map +1 -1
  9. package/dist/index.d.ts +25 -33
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +1444 -1444
  12. package/dist/index.js.map +1 -1
  13. package/dist/index.mjs +1450 -1452
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/machine-id.d.ts +3 -0
  16. package/dist/machine-id.d.ts.map +1 -0
  17. package/dist/package-manager.d.ts +7 -0
  18. package/dist/package-manager.d.ts.map +1 -0
  19. package/dist/primitives/arrays.d.ts +3 -0
  20. package/dist/primitives/arrays.d.ts.map +1 -0
  21. package/dist/primitives/dates.d.ts +3 -0
  22. package/dist/primitives/dates.d.ts.map +1 -0
  23. package/dist/primitives/index.d.ts +5 -0
  24. package/dist/primitives/index.d.ts.map +1 -0
  25. package/dist/primitives/objects.d.ts +3 -0
  26. package/dist/primitives/objects.d.ts.map +1 -0
  27. package/dist/{string-formatting.d.ts → primitives/strings.d.ts} +3 -6
  28. package/dist/primitives/strings.d.ts.map +1 -0
  29. package/dist/sanitize/index.d.ts.map +1 -1
  30. package/dist/sanitize/sanitizers.d.ts.map +1 -1
  31. package/dist/sanitize/visitors/expand-wildcard-populate.d.ts +4 -0
  32. package/dist/sanitize/visitors/expand-wildcard-populate.d.ts.map +1 -0
  33. package/dist/sanitize/visitors/index.d.ts +1 -0
  34. package/dist/sanitize/visitors/index.d.ts.map +1 -1
  35. package/dist/traverse/factory.d.ts +1 -1
  36. package/dist/traverse/query-populate.d.ts.map +1 -1
  37. package/dist/types.d.ts +1 -4
  38. package/dist/types.d.ts.map +1 -1
  39. package/dist/validate/index.d.ts +1 -0
  40. package/dist/validate/index.d.ts.map +1 -1
  41. package/dist/validate/utils.d.ts +2 -1
  42. package/dist/validate/utils.d.ts.map +1 -1
  43. package/dist/validate/validators.d.ts +2 -1
  44. package/dist/validate/validators.d.ts.map +1 -1
  45. package/dist/yup.d.ts +0 -1
  46. package/dist/yup.d.ts.map +1 -1
  47. package/package.json +10 -8
  48. package/dist/code-generator.d.ts +0 -3
  49. package/dist/code-generator.d.ts.map +0 -1
  50. package/dist/config.d.ts +0 -9
  51. package/dist/config.d.ts.map +0 -1
  52. package/dist/object-formatting.d.ts +0 -4
  53. package/dist/object-formatting.d.ts.map +0 -1
  54. package/dist/parse-multipart.d.ts +0 -7
  55. package/dist/parse-multipart.d.ts.map +0 -1
  56. package/dist/string-formatting.d.ts.map +0 -1
  57. package/dist/template-configuration.d.ts +0 -6
  58. package/dist/template-configuration.d.ts.map +0 -1
  59. package/dist/webhook.d.ts +0 -6
  60. package/dist/webhook.d.ts.map +0 -1
package/dist/index.mjs CHANGED
@@ -1,10 +1,14 @@
1
- import _$1, { isString, isPlainObject as isPlainObject$1, kebabCase } from "lodash";
2
- import { eq, isEmpty, toPath, defaults, trimChars, trimCharsEnd, trimCharsStart, get, isNumber, isInteger, has, union, getOr, assoc, assign, cloneDeep, remove, merge, isNil, pipe, omit, curry, isArray, isString as isString$1, isObject, clone, pick, trim, split, map, flatten, first, join, constant, mergeAll, toNumber } from "lodash/fp";
3
- import * as yup$1 from "yup";
4
- import { HttpError } from "http-errors";
5
- import slugify from "@sindresorhus/slugify";
1
+ import _$1, { kebabCase } from "lodash";
2
+ import { has, union, getOr, assoc, assign, cloneDeep, remove, eq, curry, isArray, isString, isNil, toPath, isObject, clone, pick, isEmpty, omit, trim, pipe as pipe$1, split, map as map$1, flatten, first, identity, constant, join, merge, mergeAll, get, toNumber, isInteger, defaults, trimChars, trimCharsEnd, trimCharsStart, isNumber } from "lodash/fp";
6
3
  import pMap from "p-map";
4
+ import { HttpError } from "http-errors";
5
+ import { randomUUID } from "crypto";
6
+ import { machineIdSync } from "node-machine-id";
7
+ import * as yup$1 from "yup";
8
+ import execa from "execa";
9
+ import preferredPM from "preferred-pm";
7
10
  import { Writable } from "node:stream";
11
+ import slugify from "@sindresorhus/slugify";
8
12
  function _mergeNamespaces(n, m) {
9
13
  for (var i = 0; i < m.length; i++) {
10
14
  const e = m[i];
@@ -24,53 +28,20 @@ function _mergeNamespaces(n, m) {
24
28
  }
25
29
  return Object.freeze(Object.defineProperty(n, Symbol.toStringTag, { value: "Module" }));
26
30
  }
27
- const parseMultipartData = (ctx) => {
28
- if (!ctx.is("multipart")) {
29
- return { data: ctx.request.body, files: {} };
30
- }
31
- const { body = {}, files = {} } = ctx.request;
32
- if (!body.data) {
33
- return ctx.badRequest(
34
- `When using multipart/form-data you need to provide your data in a JSON 'data' field.`
35
- );
36
- }
37
- let data;
38
- try {
39
- data = JSON.parse(body.data);
40
- } catch (error) {
41
- return ctx.badRequest(`Invalid 'data' field. 'data' should be a valid JSON.`);
42
- }
43
- const filesToUpload = Object.keys(files).reduce((acc2, key2) => {
44
- const fullPath = _$1.toPath(key2);
45
- if (fullPath.length <= 1 || fullPath[0] !== "files") {
46
- return ctx.badRequest(
47
- `When using multipart/form-data you need to provide your files by prefixing them with the 'files'.
48
- For example, when a media file is named "avatar", make sure the form key name is "files.avatar"`
49
- );
50
- }
51
- const path = _$1.tail(fullPath);
52
- acc2[path.join(".")] = files[key2];
53
- return acc2;
54
- }, {});
55
- return {
56
- data,
57
- files: filesToUpload
58
- };
59
- };
60
31
  const _ = require("lodash");
61
- const dates = require("date-fns");
32
+ const dates$1 = require("date-fns");
62
33
  const timeRegex = /^(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]{1,3})?$/;
63
34
  const isDate = (v) => {
64
- return dates.isDate(v);
35
+ return dates$1.isDate(v);
65
36
  };
66
- const parseTime = (value2) => {
67
- if (isDate(value2)) {
68
- return dates.format(value2, "HH:mm:ss.SSS");
37
+ const parseTime = (value) => {
38
+ if (isDate(value)) {
39
+ return dates$1.format(value, "HH:mm:ss.SSS");
69
40
  }
70
- if (typeof value2 !== "string") {
71
- throw new Error(`Expected a string, got a ${typeof value2}`);
41
+ if (typeof value !== "string") {
42
+ throw new Error(`Expected a string, got a ${typeof value}`);
72
43
  }
73
- const result = value2.match(timeRegex);
44
+ const result = value.match(timeRegex);
74
45
  if (result === null) {
75
46
  throw new Error("Invalid time format, expected HH:mm:ss.SSS");
76
47
  }
@@ -78,721 +49,289 @@ const parseTime = (value2) => {
78
49
  const fractionPart = _.padEnd(fraction.slice(1), 3, "0");
79
50
  return `${hours}:${minutes}:${seconds}.${fractionPart}`;
80
51
  };
81
- const parseDate = (value2) => {
82
- if (isDate(value2)) {
83
- return dates.format(value2, "yyyy-MM-dd");
52
+ const parseDate = (value) => {
53
+ if (isDate(value)) {
54
+ return dates$1.format(value, "yyyy-MM-dd");
84
55
  }
85
- if (typeof value2 !== "string") {
86
- throw new Error(`Expected a string, got a ${typeof value2}`);
56
+ if (typeof value !== "string") {
57
+ throw new Error(`Expected a string, got a ${typeof value}`);
87
58
  }
88
59
  try {
89
- const date = dates.parseISO(value2);
90
- if (dates.isValid(date))
91
- return dates.format(date, "yyyy-MM-dd");
60
+ const date = dates$1.parseISO(value);
61
+ if (dates$1.isValid(date))
62
+ return dates$1.format(date, "yyyy-MM-dd");
92
63
  throw new Error(`Invalid format, expected an ISO compatible date`);
93
64
  } catch (error) {
94
65
  throw new Error(`Invalid format, expected an ISO compatible date`);
95
66
  }
96
67
  };
97
- const parseDateTimeOrTimestamp = (value2) => {
98
- if (isDate(value2)) {
99
- return value2;
68
+ const parseDateTimeOrTimestamp = (value) => {
69
+ if (isDate(value)) {
70
+ return value;
100
71
  }
101
- if (typeof value2 !== "string") {
102
- throw new Error(`Expected a string, got a ${typeof value2}`);
72
+ if (typeof value !== "string") {
73
+ throw new Error(`Expected a string, got a ${typeof value}`);
103
74
  }
104
75
  try {
105
- const date = dates.parseISO(value2);
106
- if (dates.isValid(date))
76
+ const date = dates$1.parseISO(value);
77
+ if (dates$1.isValid(date))
107
78
  return date;
108
- const milliUnixDate = dates.parse(value2, "T", /* @__PURE__ */ new Date());
109
- if (dates.isValid(milliUnixDate))
79
+ const milliUnixDate = dates$1.parse(value, "T", /* @__PURE__ */ new Date());
80
+ if (dates$1.isValid(milliUnixDate))
110
81
  return milliUnixDate;
111
82
  throw new Error(`Invalid format, expected a timestamp or an ISO date`);
112
83
  } catch (error) {
113
84
  throw new Error(`Invalid format, expected a timestamp or an ISO date`);
114
85
  }
115
86
  };
116
- const parseBoolean = (value2, options) => {
87
+ const parseBoolean = (value, options) => {
117
88
  const { forceCast = false } = options;
118
- if (typeof value2 === "boolean") {
119
- return value2;
89
+ if (typeof value === "boolean") {
90
+ return value;
120
91
  }
121
- if (typeof value2 === "string" || typeof value2 === "number") {
122
- if (["true", "t", "1", 1].includes(value2)) {
92
+ if (typeof value === "string" || typeof value === "number") {
93
+ if (["true", "t", "1", 1].includes(value)) {
123
94
  return true;
124
95
  }
125
- if (["false", "f", "0", 0].includes(value2)) {
96
+ if (["false", "f", "0", 0].includes(value)) {
126
97
  return false;
127
98
  }
128
99
  }
129
100
  if (forceCast) {
130
- return Boolean(value2);
101
+ return Boolean(value);
131
102
  }
132
103
  throw new Error('Invalid boolean input. Expected "t","1","true","false","0","f"');
133
104
  };
134
105
  const parseType = (options) => {
135
- const { type, value: value2, forceCast } = options;
106
+ const { type, value, forceCast } = options;
136
107
  switch (type) {
137
108
  case "boolean":
138
- return parseBoolean(value2, { forceCast });
109
+ return parseBoolean(value, { forceCast });
139
110
  case "integer":
140
111
  case "biginteger":
141
112
  case "float":
142
113
  case "decimal": {
143
- return _.toNumber(value2);
114
+ return _.toNumber(value);
144
115
  }
145
116
  case "time": {
146
- return parseTime(value2);
117
+ return parseTime(value);
147
118
  }
148
119
  case "date": {
149
- return parseDate(value2);
120
+ return parseDate(value);
150
121
  }
151
122
  case "timestamp":
152
123
  case "datetime": {
153
- return parseDateTimeOrTimestamp(value2);
124
+ return parseDateTimeOrTimestamp(value);
154
125
  }
155
126
  default:
156
- return value2;
157
- }
158
- };
159
- const PLUGIN_PREFIX = "plugin::";
160
- const API_PREFIX = "api::";
161
- const parsePolicy = (policy2) => {
162
- if (typeof policy2 === "string") {
163
- return { policyName: policy2, config: {} };
127
+ return value;
164
128
  }
165
- const { name, config } = policy2;
166
- return { policyName: name, config };
167
129
  };
168
- const searchLocalPolicy = (policyName, policyContext) => {
169
- const { pluginName, apiName } = policyContext ?? {};
170
- if (pluginName) {
171
- return strapi.policy(`${PLUGIN_PREFIX}${pluginName}.${policyName}`);
172
- }
173
- if (apiName) {
174
- return strapi.policy(`${API_PREFIX}${apiName}.${policyName}`);
130
+ function envFn(key, defaultValue) {
131
+ return _$1.has(process.env, key) ? process.env[key] : defaultValue;
132
+ }
133
+ function getKey(key) {
134
+ return process.env[key] ?? "";
135
+ }
136
+ const utils = {
137
+ int(key, defaultValue) {
138
+ if (!_$1.has(process.env, key)) {
139
+ return defaultValue;
140
+ }
141
+ return parseInt(getKey(key), 10);
142
+ },
143
+ float(key, defaultValue) {
144
+ if (!_$1.has(process.env, key)) {
145
+ return defaultValue;
146
+ }
147
+ return parseFloat(getKey(key));
148
+ },
149
+ bool(key, defaultValue) {
150
+ if (!_$1.has(process.env, key)) {
151
+ return defaultValue;
152
+ }
153
+ return getKey(key) === "true";
154
+ },
155
+ json(key, defaultValue) {
156
+ if (!_$1.has(process.env, key)) {
157
+ return defaultValue;
158
+ }
159
+ try {
160
+ return JSON.parse(getKey(key));
161
+ } catch (error) {
162
+ if (error instanceof Error) {
163
+ throw new Error(`Invalid json environment variable ${key}: ${error.message}`);
164
+ }
165
+ throw error;
166
+ }
167
+ },
168
+ array(key, defaultValue) {
169
+ if (!_$1.has(process.env, key)) {
170
+ return defaultValue;
171
+ }
172
+ let value = getKey(key);
173
+ if (value.startsWith("[") && value.endsWith("]")) {
174
+ value = value.substring(1, value.length - 1);
175
+ }
176
+ return value.split(",").map((v) => {
177
+ return _$1.trim(_$1.trim(v, " "), '"');
178
+ });
179
+ },
180
+ date(key, defaultValue) {
181
+ if (!_$1.has(process.env, key)) {
182
+ return defaultValue;
183
+ }
184
+ return new Date(getKey(key));
185
+ },
186
+ /**
187
+ * Gets a value from env that matches oneOf provided values
188
+ * @param {string} key
189
+ * @param {string[]} expectedValues
190
+ * @param {string|undefined} defaultValue
191
+ * @returns {string|undefined}
192
+ */
193
+ oneOf(key, expectedValues, defaultValue) {
194
+ if (!expectedValues) {
195
+ throw new Error(`env.oneOf requires expectedValues`);
196
+ }
197
+ if (defaultValue && !expectedValues.includes(defaultValue)) {
198
+ throw new Error(`env.oneOf requires defaultValue to be included in expectedValues`);
199
+ }
200
+ const rawValue = env(key, defaultValue);
201
+ return expectedValues.includes(rawValue) ? rawValue : defaultValue;
175
202
  }
176
203
  };
177
- const globalPolicy = ({ method, endpoint, controller, action, plugin }) => {
178
- return async (ctx, next) => {
179
- ctx.request.route = {
180
- endpoint: `${method} ${endpoint}`,
181
- controller: _$1.toLower(controller),
182
- action: _$1.toLower(action),
183
- verb: _$1.toLower(method),
184
- plugin
185
- };
186
- await next();
187
- };
188
- };
189
- const resolvePolicies = (config, policyContext) => {
190
- const { pluginName, apiName } = policyContext ?? {};
191
- return config.map((policyConfig) => {
192
- return {
193
- handler: getPolicy(policyConfig, { pluginName, apiName }),
194
- config: typeof policyConfig === "object" && policyConfig.config || {}
195
- };
196
- });
204
+ const env = Object.assign(envFn, utils);
205
+ const SINGLE_TYPE = "singleType";
206
+ const COLLECTION_TYPE = "collectionType";
207
+ const ID_ATTRIBUTE$4 = "id";
208
+ const DOC_ID_ATTRIBUTE$4 = "documentId";
209
+ const PUBLISHED_AT_ATTRIBUTE$1 = "publishedAt";
210
+ const CREATED_BY_ATTRIBUTE$3 = "createdBy";
211
+ const UPDATED_BY_ATTRIBUTE$3 = "updatedBy";
212
+ const CREATED_AT_ATTRIBUTE = "createdAt";
213
+ const UPDATED_AT_ATTRIBUTE = "updatedAt";
214
+ const constants$1 = {
215
+ ID_ATTRIBUTE: ID_ATTRIBUTE$4,
216
+ DOC_ID_ATTRIBUTE: DOC_ID_ATTRIBUTE$4,
217
+ PUBLISHED_AT_ATTRIBUTE: PUBLISHED_AT_ATTRIBUTE$1,
218
+ CREATED_BY_ATTRIBUTE: CREATED_BY_ATTRIBUTE$3,
219
+ UPDATED_BY_ATTRIBUTE: UPDATED_BY_ATTRIBUTE$3,
220
+ CREATED_AT_ATTRIBUTE,
221
+ UPDATED_AT_ATTRIBUTE,
222
+ SINGLE_TYPE,
223
+ COLLECTION_TYPE
197
224
  };
198
- const findPolicy = (name, policyContext) => {
199
- const { pluginName, apiName } = policyContext ?? {};
200
- const resolvedPolicy = strapi.policy(name);
201
- if (resolvedPolicy !== void 0) {
202
- return resolvedPolicy;
225
+ const getTimestamps = (model) => {
226
+ const attributes = [];
227
+ if (has(CREATED_AT_ATTRIBUTE, model.attributes)) {
228
+ attributes.push(CREATED_AT_ATTRIBUTE);
203
229
  }
204
- const localPolicy = searchLocalPolicy(name, { pluginName, apiName });
205
- if (localPolicy !== void 0) {
206
- return localPolicy;
230
+ if (has(UPDATED_AT_ATTRIBUTE, model.attributes)) {
231
+ attributes.push(UPDATED_AT_ATTRIBUTE);
207
232
  }
208
- throw new Error(`Could not find policy "${name}"`);
233
+ return attributes;
209
234
  };
210
- const getPolicy = (policyConfig, policyContext) => {
211
- const { pluginName, apiName } = policyContext ?? {};
212
- if (typeof policyConfig === "function") {
213
- return policyConfig;
235
+ const getCreatorFields = (model) => {
236
+ const attributes = [];
237
+ if (has(CREATED_BY_ATTRIBUTE$3, model.attributes)) {
238
+ attributes.push(CREATED_BY_ATTRIBUTE$3);
214
239
  }
215
- const { policyName, config } = parsePolicy(policyConfig);
216
- const policy2 = findPolicy(policyName, { pluginName, apiName });
217
- if (typeof policy2 === "function") {
218
- return policy2;
240
+ if (has(UPDATED_BY_ATTRIBUTE$3, model.attributes)) {
241
+ attributes.push(UPDATED_BY_ATTRIBUTE$3);
219
242
  }
220
- if (policy2.validator) {
221
- policy2.validator(config);
243
+ return attributes;
244
+ };
245
+ const getNonWritableAttributes = (model) => {
246
+ if (!model)
247
+ return [];
248
+ const nonWritableAttributes = _$1.reduce(
249
+ model.attributes,
250
+ (acc, attr, attrName) => attr.writable === false ? acc.concat(attrName) : acc,
251
+ []
252
+ );
253
+ return _$1.uniq([
254
+ ID_ATTRIBUTE$4,
255
+ DOC_ID_ATTRIBUTE$4,
256
+ ...getTimestamps(model),
257
+ ...nonWritableAttributes
258
+ ]);
259
+ };
260
+ const getWritableAttributes = (model) => {
261
+ if (!model)
262
+ return [];
263
+ return _$1.difference(Object.keys(model.attributes), getNonWritableAttributes(model));
264
+ };
265
+ const isWritableAttribute = (model, attributeName) => {
266
+ return getWritableAttributes(model).includes(attributeName);
267
+ };
268
+ const getNonVisibleAttributes = (model) => {
269
+ const nonVisibleAttributes = _$1.reduce(
270
+ model.attributes,
271
+ (acc, attr, attrName) => attr.visible === false ? acc.concat(attrName) : acc,
272
+ []
273
+ );
274
+ return _$1.uniq([ID_ATTRIBUTE$4, DOC_ID_ATTRIBUTE$4, ...getTimestamps(model), ...nonVisibleAttributes]);
275
+ };
276
+ const getVisibleAttributes = (model) => {
277
+ return _$1.difference(_$1.keys(model.attributes), getNonVisibleAttributes(model));
278
+ };
279
+ const isVisibleAttribute = (model, attributeName) => {
280
+ return getVisibleAttributes(model).includes(attributeName);
281
+ };
282
+ const getOptions = (model) => _$1.assign({ draftAndPublish: false }, _$1.get(model, "options", {}));
283
+ const hasDraftAndPublish = (model) => _$1.get(model, "options.draftAndPublish", false) === true;
284
+ const isDraft = (data, model) => hasDraftAndPublish(model) && _$1.get(data, PUBLISHED_AT_ATTRIBUTE$1) === null;
285
+ const isSingleType = ({ kind = COLLECTION_TYPE }) => kind === SINGLE_TYPE;
286
+ const isCollectionType = ({ kind = COLLECTION_TYPE }) => kind === COLLECTION_TYPE;
287
+ const isKind = (kind) => (model) => model.kind === kind;
288
+ const getStoredPrivateAttributes = (model) => union(
289
+ strapi?.config?.get("api.responses.privateAttributes", []) ?? [],
290
+ getOr([], "options.privateAttributes", model)
291
+ );
292
+ const getPrivateAttributes = (model) => {
293
+ return _$1.union(
294
+ getStoredPrivateAttributes(model),
295
+ _$1.keys(_$1.pickBy(model.attributes, (attr) => !!attr.private))
296
+ );
297
+ };
298
+ const isPrivateAttribute = (model, attributeName) => {
299
+ if (model?.attributes?.[attributeName]?.private === true) {
300
+ return true;
222
301
  }
223
- return policy2.handler;
302
+ return getStoredPrivateAttributes(model).includes(attributeName);
224
303
  };
225
- const createPolicy = (options) => {
226
- const { name = "unnamed", validator, handler } = options;
227
- const wrappedValidator = (config) => {
228
- if (validator) {
229
- try {
230
- validator(config);
231
- } catch (e) {
232
- throw new Error(`Invalid config passed to "${name}" policy.`);
233
- }
234
- }
235
- };
236
- return {
237
- name,
238
- validator: wrappedValidator,
239
- handler
240
- };
304
+ const isScalarAttribute = (attribute) => {
305
+ return !["media", "component", "relation", "dynamiczone"].includes(attribute?.type);
241
306
  };
242
- const createPolicyContext = (type, ctx) => {
243
- return Object.assign(
244
- {
245
- is: eq(type),
246
- get type() {
247
- return type;
248
- }
307
+ const isMediaAttribute = (attribute) => attribute?.type === "media";
308
+ const isRelationalAttribute = (attribute) => attribute?.type === "relation";
309
+ const isComponentAttribute = (attribute) => ["component", "dynamiczone"].includes(attribute?.type);
310
+ const isDynamicZoneAttribute = (attribute) => attribute?.type === "dynamiczone";
311
+ const isMorphToRelationalAttribute = (attribute) => {
312
+ return isRelationalAttribute(attribute) && attribute?.relation?.startsWith?.("morphTo");
313
+ };
314
+ const getComponentAttributes = (schema) => {
315
+ return _$1.reduce(
316
+ schema.attributes,
317
+ (acc, attr, attrName) => {
318
+ if (isComponentAttribute(attr))
319
+ acc.push(attrName);
320
+ return acc;
249
321
  },
250
- ctx
322
+ []
251
323
  );
252
324
  };
253
- const policy = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
254
- __proto__: null,
255
- createPolicy,
256
- createPolicyContext,
257
- get: getPolicy,
258
- globalPolicy,
259
- resolve: resolvePolicies
260
- }, Symbol.toStringTag, { value: "Module" }));
261
- const regex = /\$\{[^()]*\}/g;
262
- const excludeConfigPaths = ["info.scripts"];
263
- const isObj$3 = (value2) => isPlainObject$1(value2);
264
- const templateConfiguration = (obj, configPath = "") => {
265
- return Object.keys(obj).reduce((acc, key) => {
266
- const value = obj[key];
267
- if (isObj$3(value) && !isString(value)) {
268
- acc[key] = templateConfiguration(value, `${configPath}.${key}`);
269
- } else if (isString(value) && !excludeConfigPaths.includes(configPath.substr(1)) && value.match(regex) !== null) {
270
- acc[key] = eval("`" + value + "`");
271
- } else {
272
- acc[key] = value;
273
- }
274
- return acc;
275
- }, {});
276
- };
277
- const formatYupInnerError = (yupError) => ({
278
- path: toPath(yupError.path),
279
- message: yupError.message,
280
- name: yupError.name
281
- });
282
- const formatYupErrors = (yupError) => ({
283
- errors: isEmpty(yupError.inner) ? [formatYupInnerError(yupError)] : yupError.inner.map(formatYupInnerError),
284
- message: yupError.message
285
- });
286
- class ApplicationError extends Error {
287
- name;
288
- details;
289
- message;
290
- constructor(message = "An application error occured", details = {}) {
291
- super();
292
- this.name = "ApplicationError";
293
- this.message = message;
294
- this.details = details;
295
- }
296
- }
297
- class ValidationError extends ApplicationError {
298
- constructor(message, details) {
299
- super(message, details);
300
- this.name = "ValidationError";
301
- }
302
- }
303
- class YupValidationError extends ValidationError {
304
- constructor(yupError, message) {
305
- super("Validation");
306
- const { errors: errors2, message: yupMessage } = formatYupErrors(yupError);
307
- this.message = message || yupMessage;
308
- this.details = { errors: errors2 };
309
- }
310
- }
311
- class PaginationError extends ApplicationError {
312
- constructor(message = "Invalid pagination", details) {
313
- super(message, details);
314
- this.name = "PaginationError";
315
- this.message = message;
316
- }
317
- }
318
- class NotFoundError extends ApplicationError {
319
- constructor(message = "Entity not found", details) {
320
- super(message, details);
321
- this.name = "NotFoundError";
322
- this.message = message;
323
- }
324
- }
325
- class ForbiddenError extends ApplicationError {
326
- constructor(message = "Forbidden access", details) {
327
- super(message, details);
328
- this.name = "ForbiddenError";
329
- this.message = message;
330
- }
331
- }
332
- class UnauthorizedError extends ApplicationError {
333
- constructor(message = "Unauthorized", details) {
334
- super(message, details);
335
- this.name = "UnauthorizedError";
336
- this.message = message;
337
- }
338
- }
339
- class RateLimitError extends ApplicationError {
340
- constructor(message = "Too many requests, please try again later.", details) {
341
- super(message, details);
342
- this.name = "RateLimitError";
343
- this.message = message;
344
- this.details = details || {};
345
- }
346
- }
347
- class PayloadTooLargeError extends ApplicationError {
348
- constructor(message = "Entity too large", details) {
349
- super(message, details);
350
- this.name = "PayloadTooLargeError";
351
- this.message = message;
352
- }
353
- }
354
- class PolicyError extends ForbiddenError {
355
- constructor(message = "Policy Failed", details) {
356
- super(message, details);
357
- this.name = "PolicyError";
358
- this.message = message;
359
- this.details = details || {};
360
- }
361
- }
362
- class NotImplementedError extends ApplicationError {
363
- constructor(message = "This feature is not implemented yet", details) {
364
- super(message, details);
365
- this.name = "NotImplementedError";
366
- this.message = message;
367
- }
368
- }
369
- const errors = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
370
- __proto__: null,
371
- ApplicationError,
372
- ForbiddenError,
373
- HttpError,
374
- NotFoundError,
375
- NotImplementedError,
376
- PaginationError,
377
- PayloadTooLargeError,
378
- PolicyError,
379
- RateLimitError,
380
- UnauthorizedError,
381
- ValidationError,
382
- YupValidationError
383
- }, Symbol.toStringTag, { value: "Module" }));
384
- const handleYupError = (error, errorMessage) => {
385
- throw new YupValidationError(error, errorMessage);
386
- };
387
- const defaultValidationParam = { strict: true, abortEarly: false };
388
- const validateYupSchema = (schema, options = {}) => async (body, errorMessage) => {
389
- try {
390
- const optionsWithDefaults = defaults(defaultValidationParam, options);
391
- const result = await schema.validate(body, optionsWithDefaults);
392
- return result;
393
- } catch (e) {
394
- if (e instanceof yup$1.ValidationError) {
395
- handleYupError(e, errorMessage);
396
- }
397
- throw e;
398
- }
399
- };
400
- const validateYupSchemaSync = (schema, options = {}) => (body, errorMessage) => {
401
- try {
402
- const optionsWithDefaults = defaults(defaultValidationParam, options);
403
- return schema.validateSync(body, optionsWithDefaults);
404
- } catch (e) {
405
- if (e instanceof yup$1.ValidationError) {
406
- handleYupError(e, errorMessage);
407
- }
408
- throw e;
409
- }
410
- };
411
- const nameToSlug = (name, options = { separator: "-" }) => slugify(name, options);
412
- const nameToCollectionName = (name) => slugify(name, { separator: "_" });
413
- const toRegressedEnumValue = (value2) => slugify(value2, {
414
- decamelize: false,
415
- lowercase: false,
416
- separator: "_"
417
- });
418
- const getCommonBeginning = (...strings) => _$1.takeWhile(strings[0], (char, index2) => strings.every((string) => string[index2] === char)).join(
419
- ""
420
- );
421
- const getCommonPath = (...paths) => {
422
- const [segments, ...otherSegments] = paths.map((it) => _$1.split(it, "/"));
423
- return _$1.join(
424
- _$1.takeWhile(segments, (str, index2) => otherSegments.every((it) => it[index2] === str)),
425
- "/"
426
- );
427
- };
428
- const escapeQuery = (query, charsToEscape, escapeChar = "\\") => {
429
- return query.split("").reduce(
430
- (escapedQuery, char) => charsToEscape.includes(char) ? `${escapedQuery}${escapeChar}${char}` : `${escapedQuery}${char}`,
431
- ""
432
- );
433
- };
434
- const stringIncludes = (arr, val) => arr.map(String).includes(String(val));
435
- const stringEquals = (a, b) => String(a) === String(b);
436
- const isCamelCase = (value2) => /^[a-z][a-zA-Z0-9]+$/.test(value2);
437
- const isKebabCase = (value2) => /^([a-z][a-z0-9]*)(-[a-z0-9]+)*$/.test(value2);
438
- const startsWithANumber = (value2) => /^[0-9]/.test(value2);
439
- const joinBy = (joint, ...args) => {
440
- const trim2 = trimChars(joint);
441
- const trimEnd = trimCharsEnd(joint);
442
- const trimStart = trimCharsStart(joint);
443
- return args.reduce((url, path, index2) => {
444
- if (args.length === 1)
445
- return path;
446
- if (index2 === 0)
447
- return trimEnd(path);
448
- if (index2 === args.length - 1)
449
- return url + joint + trimStart(path);
450
- return url + joint + trim2(path);
451
- }, "");
452
- };
453
- const toKebabCase = (value2) => kebabCase(value2);
454
- const { toString } = Object.prototype;
455
- const errorToString = Error.prototype.toString;
456
- const regExpToString = RegExp.prototype.toString;
457
- const symbolToString = typeof Symbol !== "undefined" ? Symbol.prototype.toString : () => "";
458
- const SYMBOL_REGEXP = /^Symbol\((.*)\)(.*)$/;
459
- function printNumber(val) {
460
- if (val != +val)
461
- return "NaN";
462
- const isNegativeZero = val === 0 && 1 / val < 0;
463
- return isNegativeZero ? "-0" : `${val}`;
464
- }
465
- function printSimpleValue(val, quoteStrings = false) {
466
- if (val == null || val === true || val === false)
467
- return `${val}`;
468
- if (typeof val === "number")
469
- return printNumber(val);
470
- if (typeof val === "string")
471
- return quoteStrings ? `"${val}"` : val;
472
- if (typeof val === "function")
473
- return `[Function ${val.name || "anonymous"}]`;
474
- if (typeof val === "symbol")
475
- return symbolToString.call(val).replace(SYMBOL_REGEXP, "Symbol($1)");
476
- const tag = toString.call(val).slice(8, -1);
477
- if (tag === "Date") {
478
- const v = val;
479
- return Number.isNaN(v.getTime()) ? `${v}` : v.toISOString();
480
- }
481
- if (tag === "Error" || val instanceof Error)
482
- return `[${errorToString.call(val)}]`;
483
- if (tag === "RegExp")
484
- return regExpToString.call(val);
485
- return null;
486
- }
487
- function printValue(value2, quoteStrings) {
488
- const result = printSimpleValue(value2, quoteStrings);
489
- if (result !== null)
490
- return result;
491
- return JSON.stringify(
492
- value2,
493
- function replacer(key2, value22) {
494
- const result2 = printSimpleValue(this[key2], quoteStrings);
495
- if (result2 !== null)
496
- return result2;
497
- return value22;
498
- },
499
- 2
500
- );
501
- }
502
- const strapiID = () => new StrapiIDSchema();
503
- const isNotNilTest = (value2) => !_$1.isNil(value2);
504
- const isNotNullTest = (value2) => !_$1.isNull(value2);
505
- yup$1.addMethod(yup$1.mixed, "notNil", function isNotNill(msg = "${path} must be defined.") {
506
- return this.test("defined", msg, isNotNilTest);
507
- });
508
- yup$1.addMethod(yup$1.mixed, "notNull", function isNotNull(msg = "${path} cannot be null.") {
509
- return this.test("defined", msg, isNotNullTest);
510
- });
511
- yup$1.addMethod(yup$1.mixed, "isFunction", function isFunction(message = "${path} is not a function") {
512
- return this.test(
513
- "is a function",
514
- message,
515
- (value2) => _$1.isUndefined(value2) || _$1.isFunction(value2)
516
- );
517
- });
518
- yup$1.addMethod(
519
- yup$1.string,
520
- "isCamelCase",
521
- function isCamelCase$1(message = "${path} is not in camel case (anExampleOfCamelCase)") {
522
- return this.test(
523
- "is in camelCase",
524
- message,
525
- (value2) => value2 ? isCamelCase(value2) : true
526
- );
527
- }
528
- );
529
- yup$1.addMethod(
530
- yup$1.string,
531
- "isKebabCase",
532
- function isKebabCase$1(message = "${path} is not in kebab case (an-example-of-kebab-case)") {
533
- return this.test(
534
- "is in kebab-case",
535
- message,
536
- (value2) => value2 ? isKebabCase(value2) : true
537
- );
538
- }
539
- );
540
- yup$1.addMethod(
541
- yup$1.object,
542
- "onlyContainsFunctions",
543
- function onlyContainsFunctions(message = "${path} contains values that are not functions") {
544
- return this.test(
545
- "only contains functions",
546
- message,
547
- (value2) => _$1.isUndefined(value2) || value2 && Object.values(value2).every(_$1.isFunction)
548
- );
549
- }
550
- );
551
- yup$1.addMethod(
552
- yup$1.array,
553
- "uniqueProperty",
554
- function uniqueProperty(propertyName, message) {
555
- return this.test("unique", message, function unique(list) {
556
- const errors2 = [];
557
- list?.forEach((element, index2) => {
558
- const sameElements = list.filter(
559
- (e) => get(propertyName, e) === get(propertyName, element)
560
- );
561
- if (sameElements.length > 1) {
562
- errors2.push(
563
- this.createError({
564
- path: `${this.path}[${index2}].${propertyName}`,
565
- message
566
- })
567
- );
568
- }
569
- });
570
- if (errors2.length) {
571
- throw new yup$1.ValidationError(errors2);
572
- }
573
- return true;
574
- });
575
- }
576
- );
577
- class StrapiIDSchema extends yup$1.MixedSchema {
578
- constructor() {
579
- super({ type: "strapiID" });
580
- }
581
- _typeCheck(value2) {
582
- return typeof value2 === "string" || isNumber(value2) && isInteger(value2) && value2 >= 0;
583
- }
584
- }
585
- yup$1.setLocale({
586
- mixed: {
587
- notType(options) {
588
- const { path, type, value: value2, originalValue } = options;
589
- const isCast = originalValue != null && originalValue !== value2;
590
- const msg = `${path} must be a \`${type}\` type, but the final value was: \`${printValue(value2, true)}\`${isCast ? ` (cast from the value \`${printValue(originalValue, true)}\`).` : "."}`;
591
- return msg;
592
- }
593
- }
594
- });
595
- const yup = /* @__PURE__ */ _mergeNamespaces({
596
- __proto__: null,
597
- StrapiIDSchema,
598
- strapiID
599
- }, [yup$1]);
600
- const removeUndefined = (obj2) => _$1.pickBy(obj2, (value2) => typeof value2 !== "undefined");
601
- const keysDeep = (obj2, path = []) => !_$1.isObject(obj2) ? [path.join(".")] : _$1.reduce(
602
- obj2,
603
- (acc2, next, key2) => _$1.concat(acc2, keysDeep(next, [...path, key2])),
604
- []
605
- );
606
- const getConfigUrls = (config, forAdminBuild = false) => {
607
- const serverConfig = config.get("server");
608
- const adminConfig = config.get("admin");
609
- let serverUrl = _$1.get(serverConfig, "url", "");
610
- serverUrl = _$1.trim(serverUrl, "/ ");
611
- if (typeof serverUrl !== "string") {
612
- throw new Error("Invalid server url config. Make sure the url is a string.");
613
- }
614
- if (serverUrl.startsWith("http")) {
615
- try {
616
- serverUrl = _$1.trim(new URL(serverConfig.url).toString(), "/");
617
- } catch (e) {
618
- throw new Error(
619
- "Invalid server url config. Make sure the url defined in server.js is valid."
620
- );
621
- }
622
- } else if (serverUrl !== "") {
623
- serverUrl = `/${serverUrl}`;
624
- }
625
- let adminUrl = _$1.get(adminConfig, "url", "/admin");
626
- adminUrl = _$1.trim(adminUrl, "/ ");
627
- if (typeof adminUrl !== "string") {
628
- throw new Error("Invalid admin url config. Make sure the url is a non-empty string.");
629
- }
630
- if (adminUrl.startsWith("http")) {
631
- try {
632
- adminUrl = _$1.trim(new URL(adminUrl).toString(), "/");
633
- } catch (e) {
634
- throw new Error("Invalid admin url config. Make sure the url defined in server.js is valid.");
635
- }
636
- } else {
637
- adminUrl = `${serverUrl}/${adminUrl}`;
638
- }
639
- let adminPath = adminUrl;
640
- if (serverUrl.startsWith("http") && adminUrl.startsWith("http") && new URL(adminUrl).origin === new URL(serverUrl).origin && !forAdminBuild) {
641
- adminPath = adminUrl.replace(getCommonPath(serverUrl, adminUrl), "");
642
- adminPath = `/${_$1.trim(adminPath, "/")}`;
643
- } else if (adminUrl.startsWith("http")) {
644
- adminPath = new URL(adminUrl).pathname;
645
- }
646
- return {
647
- serverUrl,
648
- adminUrl,
649
- adminPath
650
- };
651
- };
652
- const getAbsoluteUrl = (adminOrServer) => (config, forAdminBuild = false) => {
653
- const { serverUrl, adminUrl } = getConfigUrls(config, forAdminBuild);
654
- const url = adminOrServer === "server" ? serverUrl : adminUrl;
655
- if (url.startsWith("http")) {
656
- return url;
657
- }
658
- const hostname = config.get("environment") === "development" && ["127.0.0.1", "0.0.0.0"].includes(config.get("server.host")) ? "localhost" : config.get("server.host");
659
- return `http://${hostname}:${config.get("server.port")}${url}`;
660
- };
661
- const getAbsoluteAdminUrl = getAbsoluteUrl("admin");
662
- const getAbsoluteServerUrl = getAbsoluteUrl("server");
663
- const generateTimestampCode = (date) => {
664
- const referDate = date || /* @__PURE__ */ new Date();
665
- return referDate.getTime().toString(36);
666
- };
667
- const SINGLE_TYPE = "singleType";
668
- const COLLECTION_TYPE = "collectionType";
669
- const ID_ATTRIBUTE = "id";
670
- const PUBLISHED_AT_ATTRIBUTE$1 = "publishedAt";
671
- const CREATED_BY_ATTRIBUTE$3 = "createdBy";
672
- const UPDATED_BY_ATTRIBUTE$3 = "updatedBy";
673
- const CREATED_AT_ATTRIBUTE = "createdAt";
674
- const UPDATED_AT_ATTRIBUTE = "updatedAt";
675
- const DP_PUB_STATE_LIVE = "live";
676
- const DP_PUB_STATE_PREVIEW = "preview";
677
- const DP_PUB_STATES = [DP_PUB_STATE_LIVE, DP_PUB_STATE_PREVIEW];
678
- const constants$1 = {
679
- ID_ATTRIBUTE,
680
- PUBLISHED_AT_ATTRIBUTE: PUBLISHED_AT_ATTRIBUTE$1,
681
- CREATED_BY_ATTRIBUTE: CREATED_BY_ATTRIBUTE$3,
682
- UPDATED_BY_ATTRIBUTE: UPDATED_BY_ATTRIBUTE$3,
683
- CREATED_AT_ATTRIBUTE,
684
- UPDATED_AT_ATTRIBUTE,
685
- DP_PUB_STATES,
686
- DP_PUB_STATE_LIVE,
687
- DP_PUB_STATE_PREVIEW,
688
- SINGLE_TYPE,
689
- COLLECTION_TYPE
690
- };
691
- const getTimestamps = (model) => {
692
- const attributes = [];
693
- if (has(CREATED_AT_ATTRIBUTE, model.attributes)) {
694
- attributes.push(CREATED_AT_ATTRIBUTE);
695
- }
696
- if (has(UPDATED_AT_ATTRIBUTE, model.attributes)) {
697
- attributes.push(UPDATED_AT_ATTRIBUTE);
698
- }
699
- return attributes;
700
- };
701
- const getCreatorFields = (model) => {
702
- const attributes = [];
703
- if (has(CREATED_BY_ATTRIBUTE$3, model.attributes)) {
704
- attributes.push(CREATED_BY_ATTRIBUTE$3);
705
- }
706
- if (has(UPDATED_BY_ATTRIBUTE$3, model.attributes)) {
707
- attributes.push(UPDATED_BY_ATTRIBUTE$3);
708
- }
709
- return attributes;
710
- };
711
- const getNonWritableAttributes = (model) => {
712
- if (!model)
713
- return [];
714
- const nonWritableAttributes = _$1.reduce(
715
- model.attributes,
716
- (acc2, attr, attrName) => attr.writable === false ? acc2.concat(attrName) : acc2,
717
- []
718
- );
719
- return _$1.uniq([ID_ATTRIBUTE, ...getTimestamps(model), ...nonWritableAttributes]);
720
- };
721
- const getWritableAttributes = (model) => {
722
- if (!model)
723
- return [];
724
- return _$1.difference(Object.keys(model.attributes), getNonWritableAttributes(model));
725
- };
726
- const isWritableAttribute = (model, attributeName) => {
727
- return getWritableAttributes(model).includes(attributeName);
728
- };
729
- const getNonVisibleAttributes = (model) => {
730
- const nonVisibleAttributes = _$1.reduce(
731
- model.attributes,
732
- (acc2, attr, attrName) => attr.visible === false ? acc2.concat(attrName) : acc2,
733
- []
734
- );
735
- return _$1.uniq([ID_ATTRIBUTE, ...getTimestamps(model), ...nonVisibleAttributes]);
736
- };
737
- const getVisibleAttributes = (model) => {
738
- return _$1.difference(_$1.keys(model.attributes), getNonVisibleAttributes(model));
739
- };
740
- const isVisibleAttribute = (model, attributeName) => {
741
- return getVisibleAttributes(model).includes(attributeName);
742
- };
743
- const getOptions = (model) => _$1.assign({ draftAndPublish: false }, _$1.get(model, "options", {}));
744
- const hasDraftAndPublish = (model) => _$1.get(model, "options.draftAndPublish", false) === true;
745
- const isDraft = (data, model) => hasDraftAndPublish(model) && _$1.get(data, PUBLISHED_AT_ATTRIBUTE$1) === null;
746
- const isSingleType = ({ kind = COLLECTION_TYPE }) => kind === SINGLE_TYPE;
747
- const isCollectionType = ({ kind = COLLECTION_TYPE }) => kind === COLLECTION_TYPE;
748
- const isKind = (kind) => (model) => model.kind === kind;
749
- const getStoredPrivateAttributes = (model) => union(
750
- strapi?.config?.get("api.responses.privateAttributes", []) ?? [],
751
- getOr([], "options.privateAttributes", model)
752
- );
753
- const getPrivateAttributes = (model) => {
754
- return _$1.union(
755
- getStoredPrivateAttributes(model),
756
- _$1.keys(_$1.pickBy(model.attributes, (attr) => !!attr.private))
757
- );
758
- };
759
- const isPrivateAttribute = (model, attributeName) => {
760
- if (model?.attributes?.[attributeName]?.private === true) {
761
- return true;
762
- }
763
- return getStoredPrivateAttributes(model).includes(attributeName);
764
- };
765
- const isScalarAttribute = (attribute) => {
766
- return !["media", "component", "relation", "dynamiczone"].includes(attribute?.type);
767
- };
768
- const isMediaAttribute = (attribute) => attribute?.type === "media";
769
- const isRelationalAttribute = (attribute) => attribute?.type === "relation";
770
- const isComponentAttribute = (attribute) => ["component", "dynamiczone"].includes(attribute?.type);
771
- const isDynamicZoneAttribute = (attribute) => attribute?.type === "dynamiczone";
772
- const isMorphToRelationalAttribute = (attribute) => {
773
- return isRelationalAttribute(attribute) && attribute?.relation?.startsWith?.("morphTo");
774
- };
775
- const getComponentAttributes = (schema) => {
776
- return _$1.reduce(
777
- schema.attributes,
778
- (acc2, attr, attrName) => {
779
- if (isComponentAttribute(attr))
780
- acc2.push(attrName);
781
- return acc2;
782
- },
783
- []
784
- );
785
- };
786
- const getScalarAttributes = (schema) => {
787
- return _$1.reduce(
788
- schema.attributes,
789
- (acc2, attr, attrName) => {
790
- if (isScalarAttribute(attr))
791
- acc2.push(attrName);
792
- return acc2;
793
- },
794
- []
795
- );
325
+ const getScalarAttributes = (schema) => {
326
+ return _$1.reduce(
327
+ schema.attributes,
328
+ (acc, attr, attrName) => {
329
+ if (isScalarAttribute(attr))
330
+ acc.push(attrName);
331
+ return acc;
332
+ },
333
+ []
334
+ );
796
335
  };
797
336
  const isTypedAttribute = (attribute, type) => {
798
337
  return _$1.has(attribute, "type") && attribute.type === type;
@@ -830,103 +369,6 @@ const contentTypes = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.define
830
369
  isVisibleAttribute,
831
370
  isWritableAttribute
832
371
  }, Symbol.toStringTag, { value: "Module" }));
833
- function envFn(key2, defaultValue) {
834
- return _$1.has(process.env, key2) ? process.env[key2] : defaultValue;
835
- }
836
- function getKey(key2) {
837
- return process.env[key2] ?? "";
838
- }
839
- const utils = {
840
- int(key2, defaultValue) {
841
- if (!_$1.has(process.env, key2)) {
842
- return defaultValue;
843
- }
844
- return parseInt(getKey(key2), 10);
845
- },
846
- float(key2, defaultValue) {
847
- if (!_$1.has(process.env, key2)) {
848
- return defaultValue;
849
- }
850
- return parseFloat(getKey(key2));
851
- },
852
- bool(key2, defaultValue) {
853
- if (!_$1.has(process.env, key2)) {
854
- return defaultValue;
855
- }
856
- return getKey(key2) === "true";
857
- },
858
- json(key2, defaultValue) {
859
- if (!_$1.has(process.env, key2)) {
860
- return defaultValue;
861
- }
862
- try {
863
- return JSON.parse(getKey(key2));
864
- } catch (error) {
865
- if (error instanceof Error) {
866
- throw new Error(`Invalid json environment variable ${key2}: ${error.message}`);
867
- }
868
- throw error;
869
- }
870
- },
871
- array(key2, defaultValue) {
872
- if (!_$1.has(process.env, key2)) {
873
- return defaultValue;
874
- }
875
- let value2 = getKey(key2);
876
- if (value2.startsWith("[") && value2.endsWith("]")) {
877
- value2 = value2.substring(1, value2.length - 1);
878
- }
879
- return value2.split(",").map((v) => {
880
- return _$1.trim(_$1.trim(v, " "), '"');
881
- });
882
- },
883
- date(key2, defaultValue) {
884
- if (!_$1.has(process.env, key2)) {
885
- return defaultValue;
886
- }
887
- return new Date(getKey(key2));
888
- },
889
- /**
890
- * Gets a value from env that matches oneOf provided values
891
- * @param {string} key
892
- * @param {string[]} expectedValues
893
- * @param {string|undefined} defaultValue
894
- * @returns {string|undefined}
895
- */
896
- oneOf(key2, expectedValues, defaultValue) {
897
- if (!expectedValues) {
898
- throw new Error(`env.oneOf requires expectedValues`);
899
- }
900
- if (defaultValue && !expectedValues.includes(defaultValue)) {
901
- throw new Error(`env.oneOf requires defaultValue to be included in expectedValues`);
902
- }
903
- const rawValue = env(key2, defaultValue);
904
- return expectedValues.includes(rawValue) ? rawValue : defaultValue;
905
- }
906
- };
907
- const env = Object.assign(envFn, utils);
908
- const MANY_RELATIONS = ["oneToMany", "manyToMany"];
909
- const getRelationalFields = (contentType) => {
910
- return Object.keys(contentType.attributes).filter((attributeName) => {
911
- return contentType.attributes[attributeName].type === "relation";
912
- });
913
- };
914
- const isOneToAny = (attribute) => isRelationalAttribute(attribute) && ["oneToOne", "oneToMany"].includes(attribute.relation);
915
- const isManyToAny = (attribute) => isRelationalAttribute(attribute) && ["manyToMany", "manyToOne"].includes(attribute.relation);
916
- const isAnyToOne = (attribute) => isRelationalAttribute(attribute) && ["oneToOne", "manyToOne"].includes(attribute.relation);
917
- const isAnyToMany = (attribute) => isRelationalAttribute(attribute) && ["oneToMany", "manyToMany"].includes(attribute.relation);
918
- const constants = {
919
- MANY_RELATIONS
920
- };
921
- const relations = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
922
- __proto__: null,
923
- constants,
924
- getRelationalFields,
925
- isAnyToMany,
926
- isAnyToOne,
927
- isManyToAny,
928
- isOneToAny
929
- }, Symbol.toStringTag, { value: "Module" }));
930
372
  const { CREATED_BY_ATTRIBUTE: CREATED_BY_ATTRIBUTE$2, UPDATED_BY_ATTRIBUTE: UPDATED_BY_ATTRIBUTE$2 } = constants$1;
931
373
  const setCreatorFields = ({ user, isEdition = false }) => (data) => {
932
374
  if (isEdition) {
@@ -1022,26 +464,26 @@ const providerFactory = (options = {}) => {
1022
464
  };
1023
465
  return {
1024
466
  hooks: state.hooks,
1025
- async register(key2, item) {
1026
- if (throwOnDuplicates && this.has(key2)) {
1027
- throw new Error(`Duplicated item key: ${key2}`);
467
+ async register(key, item) {
468
+ if (throwOnDuplicates && this.has(key)) {
469
+ throw new Error(`Duplicated item key: ${key}`);
1028
470
  }
1029
- await state.hooks.willRegister.call({ key: key2, value: item });
1030
- state.registry.set(key2, item);
1031
- await state.hooks.didRegister.call({ key: key2, value: cloneDeep(item) });
471
+ await state.hooks.willRegister.call({ key, value: item });
472
+ state.registry.set(key, item);
473
+ await state.hooks.didRegister.call({ key, value: cloneDeep(item) });
1032
474
  return this;
1033
475
  },
1034
- async delete(key2) {
1035
- if (this.has(key2)) {
1036
- const item = this.get(key2);
1037
- await state.hooks.willDelete.call({ key: key2, value: cloneDeep(item) });
1038
- state.registry.delete(key2);
1039
- await state.hooks.didDelete.call({ key: key2, value: cloneDeep(item) });
476
+ async delete(key) {
477
+ if (this.has(key)) {
478
+ const item = this.get(key);
479
+ await state.hooks.willDelete.call({ key, value: cloneDeep(item) });
480
+ state.registry.delete(key);
481
+ await state.hooks.didDelete.call({ key, value: cloneDeep(item) });
1040
482
  }
1041
483
  return this;
1042
484
  },
1043
- get(key2) {
1044
- return state.registry.get(key2);
485
+ get(key) {
486
+ return state.registry.get(key);
1045
487
  },
1046
488
  getWhere(filters2 = {}) {
1047
489
  const items = this.values();
@@ -1050,7 +492,7 @@ const providerFactory = (options = {}) => {
1050
492
  return items;
1051
493
  }
1052
494
  return items.filter((item) => {
1053
- return filtersEntries.every(([key2, value2]) => item[key2] === value2);
495
+ return filtersEntries.every(([key, value]) => item[key] === value);
1054
496
  });
1055
497
  },
1056
498
  values() {
@@ -1059,93 +501,22 @@ const providerFactory = (options = {}) => {
1059
501
  keys() {
1060
502
  return Array.from(state.registry.keys());
1061
503
  },
1062
- has(key2) {
1063
- return state.registry.has(key2);
504
+ has(key) {
505
+ return state.registry.has(key);
1064
506
  },
1065
507
  size() {
1066
508
  return state.registry.size;
1067
509
  },
1068
510
  async clear() {
1069
511
  const keys = this.keys();
1070
- for (const key2 of keys) {
1071
- await this.delete(key2);
512
+ for (const key of keys) {
513
+ await this.delete(key);
1072
514
  }
1073
515
  return this;
1074
516
  }
1075
517
  };
1076
518
  };
1077
- const STRAPI_DEFAULTS = {
1078
- offset: {
1079
- start: 0,
1080
- limit: 10
1081
- },
1082
- page: {
1083
- page: 1,
1084
- pageSize: 10
1085
- }
1086
- };
1087
- const paginationAttributes = ["start", "limit", "page", "pageSize"];
1088
- const withMaxLimit = (limit, maxLimit = -1) => {
1089
- if (maxLimit === -1 || limit < maxLimit) {
1090
- return limit;
1091
- }
1092
- return maxLimit;
1093
- };
1094
- const ensureMinValues = ({ start, limit }) => ({
1095
- start: Math.max(start, 0),
1096
- limit: limit === -1 ? limit : Math.max(limit, 1)
1097
- });
1098
- const ensureMaxValues = (maxLimit = -1) => ({ start, limit }) => ({
1099
- start,
1100
- limit: withMaxLimit(limit, maxLimit)
1101
- });
1102
- const withNoLimit = (pagination2, maxLimit = -1) => ({
1103
- ...pagination2,
1104
- limit: pagination2.limit === -1 ? maxLimit : pagination2.limit
1105
- });
1106
- const withDefaultPagination = (args, { defaults: defaults2 = {}, maxLimit = -1 } = {}) => {
1107
- const defaultValues = merge(STRAPI_DEFAULTS, defaults2);
1108
- const usePagePagination = !isNil(args.page) || !isNil(args.pageSize);
1109
- const useOffsetPagination = !isNil(args.start) || !isNil(args.limit);
1110
- const ensureValidValues = pipe(ensureMinValues, ensureMaxValues(maxLimit));
1111
- if (!usePagePagination && !useOffsetPagination) {
1112
- return merge(args, ensureValidValues(defaultValues.offset));
1113
- }
1114
- if (usePagePagination && useOffsetPagination) {
1115
- throw new PaginationError("Cannot use both page & offset pagination in the same query");
1116
- }
1117
- const pagination2 = {
1118
- start: 0,
1119
- limit: 0
1120
- };
1121
- if (useOffsetPagination) {
1122
- const { start, limit } = merge(defaultValues.offset, args);
1123
- Object.assign(pagination2, { start, limit });
1124
- }
1125
- if (usePagePagination) {
1126
- const { page, pageSize } = merge(defaultValues.page, {
1127
- ...args,
1128
- pageSize: Math.max(1, args.pageSize ?? 0)
1129
- });
1130
- Object.assign(pagination2, {
1131
- start: (page - 1) * pageSize,
1132
- limit: pageSize
1133
- });
1134
- }
1135
- Object.assign(pagination2, withNoLimit(pagination2, maxLimit));
1136
- const replacePaginationAttributes = pipe(
1137
- // Remove pagination attributes
1138
- omit(paginationAttributes),
1139
- // Merge the object with the new pagination + ensure minimum & maximum values
1140
- merge(ensureValidValues(pagination2))
1141
- );
1142
- return replacePaginationAttributes(args);
1143
- };
1144
- const pagination = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1145
- __proto__: null,
1146
- withDefaultPagination
1147
- }, Symbol.toStringTag, { value: "Module" }));
1148
- function pipeAsync(...fns) {
519
+ function pipe(...fns) {
1149
520
  const [firstFn, ...fnRest] = fns;
1150
521
  return async (...args) => {
1151
522
  let res = await firstFn.apply(firstFn, args);
@@ -1155,34 +526,37 @@ function pipeAsync(...fns) {
1155
526
  return res;
1156
527
  };
1157
528
  }
1158
- const mapAsync = curry(pMap);
1159
- const reduceAsync = (mixedArray) => async (iteratee, initialValue) => {
1160
- let acc2 = initialValue;
529
+ const map = curry(pMap);
530
+ const reduce = (mixedArray) => async (iteratee, initialValue) => {
531
+ let acc = initialValue;
1161
532
  for (let i = 0; i < mixedArray.length; i += 1) {
1162
- acc2 = await iteratee(acc2, await mixedArray[i], i);
533
+ acc = await iteratee(acc, await mixedArray[i], i);
1163
534
  }
1164
- return acc2;
1165
- };
1166
- const forEachAsync = async (array, func, options) => {
1167
- await pMap(array, func, options);
535
+ return acc;
1168
536
  };
1169
- const visitor$7 = ({ key: key2, attribute }, { remove: remove2 }) => {
537
+ const async = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
538
+ __proto__: null,
539
+ map,
540
+ pipe,
541
+ reduce
542
+ }, Symbol.toStringTag, { value: "Module" }));
543
+ const visitor$8 = ({ key, attribute }, { remove: remove2 }) => {
1170
544
  if (attribute?.type === "password") {
1171
- remove2(key2);
545
+ remove2(key);
1172
546
  }
1173
547
  };
1174
- const visitor$6 = ({ schema, key: key2, attribute }, { remove: remove2 }) => {
548
+ const visitor$7 = ({ schema, key, attribute }, { remove: remove2 }) => {
1175
549
  if (!attribute) {
1176
550
  return;
1177
551
  }
1178
- const isPrivate = attribute.private === true || isPrivateAttribute(schema, key2);
552
+ const isPrivate = attribute.private === true || isPrivateAttribute(schema, key);
1179
553
  if (isPrivate) {
1180
- remove2(key2);
554
+ remove2(key);
1181
555
  }
1182
556
  };
1183
557
  const ACTIONS_TO_VERIFY$1 = ["find"];
1184
558
  const { CREATED_BY_ATTRIBUTE: CREATED_BY_ATTRIBUTE$1, UPDATED_BY_ATTRIBUTE: UPDATED_BY_ATTRIBUTE$1 } = constants$1;
1185
- const removeRestrictedRelations = (auth) => async ({ data, key: key2, attribute, schema }, { remove: remove2, set }) => {
559
+ const removeRestrictedRelations = (auth) => async ({ data, key, attribute, schema }, { remove: remove2, set }) => {
1186
560
  if (!attribute) {
1187
561
  return;
1188
562
  }
@@ -1192,7 +566,7 @@ const removeRestrictedRelations = (auth) => async ({ data, key: key2, attribute,
1192
566
  }
1193
567
  const handleMorphRelation = async () => {
1194
568
  const newMorphValue = [];
1195
- for (const element of data[key2]) {
569
+ for (const element of data[key]) {
1196
570
  const scopes = ACTIONS_TO_VERIFY$1.map((action) => `${element.__type}.${action}`);
1197
571
  const isAllowed = await hasAccessToSomeScopes$1(scopes, auth);
1198
572
  if (isAllowed) {
@@ -1200,19 +574,19 @@ const removeRestrictedRelations = (auth) => async ({ data, key: key2, attribute,
1200
574
  }
1201
575
  }
1202
576
  if (newMorphValue.length === 0) {
1203
- remove2(key2);
577
+ remove2(key);
1204
578
  } else {
1205
- set(key2, newMorphValue);
579
+ set(key, newMorphValue);
1206
580
  }
1207
581
  };
1208
582
  const handleRegularRelation = async () => {
1209
583
  const scopes = ACTIONS_TO_VERIFY$1.map((action) => `${attribute.target}.${action}`);
1210
584
  const isAllowed = await hasAccessToSomeScopes$1(scopes, auth);
1211
585
  if (!isAllowed) {
1212
- remove2(key2);
586
+ remove2(key);
1213
587
  }
1214
588
  };
1215
- const isCreatorRelation = [CREATED_BY_ATTRIBUTE$1, UPDATED_BY_ATTRIBUTE$1].includes(key2);
589
+ const isCreatorRelation = [CREATED_BY_ATTRIBUTE$1, UPDATED_BY_ATTRIBUTE$1].includes(key);
1216
590
  if (isMorphToRelationalAttribute(attribute)) {
1217
591
  await handleMorphRelation();
1218
592
  return;
@@ -1233,21 +607,21 @@ const hasAccessToSomeScopes$1 = async (scopes, auth) => {
1233
607
  }
1234
608
  return false;
1235
609
  };
1236
- const visitor$5 = ({ key: key2, attribute }, { remove: remove2 }) => {
610
+ const visitor$6 = ({ key, attribute }, { remove: remove2 }) => {
1237
611
  if (isMorphToRelationalAttribute(attribute)) {
1238
- remove2(key2);
612
+ remove2(key);
1239
613
  }
1240
614
  };
1241
- const visitor$4 = ({ key: key2, attribute }, { remove: remove2 }) => {
615
+ const visitor$5 = ({ key, attribute }, { remove: remove2 }) => {
1242
616
  if (isDynamicZoneAttribute(attribute)) {
1243
- remove2(key2);
617
+ remove2(key);
1244
618
  }
1245
619
  };
1246
- const removeDisallowedFields = (allowedFields = null) => ({ key: key2, path: { attribute: path } }, { remove: remove2 }) => {
620
+ const removeDisallowedFields = (allowedFields = null) => ({ key, path: { attribute: path } }, { remove: remove2 }) => {
1247
621
  if (allowedFields === null) {
1248
622
  return;
1249
623
  }
1250
- if (!(isArray(allowedFields) && allowedFields.every(isString$1))) {
624
+ if (!(isArray(allowedFields) && allowedFields.every(isString))) {
1251
625
  throw new TypeError(
1252
626
  `Expected array of strings for allowedFields but got "${typeof allowedFields}"`
1253
627
  );
@@ -1262,42 +636,52 @@ const removeDisallowedFields = (allowedFields = null) => ({ key: key2, path: { a
1262
636
  if (isPathAllowed) {
1263
637
  return;
1264
638
  }
1265
- remove2(key2);
639
+ remove2(key);
1266
640
  };
1267
641
  const getContainedPaths$1 = (path) => {
1268
642
  const parts = toPath(path);
1269
- return parts.reduce((acc2, value2, index2, list) => {
1270
- return [...acc2, list.slice(0, index2 + 1).join(".")];
643
+ return parts.reduce((acc, value, index2, list) => {
644
+ return [...acc, list.slice(0, index2 + 1).join(".")];
1271
645
  }, []);
1272
646
  };
1273
- const removeRestrictedFields = (restrictedFields = null) => ({ key: key2, path: { attribute: path } }, { remove: remove2 }) => {
647
+ const removeRestrictedFields = (restrictedFields = null) => ({ key, path: { attribute: path } }, { remove: remove2 }) => {
1274
648
  if (restrictedFields === null) {
1275
- remove2(key2);
649
+ remove2(key);
1276
650
  return;
1277
651
  }
1278
- if (!(isArray(restrictedFields) && restrictedFields.every(isString$1))) {
652
+ if (!(isArray(restrictedFields) && restrictedFields.every(isString))) {
1279
653
  throw new TypeError(
1280
654
  `Expected array of strings for restrictedFields but got "${typeof restrictedFields}"`
1281
655
  );
1282
656
  }
1283
657
  if (restrictedFields.includes(path)) {
1284
- remove2(key2);
658
+ remove2(key);
1285
659
  return;
1286
660
  }
1287
661
  const isRestrictedNested = restrictedFields.some(
1288
662
  (allowedPath) => path?.toString().startsWith(`${allowedPath}.`)
1289
663
  );
1290
664
  if (isRestrictedNested) {
1291
- remove2(key2);
665
+ remove2(key);
666
+ }
667
+ };
668
+ const visitor$4 = ({ schema, key, value }, { set }) => {
669
+ if (key === "" && value === "*") {
670
+ const { attributes } = schema;
671
+ const newPopulateQuery = Object.entries(attributes).filter(
672
+ ([, attribute]) => ["relation", "component", "media", "dynamiczone"].includes(attribute.type)
673
+ ).reduce((acc, [key2]) => ({ ...acc, [key2]: true }), {});
674
+ set("", newPopulateQuery);
1292
675
  }
1293
676
  };
1294
677
  const visitors$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1295
678
  __proto__: null,
679
+ expandWildcardPopulate: visitor$4,
1296
680
  removeDisallowedFields,
1297
- removeDynamicZones: visitor$4,
1298
- removeMorphToRelations: visitor$5,
1299
- removePassword: visitor$7,
1300
- removePrivate: visitor$6,
681
+ removeDynamicZones: visitor$5,
682
+ removeMorphToRelations: visitor$6,
683
+ removePassword: visitor$8,
684
+ removePrivate: visitor$7,
1301
685
  removeRestrictedFields,
1302
686
  removeRestrictedRelations
1303
687
  }, Symbol.toStringTag, { value: "Module" }));
@@ -1334,85 +718,85 @@ const traverseEntity = async (visitor2, options, entity) => {
1334
718
  const visitorUtils = createVisitorUtils({ data: copy });
1335
719
  const keys = Object.keys(copy);
1336
720
  for (let i = 0; i < keys.length; i += 1) {
1337
- const key2 = keys[i];
1338
- const attribute = schema.attributes[key2];
721
+ const key = keys[i];
722
+ const attribute = schema.attributes[key];
1339
723
  if (isNil(attribute)) {
1340
724
  continue;
1341
725
  }
1342
726
  const newPath = { ...path };
1343
- newPath.raw = isNil(path.raw) ? key2 : `${path.raw}.${key2}`;
727
+ newPath.raw = isNil(path.raw) ? key : `${path.raw}.${key}`;
1344
728
  if (!isNil(attribute)) {
1345
- newPath.attribute = isNil(path.attribute) ? key2 : `${path.attribute}.${key2}`;
729
+ newPath.attribute = isNil(path.attribute) ? key : `${path.attribute}.${key}`;
1346
730
  }
1347
731
  const visitorOptions = {
1348
732
  data: copy,
1349
733
  schema,
1350
- key: key2,
1351
- value: copy[key2],
734
+ key,
735
+ value: copy[key],
1352
736
  attribute,
1353
737
  path: newPath
1354
738
  };
1355
739
  await visitor2(visitorOptions, visitorUtils);
1356
- const value2 = copy[key2];
1357
- if (isNil(value2)) {
740
+ const value = copy[key];
741
+ if (isNil(value)) {
1358
742
  continue;
1359
743
  }
1360
744
  if (isRelationalAttribute(attribute)) {
1361
745
  const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
1362
746
  const method = isMorphRelation ? traverseMorphRelationTarget : traverseRelationTarget(strapi.getModel(attribute.target));
1363
- if (isArray(value2)) {
1364
- const res = new Array(value2.length);
1365
- for (let i2 = 0; i2 < value2.length; i2 += 1) {
1366
- res[i2] = await method(visitor2, newPath, value2[i2]);
747
+ if (isArray(value)) {
748
+ const res = new Array(value.length);
749
+ for (let i2 = 0; i2 < value.length; i2 += 1) {
750
+ res[i2] = await method(visitor2, newPath, value[i2]);
1367
751
  }
1368
- copy[key2] = res;
752
+ copy[key] = res;
1369
753
  } else {
1370
- copy[key2] = await method(visitor2, newPath, value2);
754
+ copy[key] = await method(visitor2, newPath, value);
1371
755
  }
1372
756
  continue;
1373
757
  }
1374
758
  if (isMediaAttribute(attribute)) {
1375
- if (isArray(value2)) {
1376
- const res = new Array(value2.length);
1377
- for (let i2 = 0; i2 < value2.length; i2 += 1) {
1378
- res[i2] = await traverseMediaTarget(visitor2, newPath, value2[i2]);
759
+ if (isArray(value)) {
760
+ const res = new Array(value.length);
761
+ for (let i2 = 0; i2 < value.length; i2 += 1) {
762
+ res[i2] = await traverseMediaTarget(visitor2, newPath, value[i2]);
1379
763
  }
1380
- copy[key2] = res;
764
+ copy[key] = res;
1381
765
  } else {
1382
- copy[key2] = await traverseMediaTarget(visitor2, newPath, value2);
766
+ copy[key] = await traverseMediaTarget(visitor2, newPath, value);
1383
767
  }
1384
768
  continue;
1385
769
  }
1386
770
  if (attribute.type === "component") {
1387
771
  const targetSchema = strapi.getModel(attribute.component);
1388
- if (isArray(value2)) {
1389
- const res = new Array(value2.length);
1390
- for (let i2 = 0; i2 < value2.length; i2 += 1) {
1391
- res[i2] = await traverseComponent(visitor2, newPath, targetSchema, value2[i2]);
772
+ if (isArray(value)) {
773
+ const res = new Array(value.length);
774
+ for (let i2 = 0; i2 < value.length; i2 += 1) {
775
+ res[i2] = await traverseComponent(visitor2, newPath, targetSchema, value[i2]);
1392
776
  }
1393
- copy[key2] = res;
777
+ copy[key] = res;
1394
778
  } else {
1395
- copy[key2] = await traverseComponent(visitor2, newPath, targetSchema, value2);
779
+ copy[key] = await traverseComponent(visitor2, newPath, targetSchema, value);
1396
780
  }
1397
781
  continue;
1398
782
  }
1399
- if (attribute.type === "dynamiczone" && isArray(value2)) {
1400
- const res = new Array(value2.length);
1401
- for (let i2 = 0; i2 < value2.length; i2 += 1) {
1402
- res[i2] = await visitDynamicZoneEntry(visitor2, newPath, value2[i2]);
783
+ if (attribute.type === "dynamiczone" && isArray(value)) {
784
+ const res = new Array(value.length);
785
+ for (let i2 = 0; i2 < value.length; i2 += 1) {
786
+ res[i2] = await visitDynamicZoneEntry(visitor2, newPath, value[i2]);
1403
787
  }
1404
- copy[key2] = res;
788
+ copy[key] = res;
1405
789
  continue;
1406
790
  }
1407
791
  }
1408
792
  return copy;
1409
793
  };
1410
794
  const createVisitorUtils = ({ data }) => ({
1411
- remove(key2) {
1412
- delete data[key2];
795
+ remove(key) {
796
+ delete data[key];
1413
797
  },
1414
- set(key2, value2) {
1415
- data[key2] = value2;
798
+ set(key, value) {
799
+ data[key] = value;
1416
800
  }
1417
801
  });
1418
802
  const traverseEntity$1 = curry(traverseEntity);
@@ -1441,37 +825,37 @@ const traverseFactory = () => {
1441
825
  }
1442
826
  let out = utils2.transform(data);
1443
827
  const keys = utils2.keys(out);
1444
- for (const key2 of keys) {
1445
- const attribute = schema?.attributes?.[key2] ?? // FIX: Needed to not break existing behavior on the API.
828
+ for (const key of keys) {
829
+ const attribute = schema?.attributes?.[key] ?? // FIX: Needed to not break existing behavior on the API.
1446
830
  // It looks for the attribute in the DB metadata when the key is in snake_case
1447
- schema?.attributes?.[strapi.db.metadata.get(schema?.uid).columnToAttribute[key2]];
831
+ schema?.attributes?.[strapi.db.metadata.get(schema?.uid).columnToAttribute[key]];
1448
832
  const newPath = { ...path };
1449
- newPath.raw = isNil(path.raw) ? key2 : `${path.raw}.${key2}`;
833
+ newPath.raw = isNil(path.raw) ? key : `${path.raw}.${key}`;
1450
834
  if (!isNil(attribute)) {
1451
- newPath.attribute = isNil(path.attribute) ? key2 : `${path.attribute}.${key2}`;
835
+ newPath.attribute = isNil(path.attribute) ? key : `${path.attribute}.${key}`;
1452
836
  }
1453
837
  const visitorOptions = {
1454
- key: key2,
1455
- value: utils2.get(key2, out),
838
+ key,
839
+ value: utils2.get(key, out),
1456
840
  attribute,
1457
841
  schema,
1458
842
  path: newPath,
1459
843
  data: out
1460
844
  };
1461
845
  const transformUtils = {
1462
- remove(key22) {
1463
- out = utils2.remove(key22, out);
846
+ remove(key2) {
847
+ out = utils2.remove(key2, out);
1464
848
  },
1465
- set(key22, value22) {
1466
- out = utils2.set(key22, value22, out);
849
+ set(key2, value2) {
850
+ out = utils2.set(key2, value2, out);
1467
851
  },
1468
852
  recurse: traverse
1469
853
  };
1470
854
  await visitor2(visitorOptions, pick(["remove", "set"], transformUtils));
1471
- const value2 = utils2.get(key2, out);
855
+ const value = utils2.get(key, out);
1472
856
  const createContext = () => ({
1473
- key: key2,
1474
- value: value2,
857
+ key,
858
+ value,
1475
859
  attribute,
1476
860
  schema,
1477
861
  path: newPath,
@@ -1530,7 +914,7 @@ const traverseFactory = () => {
1530
914
  }
1531
915
  };
1532
916
  };
1533
- const isObj$2 = (value2) => isObject(value2);
917
+ const isObj$2 = (value) => isObject(value);
1534
918
  const filters = traverseFactory().intercept(
1535
919
  // Intercept filters arrays and apply the traversal to each one individually
1536
920
  isArray,
@@ -1551,50 +935,50 @@ const filters = traverseFactory().intercept(
1551
935
  }
1552
936
  ).parse(isObj$2, () => ({
1553
937
  transform: cloneDeep,
1554
- remove(key2, data) {
1555
- return omit(key2, data);
938
+ remove(key, data) {
939
+ return omit(key, data);
1556
940
  },
1557
- set(key2, value2, data) {
1558
- return { ...data, [key2]: value2 };
941
+ set(key, value, data) {
942
+ return { ...data, [key]: value };
1559
943
  },
1560
944
  keys(data) {
1561
945
  return Object.keys(data);
1562
946
  },
1563
- get(key2, data) {
1564
- return data[key2];
947
+ get(key, data) {
948
+ return data[key];
1565
949
  }
1566
- })).ignore(({ value: value2 }) => isNil(value2)).on(
950
+ })).ignore(({ value }) => isNil(value)).on(
1567
951
  ({ attribute }) => isNil(attribute),
1568
- async ({ key: key2, visitor: visitor2, path, value: value2, schema }, { set, recurse }) => {
1569
- set(key2, await recurse(visitor2, { schema, path }, value2));
952
+ async ({ key, visitor: visitor2, path, value, schema }, { set, recurse }) => {
953
+ set(key, await recurse(visitor2, { schema, path }, value));
1570
954
  }
1571
- ).onRelation(async ({ key: key2, attribute, visitor: visitor2, path, value: value2 }, { set, recurse }) => {
955
+ ).onRelation(async ({ key, attribute, visitor: visitor2, path, value }, { set, recurse }) => {
1572
956
  const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
1573
957
  if (isMorphRelation) {
1574
958
  return;
1575
959
  }
1576
960
  const targetSchemaUID = attribute.target;
1577
961
  const targetSchema = strapi.getModel(targetSchemaUID);
1578
- const newValue = await recurse(visitor2, { schema: targetSchema, path }, value2);
1579
- set(key2, newValue);
1580
- }).onComponent(async ({ key: key2, attribute, visitor: visitor2, path, value: value2 }, { set, recurse }) => {
962
+ const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
963
+ set(key, newValue);
964
+ }).onComponent(async ({ key, attribute, visitor: visitor2, path, value }, { set, recurse }) => {
1581
965
  const targetSchema = strapi.getModel(attribute.component);
1582
- const newValue = await recurse(visitor2, { schema: targetSchema, path }, value2);
1583
- set(key2, newValue);
1584
- }).onMedia(async ({ key: key2, visitor: visitor2, path, value: value2 }, { set, recurse }) => {
966
+ const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
967
+ set(key, newValue);
968
+ }).onMedia(async ({ key, visitor: visitor2, path, value }, { set, recurse }) => {
1585
969
  const targetSchemaUID = "plugin::upload.file";
1586
970
  const targetSchema = strapi.getModel(targetSchemaUID);
1587
- const newValue = await recurse(visitor2, { schema: targetSchema, path }, value2);
1588
- set(key2, newValue);
971
+ const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
972
+ set(key, newValue);
1589
973
  });
1590
974
  const traverseQueryFilters = curry(filters.traverse);
1591
975
  const ORDERS = { asc: "asc", desc: "desc" };
1592
976
  const ORDER_VALUES = Object.values(ORDERS);
1593
- const isSortOrder = (value2) => ORDER_VALUES.includes(value2.toLowerCase());
1594
- const isStringArray$3 = (value2) => Array.isArray(value2) && value2.every(isString$1);
1595
- const isObjectArray = (value2) => Array.isArray(value2) && value2.every(isObject);
1596
- const isNestedSorts = (value2) => isString$1(value2) && value2.split(",").length > 1;
1597
- const isObj$1 = (value2) => isObject(value2);
977
+ const isSortOrder = (value) => ORDER_VALUES.includes(value.toLowerCase());
978
+ const isStringArray$3 = (value) => Array.isArray(value) && value.every(isString);
979
+ const isObjectArray = (value) => Array.isArray(value) && value.every(isObject);
980
+ const isNestedSorts = (value) => isString(value) && value.split(",").length > 1;
981
+ const isObj$1 = (value) => isObject(value);
1598
982
  const sort = traverseFactory().intercept(
1599
983
  // String with chained sorts (foo,bar,foobar) => split, map(recurse), then recompose
1600
984
  isNestedSorts,
@@ -1619,221 +1003,240 @@ const sort = traverseFactory().intercept(
1619
1003
  (res) => res.filter((nestedSort) => !isEmpty(nestedSort))
1620
1004
  );
1621
1005
  }
1622
- ).parse(isString$1, () => {
1623
- const tokenize = pipe(split("."), map(split(":")), flatten);
1006
+ ).parse(isString, () => {
1007
+ const tokenize = pipe$1(split("."), map$1(split(":")), flatten);
1624
1008
  const recompose = (parts) => {
1625
1009
  if (parts.length === 0) {
1626
1010
  return void 0;
1627
1011
  }
1628
- return parts.reduce((acc2, part) => {
1012
+ return parts.reduce((acc, part) => {
1629
1013
  if (isEmpty(part)) {
1630
- return acc2;
1014
+ return acc;
1631
1015
  }
1632
- if (acc2 === "") {
1016
+ if (acc === "") {
1633
1017
  return part;
1634
1018
  }
1635
- return isSortOrder(part) ? `${acc2}:${part}` : `${acc2}.${part}`;
1019
+ return isSortOrder(part) ? `${acc}:${part}` : `${acc}.${part}`;
1636
1020
  }, "");
1637
1021
  };
1638
1022
  return {
1639
1023
  transform: trim,
1640
- remove(key2, data) {
1024
+ remove(key, data) {
1641
1025
  const [root] = tokenize(data);
1642
- return root === key2 ? void 0 : data;
1026
+ return root === key ? void 0 : data;
1643
1027
  },
1644
- set(key2, value2, data) {
1028
+ set(key, value, data) {
1645
1029
  const [root] = tokenize(data);
1646
- if (root !== key2) {
1030
+ if (root !== key) {
1647
1031
  return data;
1648
1032
  }
1649
- return isNil(value2) ? root : `${root}.${value2}`;
1033
+ return isNil(value) ? root : `${root}.${value}`;
1650
1034
  },
1651
1035
  keys(data) {
1652
1036
  const v = first(tokenize(data));
1653
1037
  return v ? [v] : [];
1654
1038
  },
1655
- get(key2, data) {
1039
+ get(key, data) {
1656
1040
  const [root, ...rest] = tokenize(data);
1657
- return key2 === root ? recompose(rest) : void 0;
1041
+ return key === root ? recompose(rest) : void 0;
1658
1042
  }
1659
1043
  };
1660
1044
  }).parse(isObj$1, () => ({
1661
1045
  transform: cloneDeep,
1662
- remove(key2, data) {
1663
- const { [key2]: ignored, ...rest } = data;
1046
+ remove(key, data) {
1047
+ const { [key]: ignored, ...rest } = data;
1664
1048
  return rest;
1665
1049
  },
1666
- set(key2, value2, data) {
1667
- return { ...data, [key2]: value2 };
1050
+ set(key, value, data) {
1051
+ return { ...data, [key]: value };
1668
1052
  },
1669
1053
  keys(data) {
1670
1054
  return Object.keys(data);
1671
1055
  },
1672
- get(key2, data) {
1673
- return data[key2];
1056
+ get(key, data) {
1057
+ return data[key];
1674
1058
  }
1675
- })).onRelation(async ({ key: key2, value: value2, attribute, visitor: visitor2, path }, { set, recurse }) => {
1059
+ })).onRelation(async ({ key, value, attribute, visitor: visitor2, path }, { set, recurse }) => {
1676
1060
  const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
1677
1061
  if (isMorphRelation) {
1678
1062
  return;
1679
1063
  }
1680
1064
  const targetSchemaUID = attribute.target;
1681
1065
  const targetSchema = strapi.getModel(targetSchemaUID);
1682
- const newValue = await recurse(visitor2, { schema: targetSchema, path }, value2);
1683
- set(key2, newValue);
1684
- }).onMedia(async ({ key: key2, path, visitor: visitor2, value: value2 }, { recurse, set }) => {
1066
+ const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
1067
+ set(key, newValue);
1068
+ }).onMedia(async ({ key, path, visitor: visitor2, value }, { recurse, set }) => {
1685
1069
  const targetSchemaUID = "plugin::upload.file";
1686
1070
  const targetSchema = strapi.getModel(targetSchemaUID);
1687
- const newValue = await recurse(visitor2, { schema: targetSchema, path }, value2);
1688
- set(key2, newValue);
1689
- }).onComponent(async ({ key: key2, value: value2, visitor: visitor2, path, attribute }, { recurse, set }) => {
1071
+ const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
1072
+ set(key, newValue);
1073
+ }).onComponent(async ({ key, value, visitor: visitor2, path, attribute }, { recurse, set }) => {
1690
1074
  const targetSchema = strapi.getModel(attribute.component);
1691
- const newValue = await recurse(visitor2, { schema: targetSchema, path }, value2);
1692
- set(key2, newValue);
1075
+ const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
1076
+ set(key, newValue);
1693
1077
  });
1694
1078
  const traverseQuerySort = curry(sort.traverse);
1695
1079
  const isKeyword = (keyword) => {
1696
- return ({ key: key2, attribute }) => {
1697
- return !attribute && keyword === key2;
1080
+ return ({ key, attribute }) => {
1081
+ return !attribute && keyword === key;
1698
1082
  };
1699
1083
  };
1700
- const isStringArray$2 = (value2) => isArray(value2) && value2.every(isString$1);
1701
- const isWildCardConstant = (value2) => value2 === "*";
1702
- const isObj = (value2) => isObject(value2);
1084
+ const isStringArray$2 = (value) => isArray(value) && value.every(isString);
1085
+ const isObj = (value) => isObject(value);
1703
1086
  const populate = traverseFactory().intercept(isStringArray$2, async (visitor2, options, populate2, { recurse }) => {
1704
1087
  const visitedPopulate = await Promise.all(
1705
1088
  populate2.map((nestedPopulate) => recurse(visitor2, options, nestedPopulate))
1706
1089
  );
1707
1090
  return visitedPopulate.filter((item) => !isNil(item));
1708
- }).intercept(isWildCardConstant, (visitor2, options, _data, { recurse }) => {
1709
- const attributes = options.schema?.attributes;
1710
- if (!attributes) {
1711
- return "*";
1712
- }
1713
- const parsedPopulate = Object.entries(attributes).filter(([, value2]) => ["relation", "component", "dynamiczone", "media"].includes(value2.type)).reduce((acc2, [key2]) => ({ ...acc2, [key2]: true }), {});
1714
- return recurse(visitor2, options, parsedPopulate);
1715
- }).parse(isString$1, () => {
1091
+ }).parse(
1092
+ (value) => value === "*",
1093
+ () => ({
1094
+ /**
1095
+ * Since value is '*', we don't need to transform it
1096
+ */
1097
+ transform: identity,
1098
+ /**
1099
+ * '*' isn't a key/value structure, so regardless
1100
+ * of the given key, it returns the data ('*')
1101
+ */
1102
+ get: (_key, data) => data,
1103
+ /**
1104
+ * '*' isn't a key/value structure, so regardless
1105
+ * of the given `key`, use `value` as the new `data`
1106
+ */
1107
+ set: (_key, value) => value,
1108
+ /**
1109
+ * '*' isn't a key/value structure, but we need to simulate at least one to enable
1110
+ * the data traversal. We're using '' since it represents a falsy string value
1111
+ */
1112
+ keys: constant([""]),
1113
+ /**
1114
+ * Removing '*' means setting it to undefined, regardless of the given key
1115
+ */
1116
+ remove: constant(void 0)
1117
+ })
1118
+ ).parse(isString, () => {
1716
1119
  const tokenize = split(".");
1717
1120
  const recompose = join(".");
1718
1121
  return {
1719
1122
  transform: trim,
1720
- remove(key2, data) {
1123
+ remove(key, data) {
1721
1124
  const [root] = tokenize(data);
1722
- return root === key2 ? void 0 : data;
1125
+ return root === key ? void 0 : data;
1723
1126
  },
1724
- set(key2, value2, data) {
1127
+ set(key, value, data) {
1725
1128
  const [root] = tokenize(data);
1726
- if (root !== key2) {
1129
+ if (root !== key) {
1727
1130
  return data;
1728
1131
  }
1729
- return isNil(value2) || isEmpty(value2) ? root : `${root}.${value2}`;
1132
+ return isNil(value) || isEmpty(value) ? root : `${root}.${value}`;
1730
1133
  },
1731
1134
  keys(data) {
1732
1135
  const v = first(tokenize(data));
1733
1136
  return v ? [v] : [];
1734
1137
  },
1735
- get(key2, data) {
1138
+ get(key, data) {
1736
1139
  const [root, ...rest] = tokenize(data);
1737
- return key2 === root ? recompose(rest) : void 0;
1140
+ return key === root ? recompose(rest) : void 0;
1738
1141
  }
1739
1142
  };
1740
1143
  }).parse(isObj, () => ({
1741
1144
  transform: cloneDeep,
1742
- remove(key2, data) {
1743
- const { [key2]: ignored, ...rest } = data;
1145
+ remove(key, data) {
1146
+ const { [key]: ignored, ...rest } = data;
1744
1147
  return rest;
1745
1148
  },
1746
- set(key2, value2, data) {
1747
- return { ...data, [key2]: value2 };
1149
+ set(key, value, data) {
1150
+ return { ...data, [key]: value };
1748
1151
  },
1749
1152
  keys(data) {
1750
1153
  return Object.keys(data);
1751
1154
  },
1752
- get(key2, data) {
1753
- return data[key2];
1155
+ get(key, data) {
1156
+ return data[key];
1754
1157
  }
1755
- })).ignore(({ key: key2, attribute }) => {
1756
- return ["sort", "filters", "fields"].includes(key2) && !attribute;
1158
+ })).ignore(({ key, attribute }) => {
1159
+ return ["sort", "filters", "fields"].includes(key) && !attribute;
1757
1160
  }).on(
1758
1161
  // Handle recursion on populate."populate"
1759
1162
  isKeyword("populate"),
1760
- async ({ key: key2, visitor: visitor2, path, value: value2, schema }, { set, recurse }) => {
1761
- const newValue = await recurse(visitor2, { schema, path }, value2);
1762
- set(key2, newValue);
1163
+ async ({ key, visitor: visitor2, path, value, schema }, { set, recurse }) => {
1164
+ const newValue = await recurse(visitor2, { schema, path }, value);
1165
+ set(key, newValue);
1763
1166
  }
1764
- ).on(isKeyword("on"), async ({ key: key2, visitor: visitor2, path, value: value2 }, { set, recurse }) => {
1167
+ ).on(isKeyword("on"), async ({ key, visitor: visitor2, path, value }, { set, recurse }) => {
1765
1168
  const newOn = {};
1766
- if (!isObj(value2)) {
1169
+ if (!isObj(value)) {
1767
1170
  return;
1768
1171
  }
1769
- for (const [uid, subPopulate] of Object.entries(value2)) {
1172
+ for (const [uid, subPopulate] of Object.entries(value)) {
1770
1173
  const model = strapi.getModel(uid);
1771
1174
  const newPath = { ...path, raw: `${path.raw}[${uid}]` };
1772
1175
  newOn[uid] = await recurse(visitor2, { schema: model, path: newPath }, subPopulate);
1773
1176
  }
1774
- set(key2, newOn);
1775
- }).onRelation(async ({ key: key2, value: value2, attribute, visitor: visitor2, path, schema }, { set, recurse }) => {
1776
- if (isNil(value2)) {
1177
+ set(key, newOn);
1178
+ }).onRelation(async ({ key, value, attribute, visitor: visitor2, path, schema }, { set, recurse }) => {
1179
+ if (isNil(value)) {
1777
1180
  return;
1778
1181
  }
1779
1182
  if (isMorphToRelationalAttribute(attribute)) {
1780
- if (!isObject(value2) || !("on" in value2 && isObject(value2?.on))) {
1183
+ if (!isObject(value) || !("on" in value && isObject(value?.on))) {
1781
1184
  return;
1782
1185
  }
1783
- const newValue2 = await recurse(visitor2, { schema, path }, { on: value2?.on });
1784
- set(key2, { on: newValue2 });
1186
+ const newValue2 = await recurse(visitor2, { schema, path }, { on: value?.on });
1187
+ set(key, { on: newValue2 });
1785
1188
  }
1786
1189
  const targetSchemaUID = attribute.target;
1787
1190
  const targetSchema = strapi.getModel(targetSchemaUID);
1788
- const newValue = await recurse(visitor2, { schema: targetSchema, path }, value2);
1789
- set(key2, newValue);
1790
- }).onMedia(async ({ key: key2, path, visitor: visitor2, value: value2 }, { recurse, set }) => {
1791
- if (isNil(value2)) {
1191
+ const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
1192
+ set(key, newValue);
1193
+ }).onMedia(async ({ key, path, visitor: visitor2, value }, { recurse, set }) => {
1194
+ if (isNil(value)) {
1792
1195
  return;
1793
1196
  }
1794
1197
  const targetSchemaUID = "plugin::upload.file";
1795
1198
  const targetSchema = strapi.getModel(targetSchemaUID);
1796
- const newValue = await recurse(visitor2, { schema: targetSchema, path }, value2);
1797
- set(key2, newValue);
1798
- }).onComponent(async ({ key: key2, value: value2, visitor: visitor2, path, attribute }, { recurse, set }) => {
1799
- if (isNil(value2)) {
1199
+ const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
1200
+ set(key, newValue);
1201
+ }).onComponent(async ({ key, value, visitor: visitor2, path, attribute }, { recurse, set }) => {
1202
+ if (isNil(value)) {
1800
1203
  return;
1801
1204
  }
1802
1205
  const targetSchema = strapi.getModel(attribute.component);
1803
- const newValue = await recurse(visitor2, { schema: targetSchema, path }, value2);
1804
- set(key2, newValue);
1805
- }).onDynamicZone(async ({ key: key2, value: value2, attribute, schema, visitor: visitor2, path }, { set, recurse }) => {
1806
- if (isNil(value2)) {
1206
+ const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
1207
+ set(key, newValue);
1208
+ }).onDynamicZone(async ({ key, value, attribute, schema, visitor: visitor2, path }, { set, recurse }) => {
1209
+ if (isNil(value)) {
1807
1210
  return;
1808
1211
  }
1809
- if (isObject(value2)) {
1212
+ if (isObject(value)) {
1810
1213
  const { components } = attribute;
1811
1214
  const newValue = {};
1812
- let newProperties = omit("on", value2);
1215
+ let newProperties = omit("on", value);
1813
1216
  for (const componentUID of components) {
1814
1217
  const componentSchema = strapi.getModel(componentUID);
1815
- const properties = await recurse(visitor2, { schema: componentSchema, path }, value2);
1218
+ const properties = await recurse(visitor2, { schema: componentSchema, path }, value);
1816
1219
  newProperties = merge(newProperties, properties);
1817
1220
  }
1818
1221
  Object.assign(newValue, newProperties);
1819
- if ("on" in value2 && value2.on) {
1820
- const newOn = await recurse(visitor2, { schema, path }, { on: value2.on });
1222
+ if ("on" in value && value.on) {
1223
+ const newOn = await recurse(visitor2, { schema, path }, { on: value.on });
1821
1224
  Object.assign(newValue, newOn);
1822
1225
  }
1823
- set(key2, newValue);
1226
+ set(key, newValue);
1824
1227
  } else {
1825
- const newValue = await recurse(visitor2, { schema, path }, value2);
1826
- set(key2, newValue);
1228
+ const newValue = await recurse(visitor2, { schema, path }, value);
1229
+ set(key, newValue);
1827
1230
  }
1828
1231
  });
1829
1232
  const traverseQueryPopulate = curry(populate.traverse);
1830
- const isStringArray$1 = (value2) => isArray(value2) && value2.every(isString$1);
1233
+ const isStringArray$1 = (value) => isArray(value) && value.every(isString);
1831
1234
  const fields = traverseFactory().intercept(isStringArray$1, async (visitor2, options, fields2, { recurse }) => {
1832
1235
  return Promise.all(fields2.map((field) => recurse(visitor2, options, field)));
1833
- }).intercept((value2) => eq("*", value2), constant("*")).parse(isString$1, () => ({
1236
+ }).intercept((value) => eq("*", value), constant("*")).parse(isString, () => ({
1834
1237
  transform: trim,
1835
- remove(key2, data) {
1836
- return data === key2 ? void 0 : data;
1238
+ remove(key, data) {
1239
+ return data === key ? void 0 : data;
1837
1240
  },
1838
1241
  set(_key, _value, data) {
1839
1242
  return data;
@@ -1841,8 +1244,8 @@ const fields = traverseFactory().intercept(isStringArray$1, async (visitor2, opt
1841
1244
  keys(data) {
1842
1245
  return [data];
1843
1246
  },
1844
- get(key2, data) {
1845
- return key2 === data ? data : void 0;
1247
+ get(key, data) {
1248
+ return key === data ? data : void 0;
1846
1249
  }
1847
1250
  }));
1848
1251
  const traverseQueryFields = curry(fields.traverse);
@@ -1901,31 +1304,32 @@ const OPERATORS = {
1901
1304
  array: ARRAY_OPERATORS
1902
1305
  };
1903
1306
  const OPERATORS_LOWERCASE = Object.fromEntries(
1904
- Object.entries(OPERATORS).map(([key2, values]) => [
1905
- key2,
1906
- values.map((value2) => value2.toLowerCase())
1307
+ Object.entries(OPERATORS).map(([key, values]) => [
1308
+ key,
1309
+ values.map((value) => value.toLowerCase())
1907
1310
  ])
1908
1311
  );
1909
- const isObjKey = (key2, obj2) => {
1910
- return key2 in obj2;
1312
+ const isObjKey = (key, obj) => {
1313
+ return key in obj;
1911
1314
  };
1912
- const isOperatorOfType = (type, key2, ignoreCase = false) => {
1315
+ const isOperatorOfType = (type, key, ignoreCase = false) => {
1913
1316
  if (ignoreCase) {
1914
- return OPERATORS_LOWERCASE[type]?.includes(key2.toLowerCase()) ?? false;
1317
+ return OPERATORS_LOWERCASE[type]?.includes(key.toLowerCase()) ?? false;
1915
1318
  }
1916
1319
  if (isObjKey(type, OPERATORS)) {
1917
- return OPERATORS[type]?.includes(key2) ?? false;
1320
+ return OPERATORS[type]?.includes(key) ?? false;
1918
1321
  }
1919
1322
  return false;
1920
1323
  };
1921
- const isOperator = (key2, ignoreCase = false) => {
1922
- return Object.keys(OPERATORS).some((type) => isOperatorOfType(type, key2, ignoreCase));
1324
+ const isOperator = (key, ignoreCase = false) => {
1325
+ return Object.keys(OPERATORS).some((type) => isOperatorOfType(type, key, ignoreCase));
1923
1326
  };
1327
+ const { ID_ATTRIBUTE: ID_ATTRIBUTE$3, DOC_ID_ATTRIBUTE: DOC_ID_ATTRIBUTE$3 } = constants$1;
1924
1328
  const sanitizePasswords = (schema) => async (entity) => {
1925
1329
  if (!schema) {
1926
1330
  throw new Error("Missing schema in sanitizePasswords");
1927
1331
  }
1928
- return traverseEntity$1(visitor$7, { schema }, entity);
1332
+ return traverseEntity$1(visitor$8, { schema }, entity);
1929
1333
  };
1930
1334
  const defaultSanitizeOutput = async (schema, entity) => {
1931
1335
  if (!schema) {
@@ -1933,8 +1337,8 @@ const defaultSanitizeOutput = async (schema, entity) => {
1933
1337
  }
1934
1338
  return traverseEntity$1(
1935
1339
  (...args) => {
1340
+ visitor$8(...args);
1936
1341
  visitor$7(...args);
1937
- visitor$6(...args);
1938
1342
  },
1939
1343
  { schema },
1940
1344
  entity
@@ -1944,33 +1348,33 @@ const defaultSanitizeFilters = curry((schema, filters2) => {
1944
1348
  if (!schema) {
1945
1349
  throw new Error("Missing schema in defaultSanitizeFilters");
1946
1350
  }
1947
- return pipeAsync(
1351
+ return pipe(
1948
1352
  // Remove keys that are not attributes or valid operators
1949
1353
  traverseQueryFilters(
1950
- ({ key: key2, attribute }, { remove: remove2 }) => {
1354
+ ({ key, attribute }, { remove: remove2 }) => {
1951
1355
  const isAttribute = !!attribute;
1952
- if (key2 === "id") {
1356
+ if ([ID_ATTRIBUTE$3, DOC_ID_ATTRIBUTE$3].includes(key)) {
1953
1357
  return;
1954
1358
  }
1955
- if (!isAttribute && !isOperator(key2)) {
1956
- remove2(key2);
1359
+ if (!isAttribute && !isOperator(key)) {
1360
+ remove2(key);
1957
1361
  }
1958
1362
  },
1959
1363
  { schema }
1960
1364
  ),
1961
1365
  // Remove dynamic zones from filters
1962
- traverseQueryFilters(visitor$4, { schema }),
1963
- // Remove morpTo relations from filters
1964
1366
  traverseQueryFilters(visitor$5, { schema }),
1367
+ // Remove morpTo relations from filters
1368
+ traverseQueryFilters(visitor$6, { schema }),
1965
1369
  // Remove passwords from filters
1966
- traverseQueryFilters(visitor$7, { schema }),
1370
+ traverseQueryFilters(visitor$8, { schema }),
1967
1371
  // Remove private from filters
1968
- traverseQueryFilters(visitor$6, { schema }),
1372
+ traverseQueryFilters(visitor$7, { schema }),
1969
1373
  // Remove empty objects
1970
1374
  traverseQueryFilters(
1971
- ({ key: key2, value: value2 }, { remove: remove2 }) => {
1972
- if (isObject(value2) && isEmpty(value2)) {
1973
- remove2(key2);
1375
+ ({ key, value }, { remove: remove2 }) => {
1376
+ if (isObject(value) && isEmpty(value)) {
1377
+ remove2(key);
1974
1378
  }
1975
1379
  },
1976
1380
  { schema }
@@ -1981,35 +1385,35 @@ const defaultSanitizeSort = curry((schema, sort2) => {
1981
1385
  if (!schema) {
1982
1386
  throw new Error("Missing schema in defaultSanitizeSort");
1983
1387
  }
1984
- return pipeAsync(
1388
+ return pipe(
1985
1389
  // Remove non attribute keys
1986
1390
  traverseQuerySort(
1987
- ({ key: key2, attribute }, { remove: remove2 }) => {
1988
- if (key2 === "id") {
1391
+ ({ key, attribute }, { remove: remove2 }) => {
1392
+ if ([ID_ATTRIBUTE$3, DOC_ID_ATTRIBUTE$3].includes(key)) {
1989
1393
  return;
1990
1394
  }
1991
1395
  if (!attribute) {
1992
- remove2(key2);
1396
+ remove2(key);
1993
1397
  }
1994
1398
  },
1995
1399
  { schema }
1996
1400
  ),
1997
1401
  // Remove dynamic zones from sort
1998
- traverseQuerySort(visitor$4, { schema }),
1999
- // Remove morpTo relations from sort
2000
1402
  traverseQuerySort(visitor$5, { schema }),
2001
- // Remove private from sort
1403
+ // Remove morpTo relations from sort
2002
1404
  traverseQuerySort(visitor$6, { schema }),
2003
- // Remove passwords from filters
1405
+ // Remove private from sort
2004
1406
  traverseQuerySort(visitor$7, { schema }),
1407
+ // Remove passwords from filters
1408
+ traverseQuerySort(visitor$8, { schema }),
2005
1409
  // Remove keys for empty non-scalar values
2006
1410
  traverseQuerySort(
2007
- ({ key: key2, attribute, value: value2 }, { remove: remove2 }) => {
2008
- if (key2 === "id") {
1411
+ ({ key, attribute, value }, { remove: remove2 }) => {
1412
+ if ([ID_ATTRIBUTE$3, DOC_ID_ATTRIBUTE$3].includes(key)) {
2009
1413
  return;
2010
1414
  }
2011
- if (!isScalarAttribute(attribute) && isEmpty(value2)) {
2012
- remove2(key2);
1415
+ if (!isScalarAttribute(attribute) && isEmpty(value)) {
1416
+ remove2(key);
2013
1417
  }
2014
1418
  },
2015
1419
  { schema }
@@ -2020,51 +1424,55 @@ const defaultSanitizeFields = curry((schema, fields2) => {
2020
1424
  if (!schema) {
2021
1425
  throw new Error("Missing schema in defaultSanitizeFields");
2022
1426
  }
2023
- return pipeAsync(
1427
+ return pipe(
2024
1428
  // Only keep scalar attributes
2025
1429
  traverseQueryFields(
2026
- ({ key: key2, attribute }, { remove: remove2 }) => {
2027
- if (key2 === "id") {
1430
+ ({ key, attribute }, { remove: remove2 }) => {
1431
+ if ([ID_ATTRIBUTE$3, DOC_ID_ATTRIBUTE$3].includes(key)) {
2028
1432
  return;
2029
1433
  }
2030
1434
  if (isNil(attribute) || !isScalarAttribute(attribute)) {
2031
- remove2(key2);
1435
+ remove2(key);
2032
1436
  }
2033
1437
  },
2034
1438
  { schema }
2035
1439
  ),
2036
1440
  // Remove private fields
2037
- traverseQueryFields(visitor$6, { schema }),
2038
- // Remove password fields
2039
1441
  traverseQueryFields(visitor$7, { schema }),
1442
+ // Remove password fields
1443
+ traverseQueryFields(visitor$8, { schema }),
2040
1444
  // Remove nil values from fields array
2041
- (value2) => isArray(value2) ? value2.filter((field) => !isNil(field)) : value2
1445
+ (value) => isArray(value) ? value.filter((field) => !isNil(field)) : value
2042
1446
  )(fields2);
2043
1447
  });
2044
1448
  const defaultSanitizePopulate = curry((schema, populate2) => {
2045
1449
  if (!schema) {
2046
1450
  throw new Error("Missing schema in defaultSanitizePopulate");
2047
1451
  }
2048
- return pipeAsync(
1452
+ return pipe(
1453
+ traverseQueryPopulate(visitor$4, { schema }),
2049
1454
  traverseQueryPopulate(
2050
- async ({ key: key2, value: value2, schema: schema2, attribute }, { set }) => {
1455
+ async ({ key, value, schema: schema2, attribute }, { set }) => {
2051
1456
  if (attribute) {
2052
1457
  return;
2053
1458
  }
2054
- if (key2 === "sort") {
2055
- set(key2, await defaultSanitizeSort(schema2, value2));
1459
+ if (key === "sort") {
1460
+ set(key, await defaultSanitizeSort(schema2, value));
2056
1461
  }
2057
- if (key2 === "filters") {
2058
- set(key2, await defaultSanitizeFilters(schema2, value2));
1462
+ if (key === "filters") {
1463
+ set(key, await defaultSanitizeFilters(schema2, value));
2059
1464
  }
2060
- if (key2 === "fields") {
2061
- set(key2, await defaultSanitizeFields(schema2, value2));
1465
+ if (key === "fields") {
1466
+ set(key, await defaultSanitizeFields(schema2, value));
1467
+ }
1468
+ if (key === "populate") {
1469
+ set(key, await defaultSanitizePopulate(schema2, value));
2062
1470
  }
2063
1471
  },
2064
1472
  { schema }
2065
1473
  ),
2066
1474
  // Remove private fields
2067
- traverseQueryPopulate(visitor$6, { schema })
1475
+ traverseQueryPopulate(visitor$7, { schema })
2068
1476
  )(populate2);
2069
1477
  });
2070
1478
  const sanitizers = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
@@ -2087,7 +1495,8 @@ const createContentAPISanitizers = () => {
2087
1495
  const nonWritableAttributes = getNonWritableAttributes(schema);
2088
1496
  const transforms = [
2089
1497
  // Remove first level ID in inputs
2090
- omit("id"),
1498
+ omit(constants$1.ID_ATTRIBUTE),
1499
+ omit(constants$1.DOC_ID_ATTRIBUTE),
2091
1500
  // Remove non-writable attributes
2092
1501
  traverseEntity$1(removeRestrictedFields(nonWritableAttributes), { schema })
2093
1502
  ];
@@ -2095,7 +1504,7 @@ const createContentAPISanitizers = () => {
2095
1504
  transforms.push(traverseEntity$1(removeRestrictedRelations(auth), { schema }));
2096
1505
  }
2097
1506
  strapi.sanitizers.get("content-api.input").forEach((sanitizer) => transforms.push(sanitizer(schema)));
2098
- return pipeAsync(...transforms)(data);
1507
+ return pipe(...transforms)(data);
2099
1508
  };
2100
1509
  const sanitizeOutput = async (data, schema, { auth } = {}) => {
2101
1510
  if (!schema) {
@@ -2113,7 +1522,7 @@ const createContentAPISanitizers = () => {
2113
1522
  transforms.push(traverseEntity$1(removeRestrictedRelations(auth), { schema }));
2114
1523
  }
2115
1524
  strapi.sanitizers.get("content-api.output").forEach((sanitizer) => transforms.push(sanitizer(schema)));
2116
- return pipeAsync(...transforms)(data);
1525
+ return pipe(...transforms)(data);
2117
1526
  };
2118
1527
  const sanitizeQuery = async (query, schema, { auth } = {}) => {
2119
1528
  if (!schema) {
@@ -2146,7 +1555,7 @@ const createContentAPISanitizers = () => {
2146
1555
  if (auth) {
2147
1556
  transforms.push(traverseQueryFilters(removeRestrictedRelations(auth), { schema }));
2148
1557
  }
2149
- return pipeAsync(...transforms)(filters2);
1558
+ return pipe(...transforms)(filters2);
2150
1559
  };
2151
1560
  const sanitizeSort = (sort2, schema, { auth } = {}) => {
2152
1561
  if (!schema) {
@@ -2156,14 +1565,14 @@ const createContentAPISanitizers = () => {
2156
1565
  if (auth) {
2157
1566
  transforms.push(traverseQuerySort(removeRestrictedRelations(auth), { schema }));
2158
1567
  }
2159
- return pipeAsync(...transforms)(sort2);
1568
+ return pipe(...transforms)(sort2);
2160
1569
  };
2161
1570
  const sanitizeFields = (fields2, schema) => {
2162
1571
  if (!schema) {
2163
1572
  throw new Error("Missing schema in sanitizeFields");
2164
1573
  }
2165
1574
  const transforms = [defaultSanitizeFields(schema)];
2166
- return pipeAsync(...transforms)(fields2);
1575
+ return pipe(...transforms)(fields2);
2167
1576
  };
2168
1577
  const sanitizePopulate = (populate2, schema, { auth } = {}) => {
2169
1578
  if (!schema) {
@@ -2173,7 +1582,7 @@ const createContentAPISanitizers = () => {
2173
1582
  if (auth) {
2174
1583
  transforms.push(traverseQueryPopulate(removeRestrictedRelations(auth), { schema }));
2175
1584
  }
2176
- return pipeAsync(...transforms)(populate2);
1585
+ return pipe(...transforms)(populate2);
2177
1586
  };
2178
1587
  return {
2179
1588
  input: sanitizeInput,
@@ -2191,26 +1600,134 @@ const index$1 = {
2191
1600
  sanitizers,
2192
1601
  visitors: visitors$1
2193
1602
  };
2194
- const throwInvalidParam = ({ key: key2 }) => {
2195
- throw new ValidationError(`Invalid parameter ${key2}`);
1603
+ const formatYupInnerError = (yupError) => ({
1604
+ path: toPath(yupError.path),
1605
+ message: yupError.message,
1606
+ name: yupError.name
1607
+ });
1608
+ const formatYupErrors = (yupError) => ({
1609
+ errors: isEmpty(yupError.inner) ? [formatYupInnerError(yupError)] : yupError.inner.map(formatYupInnerError),
1610
+ message: yupError.message
1611
+ });
1612
+ class ApplicationError extends Error {
1613
+ name;
1614
+ details;
1615
+ message;
1616
+ constructor(message = "An application error occured", details = {}) {
1617
+ super();
1618
+ this.name = "ApplicationError";
1619
+ this.message = message;
1620
+ this.details = details;
1621
+ }
1622
+ }
1623
+ class ValidationError extends ApplicationError {
1624
+ constructor(message, details) {
1625
+ super(message, details);
1626
+ this.name = "ValidationError";
1627
+ }
1628
+ }
1629
+ class YupValidationError extends ValidationError {
1630
+ constructor(yupError, message) {
1631
+ super("Validation");
1632
+ const { errors: errors2, message: yupMessage } = formatYupErrors(yupError);
1633
+ this.message = message || yupMessage;
1634
+ this.details = { errors: errors2 };
1635
+ }
1636
+ }
1637
+ class PaginationError extends ApplicationError {
1638
+ constructor(message = "Invalid pagination", details) {
1639
+ super(message, details);
1640
+ this.name = "PaginationError";
1641
+ this.message = message;
1642
+ }
1643
+ }
1644
+ class NotFoundError extends ApplicationError {
1645
+ constructor(message = "Entity not found", details) {
1646
+ super(message, details);
1647
+ this.name = "NotFoundError";
1648
+ this.message = message;
1649
+ }
1650
+ }
1651
+ class ForbiddenError extends ApplicationError {
1652
+ constructor(message = "Forbidden access", details) {
1653
+ super(message, details);
1654
+ this.name = "ForbiddenError";
1655
+ this.message = message;
1656
+ }
1657
+ }
1658
+ class UnauthorizedError extends ApplicationError {
1659
+ constructor(message = "Unauthorized", details) {
1660
+ super(message, details);
1661
+ this.name = "UnauthorizedError";
1662
+ this.message = message;
1663
+ }
1664
+ }
1665
+ class RateLimitError extends ApplicationError {
1666
+ constructor(message = "Too many requests, please try again later.", details) {
1667
+ super(message, details);
1668
+ this.name = "RateLimitError";
1669
+ this.message = message;
1670
+ this.details = details || {};
1671
+ }
1672
+ }
1673
+ class PayloadTooLargeError extends ApplicationError {
1674
+ constructor(message = "Entity too large", details) {
1675
+ super(message, details);
1676
+ this.name = "PayloadTooLargeError";
1677
+ this.message = message;
1678
+ }
1679
+ }
1680
+ class PolicyError extends ForbiddenError {
1681
+ constructor(message = "Policy Failed", details) {
1682
+ super(message, details);
1683
+ this.name = "PolicyError";
1684
+ this.message = message;
1685
+ this.details = details || {};
1686
+ }
1687
+ }
1688
+ class NotImplementedError extends ApplicationError {
1689
+ constructor(message = "This feature is not implemented yet", details) {
1690
+ super(message, details);
1691
+ this.name = "NotImplementedError";
1692
+ this.message = message;
1693
+ }
1694
+ }
1695
+ const errors = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1696
+ __proto__: null,
1697
+ ApplicationError,
1698
+ ForbiddenError,
1699
+ HttpError,
1700
+ NotFoundError,
1701
+ NotImplementedError,
1702
+ PaginationError,
1703
+ PayloadTooLargeError,
1704
+ PolicyError,
1705
+ RateLimitError,
1706
+ UnauthorizedError,
1707
+ ValidationError,
1708
+ YupValidationError
1709
+ }, Symbol.toStringTag, { value: "Module" }));
1710
+ const throwInvalidParam = ({ key, path }) => {
1711
+ const msg = path && path !== key ? `Invalid parameter ${key} at ${path}` : `Invalid parameter ${key}`;
1712
+ throw new ValidationError(msg);
2196
1713
  };
2197
- const visitor$3 = ({ key: key2, attribute }) => {
1714
+ const visitor$3 = ({ key, attribute, path }) => {
2198
1715
  if (attribute?.type === "password") {
2199
- throwInvalidParam({ key: key2 });
1716
+ throwInvalidParam({ key, path: path.attribute });
2200
1717
  }
2201
1718
  };
2202
- const visitor$2 = ({ schema, key: key2, attribute }) => {
1719
+ const visitor$2 = ({ schema, key, attribute, path }) => {
2203
1720
  if (!attribute) {
2204
1721
  return;
2205
1722
  }
2206
- const isPrivate = attribute.private === true || isPrivateAttribute(schema, key2);
1723
+ const isPrivate = attribute.private === true || isPrivateAttribute(schema, key);
2207
1724
  if (isPrivate) {
2208
- throwInvalidParam({ key: key2 });
1725
+ throwInvalidParam({ key, path: path.attribute });
2209
1726
  }
2210
1727
  };
2211
1728
  const ACTIONS_TO_VERIFY = ["find"];
2212
1729
  const { CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE } = constants$1;
2213
- const throwRestrictedRelations = (auth) => async ({ data, key: key2, attribute, schema }) => {
1730
+ const throwRestrictedRelations = (auth) => async ({ data, key, attribute, schema, path }) => {
2214
1731
  if (!attribute) {
2215
1732
  return;
2216
1733
  }
@@ -2219,11 +1736,11 @@ const throwRestrictedRelations = (auth) => async ({ data, key: key2, attribute,
2219
1736
  return;
2220
1737
  }
2221
1738
  const handleMorphRelation = async () => {
2222
- for (const element of data[key2]) {
1739
+ for (const element of data[key]) {
2223
1740
  const scopes = ACTIONS_TO_VERIFY.map((action) => `${element.__type}.${action}`);
2224
1741
  const isAllowed = await hasAccessToSomeScopes(scopes, auth);
2225
1742
  if (!isAllowed) {
2226
- throwInvalidParam({ key: key2 });
1743
+ throwInvalidParam({ key, path: path.attribute });
2227
1744
  }
2228
1745
  }
2229
1746
  };
@@ -2231,10 +1748,10 @@ const throwRestrictedRelations = (auth) => async ({ data, key: key2, attribute,
2231
1748
  const scopes = ACTIONS_TO_VERIFY.map((action) => `${attribute.target}.${action}`);
2232
1749
  const isAllowed = await hasAccessToSomeScopes(scopes, auth);
2233
1750
  if (!isAllowed) {
2234
- throwInvalidParam({ key: key2 });
1751
+ throwInvalidParam({ key, path: path.attribute });
2235
1752
  }
2236
1753
  };
2237
- const isCreatorRelation = [CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE].includes(key2);
1754
+ const isCreatorRelation = [CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE].includes(key);
2238
1755
  if (isMorphToRelationalAttribute(attribute)) {
2239
1756
  await handleMorphRelation();
2240
1757
  return;
@@ -2255,21 +1772,21 @@ const hasAccessToSomeScopes = async (scopes, auth) => {
2255
1772
  }
2256
1773
  return false;
2257
1774
  };
2258
- const visitor$1 = ({ key: key2, attribute }) => {
1775
+ const visitor$1 = ({ key, attribute, path }) => {
2259
1776
  if (isMorphToRelationalAttribute(attribute)) {
2260
- throwInvalidParam({ key: key2 });
1777
+ throwInvalidParam({ key, path: path.attribute });
2261
1778
  }
2262
1779
  };
2263
- const visitor = ({ key: key2, attribute }) => {
1780
+ const visitor = ({ key, attribute, path }) => {
2264
1781
  if (isDynamicZoneAttribute(attribute)) {
2265
- throwInvalidParam({ key: key2 });
1782
+ throwInvalidParam({ key, path: path.attribute });
2266
1783
  }
2267
1784
  };
2268
- const throwDisallowedFields = (allowedFields = null) => ({ key: key2, path: { attribute: path } }) => {
1785
+ const throwDisallowedFields = (allowedFields = null) => ({ key, path: { attribute: path } }) => {
2269
1786
  if (allowedFields === null) {
2270
1787
  return;
2271
1788
  }
2272
- if (!(isArray(allowedFields) && allowedFields.every(isString$1))) {
1789
+ if (!(isArray(allowedFields) && allowedFields.every(isString))) {
2273
1790
  throw new TypeError(
2274
1791
  `Expected array of strings for allowedFields but got "${typeof allowedFields}"`
2275
1792
  );
@@ -2284,31 +1801,31 @@ const throwDisallowedFields = (allowedFields = null) => ({ key: key2, path: { at
2284
1801
  if (isPathAllowed) {
2285
1802
  return;
2286
1803
  }
2287
- throwInvalidParam({ key: key2 });
1804
+ throwInvalidParam({ key, path });
2288
1805
  };
2289
1806
  const getContainedPaths = (path) => {
2290
1807
  const parts = toPath(path);
2291
- return parts.reduce((acc2, value2, index2, list) => {
2292
- return [...acc2, list.slice(0, index2 + 1).join(".")];
1808
+ return parts.reduce((acc, value, index2, list) => {
1809
+ return [...acc, list.slice(0, index2 + 1).join(".")];
2293
1810
  }, []);
2294
1811
  };
2295
- const throwRestrictedFields = (restrictedFields = null) => ({ key: key2, path: { attribute: path } }) => {
1812
+ const throwRestrictedFields = (restrictedFields = null) => ({ key, path: { attribute: path } }) => {
2296
1813
  if (restrictedFields === null) {
2297
- throwInvalidParam({ key: key2 });
1814
+ throwInvalidParam({ key, path });
2298
1815
  }
2299
- if (!(isArray(restrictedFields) && restrictedFields.every(isString$1))) {
1816
+ if (!(isArray(restrictedFields) && restrictedFields.every(isString))) {
2300
1817
  throw new TypeError(
2301
1818
  `Expected array of strings for restrictedFields but got "${typeof restrictedFields}"`
2302
1819
  );
2303
1820
  }
2304
1821
  if (restrictedFields.includes(path)) {
2305
- throwInvalidParam({ key: key2 });
1822
+ throwInvalidParam({ key, path });
2306
1823
  }
2307
1824
  const isRestrictedNested = restrictedFields.some(
2308
1825
  (allowedPath) => path?.toString().startsWith(`${allowedPath}.`)
2309
1826
  );
2310
1827
  if (isRestrictedNested) {
2311
- throwInvalidParam({ key: key2 });
1828
+ throwInvalidParam({ key, path });
2312
1829
  }
2313
1830
  };
2314
1831
  const visitors = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
@@ -2321,6 +1838,7 @@ const visitors = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProp
2321
1838
  throwRestrictedFields,
2322
1839
  throwRestrictedRelations
2323
1840
  }, Symbol.toStringTag, { value: "Module" }));
1841
+ const { ID_ATTRIBUTE: ID_ATTRIBUTE$2, DOC_ID_ATTRIBUTE: DOC_ID_ATTRIBUTE$2 } = constants$1;
2324
1842
  const throwPasswords = (schema) => async (entity) => {
2325
1843
  if (!schema) {
2326
1844
  throw new Error("Missing schema in throwPasswords");
@@ -2331,16 +1849,16 @@ const defaultValidateFilters = curry((schema, filters2) => {
2331
1849
  if (!schema) {
2332
1850
  throw new Error("Missing schema in defaultValidateFilters");
2333
1851
  }
2334
- return pipeAsync(
1852
+ return pipe(
2335
1853
  // keys that are not attributes or valid operators
2336
1854
  traverseQueryFilters(
2337
- ({ key: key2, attribute }) => {
2338
- if (key2 === "id") {
1855
+ ({ key, attribute, path }) => {
1856
+ if ([ID_ATTRIBUTE$2, DOC_ID_ATTRIBUTE$2].includes(key)) {
2339
1857
  return;
2340
1858
  }
2341
1859
  const isAttribute = !!attribute;
2342
- if (!isAttribute && !isOperator(key2)) {
2343
- throwInvalidParam({ key: key2 });
1860
+ if (!isAttribute && !isOperator(key)) {
1861
+ throwInvalidParam({ key, path: path.attribute });
2344
1862
  }
2345
1863
  },
2346
1864
  { schema }
@@ -2360,15 +1878,15 @@ const defaultValidateSort = curry((schema, sort2) => {
2360
1878
  if (!schema) {
2361
1879
  throw new Error("Missing schema in defaultValidateSort");
2362
1880
  }
2363
- return pipeAsync(
1881
+ return pipe(
2364
1882
  // non attribute keys
2365
1883
  traverseQuerySort(
2366
- ({ key: key2, attribute }) => {
2367
- if (key2 === "id") {
1884
+ ({ key, attribute, path }) => {
1885
+ if ([ID_ATTRIBUTE$2, DOC_ID_ATTRIBUTE$2].includes(key)) {
2368
1886
  return;
2369
1887
  }
2370
1888
  if (!attribute) {
2371
- throwInvalidParam({ key: key2 });
1889
+ throwInvalidParam({ key, path: path.attribute });
2372
1890
  }
2373
1891
  },
2374
1892
  { schema }
@@ -2383,12 +1901,12 @@ const defaultValidateSort = curry((schema, sort2) => {
2383
1901
  traverseQuerySort(visitor$3, { schema }),
2384
1902
  // keys for empty non-scalar values
2385
1903
  traverseQuerySort(
2386
- ({ key: key2, attribute, value: value2 }) => {
2387
- if (key2 === "id") {
1904
+ ({ key, attribute, value, path }) => {
1905
+ if ([ID_ATTRIBUTE$2, DOC_ID_ATTRIBUTE$2].includes(key)) {
2388
1906
  return;
2389
1907
  }
2390
- if (!isScalarAttribute(attribute) && isEmpty(value2)) {
2391
- throwInvalidParam({ key: key2 });
1908
+ if (!isScalarAttribute(attribute) && isEmpty(value)) {
1909
+ throwInvalidParam({ key, path: path.attribute });
2392
1910
  }
2393
1911
  },
2394
1912
  { schema }
@@ -2399,15 +1917,15 @@ const defaultValidateFields = curry((schema, fields2) => {
2399
1917
  if (!schema) {
2400
1918
  throw new Error("Missing schema in defaultValidateFields");
2401
1919
  }
2402
- return pipeAsync(
1920
+ return pipe(
2403
1921
  // Only allow scalar attributes
2404
1922
  traverseQueryFields(
2405
- ({ key: key2, attribute }) => {
2406
- if (key2 === "id") {
1923
+ ({ key, attribute, path }) => {
1924
+ if ([ID_ATTRIBUTE$2, DOC_ID_ATTRIBUTE$2].includes(key)) {
2407
1925
  return;
2408
1926
  }
2409
1927
  if (isNil(attribute) || !isScalarAttribute(attribute)) {
2410
- throwInvalidParam({ key: key2 });
1928
+ throwInvalidParam({ key, path: path.attribute });
2411
1929
  }
2412
1930
  },
2413
1931
  { schema }
@@ -2418,13 +1936,44 @@ const defaultValidateFields = curry((schema, fields2) => {
2418
1936
  traverseQueryFields(visitor$3, { schema })
2419
1937
  )(fields2);
2420
1938
  });
1939
+ const defaultValidatePopulate = curry((schema, populate2) => {
1940
+ if (!schema) {
1941
+ throw new Error("Missing schema in defaultValidatePopulate");
1942
+ }
1943
+ return pipe(
1944
+ traverseQueryPopulate(
1945
+ async ({ key, value, schema: schema2, attribute }, { set }) => {
1946
+ if (attribute) {
1947
+ return;
1948
+ }
1949
+ if (key === "sort") {
1950
+ set(key, await defaultValidateSort(schema2, value));
1951
+ }
1952
+ if (key === "filters") {
1953
+ set(key, await defaultValidateFilters(schema2, value));
1954
+ }
1955
+ if (key === "fields") {
1956
+ set(key, await defaultValidateFields(schema2, value));
1957
+ }
1958
+ if (key === "populate") {
1959
+ set(key, await defaultValidatePopulate(schema2, value));
1960
+ }
1961
+ },
1962
+ { schema }
1963
+ ),
1964
+ // Remove private fields
1965
+ traverseQueryPopulate(visitor$2, { schema })
1966
+ )(populate2);
1967
+ });
2421
1968
  const validators = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2422
1969
  __proto__: null,
2423
1970
  defaultValidateFields,
2424
1971
  defaultValidateFilters,
1972
+ defaultValidatePopulate,
2425
1973
  defaultValidateSort,
2426
1974
  throwPasswords
2427
1975
  }, Symbol.toStringTag, { value: "Module" }));
1976
+ const { ID_ATTRIBUTE: ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE: DOC_ID_ATTRIBUTE$1 } = constants$1;
2428
1977
  const createContentAPIValidators = () => {
2429
1978
  const validateInput = async (data, schema, { auth } = {}) => {
2430
1979
  if (!schema) {
@@ -2437,8 +1986,13 @@ const createContentAPIValidators = () => {
2437
1986
  const nonWritableAttributes = getNonWritableAttributes(schema);
2438
1987
  const transforms = [
2439
1988
  (data2) => {
2440
- if (isObject(data2) && "id" in data2) {
2441
- throwInvalidParam({ key: "id" });
1989
+ if (isObject(data2)) {
1990
+ if (ID_ATTRIBUTE$1 in data2) {
1991
+ throwInvalidParam({ key: ID_ATTRIBUTE$1 });
1992
+ }
1993
+ if (DOC_ID_ATTRIBUTE$1 in data2) {
1994
+ throwInvalidParam({ key: DOC_ID_ATTRIBUTE$1 });
1995
+ }
2442
1996
  }
2443
1997
  },
2444
1998
  // non-writable attributes
@@ -2448,13 +2002,13 @@ const createContentAPIValidators = () => {
2448
2002
  transforms.push(traverseEntity$1(throwRestrictedRelations(auth), { schema }));
2449
2003
  }
2450
2004
  strapi.validators.get("content-api.input").forEach((validator) => transforms.push(validator(schema)));
2451
- pipeAsync(...transforms)(data);
2005
+ await pipe(...transforms)(data);
2452
2006
  };
2453
2007
  const validateQuery = async (query, schema, { auth } = {}) => {
2454
2008
  if (!schema) {
2455
2009
  throw new Error("Missing schema in validateQuery");
2456
2010
  }
2457
- const { filters: filters2, sort: sort2, fields: fields2 } = query;
2011
+ const { filters: filters2, sort: sort2, fields: fields2, populate: populate2 } = query;
2458
2012
  if (filters2) {
2459
2013
  await validateFilters(filters2, schema, { auth });
2460
2014
  }
@@ -2464,6 +2018,9 @@ const createContentAPIValidators = () => {
2464
2018
  if (fields2) {
2465
2019
  await validateFields(fields2, schema);
2466
2020
  }
2021
+ if (populate2 && populate2 !== "*") {
2022
+ await validatePopulate(populate2, schema);
2023
+ }
2467
2024
  };
2468
2025
  const validateFilters = async (filters2, schema, { auth } = {}) => {
2469
2026
  if (!schema) {
@@ -2477,7 +2034,7 @@ const createContentAPIValidators = () => {
2477
2034
  if (auth) {
2478
2035
  transforms.push(traverseQueryFilters(throwRestrictedRelations(auth), { schema }));
2479
2036
  }
2480
- return pipeAsync(...transforms)(filters2);
2037
+ await pipe(...transforms)(filters2);
2481
2038
  };
2482
2039
  const validateSort = async (sort2, schema, { auth } = {}) => {
2483
2040
  if (!schema) {
@@ -2487,21 +2044,32 @@ const createContentAPIValidators = () => {
2487
2044
  if (auth) {
2488
2045
  transforms.push(traverseQuerySort(throwRestrictedRelations(auth), { schema }));
2489
2046
  }
2490
- return pipeAsync(...transforms)(sort2);
2047
+ await pipe(...transforms)(sort2);
2491
2048
  };
2492
- const validateFields = (fields2, schema) => {
2049
+ const validateFields = async (fields2, schema) => {
2493
2050
  if (!schema) {
2494
2051
  throw new Error("Missing schema in validateFields");
2495
2052
  }
2496
2053
  const transforms = [defaultValidateFields(schema)];
2497
- return pipeAsync(...transforms)(fields2);
2054
+ await pipe(...transforms)(fields2);
2055
+ };
2056
+ const validatePopulate = async (populate2, schema, { auth } = {}) => {
2057
+ if (!schema) {
2058
+ throw new Error("Missing schema in sanitizePopulate");
2059
+ }
2060
+ const transforms = [defaultValidatePopulate(schema)];
2061
+ if (auth) {
2062
+ transforms.push(traverseQueryPopulate(throwRestrictedRelations(auth), { schema }));
2063
+ }
2064
+ await pipe(...transforms)(populate2);
2498
2065
  };
2499
2066
  return {
2500
2067
  input: validateInput,
2501
2068
  query: validateQuery,
2502
2069
  filters: validateFilters,
2503
2070
  sort: validateSort,
2504
- fields: validateFields
2071
+ fields: validateFields,
2072
+ populate: validatePopulate
2505
2073
  };
2506
2074
  };
2507
2075
  const contentAPI = createContentAPIValidators();
@@ -2510,7 +2078,7 @@ const index = {
2510
2078
  validators,
2511
2079
  visitors
2512
2080
  };
2513
- const { PUBLISHED_AT_ATTRIBUTE } = constants$1;
2081
+ const { ID_ATTRIBUTE, DOC_ID_ATTRIBUTE, PUBLISHED_AT_ATTRIBUTE } = constants$1;
2514
2082
  class InvalidOrderError extends Error {
2515
2083
  constructor() {
2516
2084
  super();
@@ -2524,7 +2092,7 @@ class InvalidSortError extends Error {
2524
2092
  }
2525
2093
  }
2526
2094
  function validateOrder(order) {
2527
- if (!isString$1(order) || !["asc", "desc"].includes(order.toLocaleLowerCase())) {
2095
+ if (!isString(order) || !["asc", "desc"].includes(order.toLocaleLowerCase())) {
2528
2096
  throw new InvalidOrderError();
2529
2097
  }
2530
2098
  }
@@ -2534,8 +2102,8 @@ const convertCountQueryParams = (countQuery) => {
2534
2102
  const convertOrderingQueryParams = (ordering) => {
2535
2103
  return ordering;
2536
2104
  };
2537
- const isPlainObject = (value2) => _$1.isPlainObject(value2);
2538
- const isStringArray = (value2) => isArray(value2) && value2.every(isString$1);
2105
+ const isPlainObject = (value) => _$1.isPlainObject(value);
2106
+ const isStringArray = (value) => isArray(value) && value.every(isString);
2539
2107
  const convertSortQueryParams = (sortQuery) => {
2540
2108
  if (typeof sortQuery === "string") {
2541
2109
  return convertStringSortQueryParam(sortQuery);
@@ -2552,13 +2120,13 @@ const convertSortQueryParams = (sortQuery) => {
2552
2120
  throw new InvalidSortError();
2553
2121
  };
2554
2122
  const convertStringSortQueryParam = (sortQuery) => {
2555
- return sortQuery.split(",").map((value2) => convertSingleSortQueryParam(value2));
2123
+ return sortQuery.split(",").map((value) => convertSingleSortQueryParam(value));
2556
2124
  };
2557
2125
  const convertSingleSortQueryParam = (sortQuery) => {
2558
2126
  if (!sortQuery) {
2559
2127
  return {};
2560
2128
  }
2561
- if (!isString$1(sortQuery)) {
2129
+ if (!isString(sortQuery)) {
2562
2130
  throw new Error("Invalid sort query");
2563
2131
  }
2564
2132
  const [field, order = "asc"] = sortQuery.split(":");
@@ -2638,15 +2206,15 @@ const convertPopulateQueryParams = (populate2, schema, depth = 0) => {
2638
2206
  return true;
2639
2207
  }
2640
2208
  if (typeof populate2 === "string") {
2641
- return populate2.split(",").map((value2) => _$1.trim(value2));
2209
+ return populate2.split(",").map((value) => _$1.trim(value));
2642
2210
  }
2643
2211
  if (Array.isArray(populate2)) {
2644
2212
  return _$1.uniq(
2645
- populate2.flatMap((value2) => {
2646
- if (typeof value2 !== "string") {
2213
+ populate2.flatMap((value) => {
2214
+ if (typeof value !== "string") {
2647
2215
  throw new InvalidPopulateError();
2648
2216
  }
2649
- return value2.split(",").map((value22) => _$1.trim(value22));
2217
+ return value.split(",").map((value2) => _$1.trim(value2));
2650
2218
  })
2651
2219
  );
2652
2220
  }
@@ -2655,25 +2223,30 @@ const convertPopulateQueryParams = (populate2, schema, depth = 0) => {
2655
2223
  }
2656
2224
  throw new InvalidPopulateError();
2657
2225
  };
2226
+ const hasFragmentPopulateDefined = (populate2) => {
2227
+ return typeof populate2 === "object" && "on" in populate2 && !isNil(populate2.on);
2228
+ };
2658
2229
  const convertPopulateObject = (populate2, schema) => {
2659
2230
  if (!schema) {
2660
2231
  return {};
2661
2232
  }
2662
2233
  const { attributes } = schema;
2663
- return Object.entries(populate2).reduce((acc2, [key2, subPopulate]) => {
2664
- const attribute = attributes[key2];
2234
+ return Object.entries(populate2).reduce((acc, [key, subPopulate]) => {
2235
+ if (_$1.isBoolean(subPopulate)) {
2236
+ return { ...acc, [key]: subPopulate };
2237
+ }
2238
+ const attribute = attributes[key];
2665
2239
  if (!attribute) {
2666
- return acc2;
2240
+ return acc;
2667
2241
  }
2668
2242
  const isAllowedAttributeForFragmentPopulate = isDynamicZoneAttribute(attribute) || isMorphToRelationalAttribute(attribute);
2669
- const hasFragmentPopulateDefined = typeof subPopulate === "object" && "on" in subPopulate && !isNil(subPopulate.on);
2670
- if (isAllowedAttributeForFragmentPopulate && hasFragmentPopulateDefined) {
2243
+ if (isAllowedAttributeForFragmentPopulate && hasFragmentPopulateDefined(subPopulate)) {
2671
2244
  return {
2672
- ...acc2,
2673
- [key2]: {
2245
+ ...acc,
2246
+ [key]: {
2674
2247
  on: Object.entries(subPopulate.on).reduce(
2675
- (acc22, [type, typeSubPopulate]) => ({
2676
- ...acc22,
2248
+ (acc2, [type, typeSubPopulate]) => ({
2249
+ ...acc2,
2677
2250
  [type]: convertNestedPopulate(typeSubPopulate, strapi.getModel(type))
2678
2251
  }),
2679
2252
  {}
@@ -2684,15 +2257,15 @@ const convertPopulateObject = (populate2, schema) => {
2684
2257
  if (isDynamicZoneAttribute(attribute)) {
2685
2258
  const populates = attribute.components.map((uid) => strapi.getModel(uid)).map((schema2) => convertNestedPopulate(subPopulate, schema2)).map((populate22) => populate22 === true ? {} : populate22).filter((populate22) => populate22 !== false);
2686
2259
  if (isEmpty(populates)) {
2687
- return acc2;
2260
+ return acc;
2688
2261
  }
2689
2262
  return {
2690
- ...acc2,
2691
- [key2]: mergeAll(populates)
2263
+ ...acc,
2264
+ [key]: mergeAll(populates)
2692
2265
  };
2693
2266
  }
2694
2267
  if (isMorphToRelationalAttribute(attribute)) {
2695
- return { ...acc2, [key2]: convertNestedPopulate(subPopulate, void 0) };
2268
+ return { ...acc, [key]: convertNestedPopulate(subPopulate, void 0) };
2696
2269
  }
2697
2270
  let targetSchemaUID;
2698
2271
  if (attribute.type === "relation") {
@@ -2702,19 +2275,19 @@ const convertPopulateObject = (populate2, schema) => {
2702
2275
  } else if (attribute.type === "media") {
2703
2276
  targetSchemaUID = "plugin::upload.file";
2704
2277
  } else {
2705
- return acc2;
2278
+ return acc;
2706
2279
  }
2707
2280
  const targetSchema = strapi.getModel(targetSchemaUID);
2708
2281
  if (!targetSchema) {
2709
- return acc2;
2282
+ return acc;
2710
2283
  }
2711
2284
  const populateObject = convertNestedPopulate(subPopulate, targetSchema);
2712
2285
  if (!populateObject) {
2713
- return acc2;
2286
+ return acc;
2714
2287
  }
2715
2288
  return {
2716
- ...acc2,
2717
- [key2]: populateObject
2289
+ ...acc,
2290
+ [key]: populateObject
2718
2291
  };
2719
2292
  }, {});
2720
2293
  };
@@ -2748,282 +2321,707 @@ const convertNestedPopulate = (subPopulate, schema) => {
2748
2321
  if (ordering) {
2749
2322
  query.ordering = convertOrderingQueryParams(ordering);
2750
2323
  }
2751
- validatePaginationParams(page, pageSize, start, limit);
2752
- if (!isNil(page)) {
2753
- query.page = convertPageQueryParams(page);
2324
+ validatePaginationParams(page, pageSize, start, limit);
2325
+ if (!isNil(page)) {
2326
+ query.page = convertPageQueryParams(page);
2327
+ }
2328
+ if (!isNil(pageSize)) {
2329
+ query.pageSize = convertPageSizeQueryParams(pageSize, page);
2330
+ }
2331
+ if (!isNil(start)) {
2332
+ query.offset = convertStartQueryParams(start);
2333
+ }
2334
+ if (!isNil(limit)) {
2335
+ query.limit = convertLimitQueryParams(limit);
2336
+ }
2337
+ return query;
2338
+ };
2339
+ const convertFieldsQueryParams = (fields2, depth = 0) => {
2340
+ if (depth === 0 && fields2 === "*") {
2341
+ return void 0;
2342
+ }
2343
+ if (typeof fields2 === "string") {
2344
+ const fieldsValues = fields2.split(",").map((value) => _$1.trim(value));
2345
+ return _$1.uniq([ID_ATTRIBUTE, DOC_ID_ATTRIBUTE, ...fieldsValues]);
2346
+ }
2347
+ if (isStringArray(fields2)) {
2348
+ const fieldsValues = fields2.flatMap((value) => convertFieldsQueryParams(value, depth + 1)).filter((v) => !isNil(v));
2349
+ return _$1.uniq([ID_ATTRIBUTE, DOC_ID_ATTRIBUTE, ...fieldsValues]);
2350
+ }
2351
+ throw new Error("Invalid fields parameter. Expected a string or an array of strings");
2352
+ };
2353
+ const isValidSchemaAttribute = (key, schema) => {
2354
+ if ([DOC_ID_ATTRIBUTE, ID_ATTRIBUTE].includes(key)) {
2355
+ return true;
2356
+ }
2357
+ if (!schema) {
2358
+ return false;
2359
+ }
2360
+ return Object.keys(schema.attributes).includes(key);
2361
+ };
2362
+ const convertFiltersQueryParams = (filters2, schema) => {
2363
+ if (!isObject(filters2)) {
2364
+ throw new Error("The filters parameter must be an object or an array");
2365
+ }
2366
+ const filtersCopy = cloneDeep(filters2);
2367
+ return convertAndSanitizeFilters(filtersCopy, schema);
2368
+ };
2369
+ const convertAndSanitizeFilters = (filters2, schema) => {
2370
+ if (Array.isArray(filters2)) {
2371
+ return filters2.map((filter) => convertAndSanitizeFilters(filter, schema)).filter((filter) => !isPlainObject(filter) || !isEmpty(filter));
2372
+ }
2373
+ if (!isPlainObject(filters2)) {
2374
+ return filters2;
2375
+ }
2376
+ const removeOperator = (operator) => delete filters2[operator];
2377
+ for (const [key, value] of Object.entries(filters2)) {
2378
+ const attribute = get(key, schema?.attributes);
2379
+ const validKey = isOperator(key) || isValidSchemaAttribute(key, schema);
2380
+ if (!validKey) {
2381
+ removeOperator(key);
2382
+ } else if (attribute) {
2383
+ if (attribute.type === "relation") {
2384
+ filters2[key] = convertAndSanitizeFilters(value, strapi.getModel(attribute.target));
2385
+ } else if (attribute.type === "component") {
2386
+ filters2[key] = convertAndSanitizeFilters(value, strapi.getModel(attribute.component));
2387
+ } else if (attribute.type === "media") {
2388
+ filters2[key] = convertAndSanitizeFilters(value, strapi.getModel("plugin::upload.file"));
2389
+ } else if (attribute.type === "dynamiczone") {
2390
+ removeOperator(key);
2391
+ } else if (attribute.type === "password") {
2392
+ removeOperator(key);
2393
+ } else {
2394
+ filters2[key] = convertAndSanitizeFilters(value, schema);
2395
+ }
2396
+ } else if (["$null", "$notNull"].includes(key)) {
2397
+ filters2[key] = parseType({ type: "boolean", value: filters2[key], forceCast: true });
2398
+ } else if (isObject(value)) {
2399
+ filters2[key] = convertAndSanitizeFilters(value, schema);
2400
+ }
2401
+ if (isPlainObject(filters2[key]) && isEmpty(filters2[key])) {
2402
+ removeOperator(key);
2403
+ }
2404
+ }
2405
+ return filters2;
2406
+ };
2407
+ const convertStatusParams = (status, query = {}) => {
2408
+ query.filters = ({ meta }) => {
2409
+ const contentType = strapi.contentTypes[meta.uid];
2410
+ if (!contentType || !hasDraftAndPublish(contentType)) {
2411
+ return {};
2412
+ }
2413
+ return { [PUBLISHED_AT_ATTRIBUTE]: { $null: status === "draft" } };
2414
+ };
2415
+ };
2416
+ const transformParamsToQuery = (uid, params) => {
2417
+ const schema = strapi.getModel(uid);
2418
+ const query = {};
2419
+ const { _q, sort: sort2, filters: filters2, fields: fields2, populate: populate2, page, pageSize, start, limit, status, ...rest } = params;
2420
+ if (!isNil(status)) {
2421
+ convertStatusParams(status, query);
2422
+ }
2423
+ if (!isNil(_q)) {
2424
+ query._q = _q;
2425
+ }
2426
+ if (!isNil(sort2)) {
2427
+ query.orderBy = convertSortQueryParams(sort2);
2428
+ }
2429
+ if (!isNil(filters2)) {
2430
+ query.where = convertFiltersQueryParams(filters2, schema);
2431
+ }
2432
+ if (!isNil(fields2)) {
2433
+ query.select = convertFieldsQueryParams(fields2);
2434
+ }
2435
+ if (!isNil(populate2)) {
2436
+ query.populate = convertPopulateQueryParams(populate2, schema);
2437
+ }
2438
+ validatePaginationParams(page, pageSize, start, limit);
2439
+ if (!isNil(page)) {
2440
+ query.page = convertPageQueryParams(page);
2441
+ }
2442
+ if (!isNil(pageSize)) {
2443
+ query.pageSize = convertPageSizeQueryParams(pageSize, page);
2444
+ }
2445
+ if (!isNil(start)) {
2446
+ query.offset = convertStartQueryParams(start);
2447
+ }
2448
+ if (!isNil(limit)) {
2449
+ query.limit = convertLimitQueryParams(limit);
2450
+ }
2451
+ return {
2452
+ ...rest,
2453
+ ...query
2454
+ };
2455
+ };
2456
+ const convertQueryParams = {
2457
+ convertSortQueryParams,
2458
+ convertStartQueryParams,
2459
+ convertLimitQueryParams,
2460
+ convertPopulateQueryParams,
2461
+ convertFiltersQueryParams,
2462
+ convertFieldsQueryParams,
2463
+ transformParamsToQuery
2464
+ };
2465
+ function importDefault(modName) {
2466
+ const mod = require(modName);
2467
+ return mod && mod.__esModule ? mod.default : mod;
2468
+ }
2469
+ const machineId = () => {
2470
+ try {
2471
+ const deviceId = machineIdSync();
2472
+ return deviceId;
2473
+ } catch (error) {
2474
+ const deviceId = randomUUID();
2475
+ return deviceId;
2476
+ }
2477
+ };
2478
+ const handleYupError = (error, errorMessage) => {
2479
+ throw new YupValidationError(error, errorMessage);
2480
+ };
2481
+ const defaultValidationParam = { strict: true, abortEarly: false };
2482
+ const validateYupSchema = (schema, options = {}) => async (body, errorMessage) => {
2483
+ try {
2484
+ const optionsWithDefaults = defaults(defaultValidationParam, options);
2485
+ const result = await schema.validate(body, optionsWithDefaults);
2486
+ return result;
2487
+ } catch (e) {
2488
+ if (e instanceof yup$1.ValidationError) {
2489
+ handleYupError(e, errorMessage);
2490
+ }
2491
+ throw e;
2492
+ }
2493
+ };
2494
+ const validateYupSchemaSync = (schema, options = {}) => (body, errorMessage) => {
2495
+ try {
2496
+ const optionsWithDefaults = defaults(defaultValidationParam, options);
2497
+ return schema.validateSync(body, optionsWithDefaults);
2498
+ } catch (e) {
2499
+ if (e instanceof yup$1.ValidationError) {
2500
+ handleYupError(e, errorMessage);
2501
+ }
2502
+ throw e;
2503
+ }
2504
+ };
2505
+ const STRAPI_DEFAULTS = {
2506
+ offset: {
2507
+ start: 0,
2508
+ limit: 10
2509
+ },
2510
+ page: {
2511
+ page: 1,
2512
+ pageSize: 10
2513
+ }
2514
+ };
2515
+ const paginationAttributes = ["start", "limit", "page", "pageSize"];
2516
+ const withMaxLimit = (limit, maxLimit = -1) => {
2517
+ if (maxLimit === -1 || limit < maxLimit) {
2518
+ return limit;
2519
+ }
2520
+ return maxLimit;
2521
+ };
2522
+ const ensureMinValues = ({ start, limit }) => ({
2523
+ start: Math.max(start, 0),
2524
+ limit: limit === -1 ? limit : Math.max(limit, 1)
2525
+ });
2526
+ const ensureMaxValues = (maxLimit = -1) => ({ start, limit }) => ({
2527
+ start,
2528
+ limit: withMaxLimit(limit, maxLimit)
2529
+ });
2530
+ const withNoLimit = (pagination2, maxLimit = -1) => ({
2531
+ ...pagination2,
2532
+ limit: pagination2.limit === -1 ? maxLimit : pagination2.limit
2533
+ });
2534
+ const withDefaultPagination = (args, { defaults: defaults2 = {}, maxLimit = -1 } = {}) => {
2535
+ const defaultValues = merge(STRAPI_DEFAULTS, defaults2);
2536
+ const usePagePagination = !isNil(args.page) || !isNil(args.pageSize);
2537
+ const useOffsetPagination = !isNil(args.start) || !isNil(args.limit);
2538
+ const ensureValidValues = pipe$1(ensureMinValues, ensureMaxValues(maxLimit));
2539
+ if (!usePagePagination && !useOffsetPagination) {
2540
+ return merge(args, ensureValidValues(defaultValues.offset));
2541
+ }
2542
+ if (usePagePagination && useOffsetPagination) {
2543
+ throw new PaginationError("Cannot use both page & offset pagination in the same query");
2754
2544
  }
2755
- if (!isNil(pageSize)) {
2756
- query.pageSize = convertPageSizeQueryParams(pageSize, page);
2545
+ const pagination2 = {
2546
+ start: 0,
2547
+ limit: 0
2548
+ };
2549
+ if (useOffsetPagination) {
2550
+ const { start, limit } = merge(defaultValues.offset, args);
2551
+ Object.assign(pagination2, { start, limit });
2757
2552
  }
2758
- if (!isNil(start)) {
2759
- query.offset = convertStartQueryParams(start);
2553
+ if (usePagePagination) {
2554
+ const { page, pageSize } = merge(defaultValues.page, {
2555
+ ...args,
2556
+ pageSize: Math.max(1, args.pageSize ?? 0)
2557
+ });
2558
+ Object.assign(pagination2, {
2559
+ start: (page - 1) * pageSize,
2560
+ limit: pageSize
2561
+ });
2760
2562
  }
2761
- if (!isNil(limit)) {
2762
- query.limit = convertLimitQueryParams(limit);
2563
+ Object.assign(pagination2, withNoLimit(pagination2, maxLimit));
2564
+ const replacePaginationAttributes = pipe$1(
2565
+ // Remove pagination attributes
2566
+ omit(paginationAttributes),
2567
+ // Merge the object with the new pagination + ensure minimum & maximum values
2568
+ merge(ensureValidValues(pagination2))
2569
+ );
2570
+ return replacePaginationAttributes(args);
2571
+ };
2572
+ const pagination = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2573
+ __proto__: null,
2574
+ withDefaultPagination
2575
+ }, Symbol.toStringTag, { value: "Module" }));
2576
+ const SUPPORTED_PACKAGE_MANAGERS = ["npm", "yarn"];
2577
+ const DEFAULT_PACKAGE_MANAGER = "npm";
2578
+ const getPreferred = async (pkgPath) => {
2579
+ const pm = await preferredPM(pkgPath);
2580
+ const hasPackageManager = pm !== void 0;
2581
+ if (!hasPackageManager) {
2582
+ throw new Error(`Couldn't find a package manager in your project.`);
2583
+ }
2584
+ const isPackageManagerSupported = SUPPORTED_PACKAGE_MANAGERS.includes(pm.name);
2585
+ if (!isPackageManagerSupported) {
2586
+ process.emitWarning(
2587
+ `We detected your package manager (${pm.name} v${pm.version}), but it's not officially supported by Strapi yet. Defaulting to npm instead.`
2588
+ );
2589
+ return DEFAULT_PACKAGE_MANAGER;
2763
2590
  }
2764
- convertPublicationStateParams(schema, subPopulate, query);
2765
- return query;
2591
+ return pm.name;
2766
2592
  };
2767
- const convertFieldsQueryParams = (fields2, depth = 0) => {
2768
- if (depth === 0 && fields2 === "*") {
2769
- return void 0;
2593
+ const installDependencies = (path, packageManager2, options = {}) => {
2594
+ return execa(packageManager2, ["install"], { ...options, cwd: path, stdin: "ignore" });
2595
+ };
2596
+ const packageManager = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2597
+ __proto__: null,
2598
+ getPreferred,
2599
+ installDependencies
2600
+ }, Symbol.toStringTag, { value: "Module" }));
2601
+ const createStrictInterpolationRegExp = (allowedVariableNames, flags) => {
2602
+ const oneOfVariables = allowedVariableNames.join("|");
2603
+ return new RegExp(`<%=\\s*(${oneOfVariables})\\s*%>`, flags);
2604
+ };
2605
+ const createLooseInterpolationRegExp = (flags) => new RegExp(/<%=([\s\S]+?)%>/, flags);
2606
+ const template = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2607
+ __proto__: null,
2608
+ createLooseInterpolationRegExp,
2609
+ createStrictInterpolationRegExp
2610
+ }, Symbol.toStringTag, { value: "Module" }));
2611
+ const kbytesToBytes = (kbytes) => kbytes * 1e3;
2612
+ const bytesToKbytes = (bytes) => Math.round(bytes / 1e3 * 100) / 100;
2613
+ const bytesToHumanReadable = (bytes) => {
2614
+ const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB"];
2615
+ if (bytes === 0)
2616
+ return "0 Bytes";
2617
+ const i = parseInt(`${Math.floor(Math.log(bytes) / Math.log(1e3))}`, 10);
2618
+ return `${Math.round(bytes / 1e3 ** i)} ${sizes[i]}`;
2619
+ };
2620
+ const streamToBuffer = (stream) => new Promise((resolve, reject) => {
2621
+ const chunks = [];
2622
+ stream.on("data", (chunk) => {
2623
+ chunks.push(chunk);
2624
+ });
2625
+ stream.on("end", () => {
2626
+ resolve(Buffer.concat(chunks));
2627
+ });
2628
+ stream.on("error", reject);
2629
+ });
2630
+ const getStreamSize = (stream) => new Promise((resolve, reject) => {
2631
+ let size = 0;
2632
+ stream.on("data", (chunk) => {
2633
+ size += Buffer.byteLength(chunk);
2634
+ });
2635
+ stream.on("close", () => resolve(size));
2636
+ stream.on("error", reject);
2637
+ stream.resume();
2638
+ });
2639
+ function writableDiscardStream(options) {
2640
+ return new Writable({
2641
+ ...options,
2642
+ write(chunk, encding, callback) {
2643
+ setImmediate(callback);
2644
+ }
2645
+ });
2646
+ }
2647
+ const file = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2648
+ __proto__: null,
2649
+ bytesToHumanReadable,
2650
+ bytesToKbytes,
2651
+ getStreamSize,
2652
+ kbytesToBytes,
2653
+ streamToBuffer,
2654
+ writableDiscardStream
2655
+ }, Symbol.toStringTag, { value: "Module" }));
2656
+ const PLUGIN_PREFIX = "plugin::";
2657
+ const API_PREFIX = "api::";
2658
+ const parsePolicy = (policy2) => {
2659
+ if (typeof policy2 === "string") {
2660
+ return { policyName: policy2, config: {} };
2770
2661
  }
2771
- if (typeof fields2 === "string") {
2772
- const fieldsValues = fields2.split(",").map((value2) => _$1.trim(value2));
2773
- return _$1.uniq(["id", ...fieldsValues]);
2662
+ const { name, config } = policy2;
2663
+ return { policyName: name, config };
2664
+ };
2665
+ const searchLocalPolicy = (policyName, policyContext) => {
2666
+ const { pluginName, apiName } = policyContext ?? {};
2667
+ if (pluginName) {
2668
+ return strapi.policy(`${PLUGIN_PREFIX}${pluginName}.${policyName}`);
2774
2669
  }
2775
- if (isStringArray(fields2)) {
2776
- const fieldsValues = fields2.flatMap((value2) => convertFieldsQueryParams(value2, depth + 1)).filter((v) => !isNil(v));
2777
- return _$1.uniq(["id", ...fieldsValues]);
2670
+ if (apiName) {
2671
+ return strapi.policy(`${API_PREFIX}${apiName}.${policyName}`);
2778
2672
  }
2779
- throw new Error("Invalid fields parameter. Expected a string or an array of strings");
2780
2673
  };
2781
- const isValidSchemaAttribute = (key2, schema) => {
2782
- if (key2 === "id") {
2783
- return true;
2674
+ const globalPolicy = ({ method, endpoint, controller, action, plugin }) => {
2675
+ return async (ctx, next) => {
2676
+ ctx.request.route = {
2677
+ endpoint: `${method} ${endpoint}`,
2678
+ controller: _$1.toLower(controller),
2679
+ action: _$1.toLower(action),
2680
+ verb: _$1.toLower(method),
2681
+ plugin
2682
+ };
2683
+ await next();
2684
+ };
2685
+ };
2686
+ const resolvePolicies = (config, policyContext) => {
2687
+ const { pluginName, apiName } = policyContext ?? {};
2688
+ return config.map((policyConfig) => {
2689
+ return {
2690
+ handler: getPolicy(policyConfig, { pluginName, apiName }),
2691
+ config: typeof policyConfig === "object" && policyConfig.config || {}
2692
+ };
2693
+ });
2694
+ };
2695
+ const findPolicy = (name, policyContext) => {
2696
+ const { pluginName, apiName } = policyContext ?? {};
2697
+ const resolvedPolicy = strapi.policy(name);
2698
+ if (resolvedPolicy !== void 0) {
2699
+ return resolvedPolicy;
2784
2700
  }
2785
- if (!schema) {
2786
- return false;
2701
+ const localPolicy = searchLocalPolicy(name, { pluginName, apiName });
2702
+ if (localPolicy !== void 0) {
2703
+ return localPolicy;
2787
2704
  }
2788
- return Object.keys(schema.attributes).includes(key2);
2705
+ throw new Error(`Could not find policy "${name}"`);
2789
2706
  };
2790
- const convertFiltersQueryParams = (filters2, schema) => {
2791
- if (!isObject(filters2)) {
2792
- throw new Error("The filters parameter must be an object or an array");
2707
+ const getPolicy = (policyConfig, policyContext) => {
2708
+ const { pluginName, apiName } = policyContext ?? {};
2709
+ if (typeof policyConfig === "function") {
2710
+ return policyConfig;
2793
2711
  }
2794
- const filtersCopy = cloneDeep(filters2);
2795
- return convertAndSanitizeFilters(filtersCopy, schema);
2796
- };
2797
- const convertAndSanitizeFilters = (filters2, schema) => {
2798
- if (Array.isArray(filters2)) {
2799
- return filters2.map((filter) => convertAndSanitizeFilters(filter, schema)).filter((filter) => !isPlainObject(filter) || !isEmpty(filter));
2712
+ const { policyName, config } = parsePolicy(policyConfig);
2713
+ const policy2 = findPolicy(policyName, { pluginName, apiName });
2714
+ if (typeof policy2 === "function") {
2715
+ return policy2;
2800
2716
  }
2801
- if (!isPlainObject(filters2)) {
2802
- return filters2;
2717
+ if (policy2.validator) {
2718
+ policy2.validator(config);
2803
2719
  }
2804
- const removeOperator = (operator) => delete filters2[operator];
2805
- for (const [key2, value2] of Object.entries(filters2)) {
2806
- const attribute = get(key2, schema?.attributes);
2807
- const validKey = isOperator(key2) || isValidSchemaAttribute(key2, schema);
2808
- if (!validKey) {
2809
- removeOperator(key2);
2810
- } else if (attribute) {
2811
- if (attribute.type === "relation") {
2812
- filters2[key2] = convertAndSanitizeFilters(value2, strapi.getModel(attribute.target));
2813
- } else if (attribute.type === "component") {
2814
- filters2[key2] = convertAndSanitizeFilters(value2, strapi.getModel(attribute.component));
2815
- } else if (attribute.type === "media") {
2816
- filters2[key2] = convertAndSanitizeFilters(value2, strapi.getModel("plugin::upload.file"));
2817
- } else if (attribute.type === "dynamiczone") {
2818
- removeOperator(key2);
2819
- } else if (attribute.type === "password") {
2820
- removeOperator(key2);
2821
- } else {
2822
- filters2[key2] = convertAndSanitizeFilters(value2, schema);
2720
+ return policy2.handler;
2721
+ };
2722
+ const createPolicy = (options) => {
2723
+ const { name = "unnamed", validator, handler } = options;
2724
+ const wrappedValidator = (config) => {
2725
+ if (validator) {
2726
+ try {
2727
+ validator(config);
2728
+ } catch (e) {
2729
+ throw new Error(`Invalid config passed to "${name}" policy.`);
2823
2730
  }
2824
- } else if (["$null", "$notNull"].includes(key2)) {
2825
- filters2[key2] = parseType({ type: "boolean", value: filters2[key2], forceCast: true });
2826
- } else if (isObject(value2)) {
2827
- filters2[key2] = convertAndSanitizeFilters(value2, schema);
2828
2731
  }
2829
- if (isPlainObject(filters2[key2]) && isEmpty(filters2[key2])) {
2830
- removeOperator(key2);
2831
- }
2832
- }
2833
- return filters2;
2732
+ };
2733
+ return {
2734
+ name,
2735
+ validator: wrappedValidator,
2736
+ handler
2737
+ };
2834
2738
  };
2835
- const convertPublicationStateParams = (schema, params = {}, query = {}) => {
2836
- if (!schema) {
2837
- return;
2838
- }
2839
- const { publicationState } = params;
2840
- if (!_$1.isNil(publicationState)) {
2841
- if (!constants$1.DP_PUB_STATES.includes(publicationState)) {
2842
- throw new Error(
2843
- `Invalid publicationState. Expected one of 'preview','live' received: ${publicationState}.`
2844
- );
2845
- }
2846
- query.filters = ({ meta }) => {
2847
- if (publicationState === "live" && has(PUBLISHED_AT_ATTRIBUTE, meta.attributes)) {
2848
- return { [PUBLISHED_AT_ATTRIBUTE]: { $notNull: true } };
2739
+ const createPolicyContext = (type, ctx) => {
2740
+ return Object.assign(
2741
+ {
2742
+ is: eq(type),
2743
+ get type() {
2744
+ return type;
2849
2745
  }
2850
- };
2851
- }
2746
+ },
2747
+ ctx
2748
+ );
2749
+ };
2750
+ const policy = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2751
+ __proto__: null,
2752
+ createPolicy,
2753
+ createPolicyContext,
2754
+ get: getPolicy,
2755
+ globalPolicy,
2756
+ resolve: resolvePolicies
2757
+ }, Symbol.toStringTag, { value: "Module" }));
2758
+ const nameToSlug = (name, options = { separator: "-" }) => slugify(name, options);
2759
+ const nameToCollectionName = (name) => slugify(name, { separator: "_" });
2760
+ const toRegressedEnumValue = (value) => slugify(value, {
2761
+ decamelize: false,
2762
+ lowercase: false,
2763
+ separator: "_"
2764
+ });
2765
+ const getCommonPath = (...paths) => {
2766
+ const [segments, ...otherSegments] = paths.map((it) => _$1.split(it, "/"));
2767
+ return _$1.join(
2768
+ _$1.takeWhile(segments, (str, index2) => otherSegments.every((it) => it[index2] === str)),
2769
+ "/"
2770
+ );
2771
+ };
2772
+ const isEqual = (a, b) => String(a) === String(b);
2773
+ const isCamelCase = (value) => /^[a-z][a-zA-Z0-9]+$/.test(value);
2774
+ const isKebabCase = (value) => /^([a-z][a-z0-9]*)(-[a-z0-9]+)*$/.test(value);
2775
+ const startsWithANumber = (value) => /^[0-9]/.test(value);
2776
+ const joinBy = (joint, ...args) => {
2777
+ const trim2 = trimChars(joint);
2778
+ const trimEnd = trimCharsEnd(joint);
2779
+ const trimStart = trimCharsStart(joint);
2780
+ return args.reduce((url, path, index2) => {
2781
+ if (args.length === 1)
2782
+ return path;
2783
+ if (index2 === 0)
2784
+ return trimEnd(path);
2785
+ if (index2 === args.length - 1)
2786
+ return url + joint + trimStart(path);
2787
+ return url + joint + trim2(path);
2788
+ }, "");
2789
+ };
2790
+ const toKebabCase = (value) => kebabCase(value);
2791
+ const strings = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2792
+ __proto__: null,
2793
+ getCommonPath,
2794
+ isCamelCase,
2795
+ isEqual,
2796
+ isKebabCase,
2797
+ joinBy,
2798
+ nameToCollectionName,
2799
+ nameToSlug,
2800
+ startsWithANumber,
2801
+ toKebabCase,
2802
+ toRegressedEnumValue
2803
+ }, Symbol.toStringTag, { value: "Module" }));
2804
+ const castIncludes = (arr, val, cast) => arr.map((val2) => cast(val2)).includes(cast(val));
2805
+ const includesString = (arr, val) => castIncludes(arr, val, String);
2806
+ const arrays = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2807
+ __proto__: null,
2808
+ includesString
2809
+ }, Symbol.toStringTag, { value: "Module" }));
2810
+ const keysDeep = (obj, path = []) => !_$1.isObject(obj) ? [path.join(".")] : _$1.reduce(
2811
+ obj,
2812
+ (acc, next, key) => _$1.concat(acc, keysDeep(next, [...path, key])),
2813
+ []
2814
+ );
2815
+ const objects = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2816
+ __proto__: null,
2817
+ keysDeep
2818
+ }, Symbol.toStringTag, { value: "Module" }));
2819
+ const timestampCode = (date) => {
2820
+ const referDate = date ?? /* @__PURE__ */ new Date();
2821
+ return referDate.getTime().toString(36);
2852
2822
  };
2853
- const transformParamsToQuery = (uid, params) => {
2854
- const schema = strapi.getModel(uid);
2855
- const query = {};
2856
- const { _q, sort: sort2, filters: filters2, fields: fields2, populate: populate2, page, pageSize, start, limit } = params;
2857
- if (!isNil(_q)) {
2858
- query._q = _q;
2859
- }
2860
- if (!isNil(sort2)) {
2861
- query.orderBy = convertSortQueryParams(sort2);
2862
- }
2863
- if (!isNil(filters2)) {
2864
- query.where = convertFiltersQueryParams(filters2, schema);
2823
+ const dates = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2824
+ __proto__: null,
2825
+ timestampCode
2826
+ }, Symbol.toStringTag, { value: "Module" }));
2827
+ const { toString } = Object.prototype;
2828
+ const errorToString = Error.prototype.toString;
2829
+ const regExpToString = RegExp.prototype.toString;
2830
+ const symbolToString = typeof Symbol !== "undefined" ? Symbol.prototype.toString : () => "";
2831
+ const SYMBOL_REGEXP = /^Symbol\((.*)\)(.*)$/;
2832
+ function printNumber(val) {
2833
+ if (val != +val)
2834
+ return "NaN";
2835
+ const isNegativeZero = val === 0 && 1 / val < 0;
2836
+ return isNegativeZero ? "-0" : `${val}`;
2837
+ }
2838
+ function printSimpleValue(val, quoteStrings = false) {
2839
+ if (val == null || val === true || val === false)
2840
+ return `${val}`;
2841
+ if (typeof val === "number")
2842
+ return printNumber(val);
2843
+ if (typeof val === "string")
2844
+ return quoteStrings ? `"${val}"` : val;
2845
+ if (typeof val === "function")
2846
+ return `[Function ${val.name || "anonymous"}]`;
2847
+ if (typeof val === "symbol")
2848
+ return symbolToString.call(val).replace(SYMBOL_REGEXP, "Symbol($1)");
2849
+ const tag = toString.call(val).slice(8, -1);
2850
+ if (tag === "Date") {
2851
+ const v = val;
2852
+ return Number.isNaN(v.getTime()) ? `${v}` : v.toISOString();
2865
2853
  }
2866
- if (!isNil(fields2)) {
2867
- query.select = convertFieldsQueryParams(fields2);
2854
+ if (tag === "Error" || val instanceof Error)
2855
+ return `[${errorToString.call(val)}]`;
2856
+ if (tag === "RegExp")
2857
+ return regExpToString.call(val);
2858
+ return null;
2859
+ }
2860
+ function printValue(value, quoteStrings) {
2861
+ const result = printSimpleValue(value, quoteStrings);
2862
+ if (result !== null)
2863
+ return result;
2864
+ return JSON.stringify(
2865
+ value,
2866
+ function replacer(key, value2) {
2867
+ const result2 = printSimpleValue(this[key], quoteStrings);
2868
+ if (result2 !== null)
2869
+ return result2;
2870
+ return value2;
2871
+ },
2872
+ 2
2873
+ );
2874
+ }
2875
+ const strapiID = () => new StrapiIDSchema();
2876
+ const isNotNilTest = (value) => !_$1.isNil(value);
2877
+ const isNotNullTest = (value) => !_$1.isNull(value);
2878
+ yup$1.addMethod(yup$1.mixed, "notNil", function isNotNill(msg = "${path} must be defined.") {
2879
+ return this.test("defined", msg, isNotNilTest);
2880
+ });
2881
+ yup$1.addMethod(yup$1.mixed, "notNull", function isNotNull(msg = "${path} cannot be null.") {
2882
+ return this.test("defined", msg, isNotNullTest);
2883
+ });
2884
+ yup$1.addMethod(yup$1.mixed, "isFunction", function isFunction(message = "${path} is not a function") {
2885
+ return this.test(
2886
+ "is a function",
2887
+ message,
2888
+ (value) => _$1.isUndefined(value) || _$1.isFunction(value)
2889
+ );
2890
+ });
2891
+ yup$1.addMethod(
2892
+ yup$1.string,
2893
+ "isCamelCase",
2894
+ function isCamelCase$1(message = "${path} is not in camel case (anExampleOfCamelCase)") {
2895
+ return this.test(
2896
+ "is in camelCase",
2897
+ message,
2898
+ (value) => value ? isCamelCase(value) : true
2899
+ );
2868
2900
  }
2869
- if (!isNil(populate2)) {
2870
- query.populate = convertPopulateQueryParams(populate2, schema);
2901
+ );
2902
+ yup$1.addMethod(
2903
+ yup$1.string,
2904
+ "isKebabCase",
2905
+ function isKebabCase$1(message = "${path} is not in kebab case (an-example-of-kebab-case)") {
2906
+ return this.test(
2907
+ "is in kebab-case",
2908
+ message,
2909
+ (value) => value ? isKebabCase(value) : true
2910
+ );
2871
2911
  }
2872
- validatePaginationParams(page, pageSize, start, limit);
2873
- if (!isNil(page)) {
2874
- query.page = convertPageQueryParams(page);
2912
+ );
2913
+ yup$1.addMethod(
2914
+ yup$1.object,
2915
+ "onlyContainsFunctions",
2916
+ function onlyContainsFunctions(message = "${path} contains values that are not functions") {
2917
+ return this.test(
2918
+ "only contains functions",
2919
+ message,
2920
+ (value) => _$1.isUndefined(value) || value && Object.values(value).every(_$1.isFunction)
2921
+ );
2875
2922
  }
2876
- if (!isNil(pageSize)) {
2877
- query.pageSize = convertPageSizeQueryParams(pageSize, page);
2923
+ );
2924
+ yup$1.addMethod(
2925
+ yup$1.array,
2926
+ "uniqueProperty",
2927
+ function uniqueProperty(propertyName, message) {
2928
+ return this.test("unique", message, function unique(list) {
2929
+ const errors2 = [];
2930
+ list?.forEach((element, index2) => {
2931
+ const sameElements = list.filter(
2932
+ (e) => get(propertyName, e) === get(propertyName, element)
2933
+ );
2934
+ if (sameElements.length > 1) {
2935
+ errors2.push(
2936
+ this.createError({
2937
+ path: `${this.path}[${index2}].${propertyName}`,
2938
+ message
2939
+ })
2940
+ );
2941
+ }
2942
+ });
2943
+ if (errors2.length) {
2944
+ throw new yup$1.ValidationError(errors2);
2945
+ }
2946
+ return true;
2947
+ });
2878
2948
  }
2879
- if (!isNil(start)) {
2880
- query.offset = convertStartQueryParams(start);
2949
+ );
2950
+ class StrapiIDSchema extends yup$1.MixedSchema {
2951
+ constructor() {
2952
+ super({ type: "strapiID" });
2881
2953
  }
2882
- if (!isNil(limit)) {
2883
- query.limit = convertLimitQueryParams(limit);
2954
+ _typeCheck(value) {
2955
+ return typeof value === "string" || isNumber(value) && isInteger(value) && value >= 0;
2884
2956
  }
2885
- convertPublicationStateParams(schema, params, query);
2886
- return query;
2887
- };
2888
- const convertQueryParams = {
2889
- convertSortQueryParams,
2890
- convertStartQueryParams,
2891
- convertLimitQueryParams,
2892
- convertPopulateQueryParams,
2893
- convertFiltersQueryParams,
2894
- convertFieldsQueryParams,
2895
- convertPublicationStateParams,
2896
- transformParamsToQuery
2897
- };
2898
- function importDefault(modName) {
2899
- const mod = require(modName);
2900
- return mod && mod.__esModule ? mod.default : mod;
2901
2957
  }
2902
- const createStrictInterpolationRegExp = (allowedVariableNames, flags) => {
2903
- const oneOfVariables = allowedVariableNames.join("|");
2904
- return new RegExp(`<%=\\s*(${oneOfVariables})\\s*%>`, flags);
2905
- };
2906
- const createLooseInterpolationRegExp = (flags) => new RegExp(/<%=([\s\S]+?)%>/, flags);
2907
- const template = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2908
- __proto__: null,
2909
- createLooseInterpolationRegExp,
2910
- createStrictInterpolationRegExp
2911
- }, Symbol.toStringTag, { value: "Module" }));
2912
- const kbytesToBytes = (kbytes) => kbytes * 1e3;
2913
- const bytesToKbytes = (bytes) => Math.round(bytes / 1e3 * 100) / 100;
2914
- const bytesToHumanReadable = (bytes) => {
2915
- const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB"];
2916
- if (bytes === 0)
2917
- return "0 Bytes";
2918
- const i = parseInt(`${Math.floor(Math.log(bytes) / Math.log(1e3))}`, 10);
2919
- return `${Math.round(bytes / 1e3 ** i)} ${sizes[i]}`;
2920
- };
2921
- const streamToBuffer = (stream) => new Promise((resolve, reject) => {
2922
- const chunks = [];
2923
- stream.on("data", (chunk) => {
2924
- chunks.push(chunk);
2925
- });
2926
- stream.on("end", () => {
2927
- resolve(Buffer.concat(chunks));
2928
- });
2929
- stream.on("error", reject);
2930
- });
2931
- const getStreamSize = (stream) => new Promise((resolve, reject) => {
2932
- let size = 0;
2933
- stream.on("data", (chunk) => {
2934
- size += Buffer.byteLength(chunk);
2935
- });
2936
- stream.on("close", () => resolve(size));
2937
- stream.on("error", reject);
2938
- stream.resume();
2939
- });
2940
- function writableDiscardStream(options) {
2941
- return new Writable({
2942
- ...options,
2943
- write(chunk, encding, callback) {
2944
- setImmediate(callback);
2958
+ yup$1.setLocale({
2959
+ mixed: {
2960
+ notType(options) {
2961
+ const { path, type, value, originalValue } = options;
2962
+ const isCast = originalValue != null && originalValue !== value;
2963
+ const msg = `${path} must be a \`${type}\` type, but the final value was: \`${printValue(value, true)}\`${isCast ? ` (cast from the value \`${printValue(originalValue, true)}\`).` : "."}`;
2964
+ return msg;
2945
2965
  }
2946
- });
2947
- }
2948
- const file = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2949
- __proto__: null,
2950
- bytesToHumanReadable,
2951
- bytesToKbytes,
2952
- getStreamSize,
2953
- kbytesToBytes,
2954
- streamToBuffer,
2955
- writableDiscardStream
2956
- }, Symbol.toStringTag, { value: "Module" }));
2957
- const webhookEvents = {
2958
- ENTRY_CREATE: "entry.create",
2959
- ENTRY_UPDATE: "entry.update",
2960
- ENTRY_DELETE: "entry.delete",
2961
- ENTRY_PUBLISH: "entry.publish",
2962
- ENTRY_UNPUBLISH: "entry.unpublish",
2963
- MEDIA_CREATE: "media.create",
2964
- MEDIA_UPDATE: "media.update",
2965
- MEDIA_DELETE: "media.delete"
2966
- };
2967
- const deprecatedWebhookEvents = new Proxy(webhookEvents, {
2968
- get(target, prop) {
2969
- console.warn(
2970
- "[deprecated] @strapi/utils/webhook will no longer exist in the next major release of Strapi. Instead, the webhookEvents object can be retrieved from strapi.webhookStore.allowedEvents"
2971
- );
2972
- return target[prop];
2973
2966
  }
2974
2967
  });
2975
- const webhook = {
2976
- webhookEvents: deprecatedWebhookEvents
2968
+ const yup = /* @__PURE__ */ _mergeNamespaces({
2969
+ __proto__: null,
2970
+ StrapiIDSchema,
2971
+ strapiID
2972
+ }, [yup$1]);
2973
+ const MANY_RELATIONS = ["oneToMany", "manyToMany"];
2974
+ const getRelationalFields = (contentType) => {
2975
+ return Object.keys(contentType.attributes).filter((attributeName) => {
2976
+ return contentType.attributes[attributeName].type === "relation";
2977
+ });
2978
+ };
2979
+ const isOneToAny = (attribute) => isRelationalAttribute(attribute) && ["oneToOne", "oneToMany"].includes(attribute.relation);
2980
+ const isManyToAny = (attribute) => isRelationalAttribute(attribute) && ["manyToMany", "manyToOne"].includes(attribute.relation);
2981
+ const isAnyToOne = (attribute) => isRelationalAttribute(attribute) && ["oneToOne", "manyToOne"].includes(attribute.relation);
2982
+ const isAnyToMany = (attribute) => isRelationalAttribute(attribute) && ["oneToMany", "manyToMany"].includes(attribute.relation);
2983
+ const constants = {
2984
+ MANY_RELATIONS
2977
2985
  };
2986
+ const relations = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2987
+ __proto__: null,
2988
+ constants,
2989
+ getRelationalFields,
2990
+ isAnyToMany,
2991
+ isAnyToOne,
2992
+ isManyToAny,
2993
+ isOneToAny
2994
+ }, Symbol.toStringTag, { value: "Module" }));
2978
2995
  export {
2996
+ arrays,
2997
+ async,
2979
2998
  contentTypes,
2980
2999
  convertQueryParams,
3000
+ dates,
2981
3001
  env,
2982
3002
  errors,
2983
- escapeQuery,
2984
3003
  file,
2985
- forEachAsync,
2986
- generateTimestampCode,
2987
- getAbsoluteAdminUrl,
2988
- getAbsoluteServerUrl,
2989
- getCommonBeginning,
2990
- getConfigUrls,
2991
- handleYupError,
2992
3004
  hooks,
2993
3005
  importDefault,
2994
- isCamelCase,
2995
- isKebabCase,
2996
3006
  isOperator,
2997
3007
  isOperatorOfType,
2998
- joinBy,
2999
- keysDeep,
3000
- mapAsync,
3001
- nameToCollectionName,
3002
- nameToSlug,
3008
+ machineId as machineID,
3009
+ objects,
3010
+ packageManager,
3003
3011
  pagination,
3004
- parseMultipartData,
3005
3012
  parseType,
3006
- pipeAsync,
3007
3013
  policy,
3008
3014
  providerFactory,
3009
- reduceAsync,
3010
3015
  relations,
3011
- removeUndefined,
3012
3016
  index$1 as sanitize,
3013
3017
  setCreatorFields,
3014
- startsWithANumber,
3015
- stringEquals,
3016
- stringIncludes,
3018
+ strings,
3017
3019
  template,
3018
- templateConfiguration,
3019
- toKebabCase,
3020
- toRegressedEnumValue,
3021
3020
  index$2 as traverse,
3022
3021
  traverseEntity$1 as traverseEntity,
3023
3022
  index as validate,
3024
3023
  validateYupSchema,
3025
3024
  validateYupSchemaSync,
3026
- webhook,
3027
3025
  yup
3028
3026
  };
3029
3027
  //# sourceMappingURL=index.mjs.map