@nocobase/plugin-data-source-main 2.1.0-alpha.21 → 2.1.0-alpha.22

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.
@@ -8,16 +8,16 @@
8
8
  */
9
9
 
10
10
  module.exports = {
11
- "@nocobase/client": "2.1.0-alpha.21",
11
+ "@nocobase/client": "2.1.0-alpha.22",
12
12
  "lodash": "4.18.1",
13
- "@nocobase/ai": "2.1.0-alpha.21",
14
- "@nocobase/database": "2.1.0-alpha.21",
15
- "@nocobase/plugin-error-handler": "2.1.0-alpha.21",
16
- "@nocobase/server": "2.1.0-alpha.21",
13
+ "@nocobase/ai": "2.1.0-alpha.22",
14
+ "@nocobase/database": "2.1.0-alpha.22",
15
+ "@nocobase/plugin-error-handler": "2.1.0-alpha.22",
16
+ "@nocobase/server": "2.1.0-alpha.22",
17
17
  "sequelize": "6.35.2",
18
18
  "@formily/json-schema": "2.3.7",
19
- "@nocobase/test": "2.1.0-alpha.21",
20
- "@nocobase/utils": "2.1.0-alpha.21",
21
- "@nocobase/actions": "2.1.0-alpha.21",
19
+ "@nocobase/test": "2.1.0-alpha.22",
20
+ "@nocobase/utils": "2.1.0-alpha.22",
21
+ "@nocobase/actions": "2.1.0-alpha.22",
22
22
  "dayjs": "1.11.13"
23
23
  };
@@ -219,6 +219,7 @@ function buildTemplateBaseline(input) {
219
219
  }
220
220
  }
