@strapi/content-type-builder 5.0.0-rc.2 → 5.0.0-rc.21

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 (34) hide show
  1. package/dist/_chunks/{ListView-XE65NvP8.js → ListView-BJkF062E.js} +21 -16
  2. package/dist/_chunks/ListView-BJkF062E.js.map +1 -0
  3. package/dist/_chunks/{ListView-yYLey9cN.mjs → ListView-ChHlVW9E.mjs} +21 -16
  4. package/dist/_chunks/ListView-ChHlVW9E.mjs.map +1 -0
  5. package/dist/_chunks/{index-BUl4iZYG.mjs → index-CclXDFWL.mjs} +10 -9
  6. package/dist/_chunks/{index-BUl4iZYG.mjs.map → index-CclXDFWL.mjs.map} +1 -1
  7. package/dist/_chunks/{index--5pQbGLD.js → index-DJuRylRg.js} +170 -60
  8. package/dist/_chunks/index-DJuRylRg.js.map +1 -0
  9. package/dist/_chunks/{index-b5GKS0j7.mjs → index-DoESWWlo.mjs} +171 -61
  10. package/dist/_chunks/index-DoESWWlo.mjs.map +1 -0
  11. package/dist/_chunks/{index-CcKr65ti.js → index-DrmFbRLA.js} +10 -9
  12. package/dist/_chunks/{index-CcKr65ti.js.map → index-DrmFbRLA.js.map} +1 -1
  13. package/dist/admin/index.js +1 -1
  14. package/dist/admin/index.mjs +1 -1
  15. package/dist/admin/src/components/FormModalNavigationProvider/constants.d.ts +1 -0
  16. package/dist/admin/src/contexts/FormModalNavigationContext.d.ts +2 -0
  17. package/dist/admin/src/utils/parseDateValue.d.ts +1 -0
  18. package/dist/admin/src/utils/timeFormat.d.ts +16 -0
  19. package/dist/server/index.js +91 -54
  20. package/dist/server/index.js.map +1 -1
  21. package/dist/server/index.mjs +92 -55
  22. package/dist/server/index.mjs.map +1 -1
  23. package/dist/server/src/controllers/validation/model-schema.d.ts.map +1 -1
  24. package/dist/server/src/services/builder.d.ts +4 -0
  25. package/dist/server/src/services/builder.d.ts.map +1 -1
  26. package/dist/server/src/services/constants.d.ts +0 -1
  27. package/dist/server/src/services/constants.d.ts.map +1 -1
  28. package/dist/server/src/services/schema-builder/content-type-builder.d.ts.map +1 -1
  29. package/package.json +9 -8
  30. package/dist/_chunks/ListView-XE65NvP8.js.map +0 -1
  31. package/dist/_chunks/ListView-yYLey9cN.mjs.map +0 -1
  32. package/dist/_chunks/index--5pQbGLD.js.map +0 -1
  33. package/dist/_chunks/index-b5GKS0j7.mjs.map +0 -1
  34. package/strapi-server.js +0 -3
@@ -460,7 +460,6 @@ const DEFAULT_TYPES = [
460
460
  "relation"
461
461
  ];
462
462
  const VALID_UID_TARGETS = ["string", "text"];
