@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.
- package/dist/_chunks/{ListView-XE65NvP8.js → ListView-BJkF062E.js} +21 -16
- package/dist/_chunks/ListView-BJkF062E.js.map +1 -0
- package/dist/_chunks/{ListView-yYLey9cN.mjs → ListView-ChHlVW9E.mjs} +21 -16
- package/dist/_chunks/ListView-ChHlVW9E.mjs.map +1 -0
- package/dist/_chunks/{index-BUl4iZYG.mjs → index-CclXDFWL.mjs} +10 -9
- package/dist/_chunks/{index-BUl4iZYG.mjs.map → index-CclXDFWL.mjs.map} +1 -1
- package/dist/_chunks/{index--5pQbGLD.js → index-DJuRylRg.js} +170 -60
- package/dist/_chunks/index-DJuRylRg.js.map +1 -0
- package/dist/_chunks/{index-b5GKS0j7.mjs → index-DoESWWlo.mjs} +171 -61
- package/dist/_chunks/index-DoESWWlo.mjs.map +1 -0
- package/dist/_chunks/{index-CcKr65ti.js → index-DrmFbRLA.js} +10 -9
- package/dist/_chunks/{index-CcKr65ti.js.map → index-DrmFbRLA.js.map} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/components/FormModalNavigationProvider/constants.d.ts +1 -0
- package/dist/admin/src/contexts/FormModalNavigationContext.d.ts +2 -0
- package/dist/admin/src/utils/parseDateValue.d.ts +1 -0
- package/dist/admin/src/utils/timeFormat.d.ts +16 -0
- package/dist/server/index.js +91 -54
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +92 -55
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/controllers/validation/model-schema.d.ts.map +1 -1
- package/dist/server/src/services/builder.d.ts +4 -0
- package/dist/server/src/services/builder.d.ts.map +1 -1
- package/dist/server/src/services/constants.d.ts +0 -1
- package/dist/server/src/services/constants.d.ts.map +1 -1
- package/dist/server/src/services/schema-builder/content-type-builder.d.ts.map +1 -1
- package/package.json +9 -8
- package/dist/_chunks/ListView-XE65NvP8.js.map +0 -1
- package/dist/_chunks/ListView-yYLey9cN.mjs.map +0 -1
- package/dist/_chunks/index--5pQbGLD.js.map +0 -1
- package/dist/_chunks/index-b5GKS0j7.mjs.map +0 -1
- package/strapi-server.js +0 -3
package/dist/server/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _, { get, has } from "lodash";
|
|
2
|
-
import { getOr,
|
|
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.
|
|
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.
|
|
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
|
-
|
|
1126
|
-
|
|
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
|
-
|
|
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
|
|
1947
|
+
return !getService("builder").isReservedModelName(value);
|
|
1911
1948
|
}
|
|
1912
1949
|
};
|
|
1913
1950
|
};
|