@strapi/utils 5.0.0-beta.7 → 5.0.0-beta.9

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.
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as _ from "lodash";
2
2
  import ___default, { kebabCase } from "lodash";
3
3
  import * as dates$1 from "date-fns";
4
- import { has, union, getOr, assoc, assign, cloneDeep, remove, eq, curry, isObject, isNil, clone, isArray, isEmpty, toPath, defaults, isString, mergeAll, get, toNumber, isInteger, pick, omit, trim, pipe as pipe$1, split, map as map$1, flatten, first, identity, constant, join, merge, trimChars, trimCharsEnd, trimCharsStart, isNumber } from "lodash/fp";
4
+ import { has, union, getOr, assoc, assign, cloneDeep, remove, eq, curry, isObject, isNil, clone, isArray, isEmpty, toPath, defaults, isString, get, toNumber, isInteger, pick, omit, trim, pipe as pipe$1, split, map as map$1, flatten, first, identity, constant, join, merge, trimChars, trimCharsEnd, trimCharsStart, isNumber } from "lodash/fp";
5
5
  import { randomUUID } from "crypto";
6
6
  import { machineIdSync } from "node-machine-id";
7
7
  import * as yup$1 from "yup";
@@ -314,6 +314,9 @@ const isPrivateAttribute = (model, attributeName) => {
314
314
  const isScalarAttribute = (attribute) => {
315
315
  return attribute && !["media", "component", "relation", "dynamiczone"].includes(attribute.type);
316
316
  };
317
+ const getDoesAttributeRequireValidation = (attribute) => {
318
+ return attribute.required || attribute.unique || Object.prototype.hasOwnProperty.call(attribute, "max") || Object.prototype.hasOwnProperty.call(attribute, "min") || Object.prototype.hasOwnProperty.call(attribute, "maxLength") || Object.prototype.hasOwnProperty.call(attribute, "minLength");
319
+ };
317
320
  const isMediaAttribute = (attribute) => attribute?.type === "media";
318
321
  const isRelationalAttribute = (attribute) => attribute?.type === "relation";
319
322
  const HAS_RELATION_REORDERING = ["manyToMany", "manyToOne", "oneToMany"];
@@ -368,6 +371,7 @@ const contentTypes = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.define
368
371
  getComponentAttributes,
369
372
  getContentTypeRoutePrefix,
370
373
  getCreatorFields,
374
+ getDoesAttributeRequireValidation,
371
375
  getNonVisibleAttributes,
372
376
  getNonWritableAttributes,
373
377
  getOptions,
@@ -1020,27 +1024,45 @@ const createTransformer = ({ getModel }) => {
1020
1024
  }
1021
1025
  throw new InvalidPopulateError();
1022
1026
  };