463
- const FORBIDDEN_ATTRIBUTE_NAMES = ["__component", "__contentType"];
464
463
  const coreUids = {
465
464
  STRAPI_USER: "admin::user",
466
465
  PREFIX: "strapi::"
@@ -551,7 +550,16 @@ function createComponentBuilder() {
551
550
  const attribute = infos.attributes[key];
552
551
  if (isRelation(attribute)) {
553
552
  if (["manyToMany", "oneToOne"].includes(attribute.relation)) {
554
- attribute.dominant = true;
553
+ if (attribute.target === uid && attribute.targetAttribute !== void 0) {
554
+ const targetAttribute = infos.attributes[attribute.targetAttribute];
555
+ if (targetAttribute.dominant === void 0) {
556
+ attribute.dominant = true;
557
+ } else {
558
+ attribute.dominant = false;
559
+ }
560
+ } else {
561
+ attribute.dominant = true;
562
+ }
555
563
  }
556
564
  this.setRelation({
557
565
  key,
@@ -619,7 +627,16 @@ function createComponentBuilder() {
619
627
  const attribute = newAttributes[key];
620
628
  if (isRelation(attribute)) {
621
629
  if (["manyToMany", "oneToOne"].includes(attribute.relation)) {
622
- attribute.dominant = true;
630
+ if (attribute.target === uid && attribute.targetAttribute !== void 0) {
631
+ const targetAttribute = newAttributes[attribute.targetAttribute];
632
+ if (targetAttribute.dominant === void 0) {
633
+ attribute.dominant = true;
634
+ } else {
635
+ attribute.dominant = false;
636
+ }
637
+ } else {
638
+ attribute.dominant = true;
639
+ }
623
640
  }
624
641
  this.setRelation({
625
642
  key,
@@ -1143,50 +1160,80 @@ const componentCategories$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Obje
1143
1160
  deleteCategory,
1144
1161
  editCategory
1145
1162
  }, Symbol.toStringTag, { value: "Module" }));
1163
+ const reservedAttributes = [
1164
+ // TODO: these need to come from a centralized place so we don't break things accidentally in the future and can share them outside the CTB, for example on Strapi bootstrap prior to schema db sync
1165
+ // ID fields
1166
+ "id",
1167
+ "document_id",
1168
+ // Creator fields
1169
+ "created_at",
1170
+ "updated_at",
1171
+ "published_at",
1172
+ "created_by_id",
1173
+ "updated_by_id",
1174
+ // does not actually conflict because the fields are called *_by_id but we'll leave it to avoid confusion
1175
+ "created_by",
1176
+ "updated_by",
1177
+ // Used for Strapi functionality
1178
+ "entry_id",
1179
+ "status",
1180
+ "localizations",
1181
+ "meta",
1182
+ "locale",
1183
+ "__component",
1184
+ "__contentType",
1185
+ // We support ending with * to denote prefixes
1186
+ "strapi*",
1187
+ "_strapi*",
1188
+ "__strapi*"
1189
+ ];
1190
+ const reservedModels = [
1191
+ "boolean",
1192
+ "date",
1193
+ "date_time",
1194
+ "time",
1195
+ "upload",
1196
+ "document",
1197
+ "then",
1198
+ // no longer an issue but still restricting for being a javascript keyword
1199
+ // We support ending with * to denote prefixes
1200
+ "strapi*",
1201
+ "_strapi*",
1202
+ "__strapi*"
1203
+ ];
1146
1204
  const getReservedNames = () => {
1147
1205
  return {
1148
- // use kebab case everywhere since singularName and pluralName are validated that way
1149
- models: [
1150
- "boolean",
1151
- "date",
1152
- "date-time",
1153
- "time",
1154
- "upload",
1155
- "document",
1156
- "then"
1157
- // no longer an issue but still restricting for being a javascript keyword
1158
- ],
1159
- // attributes are compared with snake_case(name), so only snake_case is needed here and camelCase + UPPER_CASE matches will still be caught
1160
- attributes: [
1161
- // TODO: these need to come from a centralized place so we don't break things accidentally in the future and can share them outside the CTB, for example on Strapi bootstrap prior to schema db sync
1162
- // ID fields
1163
- "id",
1164
- "document_id",
1165
- // Creator fields
1166
- "created_at",
1167
- "updated_at",
1168
- "published_at",
1169
- "created_by_id",
1170
- "updated_by_id",
1171
- // does not actually conflict because the fields are called *_by_id but we'll leave it to avoid confusion
1172
- "created_by",
1173
- "updated_by",
1174
- // Used for Strapi functionality
1175
- "entry_id",
1176
- "status",
1177
- "localizations",
1178
- "meta",
1179
- "locale",
1180
- // TODO: remove these in favor of restricting the strapi_ prefix
1181
- "strapi",
1182
- "strapi_stage",
1183
- "strapi_assignee"
1184
- ]
1206
+ models: reservedModels,
1207
+ attributes: reservedAttributes
1185
1208
  };
1186
1209
  };
1210
+ const isReservedModelName = (name) => {
1211
+ const snakeCaseName = fp.snakeCase(name);
1212
+ if (reservedModels.includes(snakeCaseName)) {
1213
+ return true;
1214
+ }
1215
+ if (reservedModels.filter((key) => key.endsWith("*")).map((key) => key.slice(0, -1)).some((prefix) => snakeCaseName.startsWith(prefix))) {
1216
+ return true;
1217
+ }
1218
+ return false;
1219
+ };
1220
+ const isReservedAttributeName = (name) => {
1221
+ const snakeCaseName = fp.snakeCase(name);
1222
+ if (reservedAttributes.includes(snakeCaseName)) {
1223
+ return true;
1224
+ }
1225
+ if (reservedAttributes.filter((key) => key.endsWith("*")).map((key) => key.slice(0, -1)).some((prefix) => snakeCaseName.startsWith(prefix))) {
1226
+ return true;
1227
+ }
1228
+ return false;
1229
+ };
1187
1230
  const builder$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1188
1231
  __proto__: null,
1189
- getReservedNames
1232
+ getReservedNames,
1233
+ isReservedAttributeName,
1234
+ isReservedModelName,
1235
+ reservedAttributes,
1236
+ reservedModels
1190
1237
  }, Symbol.toStringTag, { value: "Module" }));
1191
1238
  async function clear(uid) {
1192
1239
  const { apiName, modelName } = strapi.contentTypes[uid];
@@ -1649,20 +1696,10 @@ const isConflictingKey = (key, attributes) => {
1649
1696
  });
1650
1697
  };
1651
1698
  const isForbiddenKey = (key) => {
1652
- const snakeCaseKey = fp.snakeCase(key);
1653
- const reservedNames = [
1654
- ...FORBIDDEN_ATTRIBUTE_NAMES,
1655
- ...getService("builder").getReservedNames().attributes
1656
- ];
1657
- return reservedNames.some((reserved) => {
1658
- return fp.snakeCase(reserved) === snakeCaseKey;
1659
- });
1699
+ return getService("builder").isReservedAttributeName(key);
1660
1700
  };
1661
1701
  const forbiddenValidator = () => {
1662
- const reservedNames = [
1663
- ...FORBIDDEN_ATTRIBUTE_NAMES,
1664
- ...getService("builder").getReservedNames().attributes
1665
- ];
1702
+ const reservedNames = [...getService("builder").getReservedNames().attributes];
1666
1703
  return utils.yup.mixed().test({
1667
1704
  name: "forbiddenKeys",
1668
1705
  message: `Attribute keys cannot be one of ${reservedNames.join(", ")}`,
@@ -1930,7 +1967,7 @@ const forbiddenContentTypeNameValidator = () => {
1930
1967
  if (typeof value !== "string") {
1931
1968
  return true;
1932
1969
  }
1933
- return reservedNames.every((reservedName) => fp.snakeCase(reservedName) !== fp.snakeCase(value));
1970
+ return !getService("builder").isReservedModelName(value);
1934
1971
  }
1935
1972
  };
1936
1973
  };