@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
@@ -1,5 +1,5 @@
1
1
  import _, { get, has } from "lodash";
2
- import { getOr, isUndefined, snakeCase, has as has$1, flatMap } from "lodash/fp";
2
+ import { getOr, snakeCase, isUndefined, has as has$1, flatMap } from "lodash/fp";
3
3
  import utils, { errors, strings, contentTypes as contentTypes$2, yup, validateYupSchema } from "@strapi/utils";
4
4
  import * as path from "path";
5
5
  import path__default, { join } from "path";
@@ -437,7 +437,6 @@ const DEFAULT_TYPES = [
437
437
  "relation"
438
438
  ];
439
439
  const VALID_UID_TARGETS = ["string", "text"];
440
- const FORBIDDEN_ATTRIBUTE_NAMES = ["__component", "__contentType"];
441
440
  const coreUids = {
442
441
  STRAPI_USER: "admin::user",
443
442
  PREFIX: "strapi::"
@@ -528,7 +527,16 @@ function createComponentBuilder() {
528
527
  const attribute = infos.attributes[key];
529
528
  if (isRelation(attribute)) {
530
529
  if (["manyToMany", "oneToOne"].includes(attribute.relation)) {
531
- attribute.dominant = true;
530
+ if (attribute.target === uid && attribute.targetAttribute !== void 0) {
531
+ const targetAttribute = infos.attributes[attribute.targetAttribute];
532
+ if (targetAttribute.dominant === void 0) {
533
+ attribute.dominant = true;
534
+ } else {
535
+ attribute.dominant = false;
536
+ }
537
+ } else {
538
+ attribute.dominant = true;
539
+ }
532
540
  }
533
541
  this.setRelation({
534
542
  key,
@@ -596,7 +604,16 @@ function createComponentBuilder() {
596
604
  const attribute = newAttributes[key];
597
605
  if (isRelation(attribute)) {
598
606
  if (["manyToMany", "oneToOne"].includes(attribute.relation)) {
599
- attribute.dominant = true;
607
+ if (attribute.target === uid && attribute.targetAttribute !== void 0) {
608
+ const targetAttribute = newAttributes[attribute.targetAttribute];
609
+ if (targetAttribute.dominant === void 0) {
610
+ attribute.dominant = true;
611
+ } else {
612
+ attribute.dominant = false;
613
+ }
614
+ } else {
615
+ attribute.dominant = true;
616
+ }
600
617
  }
601
618
  this.setRelation({
602
619
  key,
@@ -1120,50 +1137,80 @@ const componentCategories$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Obje
1120
1137
  deleteCategory,
1121
1138
  editCategory
1122
1139
  }, Symbol.toStringTag, { value: "Module" }));
1140
+ const reservedAttributes = [
1141
+ // 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
1142
+ // ID fields
1143
+ "id",
1144
+ "document_id",
1145
+ // Creator fields
1146
+ "created_at",
1147
+ "updated_at",
1148
+ "published_at",
1149
+ "created_by_id",
1150
+ "updated_by_id",
1151
+ // does not actually conflict because the fields are called *_by_id but we'll leave it to avoid confusion
1152
+ "created_by",
1153
+ "updated_by",
1154
+ // Used for Strapi functionality
1155
+ "entry_id",
1156
+ "status",
1157
+ "localizations",
1158
+ "meta",
1159
+ "locale",
1160
+ "__component",
1161
+ "__contentType",
1162
+ // We support ending with * to denote prefixes
1163
+ "strapi*",
1164
+ "_strapi*",
1165
+ "__strapi*"
1166
+ ];
1167
+ const reservedModels = [
1168
+ "boolean",
1169
+ "date",
1170
+ "date_time",
1171
+ "time",
1172
+ "upload",
1173
+ "document",
1174
+ "then",
1175
+ // no longer an issue but still restricting for being a javascript keyword
1176
+ // We support ending with * to denote prefixes
1177
+ "strapi*",
1178
+ "_strapi*",
1179
+ "__strapi*"
1180
+ ];
1123
1181
  const getReservedNames = () => {
1124
1182
  return {
1125
- // use kebab case everywhere since singularName and pluralName are validated that way
1126
- models: [
1127
- "boolean",
1128
- "date",
1129
- "date-time",
1130
- "time",
1131
- "upload",
1132
- "document",
1133
- "then"
1134
- // no longer an issue but still restricting for being a javascript keyword
1135
- ],
1136
- // attributes are compared with snake_case(name), so only snake_case is needed here and camelCase + UPPER_CASE matches will still be caught
1137
- attributes: [
1138
- // 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
1139
- // ID fields
1140
- "id",
1141
- "document_id",
1142
- // Creator fields
1143
- "created_at",
1144
- "updated_at",
1145
- "published_at",
1146
- "created_by_id",
1147
- "updated_by_id",
1148
- // does not actually conflict because the fields are called *_by_id but we'll leave it to avoid confusion
1149
- "created_by",
1150
- "updated_by",
1151
- // Used for Strapi functionality
1152
- "entry_id",
1153
- "status",
1154
- "localizations",
1155
- "meta",
1156
- "locale",
1157
- // TODO: remove these in favor of restricting the strapi_ prefix
1158
- "strapi",
1159
- "strapi_stage",
1160
- "strapi_assignee"
1161
- ]
1183
+ models: reservedModels,
1184
+ attributes: reservedAttributes
1162
1185
  };
1163
1186
  };
1187
+ const isReservedModelName = (name) => {
1188
+ const snakeCaseName = snakeCase(name);
1189
+ if (reservedModels.includes(snakeCaseName)) {
1190
+ return true;
1191
+ }
1192
+ if (reservedModels.filter((key) => key.endsWith("*")).map((key) => key.slice(0, -1)).some((prefix) => snakeCaseName.startsWith(prefix))) {
1193
+ return true;
1194
+ }
1195
+ return false;
1196
+ };
1197
+ const isReservedAttributeName = (name) => {
1198
+ const snakeCaseName = snakeCase(name);
1199
+ if (reservedAttributes.includes(snakeCaseName)) {
1200
+ return true;
1201
+ }
1202
+ if (reservedAttributes.filter((key) => key.endsWith("*")).map((key) => key.slice(0, -1)).some((prefix) => snakeCaseName.startsWith(prefix))) {
1203
+ return true;
1204
+ }
1205
+ return false;
1206
+ };
1164
1207
  const builder$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1165
1208
  __proto__: null,
1166
- getReservedNames
1209
+ getReservedNames,
1210
+ isReservedAttributeName,
1211
+ isReservedModelName,
1212
+ reservedAttributes,
1213
+ reservedModels
1167
1214
  }, Symbol.toStringTag, { value: "Module" }));
1168
1215
  async function clear(uid) {
1169
1216
  const { apiName, modelName } = strapi.contentTypes[uid];
@@ -1626,20 +1673,10 @@ const isConflictingKey = (key, attributes) => {
1626
1673
  });
1627
1674
  };
1628
1675
  const isForbiddenKey = (key) => {
1629
- const snakeCaseKey = snakeCase(key);
1630
- const reservedNames = [
1631
- ...FORBIDDEN_ATTRIBUTE_NAMES,
1632
- ...getService("builder").getReservedNames().attributes
1633
- ];
1634
- return reservedNames.some((reserved) => {
1635
- return snakeCase(reserved) === snakeCaseKey;
1636
- });
1676
+ return getService("builder").isReservedAttributeName(key);
1637
1677
  };
1638
1678
  const forbiddenValidator = () => {
1639
- const reservedNames = [
1640
- ...FORBIDDEN_ATTRIBUTE_NAMES,
1641
- ...getService("builder").getReservedNames().attributes
1642
- ];
1679
+ const reservedNames = [...getService("builder").getReservedNames().attributes];
1643
1680
  return yup.mixed().test({
1644
1681
  name: "forbiddenKeys",
1645
1682
  message: `Attribute keys cannot be one of ${reservedNames.join(", ")}`,
@@ -1907,7 +1944,7 @@ const forbiddenContentTypeNameValidator = () => {
1907
1944
  if (typeof value !== "string") {
1908
1945
  return true;
1909
1946
  }
1910
- return reservedNames.every((reservedName) => snakeCase(reservedName) !== snakeCase(value));
1947
+ return !getService("builder").isReservedModelName(value);
1911
1948
  }
1912
1949
  };
1913
1950
  };