@nocobase/plugin-flow-engine 2.1.0-alpha.25 → 2.1.0-alpha.27

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 (40) hide show
  1. package/dist/ai/ai-employees/nathan/index.js +1 -0
  2. package/dist/ai/ai-employees/nathan/prompt.md +46 -10
  3. package/dist/ai/ai-employees/nathan/skills/frontend-developer/SKILLS.md +20 -3
  4. package/dist/ai/ai-employees/nathan/skills/frontend-developer/tools/lintAndTestJS.js +4 -2
  5. package/dist/ai/ai-employees/nathan/skills/frontend-developer/tools/patchJSCode.d.ts +10 -0
  6. package/dist/ai/ai-employees/nathan/skills/frontend-developer/tools/patchJSCode.js +65 -0
  7. package/dist/ai/ai-employees/nathan/skills/frontend-developer/tools/readJSCode.d.ts +10 -0
  8. package/dist/ai/ai-employees/nathan/skills/frontend-developer/tools/readJSCode.js +61 -0
  9. package/dist/ai/ai-employees/nathan/skills/frontend-developer/tools/writeJSCode.d.ts +10 -0
  10. package/dist/ai/ai-employees/nathan/skills/frontend-developer/tools/writeJSCode.js +65 -0
  11. package/dist/externalVersion.js +10 -10
  12. package/dist/node_modules/ses/package.json +1 -1
  13. package/dist/node_modules/zod/package.json +1 -1
  14. package/dist/server/flow-surfaces/blueprint/compile-blocks.js +66 -9
  15. package/dist/server/flow-surfaces/blueprint/normalize-document.js +5 -14
  16. package/dist/server/flow-surfaces/blueprint/private-utils.d.ts +0 -1
  17. package/dist/server/flow-surfaces/blueprint/private-utils.js +0 -3
  18. package/dist/server/flow-surfaces/blueprint/public-types.d.ts +0 -1
  19. package/dist/server/flow-surfaces/builder.js +18 -0
  20. package/dist/server/flow-surfaces/catalog.js +19 -24
  21. package/dist/server/flow-surfaces/compose-compiler.d.ts +1 -2
  22. package/dist/server/flow-surfaces/compose-compiler.js +0 -1
  23. package/dist/server/flow-surfaces/compose-runtime.d.ts +1 -0
  24. package/dist/server/flow-surfaces/compose-runtime.js +2 -1
  25. package/dist/server/flow-surfaces/configure-options.js +12 -5
  26. package/dist/server/flow-surfaces/contract-guard.js +11 -3
  27. package/dist/server/flow-surfaces/field-binding-registry.js +1 -1
  28. package/dist/server/flow-surfaces/field-type-resolver.d.ts +0 -1
  29. package/dist/server/flow-surfaces/field-type-resolver.js +3 -13
  30. package/dist/server/flow-surfaces/public-compatibility.d.ts +16 -0
  31. package/dist/server/flow-surfaces/public-compatibility.js +139 -0
  32. package/dist/server/flow-surfaces/service-helpers.js +2 -2
  33. package/dist/server/flow-surfaces/service-utils.d.ts +1 -1
  34. package/dist/server/flow-surfaces/service-utils.js +21 -6
  35. package/dist/server/flow-surfaces/service.d.ts +23 -3
  36. package/dist/server/flow-surfaces/service.js +720 -167
  37. package/dist/swagger/flow-surfaces.d.ts +0 -29
  38. package/dist/swagger/flow-surfaces.js +8 -17
  39. package/dist/swagger/index.d.ts +0 -29
  40. package/package.json +2 -2