221
221
  function normalizeCollectionInput(input, options = {}) {
222
+ var _a, _b;
222
223
  const values = import_lodash.default.cloneDeep(input || {});
223
224
  if ((options.mode || "create") === "create") {
224
225
  values.template = values.template || "general";
@@ -227,6 +228,12 @@ function normalizeCollectionInput(input, options = {}) {
227
228
  if (Array.isArray(values.fields)) {
228
229
  values.fields = values.fields.map((field) => (0, import_fields.normalizeFieldInput)(field, { collectionName: values.name }));
229
230
  }
231
+ if ((options.mode || "create") === "create" && !values.titleField) {
232
+ const primaryKeyField = (_b = (_a = values.fields) == null ? void 0 : _a.find) == null ? void 0 : _b.call(_a, (field) => (field == null ? void 0 : field.primaryKey) === true);
233
+ if (primaryKeyField == null ? void 0 : primaryKeyField.name) {
234
+ values.titleField = primaryKeyField.name;
235
+ }
236
+ }
230
237
  return values;
231
238
  }
232
239
  function composeCollectionDefinition(input, options = {}) {
@@ -14,6 +14,7 @@ export declare const ARRAY_DEFAULT_INTERFACES: Set<string>;
14
14
  export declare const CHOICE_INTERFACES: Set<string>;
15
15
  export declare const RELATION_INTERFACES: Set<string>;
16
16
  export declare const INTERFACE_ALIASES: Record<string, string>;
17
+ export declare const CHOICE_COLOR_OPTIONS: string[];
17
18
  export declare const PLUGIN_REQUIREMENTS: Record<string, {
18
19
  runtimeName: string;
19
20
  packageName: string;
@@ -21,4 +22,5 @@ export declare const PLUGIN_REQUIREMENTS: Record<string, {
21
22
  }>;
22
23
  export declare function toDisplayTitle(value?: string): string;
23
24
  export declare function normalizeChoiceEnum(enumValues?: any[]): any[];
25
+ export declare function validateChoiceEnumColors(enumValues?: any[], fieldName?: string): void;
24
26
  export declare function uniqueByName(fields: PlainObject[]): PlainObject[];
@@ -37,6 +37,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
37
37
  var constants_exports = {};
38
38
  __export(constants_exports, {
39
39
  ARRAY_DEFAULT_INTERFACES: () => ARRAY_DEFAULT_INTERFACES,
40
+ CHOICE_COLOR_OPTIONS: () => CHOICE_COLOR_OPTIONS,
40
41
  CHOICE_INTERFACES: () => CHOICE_INTERFACES,
41
42
  INTERFACE_ALIASES: () => INTERFACE_ALIASES,
42
43
  MULTI_COMPONENT_INTERFACES: () => MULTI_COMPONENT_INTERFACES,
@@ -45,7 +46,8 @@ __export(constants_exports, {
45
46
  TEMPLATE_NAMES: () => TEMPLATE_NAMES,
46
47
  normalizeChoiceEnum: () => normalizeChoiceEnum,
47
48
  toDisplayTitle: () => toDisplayTitle,
48
- uniqueByName: () => uniqueByName
49
+ uniqueByName: () => uniqueByName,
50
+ validateChoiceEnumColors: () => validateChoiceEnumColors
49
51
  });
50
52
  module.exports = __toCommonJS(constants_exports);
51
53
  var import_lodash = __toESM(require("lodash"));
@@ -75,6 +77,21 @@ const INTERFACE_ALIASES = {
75
77
  unixTs: "unixTimestamp",
76
78
  o2o: "obo"
77
79
  };
80
+ const CHOICE_COLOR_OPTIONS = [
81
+ "red",
82
+ "magenta",
83
+ "volcano",
84
+ "orange",
85
+ "gold",
86
+ "lime",
87
+ "green",
88
+ "cyan",
89
+ "blue",
90
+ "geekblue",
91
+ "purple",
92
+ "default"
93
+ ];
94
+ const CHOICE_COLOR_OPTION_SET = new Set(CHOICE_COLOR_OPTIONS);
78
95
  const PLUGIN_REQUIREMENTS = {
79
96
  file: {
80
97
  runtimeName: "file-manager",
@@ -169,12 +186,32 @@ function normalizeChoiceEnum(enumValues = []) {
169
186
  };
170
187
  });
171
188
  }
189
+ function validateChoiceEnumColors(enumValues = [], fieldName = "(unknown)") {
190
+ const allowedColors = CHOICE_COLOR_OPTIONS.join(", ");
191
+ enumValues.forEach((item, index) => {
192
+ if (!import_lodash.default.isPlainObject(item)) {
193
+ throw new Error(
194
+ `Field ${fieldName} enum item #${index + 1} must be an object with value, label, and color; string shorthand is not allowed`
195
+ );
196
+ }
197
+ const optionName = item.value ?? item.label ?? `#${index + 1}`;
198
+ if (!item.color) {
199
+ throw new Error(`Field ${fieldName} enum item ${optionName} requires color`);
200
+ }
201
+ if (!CHOICE_COLOR_OPTION_SET.has(item.color)) {
202
+ throw new Error(
203
+ `Field ${fieldName} enum item ${optionName} color ${item.color} is invalid. Allowed colors: ${allowedColors}`
204
+ );
205
+ }
206
+ });
207
+ }
172
208
  function uniqueByName(fields) {
173
209
  return import_lodash.default.uniqBy(fields.filter(Boolean).reverse(), "name").reverse();
174
210
  }
175
211
  // Annotate the CommonJS export names for ESM import in node:
176
212
  0 && (module.exports = {
177
213
  ARRAY_DEFAULT_INTERFACES,
214
+ CHOICE_COLOR_OPTIONS,
178
215
  CHOICE_INTERFACES,
179
216
  INTERFACE_ALIASES,
180
217
  MULTI_COMPONENT_INTERFACES,
@@ -183,5 +220,6 @@ function uniqueByName(fields) {
183
220
  TEMPLATE_NAMES,
184
221
  normalizeChoiceEnum,
185
222
  toDisplayTitle,
186
- uniqueByName
223
+ uniqueByName,
224
+ validateChoiceEnumColors
187
225
  });
@@ -8,5 +8,6 @@
8
8
  */
9
9
  import { PlainObject } from './constants';
10
10
  export declare function normalizeInterfaceName(value?: string): string;
11
+ export declare function validateChoiceFieldInput(field?: PlainObject): void;
11
12
  export declare function normalizeFieldInput(input: PlainObject, context?: PlainObject): PlainObject;
12
13
  export declare function normalizeFieldList(fields?: PlainObject[], collectionName?: string): PlainObject[];
@@ -38,7 +38,8 @@ var fields_exports = {};
38
38
  __export(fields_exports, {
39
39
  normalizeFieldInput: () => normalizeFieldInput,
40
40
  normalizeFieldList: () => normalizeFieldList,
41
- normalizeInterfaceName: () => normalizeInterfaceName
41
+ normalizeInterfaceName: () => normalizeInterfaceName,
42
+ validateChoiceFieldInput: () => validateChoiceFieldInput
42
43
  });
43
44
  module.exports = __toCommonJS(fields_exports);
44
45
  var import_lodash = __toESM(require("lodash"));
@@ -438,6 +439,27 @@ function buildReverseField(field) {
438
439
  { collectionName: field.target }
439
440
  );
440
441
  }
442
+ function getChoiceEnumInput(field) {
443
+ var _a;
444
+ if (Array.isArray(field == null ? void 0 : field.enum)) {
445
+ return field.enum;
446
+ }
447
+ if (Array.isArray((_a = field == null ? void 0 : field.uiSchema) == null ? void 0 : _a.enum)) {
448
+ return field.uiSchema.enum;
449
+ }
450
+ return [];
451
+ }
452
+ function validateChoiceFieldInput(field = {}) {
453
+ const interfaceName = normalizeInterfaceName(field.interface);
454
+ if (!import_constants.CHOICE_INTERFACES.has(interfaceName)) {
455
+ return;
456
+ }
457
+ const enumValues = getChoiceEnumInput(field);
458
+ if (!enumValues.length) {
459
+ return;
460
+ }
461
+ (0, import_constants.validateChoiceEnumColors)(enumValues, field.name || "(unknown)");
462
+ }
441
463
  function normalizeFieldInput(input, context = {}) {
442
464
  var _a, _b;
443
465
  const field = import_lodash.default.cloneDeep(input || {});
@@ -539,5 +561,6 @@ function normalizeFieldList(fields = [], collectionName) {
539
561
  0 && (module.exports = {
540
562
  normalizeFieldInput,
541
563
  normalizeFieldList,
542
- normalizeInterfaceName
564
+ normalizeInterfaceName,
565
+ validateChoiceFieldInput
543
566
  });
@@ -44,6 +44,12 @@ function mergeSettings(input = {}) {
44
44
  ...rest
45
45
  };
46
46
  }
47
+ function validateApplyFieldInputs(fields) {
48
+ if (!Array.isArray(fields)) {
49
+ return;
50
+ }
51
+ fields.forEach((field) => (0, import_fields.validateChoiceFieldInput)(field));
52
+ }
47
53
  async function findCollection(ctx, collectionName) {
48
54
  return ctx.app.db.getRepository("collections").findOne({
49
55
  filter: {
@@ -67,6 +73,7 @@ async function upsertFieldDefinition(ctx, rawInput) {
67
73
  if (!collectionName) {
68
74
  throw new Error("field apply requires collectionName");
69
75
  }
76
+ (0, import_fields.validateChoiceFieldInput)(input);
70
77
  const values = (0, import_fields.normalizeFieldInput)(input, { collectionName });
71
78
  await (0, import_capabilities.assertModelingSupport)(ctx.app, { fields: [values] });
72
79
  const repository = ctx.app.db.getRepository("fields");
@@ -111,6 +118,7 @@ async function applyCollectionDefinition(ctx, rawInput, syncCollectionFields) {
111
118
  if (!collectionName) {
112
119
  throw new Error("collections:apply requires name");
113
120
  }
121
+ validateApplyFieldInputs(input.fields);
114
122
  const existing = await findCollection(ctx, collectionName);
115
123
  if (!existing) {
116
124
  const values = (0, import_collections.composeCollectionDefinition)({ ...input, name: collectionName }, { mode: "create" });
@@ -406,6 +406,7 @@ class PluginDataSourceMainServer extends import_server.Plugin {
406
406
  this.db.getRepository("collections").setApp(this.app);
407
407
  this.registerErrorHandler();
408
408
  (0, import_mcp_post_processors.registerDataSourceMainMcpPostProcessors)(this.ai.mcpToolsManager);
409
+ this.app.auditManager.registerActions(["collections:apply", "fields:apply"]);
409
410
  this.app.resourceManager.use(async function mergeReverseFieldWhenSaveCollectionField(ctx, next) {
410
411
  if (ctx.action.resourceName === "collections.fields" && ["create", "update"].includes(ctx.action.actionName)) {
411
412
  ctx.action.mergeParams({
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "description": "NocoBase main database, supports relational databases such as PostgreSQL, MySQL, MariaDB and so on.",
7
7
  "description.ru-RU": "Основная база данных NocoBase: поддерживает реляционные СУБД, включая PostgreSQL, MySQL, MariaDB и другие.",
8
8
  "description.zh-CN": "NocoBase 主数据库,支持 PostgreSQL、MySQL、MariaDB 等关系型数据库。",
9
- "version": "2.1.0-alpha.21",
9
+ "version": "2.1.0-alpha.22",
10
10
  "main": "./dist/server/index.js",
11
11
  "homepage": "https://docs.nocobase.com/handbook/data-source-main",
12
12
  "homepage.ru-RU": "https://docs-ru.nocobase.com/handbook/data-source-main",
@@ -25,7 +25,7 @@
25
25
  "@nocobase/test": "2.x",
26
26
  "@nocobase/utils": "2.x"
27
27
  },
28
- "gitHead": "b4c2b469f321ecaec7863a8ae371a02fe6a35aa2",
28
+ "gitHead": "81ed83f158f172cca607b36beaf8428b14ba16ad",
29
29
  "keywords": [
30
30
  "Data sources"
31
31
  ]