1023
- const hasFragmentPopulateDefined = (populate2) => {
1027
+ const hasPopulateFragmentDefined = (populate2) => {
1024
1028
  return typeof populate2 === "object" && "on" in populate2 && !isNil(populate2.on);
1025
1029
  };
1030
+ const hasCountDefined = (populate2) => {
1031
+ return typeof populate2 === "object" && "count" in populate2 && typeof populate2.count === "boolean";
1032
+ };
1026
1033
  const convertPopulateObject = (populate2, schema) => {
1027
1034
  if (!schema) {
1028
1035
  return {};
1029
1036
  }
1030
1037
  const { attributes } = schema;
1031
1038
  return Object.entries(populate2).reduce((acc, [key, subPopulate]) => {
1039
+ if (___default.isString(subPopulate)) {
1040
+ try {
1041
+ const subPopulateAsBoolean = parseType({ type: "boolean", value: subPopulate });
1042
+ return subPopulateAsBoolean === true ? { ...acc, [key]: true } : acc;
1043
+ } catch {
1044
+ }
1045
+ }
1032
1046
  if (___default.isBoolean(subPopulate)) {
1033
- return { ...acc, [key]: subPopulate };
1047
+ return subPopulate === true ? { ...acc, [key]: true } : acc;
1034
1048
  }
1035
1049
  const attribute = attributes[key];
1036
1050
  if (!attribute) {
1037
1051
  return acc;
1038
1052
  }
1039
- const isAllowedAttributeForFragmentPopulate = isDynamicZoneAttribute(attribute) || isMorphToRelationalAttribute(attribute);
1040
- if (isAllowedAttributeForFragmentPopulate && hasFragmentPopulateDefined(subPopulate)) {
1041
- return {
1042
- ...acc,
1043
- [key]: {
1053
+ const isMorphLikeRelationalAttribute = isDynamicZoneAttribute(attribute) || isMorphToRelationalAttribute(attribute);
1054
+ if (isMorphLikeRelationalAttribute) {
1055
+ const hasInvalidProperties = Object.keys(subPopulate).some(
1056
+ (key2) => !["on", "count"].includes(key2)
1057
+ );
1058
+ if (hasInvalidProperties) {
1059
+ throw new Error(
1060
+ `Invalid nested populate for ${schema.info?.singularName}.${key} (${schema.uid}). Expected a fragment ("on") or "count" but found ${JSON.stringify(subPopulate)}`
1061
+ );
1062
+ }
1063
+ const newSubPopulate = {};
1064
+ if (hasPopulateFragmentDefined(subPopulate)) {
1065
+ Object.assign(newSubPopulate, {
1044
1066
  on: Object.entries(subPopulate.on).reduce(
1045
1067
  (acc2, [type, typeSubPopulate]) => ({
1046
1068
  ...acc2,
@@ -1048,21 +1070,15 @@ const createTransformer = ({ getModel }) => {
1048
1070
  }),
1049
1071
  {}
1050
1072
  )
1051
- }
1052
- };
1053
- }
1054
- if (isDynamicZoneAttribute(attribute)) {
1055
- const populates = attribute.components.map((uid) => getModel(uid)).map((schema2) => convertNestedPopulate(subPopulate, schema2)).map((populate22) => populate22 === true ? {} : populate22).filter((populate22) => populate22 !== false);
1056
- if (isEmpty(populates)) {
1057
- return acc;
1073
+ });
1058
1074
  }
1059
- return {
1060
- ...acc,
1061
- [key]: mergeAll(populates)
1062
- };
1075
+ if (hasCountDefined(subPopulate)) {
1076
+ Object.assign(newSubPopulate, { count: subPopulate.count });
1077
+ }
1078
+ return { ...acc, [key]: newSubPopulate };
1063
1079
  }
1064
- if (isMorphToRelationalAttribute(attribute)) {
1065
- return { ...acc, [key]: convertNestedPopulate(subPopulate, void 0) };
1080
+ if (!isMorphLikeRelationalAttribute && hasPopulateFragmentDefined(subPopulate)) {
1081
+ throw new Error(`Using fragments is not permitted to populate "${key}" in "${schema.uid}"`);
1066
1082
  }
1067
1083
  let targetSchemaUID;
1068
1084
  if (attribute.type === "relation") {
@@ -1818,7 +1834,8 @@ const populate = traverseFactory().intercept(isStringArray$1, async (visitor2, o
1818
1834
  return;
1819
1835
  }
1820
1836
  const newValue2 = await recurse(visitor2, { schema, path, getModel }, { on: value?.on });
1821
- set(key, { on: newValue2 });
1837
+ set(key, newValue2);
1838
+ return;
1822
1839
  }
1823
1840
  const targetSchemaUID = attribute.target;
1824
1841
  const targetSchema = getModel(targetSchemaUID);
@@ -1840,36 +1857,15 @@ const populate = traverseFactory().intercept(isStringArray$1, async (visitor2, o
1840
1857
  const targetSchema = getModel(attribute.component);
1841
1858
  const newValue = await recurse(visitor2, { schema: targetSchema, path, getModel }, value);
1842
1859
  set(key, newValue);
1843
- }).onDynamicZone(
1844
- async ({ key, value, attribute, schema, visitor: visitor2, path, getModel }, { set, recurse }) => {
1845
- if (isNil(value)) {
1846
- return;
1847
- }
1848
- if (isObject(value)) {
1849
- const { components } = attribute;
1850
- const newValue = {};
1851
- let newProperties = omit("on", value);
1852
- for (const componentUID of components) {
1853
- const componentSchema = getModel(componentUID);
1854
- const properties = await recurse(
1855
- visitor2,
1856
- { schema: componentSchema, path, getModel },
1857
- value
1858
- );
1859
- newProperties = merge(newProperties, properties);
1860
- }
1861
- Object.assign(newValue, newProperties);
1862
- if ("on" in value && value.on) {
1863
- const newOn = await recurse(visitor2, { schema, path, getModel }, { on: value.on });
1864
- Object.assign(newValue, newOn);
1865
- }
1866
- set(key, newValue);
1867
- } else {
1868
- const newValue = await recurse(visitor2, { schema, path, getModel }, value);
1869
- set(key, newValue);
1870
- }
1860
+ }).onDynamicZone(async ({ key, value, schema, visitor: visitor2, path, getModel }, { set, recurse }) => {
1861
+ if (isNil(value) || !isObject(value)) {
1862
+ return;
1871
1863
  }
1872
- );
1864
+ if ("on" in value && value.on) {
1865
+ const newOn = await recurse(visitor2, { schema, path, getModel }, { on: value.on });
1866
+ set(key, newOn);
1867
+ }
1868
+ });
1873
1869
  const traverseQueryPopulate = curry(populate.traverse);
1874
1870
  const isStringArray = (value) => isArray(value) && value.every(isString);
1875
1871
  const fields = traverseFactory().intercept(isStringArray, async (visitor2, options, fields2, { recurse }) => {