@@ -123,27 +123,18 @@ function normalizeNavigation(input) {
123
123
  if (!import_lodash.default.isUndefined(routeId) && !import_lodash.default.isString(routeId) && !import_lodash.default.isNumber(routeId)) {
124
124
  (0, import_errors.throwBadRequest)(`flowSurfaces applyBlueprint navigation.group.routeId must be a string or integer`);
125
125
  }
126
- if (!import_lodash.default.isUndefined(routeId) && (0, import_private_utils.readString)(input.group.title)) {
127
- (0, import_errors.throwBadRequest)(`flowSurfaces applyBlueprint navigation.group cannot mix routeId with title`);
128
- }
129
- const routeMetadataKeys = import_private_utils.APPLY_BLUEPRINT_CREATE_MENU_GROUP_METADATA_KEYS.filter(
130
- (key) => !import_lodash.default.isUndefined(input.group[key])
131
- );
132
- if (!import_lodash.default.isUndefined(routeId) && routeMetadataKeys.length) {
133
- (0, import_errors.throwBadRequest)(
134
- `flowSurfaces applyBlueprint navigation.group.routeId cannot mix with ${routeMetadataKeys.map((key) => `navigation.group.${key}`).join(
135
- ", "
136
- )}; applyBlueprint create mode does not update existing menu-group metadata. Use flowSurfaces:updateMenu separately if needed`
137
- );
126
+ if (!import_lodash.default.isUndefined(routeId)) {
127
+ return {
128
+ routeId
129
+ };
138
130
  }
139
131
  const normalized2 = (0, import_service_utils.buildDefinedPayload)({
140
- routeId: import_lodash.default.isUndefined(routeId) ? void 0 : routeId,
141
132
  title: (0, import_private_utils.readOptionalString)(input.group.title),
142
133
  icon: (0, import_private_utils.readOptionalString)(input.group.icon),
143
134
  tooltip: (0, import_private_utils.readOptionalString)(input.group.tooltip),
144
135
  hideInMenu: (0, import_private_utils.readBoolean)(input.group.hideInMenu, "flowSurfaces applyBlueprint navigation.group.hideInMenu")
145
136
  });
146
- if (import_lodash.default.isUndefined(normalized2.routeId) && !normalized2.title) {
137
+ if (!normalized2.title) {
147
138
  (0, import_errors.throwBadRequest)(`flowSurfaces applyBlueprint navigation.group requires routeId or title`);
148
139
  }
149
140
  return normalized2;
@@ -7,7 +7,6 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
  import type { FlowSurfaceApplyBlueprintAssetMap } from './public-types';
10
- export declare const APPLY_BLUEPRINT_CREATE_MENU_GROUP_METADATA_KEYS: readonly ["icon", "tooltip", "hideInMenu"];
11
10
  export declare function assertPlainObject(value: any, context: string): void;
12
11
  export declare function assertOnlyAllowedKeys(input: Record<string, any>, context: string, allowedKeys: string[]): void;
13
12
  export declare function normalizeApplyBlueprintToken(value: any, fallback?: string): string;
@@ -36,7 +36,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
36
36
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
37
37
  var private_utils_exports = {};
38
38
  __export(private_utils_exports, {
39
- APPLY_BLUEPRINT_CREATE_MENU_GROUP_METADATA_KEYS: () => APPLY_BLUEPRINT_CREATE_MENU_GROUP_METADATA_KEYS,
40
39
  assertNonEmptyString: () => assertNonEmptyString,
41
40
  assertOnlyAllowedKeys: () => assertOnlyAllowedKeys,
42
41
  assertPlainObject: () => assertPlainObject,
@@ -56,7 +55,6 @@ module.exports = __toCommonJS(private_utils_exports);
56
55
  var import_lodash = __toESM(require("lodash"));
57
56
  var import_errors = require("../errors");
58
57
  var import_service_utils = require("../service-utils");
59
- const APPLY_BLUEPRINT_CREATE_MENU_GROUP_METADATA_KEYS = ["icon", "tooltip", "hideInMenu"];
60
58
  function assertPlainObject(value, context) {
61
59
  if (!import_lodash.default.isPlainObject(value)) {
62
60
  (0, import_errors.throwBadRequest)(`${context} must be an object`);
@@ -164,7 +162,6 @@ function normalizeAssetRegistry(input, context) {
164
162
  }
165
163
  // Annotate the CommonJS export names for ESM import in node:
166
164
  0 && (module.exports = {
167
- APPLY_BLUEPRINT_CREATE_MENU_GROUP_METADATA_KEYS,
168
165
  assertNonEmptyString,
169
166
  assertOnlyAllowedKeys,
170
167
  assertPlainObject,
@@ -87,7 +87,6 @@ export type FlowSurfaceApplyBlueprintFieldObjectSpec = {
87
87
  type?: string;
88
88
  fieldType?: string;
89
89
  fields?: string[];
90
- selectorFields?: string[];
91
90
  titleField?: string;
92
91
  openMode?: string;
93
92
  popupSize?: string;
@@ -1030,6 +1030,24 @@ function buildBlockDefaults(use) {
1030
1030
  defaultView: "month",
1031
1031
  enableQuickCreateEvent: true,
1032
1032
  weekStart: 1
1033
+ },
1034
+ stepParams: {
1035
+ cardSettings: {
1036
+ blockHeight: {
1037
+ heightMode: "fullHeight"
1038
+ }
1039
+ }
1040
+ }
1041
+ };
1042
+ }
1043
+ if (use === "KanbanBlockModel") {
1044
+ return {
1045
+ stepParams: {
1046
+ cardSettings: {
1047
+ blockHeight: {
1048
+ heightMode: "fullHeight"
1049
+ }
1050
+ }
1033
1051
  }
1034
1052
  };
1035
1053
  }
@@ -72,6 +72,10 @@ const OPEN_VIEW_SCENE_SCHEMA = {
72
72
  const OBJECT_SCHEMA = { type: "object" };
73
73
  const NUMBER_SCHEMA = { type: "number" };
74
74
  const ARRAY_SCHEMA = { type: "array" };
75
+ const BLOCK_HEIGHT_MODE_SCHEMA = {
76
+ type: "string",
77
+ enum: ["defaultHeight", "specifyValue", "fullHeight"]
78
+ };
75
79
  const NULLABLE_NUMBER_OR_STRING_SCHEMA = {
76
80
  oneOf: [NUMBER_SCHEMA, NULLABLE_STRING_SCHEMA]
77
81
  };
@@ -295,13 +299,21 @@ const FILTER_FORM_BLOCK_SETTINGS_GROUP = {
295
299
  }
296
300
  };
297
301
  const BLOCK_CARD_SETTINGS_GROUP = {
298
- allowedPaths: ["titleDescription.title", "titleDescription.description", "linkageRules"],
302
+ allowedPaths: [
303
+ "titleDescription.title",
304
+ "titleDescription.description",
305
+ "blockHeight.heightMode",
306
+ "blockHeight.height",
307
+ "linkageRules"
308
+ ],
299
309
  clearable: true,
300
310
  mergeStrategy: "deep",
301
- eventBindingSteps: ["titleDescription", "linkageRules"],
311
+ eventBindingSteps: ["titleDescription", "blockHeight", "linkageRules"],
302
312
  pathSchemas: {
303
313
  "titleDescription.title": STRING_SCHEMA,
304
314
  "titleDescription.description": STRING_SCHEMA,
315
+ "blockHeight.heightMode": BLOCK_HEIGHT_MODE_SCHEMA,
316
+ "blockHeight.height": NUMBER_SCHEMA,
305
317
  linkageRules: ARRAY_SCHEMA
306
318
  }
307
319
  };
@@ -833,8 +845,6 @@ TAB_NODE_CONTRACT.domains.stepParams = groupedDomain({
833
845
  });
834
846
  const TABLE_BLOCK_CONTRACT = createContract({
835
847
  editableDomains: ["props", "decoratorProps", "stepParams", "flowRegistry"],
836
- props: ["height", "heightMode"],
837
- decoratorProps: ["height", "heightMode"],
838
848
  stepParams: ["resourceSettings", "tableSettings", "cardSettings"],
839
849
  flowRegistry: true,
840
850
  eventCapabilities: {
@@ -942,7 +952,6 @@ const CALENDAR_BLOCK_CONTRACT = createContract({
942
952
  "quickCreatePopupSettings",
943
953
  "eventPopupSettings"
944
954
  ],
945
- decoratorProps: ["height", "heightMode"],
946
955
  stepParams: ["resourceSettings", "calendarSettings", "cardSettings"],
947
956
  flowRegistry: true,
948
957
  eventCapabilities: {
@@ -958,7 +967,6 @@ CALENDAR_BLOCK_CONTRACT.domains.stepParams = groupedDomain({
958
967
  const TREE_BLOCK_CONTRACT = createContract({
959
968
  editableDomains: ["props", "decoratorProps", "stepParams", "flowRegistry"],
960
969
  props: ["searchable", "defaultExpandAll", "includeDescendants", "fieldNames", "pageSize"],
961
- decoratorProps: ["height", "heightMode"],
962
970
  stepParams: ["resourceSettings", "treeSettings", "cardSettings"],
963
971
  flowRegistry: true,
964
972
  eventCapabilities: {
@@ -997,7 +1005,6 @@ const KANBAN_BLOCK_CONTRACT = createContract({
997
1005
  "pageSize",
998
1006
  "columnWidth"
999
1007
  ],
1000
- decoratorProps: ["height", "heightMode"],
1001
1008
  stepParams: ["resourceSettings", "kanbanSettings", "cardSettings"],
1002
1009
  flowRegistry: true,
1003
1010
  eventCapabilities: {
@@ -1013,7 +1020,6 @@ KANBAN_BLOCK_CONTRACT.domains.stepParams = groupedDomain({
1013
1020
  const LIST_BLOCK_CONTRACT = createContract({
1014
1021
  editableDomains: ["props", "decoratorProps", "stepParams", "flowRegistry"],
1015
1022
  props: [],
1016
- decoratorProps: ["height", "heightMode"],
1017
1023
  stepParams: ["resourceSettings", "listSettings", "cardSettings"],
1018
1024
  flowRegistry: true,
1019
1025
  eventCapabilities: {
@@ -1053,7 +1059,6 @@ LIST_BLOCK_CONTRACT.domains.stepParams = groupedDomain({
1053
1059
  const GRID_CARD_BLOCK_CONTRACT = createContract({
1054
1060
  editableDomains: ["props", "decoratorProps", "stepParams", "flowRegistry"],
1055
1061
  props: [],
1056
- decoratorProps: ["height", "heightMode"],
1057
1062
  stepParams: ["resourceSettings", "GridCardSettings", "cardSettings"],
1058
1063
  flowRegistry: true,
1059
1064
  eventCapabilities: {
@@ -1217,22 +1222,12 @@ IFRAME_BLOCK_CONTRACT.domains.stepParams = groupedDomain({
1217
1222
  }
1218
1223
  });
1219
1224
  const CHART_CARD_SETTINGS_GROUP = {
1220
- allowedPaths: [
1221
- "titleDescription.title",
1222
- "titleDescription.description",
1223
- "blockHeight.heightMode",
1224
- "blockHeight.height",
1225
- "linkageRules"
1226
- ],
1225
+ allowedPaths: BLOCK_CARD_SETTINGS_GROUP.allowedPaths,
1227
1226
  clearable: true,
1228
1227
  mergeStrategy: "deep",
1229
- eventBindingSteps: ["titleDescription", "blockHeight", "linkageRules"],
1228
+ eventBindingSteps: BLOCK_CARD_SETTINGS_GROUP.eventBindingSteps,
1230
1229
  pathSchemas: {
1231
- "titleDescription.title": STRING_SCHEMA,
1232
- "titleDescription.description": STRING_SCHEMA,
1233
- "blockHeight.heightMode": STRING_SCHEMA,
1234
- "blockHeight.height": NUMBER_SCHEMA,
1235
- linkageRules: ARRAY_SCHEMA
1230
+ ...BLOCK_CARD_SETTINGS_GROUP.pathSchemas
1236
1231
  }
1237
1232
  };
1238
1233
  const CHART_BLOCK_CONTRACT = createContract({
@@ -1294,8 +1289,7 @@ JS_BLOCK_CONTRACT.domains.stepParams = groupedDomain({
1294
1289
  });
1295
1290
  const MAP_BLOCK_CONTRACT = createContract({
1296
1291
  editableDomains: ["props", "decoratorProps", "stepParams", "flowRegistry"],
1297
- props: ["height", "heightMode", "mapField", "marker", "lineSort", "zoom"],
1298
- decoratorProps: ["height", "heightMode"],
1292
+ props: ["mapField", "marker", "lineSort", "zoom"],
1299
1293
  stepParams: ["resourceSettings", "createMapBlock", "cardSettings"],
1300
1294
  flowRegistry: true,
1301
1295
  eventCapabilities: {
@@ -2440,6 +2434,7 @@ const NODE_CONTRACT_ENTRIES = [
2440
2434
  ["TriggerBlockGridModel", GRID_NODE_CONTRACT],
2441
2435
  ["ApprovalBlockGridModel", GRID_NODE_CONTRACT],
2442
2436
  ["TableBlockModel", TABLE_BLOCK_CONTRACT],
2437
+ ["TableSelectModel", TABLE_BLOCK_CONTRACT],
2443
2438
  ["CalendarBlockModel", CALENDAR_BLOCK_CONTRACT],
2444
2439
  ["TreeBlockModel", TREE_BLOCK_CONTRACT],
2445
2440
  ["KanbanBlockModel", KANBAN_BLOCK_CONTRACT],
@@ -25,7 +25,6 @@ export type FlowSurfaceComposeNormalizedFieldSpec = {
25
25
  type?: string;
26
26
  fieldType?: string;
27
27
  fields?: string[];
28
- selectorFields?: string[];
29
28
  titleField?: string;
30
29
  openMode?: string;
31
30
  popupSize?: string;
@@ -113,4 +112,4 @@ export declare function compileComposeExecutionPlan(input: {
113
112
  layout?: FlowSurfaceComposeObject;
114
113
  }): FlowSurfaceCompiledComposePlan;
115
114
  export declare function resolveComposeFieldContainerSource(blockSpec: Pick<FlowSurfaceComposeNormalizedBlockSpec, 'type'>): 'block' | 'item';
116
- export declare function resolveComposeTargetKey(targetKey: string, keyMap: Record<string, FlowSurfaceComposeTargetKey | undefined>, kind: 'field' | 'layout'): string;
115
+ export declare function resolveComposeTargetKey(targetKey: string, keyMap: Record<string, FlowSurfaceComposeTargetKey | undefined>, kind: 'field' | 'layout' | 'tree connectFields'): string;
@@ -125,7 +125,6 @@ function buildComposeFieldCreatePayload(fieldSpec) {
125
125
  ...fieldSpec.type ? { type: fieldSpec.type } : {},
126
126
  ...fieldSpec.fieldType ? { fieldType: fieldSpec.fieldType } : {},
127
127
  ...typeof fieldSpec.fields !== "undefined" ? { fields: fieldSpec.fields } : {},
128
- ...typeof fieldSpec.selectorFields !== "undefined" ? { selectorFields: fieldSpec.selectorFields } : {},
129
128
  ...fieldSpec.titleField ? { titleField: fieldSpec.titleField } : {},
130
129
  ...fieldSpec.openMode ? { openMode: fieldSpec.openMode } : {},
131
130
  ...fieldSpec.popupSize ? { popupSize: fieldSpec.popupSize } : {},
@@ -66,6 +66,7 @@ export type FlowSurfaceComposeRuntimeDeps = {
66
66
  removeExistingItem?: (uid: string) => Promise<void>;
67
67
  createBlock: (payload: Record<string, unknown>, spec: FlowSurfaceComposeNormalizedBlockSpec) => Promise<FlowSurfaceComposeBlockResult>;
68
68
  applyNodeSettings?: (actionName: string, targetUid: string | undefined, settings?: FlowSurfaceComposeObject) => Promise<void>;
69
+ resolveBlockSettings?: (settings: FlowSurfaceComposeObject, state: FlowSurfaceComposeRuntimeState, block: FlowSurfaceComposeRuntimeBlockState) => FlowSurfaceComposeObject | Promise<FlowSurfaceComposeObject>;
69
70
  createField: (payload: Record<string, unknown>, spec: FlowSurfaceComposeNormalizedFieldSpec, blockResult: FlowSurfaceComposeBlockResult) => Promise<FlowSurfaceComposeFieldResult | null>;
70
71
  applyFieldSettings?: (actionName: string, result: FlowSurfaceComposeFieldResult, settings?: FlowSurfaceComposeObject) => Promise<void>;
71
72
  onFieldError?: (input: {
@@ -142,7 +142,8 @@ async function applyBlockSettings(deps, state) {
142
142
  if (!hasInlineSettings(block.spec.settings)) {
143
143
  continue;
144
144
  }
145
- await applyNodeSettings("compose block", block.result.uid, block.spec.settings);
145
+ const settings = deps.resolveBlockSettings ? await deps.resolveBlockSettings(block.spec.settings || {}, state, block) : block.spec.settings;
146
+ await applyNodeSettings("compose block", block.result.uid, settings);
146
147
  }
147
148
  }
148
149
  async function createFields(plan, deps, state) {
@@ -80,6 +80,16 @@ const SORTING = arrayOption("Sorting rule array", {
80
80
  }
81
81
  ]
82
82
  });
83
+ const CONNECT_FIELDS = objectOption("Tree connect data block targets", {
84
+ example: {
85
+ targets: [
86
+ {
87
+ targetId: "target-block-uid",
88
+ filterPaths: ["id"]
89
+ }
90
+ ]
91
+ }
92
+ });
83
93
  const OPEN_VIEW = objectOption("Popup or drawer open configuration", {
84
94
  example: {
85
95
  dataSourceKey: "main",
@@ -98,13 +108,9 @@ const FIELD_TYPE = stringOption("Public relation field presentation type", {
98
108
  const RELATION_FIELDS = arrayOption("Relation target fields", {
99
109
  example: ["title", "name"]
100
110
  });
101
- const SELECTOR_FIELDS = arrayOption("Record picker selector fields", {
102
- example: ["title", "code"]
103
- });
104
111
  const RELATION_FIELD_TYPE_OPTIONS = {
105
112
  fieldType: FIELD_TYPE,
106
113
  fields: RELATION_FIELDS,
107
- selectorFields: SELECTOR_FIELDS,
108
114
  openMode: stringOption("Popup open mode", { example: "drawer" }),
109
115
  popupSize: stringOption("Popup size", { example: "medium" }),
110
116
  pageSize: numberOption("Page size", { example: 10 }),
@@ -247,7 +253,8 @@ const TREE_OPTIONS = {
247
253
  fieldNames: objectOption("Tree field names", { example: { title: "title", key: "id", children: "children" } }),
248
254
  pageSize: numberOption("Root records per page", { example: 200 }),
249
255
  dataScope: FILTER_GROUP,
250
- sorting: SORTING
256
+ sorting: SORTING,
257
+ connectFields: CONNECT_FIELDS
251
258
  };
252
259
  const KANBAN_OPTIONS = {
253
260
  ...COMMON_BLOCK_HEADER_OPTIONS,
@@ -53,7 +53,7 @@ class FlowSurfaceContractGuard {
53
53
  if (!Object.keys(nextValue).length) {
54
54
  return {};
55
55
  }
56
- return contract.mergeStrategy === "replace" ? import_lodash.default.cloneDeep(nextValue) : import_lodash.default.merge({}, currentValue || {}, nextValue);
56
+ return contract.mergeStrategy === "replace" ? import_lodash.default.cloneDeep(nextValue) : mergeFlowSurfaceSettingsValue(currentValue || {}, nextValue);
57
57
  }
58
58
  if (contract.groups) {
59
59
  const unknownGroups = Object.keys(nextValue).filter((key) => !contract.allowedKeys.includes(key));
@@ -108,7 +108,7 @@ class FlowSurfaceContractGuard {
108
108
  )}`
109
109
  );
110
110
  }
111
- next2[groupKey] = groupContract.mergeStrategy === "replace" ? import_lodash.default.cloneDeep(normalizedValue2) : import_lodash.default.merge({}, (currentValue == null ? void 0 : currentValue[groupKey]) || {}, normalizedValue2);
111
+ next2[groupKey] = groupContract.mergeStrategy === "replace" ? import_lodash.default.cloneDeep(normalizedValue2) : mergeFlowSurfaceSettingsValue((currentValue == null ? void 0 : currentValue[groupKey]) || {}, normalizedValue2);
112
112
  });
113
113
  return next2;
114
114
  }
@@ -135,7 +135,7 @@ class FlowSurfaceContractGuard {
135
135
  }
136
136
  const next = import_lodash.default.cloneDeep(currentValue || {});
137
137
  Object.entries(normalizedValue).forEach(([key, value]) => {
138
- next[key] = contract.mergeStrategy === "replace" || !import_lodash.default.isPlainObject(value) || !Object.keys(value).length ? import_lodash.default.cloneDeep(value) : import_lodash.default.merge({}, (currentValue == null ? void 0 : currentValue[key]) || {}, value);
138
+ next[key] = contract.mergeStrategy === "replace" || !import_lodash.default.isPlainObject(value) || !Object.keys(value).length ? import_lodash.default.cloneDeep(value) : mergeFlowSurfaceSettingsValue((currentValue == null ? void 0 : currentValue[key]) || {}, value);
139
139
  });
140
140
  return next;
141
141
  }
@@ -275,6 +275,14 @@ class FlowSurfaceContractGuard {
275
275
  });
276
276
  }
277
277
  }
278
+ function mergeFlowSurfaceSettingsValue(currentValue, nextValue) {
279
+ return import_lodash.default.mergeWith({}, currentValue || {}, nextValue, (_current, next) => {
280
+ if (Array.isArray(next)) {
281
+ return import_lodash.default.cloneDeep(next);
282
+ }
283
+ return void 0;
284
+ });
285
+ }
278
286
  function matchesContractPath(pattern, path) {
279
287
  if (pattern === "*") {
280
288
  return true;
@@ -103,7 +103,7 @@ const FIELD_BINDING_RULE_DEFINITIONS = [
103
103
  {
104
104
  scope: "display",
105
105
  modelClassName: "DisplayPreviewFieldModel",
106
- interfaces: ["url", "attachment", "attachmentURL", "m2m", "m2o", "o2o", "o2m", "oho", "obo", "mbm"],
106
+ interfaces: ["attachment", "attachmentURL", "m2m", "m2o", "o2o", "o2m", "oho", "obo", "mbm"],
107
107
  ownerPlugin: FILE_MANAGER_PLUGIN,
108
108
  isDefault: true,
109
109
  when: ({ field, targetCollection }) => isAttachmentInterface(field) || !targetCollection || getCollectionTemplate(targetCollection) === "file"
@@ -22,7 +22,6 @@ export declare function resolveRelationFieldType(input: {
22
22
  dataSourceKey: string;
23
23
  getCollection: (dataSourceKey: string, collectionName: string) => any;
24
24
  fields?: any;
25
- selectorFields?: any;
26
25
  titleField?: any;
27
26
  openMode?: any;
28
27
  popupSize?: any;
@@ -93,6 +93,7 @@ const FIELD_USE_TO_PUBLIC_FIELD_TYPE = {
93
93
  PopupSubTableFieldModel: "popupSubTable"
94
94
  };
95
95
  const FIELD_TYPES_WITH_FIELDS = /* @__PURE__ */ new Set([
96
+ "picker",
96
97
  "subForm",
97
98
  "subFormList",
98
99
  "subDetails",
@@ -100,7 +101,6 @@ const FIELD_TYPES_WITH_FIELDS = /* @__PURE__ */ new Set([
100
101
  "subTable",
101
102
  "popupSubTable"
102
103
  ]);
103
- const FIELD_TYPES_WITH_SELECTOR_FIELDS = /* @__PURE__ */ new Set(["picker"]);
104
104
  const FIELD_TYPES_WITH_TABLE_PROPS = /* @__PURE__ */ new Set(["subTable", "popupSubTable"]);
105
105
  function assertNoInternalFieldKeys(input, context) {
106
106
  if (!import_lodash.default.isPlainObject(input)) {
@@ -250,16 +250,9 @@ function resolveRelationFieldType(input) {
250
250
  break;
251
251
  }
252
252
  const explicitFields = normalizePublicFieldNameList(input.fields, `${input.context}.fields`);
253
- const explicitSelectorFields = normalizePublicFieldNameList(input.selectorFields, `${input.context}.selectorFields`);
254
- if (explicitFields && explicitSelectorFields) {
255
- (0, import_errors.throwBadRequest)(`flowSurfaces ${input.context} cannot mix fields and selectorFields on the same field`);
256
- }
257
253
  if (explicitFields && !FIELD_TYPES_WITH_FIELDS.has(fieldType)) {
258
254
  (0, import_errors.throwBadRequest)(`flowSurfaces ${input.context} fieldType '${fieldType}' does not support fields`);
259
255
  }
260
- if (explicitSelectorFields && !FIELD_TYPES_WITH_SELECTOR_FIELDS.has(fieldType)) {
261
- (0, import_errors.throwBadRequest)(`flowSurfaces ${input.context} fieldType '${fieldType}' does not support selectorFields`);
262
- }
263
256
  if ((!import_lodash.default.isUndefined(input.openMode) || !import_lodash.default.isUndefined(input.popupSize)) && fieldType !== "picker") {
264
257
  (0, import_errors.throwBadRequest)(`flowSurfaces ${input.context} fieldType '${fieldType}' does not support openMode or popupSize`);
265
258
  }
@@ -268,15 +261,12 @@ function resolveRelationFieldType(input) {
268
261
  }
269
262
  const shouldApplyDefaults = input.applyDefaults !== false;
270
263
  const defaultTargetField = shouldApplyDefaults ? pickCollectionFallbackFieldName(targetCollection) : void 0;
271
- const fields = explicitFields ?? (shouldApplyDefaults && usesNestedRelationFields(fieldUse) ? [defaultTargetField] : void 0);
272
- const selectorFields = explicitSelectorFields ?? (shouldApplyDefaults && fieldType === "picker" && import_lodash.default.isUndefined(input.selectorFields) ? [defaultTargetField] : void 0);
264
+ const fields = explicitFields ?? (shouldApplyDefaults && (usesNestedRelationFields(fieldUse) || fieldType === "picker") ? [defaultTargetField] : void 0);
265
+ const selectorFields = ["picker", "popupSubTable"].includes(fieldType) ? fields : void 0;
273
266
  const titleField = import_lodash.default.isUndefined(input.titleField) ? defaultTargetField : String(input.titleField || "").trim() || void 0;
274
267
  if (fields == null ? void 0 : fields.length) {
275
268
  assertTargetFieldNamesExist(targetCollection, fields, `${input.context}.fields`);
276
269
  }
277
- if (selectorFields == null ? void 0 : selectorFields.length) {
278
- assertTargetFieldNamesExist(targetCollection, selectorFields, `${input.context}.selectorFields`);
279
- }
280
270
  if (titleField && !(0, import_service_helpers.resolveFieldFromCollection)(targetCollection, titleField)) {
281
271
  (0, import_errors.throwBadRequest)(
282
272
  `flowSurfaces ${input.context}.titleField '${titleField}' does not exist on relation target collection`
@@ -0,0 +1,16 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ type NormalizeSortingAliasInput = {
10
+ context: string;
11
+ type?: string;
12
+ use?: string;
13
+ settings?: any;
14
+ };
15
+ export declare function normalizeFlowSurfacePublicSortingAlias(input: NormalizeSortingAliasInput): any;
16
+ export {};
@@ -0,0 +1,139 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ var __create = Object.create;
11
+ var __defProp = Object.defineProperty;
12
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
13
+ var __getOwnPropNames = Object.getOwnPropertyNames;
14
+ var __getProtoOf = Object.getPrototypeOf;
15
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
16
+ var __export = (target, all) => {
17
+ for (var name in all)
18
+ __defProp(target, name, { get: all[name], enumerable: true });
19
+ };
20
+ var __copyProps = (to, from, except, desc) => {
21
+ if (from && typeof from === "object" || typeof from === "function") {
22
+ for (let key of __getOwnPropNames(from))
23
+ if (!__hasOwnProp.call(to, key) && key !== except)
24
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
25
+ }
26
+ return to;
27
+ };
28
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
29
+ // If the importer is in node compatibility mode or this is not an ESM
30
+ // file that has been converted to a CommonJS file using a Babel-
31
+ // compatible transform (i.e. "__esModule" has not been set), then set
32
+ // "default" to the CommonJS "module.exports" for node compatibility.
33
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
34
+ mod
35
+ ));
36
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
37
+ var public_compatibility_exports = {};
38
+ __export(public_compatibility_exports, {
39
+ normalizeFlowSurfacePublicSortingAlias: () => normalizeFlowSurfacePublicSortingAlias
40
+ });
41
+ module.exports = __toCommonJS(public_compatibility_exports);
42
+ var import_lodash = __toESM(require("lodash"));
43
+ var import_configure_options = require("./configure-options");
44
+ var import_errors = require("./errors");
45
+ var import_support_matrix = require("./support-matrix");
46
+ function resolveBlockUse(input) {
47
+ var _a;
48
+ const explicitUse = String(input.use || "").trim();
49
+ if (explicitUse) {
50
+ return explicitUse;
51
+ }
52
+ const typeOrUse = String(input.type || "").trim();
53
+ if (!typeOrUse) {
54
+ return void 0;
55
+ }
56
+ if (import_support_matrix.FLOW_SURFACE_BLOCK_SUPPORT_BY_USE.has(typeOrUse)) {
57
+ return typeOrUse;
58
+ }
59
+ return ((_a = import_support_matrix.FLOW_SURFACE_BLOCK_SUPPORT_BY_KEY.get(typeOrUse)) == null ? void 0 : _a.modelUse) || typeOrUse;
60
+ }
61
+ function blockSupportsSorting(use) {
62
+ return !!use && (0, import_configure_options.getConfigureOptionKeysForUse)(use).includes("sorting");
63
+ }
64
+ function normalizeSortingDirection(input, context) {
65
+ const normalized = String(input || "").trim().toLowerCase();
66
+ if (!normalized || normalized === "asc" || normalized === "ascend" || normalized === "ascending") {
67
+ return "asc";
68
+ }
69
+ if (normalized === "desc" || normalized === "descend" || normalized === "descending") {
70
+ return "desc";
71
+ }
72
+ (0, import_errors.throwBadRequest)(`${context} must be 'asc' or 'desc'`);
73
+ }
74
+ function normalizeSortingField(input, context) {
75
+ const field = String(input || "").trim();
76
+ if (!field) {
77
+ (0, import_errors.throwBadRequest)(`${context} must be a non-empty field name`);
78
+ }
79
+ return field;
80
+ }
81
+ function normalizeSortingEntry(input, context) {
82
+ if (import_lodash.default.isString(input)) {
83
+ const value = input.trim();
84
+ if (!value) {
85
+ (0, import_errors.throwBadRequest)(`${context} must be a non-empty sort field`);
86
+ }
87
+ const descending = value.startsWith("-");
88
+ const field = descending ? value.slice(1).trim() : value;
89
+ return {
90
+ field: normalizeSortingField(field, context),
91
+ direction: descending ? "desc" : "asc"
92
+ };
93
+ }
94
+ if (!import_lodash.default.isPlainObject(input)) {
95
+ (0, import_errors.throwBadRequest)(`${context} must be a string or an object with field and direction`);
96
+ }
97
+ return {
98
+ field: normalizeSortingField(input.field, `${context}.field`),
99
+ direction: normalizeSortingDirection(input.direction, `${context}.direction`)
100
+ };
101
+ }
102
+ function normalizeSortingArray(input, context) {
103
+ if (!Array.isArray(input)) {
104
+ (0, import_errors.throwBadRequest)(`${context} must be an array`);
105
+ }
106
+ return input.map((item, index) => normalizeSortingEntry(item, `${context}[${index}]`));
107
+ }
108
+ function normalizeFlowSurfacePublicSortingAlias(input) {
109
+ if (import_lodash.default.isUndefined(input.settings)) {
110
+ return input.settings;
111
+ }
112
+ if (!import_lodash.default.isPlainObject(input.settings)) {
113
+ (0, import_errors.throwBadRequest)(`${input.context} must be an object`);
114
+ }
115
+ if (!Object.prototype.hasOwnProperty.call(input.settings, "sort")) {
116
+ return input.settings;
117
+ }
118
+ const use = resolveBlockUse(input);
119
+ if (!blockSupportsSorting(use)) {
120
+ return input.settings;
121
+ }
122
+ const nextSettings = import_lodash.default.cloneDeep(input.settings);
123
+ const sortingFromSort = normalizeSortingArray(nextSettings.sort, `${input.context}.sort`);
124
+ if (Object.prototype.hasOwnProperty.call(nextSettings, "sorting")) {
125
+ const canonicalSorting = normalizeSortingArray(nextSettings.sorting, `${input.context}.sorting`);
126
+ if (!import_lodash.default.isEqual(sortingFromSort, canonicalSorting)) {
127
+ (0, import_errors.throwBadRequest)(`${input.context}.sort conflicts with ${input.context}.sorting; use canonical sorting`);
128
+ }
129
+ nextSettings.sorting = canonicalSorting;
130
+ } else {
131
+ nextSettings.sorting = sortingFromSort;
132
+ }
133
+ delete nextSettings.sort;
134
+ return nextSettings;
135
+ }
136
+ // Annotate the CommonJS export names for ESM import in node:
137
+ 0 && (module.exports = {
138
+ normalizeFlowSurfacePublicSortingAlias
139
+ });
@@ -155,8 +155,8 @@ function getFieldName(field) {
155
155
  return (field == null ? void 0 : field.name) || ((_a = field == null ? void 0 : field.options) == null ? void 0 : _a.name);
156
156
  }
157
157
  function getFieldTitle(field) {
158
- var _a;
159
- return (field == null ? void 0 : field.title) || ((_a = field == null ? void 0 : field.options) == null ? void 0 : _a.title) || getFieldName(field);
158
+ var _a, _b, _c, _d;
159
+ return ((_a = field == null ? void 0 : field.uiSchema) == null ? void 0 : _a.title) || ((_c = (_b = field == null ? void 0 : field.options) == null ? void 0 : _b.uiSchema) == null ? void 0 : _c.title) || (field == null ? void 0 : field.title) || ((_d = field == null ? void 0 : field.options) == null ? void 0 : _d.title) || getFieldName(field);
160
160
  }
161
161
  function resolveAssociationNameFromField(field, fallbackCollection) {
162
162
  const resourceName = typeof (field == null ? void 0 : field.resourceName) === "string" ? field.resourceName.trim() : "";
@@ -21,6 +21,7 @@ export declare function normalizeBlockTitleDescription(titleDescription: any): a
21
21
  export declare function buildBlockTitleDescriptionFromSemanticChanges(changes: Record<string, any>): {
22
22
  titleDescription: _.Dictionary<any>;
23
23
  };
24
+ export declare function buildBlockCardSettingsFromSemanticChanges(changes: Record<string, any>): {};
24
25
  export declare function buildChartCardSettingsFromSemanticChanges(currentCardSettings: any, changes: Record<string, any>): any;
25
26
  export declare function buildPopupTabTree(options: {
26
27
  tabUid?: string;
@@ -68,7 +69,6 @@ export type NormalizedComposeFieldSpec = {
68
69
  type?: string;
69
70
  fieldType?: FlowSurfacePublicRelationFieldType;
70
71
  fields?: string[];
71
- selectorFields?: string[];
72
72
  titleField?: string;
73
73
  openMode?: string;
74
74
  popupSize?: string;