@nocobase/plugin-flow-engine 2.2.0-beta.2 → 2.2.0-beta.3

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 (45) hide show
  1. package/dist/externalVersion.js +9 -9
  2. package/dist/node_modules/@ant-design/icons-svg/package.json +1 -1
  3. package/dist/node_modules/acorn/package.json +1 -1
  4. package/dist/node_modules/acorn-jsx/package.json +1 -1
  5. package/dist/node_modules/acorn-walk/package.json +1 -1
  6. package/dist/node_modules/ses/package.json +1 -1
  7. package/dist/node_modules/zod/package.json +1 -1
  8. package/dist/server/flow-surfaces/approval/authoring-validation.d.ts +9 -0
  9. package/dist/server/flow-surfaces/approval/authoring-validation.js +1151 -0
  10. package/dist/server/flow-surfaces/approval/blueprint-service.js +2 -0
  11. package/dist/server/flow-surfaces/authoring-validation.js +372 -32
  12. package/dist/server/flow-surfaces/blueprint/export-document.d.ts +50 -0
  13. package/dist/server/flow-surfaces/blueprint/export-document.js +2503 -0
  14. package/dist/server/flow-surfaces/constants.d.ts +9 -2
  15. package/dist/server/flow-surfaces/constants.js +1 -0
  16. package/dist/server/flow-surfaces/default-action-popup.d.ts +2 -0
  17. package/dist/server/flow-surfaces/default-action-popup.js +27 -13
  18. package/dist/server/flow-surfaces/filter-group.d.ts +19 -2
  19. package/dist/server/flow-surfaces/filter-group.js +232 -3
  20. package/dist/server/flow-surfaces/planning/compiler.d.ts +1 -0
  21. package/dist/server/flow-surfaces/planning/compiler.js +205 -82
  22. package/dist/server/flow-surfaces/planning/runtime.js +1 -0
  23. package/dist/server/flow-surfaces/planning/step-link.d.ts +1 -1
  24. package/dist/server/flow-surfaces/planning/step-link.js +22 -3
  25. package/dist/server/flow-surfaces/public-data-surface-default-filter.js +0 -9
  26. package/dist/server/flow-surfaces/reaction/field-value.d.ts +9 -0
  27. package/dist/server/flow-surfaces/reaction/field-value.js +51 -2
  28. package/dist/server/flow-surfaces/reaction/linkage.d.ts +6 -1
  29. package/dist/server/flow-surfaces/reaction/linkage.js +18 -3
  30. package/dist/server/flow-surfaces/reaction/meta.js +19 -1
  31. package/dist/server/flow-surfaces/reaction/types.d.ts +19 -0
  32. package/dist/server/flow-surfaces/relation-backing-foreign-key.d.ts +10 -0
  33. package/dist/server/flow-surfaces/relation-backing-foreign-key.js +79 -0
  34. package/dist/server/flow-surfaces/runjs-authoring/ast/source.d.ts +1 -0
  35. package/dist/server/flow-surfaces/runjs-authoring/ast/source.js +20 -0
  36. package/dist/server/flow-surfaces/runjs-authoring/scan/filter.js +12 -2
  37. package/dist/server/flow-surfaces/runjs-authoring/scan/index.js +9 -1
  38. package/dist/server/flow-surfaces/service.d.ts +19 -0
  39. package/dist/server/flow-surfaces/service.js +189 -20
  40. package/dist/swagger/flow-surfaces.d.ts +180 -0
  41. package/dist/swagger/flow-surfaces.examples.d.ts +8 -0
  42. package/dist/swagger/flow-surfaces.examples.js +8 -0
  43. package/dist/swagger/flow-surfaces.js +160 -4
  44. package/dist/swagger/index.d.ts +180 -0
  45. package/package.json +2 -2
@@ -163,6 +163,13 @@ export type FlowSurfaceReactionCapabilityBase<TKind extends FlowSurfaceReactionK
163
163
  };
164
164
  export type FlowSurfaceFieldValueCapability = FlowSurfaceReactionCapabilityBase<'fieldValue', FlowSurfaceFieldValueRule> & {
165
165
  targetFields: FlowSurfaceFieldOption[];
166
+ conditionMeta: {
167
+ operatorsByPath: Record<string, string[]>;
168
+ fieldMetaByPath?: Record<string, {
169
+ type?: string;
170
+ interface?: string;
171
+ }>;
172
+ };
166
173
  valueExprMeta: {
167
174
  supportedSources: Array<'literal' | 'path' | 'runjs'>;
168
175
  runjsScene: 'fieldValue';
@@ -172,17 +179,29 @@ export type FlowSurfaceLinkageCapability = (FlowSurfaceReactionCapabilityBase<'b
172
179
  supportedActions: Array<Record<string, any>>;
173
180
  conditionMeta: {
174
181
  operatorsByPath: Record<string, string[]>;
182
+ fieldMetaByPath?: Record<string, {
183
+ type?: string;
184
+ interface?: string;
185
+ }>;
175
186
  };
176
187
  }) | (FlowSurfaceReactionCapabilityBase<'actionLinkage', FlowSurfaceActionLinkageRule> & {
177
188
  supportedActions: Array<Record<string, any>>;
178
189
  conditionMeta: {
179
190
  operatorsByPath: Record<string, string[]>;
191
+ fieldMetaByPath?: Record<string, {
192
+ type?: string;
193
+ interface?: string;
194
+ }>;
180
195
  };
181
196
  }) | (FlowSurfaceReactionCapabilityBase<'fieldLinkage', FlowSurfaceFieldLinkageRule> & {
182
197
  supportedActions: Array<Record<string, any>>;
183
198
  targetFields: FlowSurfaceFieldOption[];
184
199
  conditionMeta: {
185
200
  operatorsByPath: Record<string, string[]>;
201
+ fieldMetaByPath?: Record<string, {
202
+ type?: string;
203
+ interface?: string;
204
+ }>;
186
205
  };
187
206
  valueExprMeta?: {
188
207
  supportedSources: Array<'literal' | 'path' | 'runjs'>;
@@ -0,0 +1,10 @@
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
+ export declare function collectRelationBackingForeignKeyNames(collection: any): Set<string>;
10
+ export declare function isRelationBackingForeignKeyField(collection: any, fieldOrFieldName: any): boolean;
@@ -0,0 +1,79 @@
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 __defProp = Object.defineProperty;
11
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
+ var __getOwnPropNames = Object.getOwnPropertyNames;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __export = (target, all) => {
15
+ for (var name in all)
16
+ __defProp(target, name, { get: all[name], enumerable: true });
17
+ };
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") {
20
+ for (let key of __getOwnPropNames(from))
21
+ if (!__hasOwnProp.call(to, key) && key !== except)
22
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
23
+ }
24
+ return to;
25
+ };
26
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
27
+ var relation_backing_foreign_key_exports = {};
28
+ __export(relation_backing_foreign_key_exports, {
29
+ collectRelationBackingForeignKeyNames: () => collectRelationBackingForeignKeyNames,
30
+ isRelationBackingForeignKeyField: () => isRelationBackingForeignKeyField
31
+ });
32
+ module.exports = __toCommonJS(relation_backing_foreign_key_exports);
33
+ var import_service_helpers = require("./service-helpers");
34
+ const CURRENT_COLLECTION_FOREIGN_KEY_RELATION_TYPES = /* @__PURE__ */ new Set(["belongsto"]);
35
+ const CURRENT_COLLECTION_FOREIGN_KEY_RELATION_INTERFACES = /* @__PURE__ */ new Set(["m2o"]);
36
+ const CONDITIONAL_CURRENT_COLLECTION_FOREIGN_KEY_RELATION_INTERFACES = /* @__PURE__ */ new Set(["o2o"]);
37
+ const RELATION_INTERFACES_WITH_FOREIGN_KEYS_OUTSIDE_CURRENT_COLLECTION = /* @__PURE__ */ new Set(["o2m", "m2m", "mbm"]);
38
+ const RELATION_TYPES_WITH_FOREIGN_KEYS_OUTSIDE_CURRENT_COLLECTION = /* @__PURE__ */ new Set(["hasone", "hasmany", "belongstomany"]);
39
+ function collectRelationBackingForeignKeyNames(collection) {
40
+ const fields = (0, import_service_helpers.getCollectionFields)(collection);
41
+ const scalarFieldNames = new Set(
42
+ fields.filter((field) => !(0, import_service_helpers.isAssociationField)(field)).map((field) => String((0, import_service_helpers.getFieldName)(field) || "").trim()).filter(Boolean)
43
+ );
44
+ const names = /* @__PURE__ */ new Set();
45
+ fields.forEach((field) => {
46
+ const foreignKey = getCurrentCollectionRelationForeignKey(field);
47
+ if (foreignKey && scalarFieldNames.has(foreignKey)) {
48
+ names.add(foreignKey);
49
+ }
50
+ });
51
+ return names;
52
+ }
53
+ function isRelationBackingForeignKeyField(collection, fieldOrFieldName) {
54
+ const fieldName = typeof fieldOrFieldName === "string" ? fieldOrFieldName.trim() : String((0, import_service_helpers.getFieldName)(fieldOrFieldName) || "").trim();
55
+ return !!fieldName && collectRelationBackingForeignKeyNames(collection).has(fieldName);
56
+ }
57
+ function getCurrentCollectionRelationForeignKey(field) {
58
+ var _a;
59
+ if (!(0, import_service_helpers.isAssociationField)(field)) {
60
+ return "";
61
+ }
62
+ if (!relationCanStoreForeignKeyInCurrentCollection(field)) {
63
+ return "";
64
+ }
65
+ return String((field == null ? void 0 : field.foreignKey) || ((_a = field == null ? void 0 : field.options) == null ? void 0 : _a.foreignKey) || "").trim();
66
+ }
67
+ function relationCanStoreForeignKeyInCurrentCollection(field) {
68
+ const type = String((0, import_service_helpers.getFieldType)(field) || "").trim().toLowerCase();
69
+ const fieldInterface = String((0, import_service_helpers.getFieldInterface)(field) || "").trim().toLowerCase();
70
+ if (RELATION_TYPES_WITH_FOREIGN_KEYS_OUTSIDE_CURRENT_COLLECTION.has(type) || RELATION_INTERFACES_WITH_FOREIGN_KEYS_OUTSIDE_CURRENT_COLLECTION.has(fieldInterface)) {
71
+ return false;
72
+ }
73
+ return CURRENT_COLLECTION_FOREIGN_KEY_RELATION_TYPES.has(type) || CURRENT_COLLECTION_FOREIGN_KEY_RELATION_INTERFACES.has(fieldInterface) || CONDITIONAL_CURRENT_COLLECTION_FOREIGN_KEY_RELATION_INTERFACES.has(fieldInterface);
74
+ }
75
+ // Annotate the CommonJS export names for ESM import in node:
76
+ 0 && (module.exports = {
77
+ collectRelationBackingForeignKeyNames,
78
+ isRelationBackingForeignKeyField
79
+ });
@@ -23,6 +23,7 @@ export declare function getPreviousSignificantTokenInfo(sourceLike: string | str
23
23
  export declare function skipQuotedLiteral(source: string, start: number, quote: string): number;
24
24
  export declare function skipTemplateLiteral(source: string, start: number): number;
25
25
  export declare function findFunctionRanges(masked: string): SourceRange[];
26
+ export declare function collectAstFunctionBodyRanges(ast: unknown): SourceRange[];
26
27
  export declare function collectFunctionRanges(masked: string, pattern: RegExp, ranges: SourceRange[]): void;
27
28
  export declare function collectArrowExpressionRanges(masked: string, ranges: SourceRange[]): void;
28
29
  export declare function collectMethodFunctionRanges(masked: string, ranges: SourceRange[]): void;
@@ -27,6 +27,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
27
27
  var source_exports = {};
28
28
  __export(source_exports, {
29
29
  collectArrowExpressionRanges: () => collectArrowExpressionRanges,
30
+ collectAstFunctionBodyRanges: () => collectAstFunctionBodyRanges,
30
31
  collectBraceRanges: () => collectBraceRanges,
31
32
  collectComputedMethodCandidates: () => collectComputedMethodCandidates,
32
33
  collectFunctionRanges: () => collectFunctionRanges,
@@ -69,6 +70,7 @@ __export(source_exports, {
69
70
  });
70
71
  module.exports = __toCommonJS(source_exports);
71
72
  var import_constants = require("../runtime/constants");
73
+ var import_walk = require("./walk");
72
74
  function maskJavaScriptSource(source) {
73
75
  const chars = source.split("");
74
76
  const maskRange = (start, end) => {
@@ -406,6 +408,23 @@ function findFunctionRanges(masked) {
406
408
  collectMethodFunctionRanges(masked, ranges);
407
409
  return mergeRanges(ranges);
408
410
  }
411
+ function collectAstFunctionBodyRanges(ast) {
412
+ const ranges = [];
413
+ const addBodyRange = (node) => {
414
+ var _a, _b;
415
+ const start = (_a = node.body) == null ? void 0 : _a.start;
416
+ const end = (_b = node.body) == null ? void 0 : _b.end;
417
+ if (typeof start === "number" && typeof end === "number" && end > start) {
418
+ ranges.push({ start, end });
419
+ }
420
+ };
421
+ (0, import_walk.walkAstSimple)(ast, {
422
+ FunctionDeclaration: addBodyRange,
423
+ FunctionExpression: addBodyRange,
424
+ ArrowFunctionExpression: addBodyRange
425
+ });
426
+ return mergeRanges(ranges);
427
+ }
409
428
  function collectFunctionRanges(masked, pattern, ranges) {
410
429
  for (const match of masked.matchAll(pattern)) {
411
430
  const openBrace = masked.indexOf("{", match.index || 0);
@@ -853,6 +872,7 @@ function getAstSource(node, source) {
853
872
  // Annotate the CommonJS export names for ESM import in node:
854
873
  0 && (module.exports = {
855
874
  collectArrowExpressionRanges,
875
+ collectAstFunctionBodyRanges,
856
876
  collectBraceRanges,
857
877
  collectComputedMethodCandidates,
858
878
  collectFunctionRanges,
@@ -900,7 +900,13 @@ function buildRunJsResourceFilterOperatorError(operator, index, input) {
900
900
  };
901
901
  }
902
902
  function buildRunJsResourceDateFilterValueError(operator, index, valueNode, input) {
903
- if (!isRunJsDateFilterOperator(operator)) {
903
+ const fieldType = String((0, import_service_helpers.getFieldType)(input.field) || "").trim();
904
+ const fieldInterface = String((0, import_service_helpers.getFieldInterface)(input.field) || "").trim();
905
+ const shouldValidateDateValue = isRunJsDateFilterOperator(operator) || (0, import_filter_group.isFlowSurfaceDateLikeFieldMeta)({
906
+ type: fieldType,
907
+ interface: fieldInterface
908
+ });
909
+ if (!shouldValidateDateValue) {
904
910
  return null;
905
911
  }
906
912
  const valueObject = resolveRunJsStaticFilterObjectNode(
@@ -924,7 +930,11 @@ function buildRunJsResourceDateFilterValueError(operator, index, valueNode, inpu
924
930
  return null;
925
931
  }
926
932
  try {
927
- (0, import_filter_group.normalizeFlowSurfaceStrictFilterDateValue)(operator, resolvedValue.value, `${input.fieldPath}.${operator}`);
933
+ (0, import_filter_group.normalizeFlowSurfaceDateConditionValue)(operator, resolvedValue.value, `${input.fieldPath}.${operator}`, {
934
+ fieldPath: input.fieldPath,
935
+ fieldType,
936
+ fieldInterface
937
+ });
928
938
  return null;
929
939
  } catch (error) {
930
940
  return buildRunJsStrictDateFilterValueError(operator, index, resolvedValue.value, input, error);
@@ -43,7 +43,7 @@ var import_filter = require("./filter");
43
43
  var import_constants = require("../runtime/constants");
44
44
  function scanJavaScriptSource(source, ast, context = {}, modelUse = "") {
45
45
  const masked = (0, import_source.maskJavaScriptSource)(source);
46
- const functionRanges = (0, import_source.findFunctionRanges)(masked);
46
+ const functionRanges = collectScanFunctionRanges(masked, ast);
47
47
  const blockRanges = (0, import_source.collectBraceRanges)(masked);
48
48
  const staticBlockRanges = (0, import_source.collectStaticBlockRanges)(masked);
49
49
  const sourceBindings = (0, import_bindings.collectSourceBindings)(masked, functionRanges, blockRanges, staticBlockRanges);
@@ -139,6 +139,14 @@ function scanJavaScriptSource(source, ast, context = {}, modelUse = "") {
139
139
  isTopLevelFunctionWrapper: (0, import_source_patterns.isTopLevelFunctionWrapper)(masked, functionRanges, topLevelReachableCtxRenderCalls)
140
140
  };
141
141
  }
142
+ function collectScanFunctionRanges(masked, ast) {
143
+ if (!ast) {
144
+ return (0, import_source.findFunctionRanges)(masked);
145
+ }
146
+ const ranges = (0, import_source.collectAstFunctionBodyRanges)(ast);
147
+ (0, import_source.collectArrowExpressionRanges)(masked, ranges);
148
+ return (0, import_source.mergeRanges)(ranges);
149
+ }
142
150
  function collectAstUnknownBareGlobalsFromAst(ast, identifierBindings, modelUse) {
143
151
  var _a;
144
152
  const allowedGlobals = new Set(import_constants.RUNJS_ALLOWED_BARE_GLOBALS);
@@ -160,6 +160,7 @@ export declare class FlowSurfacesService {
160
160
  private persistReactionSlot;
161
161
  private buildLinkageWriteResult;
162
162
  private getLiveLinkageCapability;
163
+ private getLiveFieldValueCapability;
163
164
  getReactionMeta(values: FlowSurfaceGetReactionMetaValues, options?: {
164
165
  transaction?: any;
165
166
  }): Promise<FlowSurfaceGetReactionMetaResult>;
@@ -182,6 +183,17 @@ export declare class FlowSurfacesService {
182
183
  private buildSurfaceReadPayload;
183
184
  private buildSurfaceContextFingerprint;
184
185
  get(input: Record<string, any>, options?: FlowSurfaceReadOptions): Promise<Record<string, any>>;
186
+ exportBlueprint(input: Record<string, unknown>, options?: FlowSurfaceReadOptions): Promise<{
187
+ document: FlowSurfaceApplyBlueprintDocument;
188
+ source: {
189
+ target: {
190
+ pageSchemaUid: string;
191
+ };
192
+ pageTitle?: string;
193
+ };
194
+ warnings: string[];
195
+ unsupported: import("./blueprint/export-document").FlowSurfaceExportBlueprintUnsupportedItem[];
196
+ }>;
185
197
  private getDeclaredKeyPersistenceDeps;
186
198
  private patchDeclaredKeyModel;
187
199
  private persistCreatedKeysForAction;
@@ -916,6 +928,12 @@ export declare class FlowSurfacesService {
916
928
  private normalizeRemoveNodeTarget;
917
929
  private assertRemoveNodeResolvedTarget;
918
930
  private normalizeGetTarget;
931
+ private normalizeExportBlueprintRequest;
932
+ private normalizeExportBlueprintUnsupportedPolicy;
933
+ private normalizeExportBlueprintLocatorValue;
934
+ private readRouteString;
935
+ private resolveExportBlueprintPageSchemaUid;
936
+ private assertExportBlueprintRootTarget;
919
937
  private normalizeContextPath;
920
938
  private normalizeContextMaxDepth;
921
939
  private buildReadTargetSummary;
@@ -1088,6 +1106,7 @@ export declare class FlowSurfacesService {
1088
1106
  private buildFieldCatalog;
1089
1107
  private getFieldMenuCatalogMode;
1090
1108
  private resolveRegisteredFieldBinding;
1109
+ private isCollectionTitleField;
1091
1110
  private resolveAssociationLeafDisplaySemantics;
1092
1111
  private buildFieldMenuDirectCandidates;
1093
1112
  private collectFieldMenuAssociationLeafCandidates;
@@ -56,6 +56,7 @@ var import_executor = require("./executor");
56
56
  var import_reference_guards = require("./reference-guards");
57
57
  var import_key_registry = require("./planning/key-registry");
58
58
  var import_blueprint = require("./blueprint");
59
+ var import_export_document = require("./blueprint/export-document");
59
60
  var import_compile_blocks = require("./blueprint/compile-blocks");
60
61
  var import_default_block_actions = require("./default-block-actions");
61
62
  var import_template_reference = require("./template-reference");
@@ -96,6 +97,7 @@ var import_meta = require("./reaction/meta");
96
97
  var import_resolver = require("./reaction/resolver");
97
98
  var import_association_title_field = require("./association-title-field");
98
99
  var import_default_action_popup = require("./default-action-popup");
100
+ var import_relation_backing_foreign_key = require("./relation-backing-foreign-key");
99
101
  var import_defaults = require("./blueprint/defaults");
100
102
  var import_service_utils = require("./service-utils");
101
103
  var import_field_type_resolver = require("./field-type-resolver");
@@ -229,6 +231,7 @@ function isFlowSurfaceChartRepairError(error) {
229
231
  var _a, _b;
230
232
  return error instanceof import_errors.FlowSurfaceBadRequestError && ((_b = (_a = error.options) == null ? void 0 : _a.details) == null ? void 0 : _b.repairHint) === FLOW_SURFACE_CHART_REPAIR_HINT;
231
233
  }
234
+ const FLOW_SURFACE_EXPORT_BLUEPRINT_ROOT_ONLY_MESSAGE = "exportBlueprint v1 only supports root page export";
232
235
  const FORM_BLOCK_USES = /* @__PURE__ */ new Set(["FormBlockModel", "CreateFormModel", "EditFormModel", ...import_approval.APPROVAL_FORM_BLOCK_USES]);
233
236
  const AUTO_SUBMIT_FORM_BLOCK_USES = /* @__PURE__ */ new Set(["CreateFormModel", "EditFormModel"]);
234
237
  const FLOW_SURFACE_DEFAULT_ACTION_SETTINGS_KEYS = /* @__PURE__ */ new Set(["filter"]);
@@ -2621,6 +2624,28 @@ class FlowSurfacesService {
2621
2624
  }
2622
2625
  return capability;
2623
2626
  }
2627
+ async getLiveFieldValueCapability(writeTarget, resolvedTarget, node, options = {}) {
2628
+ const context = await this.context(
2629
+ {
2630
+ target: writeTarget
2631
+ },
2632
+ options
2633
+ );
2634
+ const { capabilities } = (0, import_meta.buildReactionMetaCapabilities)({
2635
+ resolvedTarget: {
2636
+ ...resolvedTarget,
2637
+ node
2638
+ },
2639
+ context
2640
+ });
2641
+ const capability = capabilities.find((item) => item.kind === "fieldValue");
2642
+ if (!capability) {
2643
+ (0, import_errors.throwBadRequest)(
2644
+ `flowSurfaces reaction target '${resolvedTarget.use || resolvedTarget.target.uid}' does not support fieldValue`
2645
+ );
2646
+ }
2647
+ return capability;
2648
+ }
2624
2649
  async getReactionMeta(values, options = {}) {
2625
2650
  (0, import_payload_shape.validateFlowSurfacePayloadShape)("getReactionMeta", values, "values");
2626
2651
  const { writeTarget, node, resolvedTarget } = await this.resolveReactionRequest("getReactionMeta", values == null ? void 0 : values.target, {
@@ -2666,6 +2691,8 @@ class FlowSurfacesService {
2666
2691
  },
2667
2692
  rules: Array.isArray(values == null ? void 0 : values.rules) ? values.rules : []
2668
2693
  });
2694
+ const liveCapability = await this.getLiveFieldValueCapability(writeTarget, resolvedTarget, node, options);
2695
+ (0, import_field_value.validateFieldValueRulesAgainstCapability)(result.normalizedRules, liveCapability);
2669
2696
  await this.persistReactionSlot(storageNode, capability.resolvedSlot, result.canonicalRules, options);
2670
2697
  return result;
2671
2698
  }
@@ -2873,6 +2900,41 @@ class FlowSurfacesService {
2873
2900
  const publicNode = this.stripInternalSurfaceMetaFromNodeTree(import_lodash.default.cloneDeep(rawNode));
2874
2901
  return this.buildSurfaceReadPayload(target, resolved, publicNode, options);
2875
2902
  }
2903
+ async exportBlueprint(input, options = {}) {
2904
+ const request = this.normalizeExportBlueprintRequest(input);
2905
+ const resolved = await this.locator.resolve(request.target, options);
2906
+ if (resolved.kind !== "page" || !resolved.pageRoute) {
2907
+ (0, import_errors.throwBadRequest)(FLOW_SURFACE_EXPORT_BLUEPRINT_ROOT_ONLY_MESSAGE);
2908
+ }
2909
+ const pageSchemaUid = this.resolveExportBlueprintPageSchemaUid(request.target, resolved);
2910
+ await this.assertExportBlueprintRootTarget(request.target, resolved, pageSchemaUid, options.transaction);
2911
+ const rawNode = await this.decorateTemplateReadbackTree(
2912
+ this.normalizePopupTreeShape(
2913
+ await this.loadResolvedNode(resolved, options.transaction, {
2914
+ persistCalendarPopupHosts: false
2915
+ })
2916
+ ),
2917
+ options.transaction
2918
+ );
2919
+ if (!(rawNode == null ? void 0 : rawNode.uid)) {
2920
+ (0, import_errors.throwBadRequest)(`flowSurfaces exportBlueprint target '${pageSchemaUid}' could not resolve a readable page tree`);
2921
+ }
2922
+ const pageRoute = resolved.pageRoute ? await this.routeSync.hydrateRoute(resolved.pageRoute, options.transaction) : void 0;
2923
+ const result = (0, import_export_document.exportFlowSurfaceBlueprintDocument)({
2924
+ page: rawNode,
2925
+ pageRoute,
2926
+ target: {
2927
+ pageSchemaUid
2928
+ },
2929
+ unsupportedPolicy: request.unsupportedPolicy
2930
+ });
2931
+ return {
2932
+ ...result,
2933
+ document: (0, import_blueprint.prepareFlowSurfaceApplyBlueprintDocument)(
2934
+ result.document
2935
+ )
2936
+ };
2937
+ }
2876
2938
  getDeclaredKeyPersistenceDeps() {
2877
2939
  return {
2878
2940
  findModelById: (uid2, findOptions) => this.repository.findModelById(uid2, findOptions),
@@ -6679,11 +6741,6 @@ class FlowSurfacesService {
6679
6741
  requiredFieldCount: options.requiredFieldCount
6680
6742
  }
6681
6743
  );
6682
- if (!(0, import_service_utils.hasOwnDefined)(normalizedSettings, "filterableFieldNames")) {
6683
- normalizedSettings.filterableFieldNames = (0, import_public_data_surface_default_filter.resolveFlowSurfaceDefaultFilterFieldNames)(
6684
- normalizedSettings.defaultFilter
6685
- );
6686
- }
6687
6744
  }
6688
6745
  return normalizedSettings;
6689
6746
  }
@@ -11972,17 +12029,6 @@ class FlowSurfacesService {
11972
12029
  const filterValue = this.normalizeEffectivePublicDataSurfaceDefaultFilter(normalizedFilterValue, {
11973
12030
  requiredFieldCount: options.requiredFieldCount
11974
12031
  });
11975
- if (!hasPropsFilterableFieldNames && !hasStepFilterableFieldNames) {
11976
- const filterableFieldNames = (0, import_public_data_surface_default_filter.resolveFlowSurfaceDefaultFilterFieldNames)(filterValue);
11977
- if (filterableFieldNames.length) {
11978
- nextProps.filterableFieldNames = filterableFieldNames;
11979
- import_lodash.default.set(
11980
- nextStepParams,
11981
- ["filterSettings", "filterableFieldNames", "filterableFieldNames"],
11982
- import_lodash.default.cloneDeep(filterableFieldNames)
11983
- );
11984
- }
11985
- }
11986
12032
  nextProps.defaultFilterValue = import_lodash.default.cloneDeep(filterValue);
11987
12033
  nextProps.filterValue = import_lodash.default.cloneDeep(filterValue);
11988
12034
  import_lodash.default.set(nextStepParams, ["filterSettings", "defaultFilter", "defaultFilter"], import_lodash.default.cloneDeep(filterValue));
@@ -13694,6 +13740,111 @@ class FlowSurfacesService {
13694
13740
  }
13695
13741
  return target;
13696
13742
  }
13743
+ normalizeExportBlueprintRequest(input) {
13744
+ if (!import_lodash.default.isPlainObject(input)) {
13745
+ (0, import_errors.throwBadRequest)(`flowSurfaces exportBlueprint payload must be an object`);
13746
+ }
13747
+ const unsupportedKeys = Object.keys(input).filter((key) => key !== "target" && key !== "options");
13748
+ if (unsupportedKeys.length) {
13749
+ (0, import_errors.throwBadRequest)(`flowSurfaces exportBlueprint only accepts target and options`);
13750
+ }
13751
+ if (!import_lodash.default.isPlainObject(input.target)) {
13752
+ (0, import_errors.throwBadRequest)(`flowSurfaces exportBlueprint requires target`);
13753
+ }
13754
+ const targetInput = input.target;
13755
+ const target = (0, import_service_utils.buildDefinedPayload)({
13756
+ uid: this.normalizeExportBlueprintLocatorValue(targetInput.uid, "uid"),
13757
+ pageSchemaUid: this.normalizeExportBlueprintLocatorValue(targetInput.pageSchemaUid, "pageSchemaUid"),
13758
+ tabSchemaUid: this.normalizeExportBlueprintLocatorValue(targetInput.tabSchemaUid, "tabSchemaUid"),
13759
+ routeId: this.normalizeExportBlueprintLocatorValue(targetInput.routeId, "routeId")
13760
+ });
13761
+ const unsupportedTargetKeys = Object.keys(targetInput).filter(
13762
+ (key) => !["uid", "pageSchemaUid", "tabSchemaUid", "routeId"].includes(key)
13763
+ );
13764
+ if (unsupportedTargetKeys.length) {
13765
+ (0, import_errors.throwBadRequest)(`flowSurfaces exportBlueprint target only accepts uid, pageSchemaUid, tabSchemaUid or routeId`);
13766
+ }
13767
+ if (!Object.keys(target).length) {
13768
+ (0, import_errors.throwBadRequest)(
13769
+ `flowSurfaces exportBlueprint target requires one of uid, pageSchemaUid, tabSchemaUid or routeId`
13770
+ );
13771
+ }
13772
+ if (Object.keys(target).length > 1) {
13773
+ (0, import_errors.throwBadRequest)(
13774
+ `flowSurfaces exportBlueprint target only accepts exactly one locator: uid, pageSchemaUid, tabSchemaUid or routeId`
13775
+ );
13776
+ }
13777
+ if (target.tabSchemaUid) {
13778
+ (0, import_errors.throwBadRequest)(FLOW_SURFACE_EXPORT_BLUEPRINT_ROOT_ONLY_MESSAGE);
13779
+ }
13780
+ return {
13781
+ target,
13782
+ unsupportedPolicy: this.normalizeExportBlueprintUnsupportedPolicy(input.options)
13783
+ };
13784
+ }
13785
+ normalizeExportBlueprintUnsupportedPolicy(input) {
13786
+ if (import_lodash.default.isUndefined(input)) {
13787
+ return "error";
13788
+ }
13789
+ if (!import_lodash.default.isPlainObject(input)) {
13790
+ (0, import_errors.throwBadRequest)(`flowSurfaces exportBlueprint options must be an object`);
13791
+ }
13792
+ const options = input;
13793
+ const unsupportedKeys = Object.keys(options).filter((key) => key !== "unsupported");
13794
+ if (unsupportedKeys.length) {
13795
+ (0, import_errors.throwBadRequest)(`flowSurfaces exportBlueprint options only accepts unsupported`);
13796
+ }
13797
+ const policy = options.unsupported;
13798
+ if (import_lodash.default.isUndefined(policy)) {
13799
+ return "error";
13800
+ }
13801
+ if (policy === "error" || policy === "warn") {
13802
+ return policy;
13803
+ }
13804
+ (0, import_errors.throwBadRequest)(`flowSurfaces exportBlueprint options.unsupported must be 'error' or 'warn'`);
13805
+ }
13806
+ normalizeExportBlueprintLocatorValue(value, key) {
13807
+ if (import_lodash.default.isNil(value)) {
13808
+ return void 0;
13809
+ }
13810
+ if (typeof value !== "string" && typeof value !== "number") {
13811
+ (0, import_errors.throwBadRequest)(`flowSurfaces exportBlueprint target.${key} must be a string`);
13812
+ }
13813
+ const normalized = String(value).trim();
13814
+ return normalized || void 0;
13815
+ }
13816
+ readRouteString(route, key) {
13817
+ var _a;
13818
+ const routeRecord = route;
13819
+ const value = ((_a = routeRecord == null ? void 0 : routeRecord.get) == null ? void 0 : _a.call(routeRecord, key)) ?? (routeRecord == null ? void 0 : routeRecord[key]);
13820
+ const normalized = typeof value === "string" ? value.trim() : "";
13821
+ return normalized || void 0;
13822
+ }
13823
+ resolveExportBlueprintPageSchemaUid(target, resolved) {
13824
+ const pageSchemaUid = this.readRouteString(resolved.pageRoute, "schemaUid") || (target.pageSchemaUid ? String(target.pageSchemaUid).trim() : "");
13825
+ if (!pageSchemaUid) {
13826
+ (0, import_errors.throwBadRequest)(FLOW_SURFACE_EXPORT_BLUEPRINT_ROOT_ONLY_MESSAGE);
13827
+ }
13828
+ return pageSchemaUid;
13829
+ }
13830
+ async assertExportBlueprintRootTarget(target, resolved, pageSchemaUid, transaction) {
13831
+ const targetUid = target.uid ? String(target.uid).trim() : "";
13832
+ if (!targetUid) {
13833
+ return;
13834
+ }
13835
+ if (targetUid === pageSchemaUid) {
13836
+ return;
13837
+ }
13838
+ const rootPageModel = await this.repository.findModelByParentId(pageSchemaUid, {
13839
+ transaction,
13840
+ subKey: "page",
13841
+ includeAsyncNode: false
13842
+ });
13843
+ if ((rootPageModel == null ? void 0 : rootPageModel.uid) && targetUid === String(rootPageModel.uid).trim()) {
13844
+ return;
13845
+ }
13846
+ (0, import_errors.throwBadRequest)(FLOW_SURFACE_EXPORT_BLUEPRINT_ROOT_ONLY_MESSAGE);
13847
+ }
13697
13848
  normalizeContextPath(path) {
13698
13849
  if (import_lodash.default.isUndefined(path) || import_lodash.default.isNull(path)) {
13699
13850
  return void 0;
@@ -18786,6 +18937,11 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18786
18937
  useStrictOnly: input.useStrictOnly
18787
18938
  });
18788
18939
  }
18940
+ isCollectionTitleField(collection, fieldName) {
18941
+ const normalizedFieldName = String(fieldName || "").trim();
18942
+ const titleFieldName = String((0, import_service_helpers.getCollectionTitleFieldName)(collection) || "").trim();
18943
+ return !!normalizedFieldName && normalizedFieldName === titleFieldName;
18944
+ }
18789
18945
  resolveAssociationLeafDisplaySemantics(field, dataSourceKey, enabledPackages) {
18790
18946
  const registeredBinding = this.resolveRegisteredFieldBinding({
18791
18947
  containerUse: "DetailsItemModel",
@@ -18821,6 +18977,9 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18821
18977
  }
18822
18978
  buildFieldMenuDirectCandidates(input) {
18823
18979
  const collection = this.getCollection(input.resourceInit.dataSourceKey, input.resourceInit.collectionName);
18980
+ const explicitDefaultFieldPaths = (0, import_default_action_popup.collectFlowSurfaceDefaultActionPopupFieldGroupFieldPaths)(
18981
+ input.defaultFieldGroups
18982
+ );
18824
18983
  return (0, import_service_helpers.getCollectionFields)(collection).flatMap((field) => {
18825
18984
  var _a;
18826
18985
  const fieldName = (0, import_service_helpers.getFieldName)(field);
@@ -18831,6 +18990,9 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18831
18990
  if (input.generatedPopupOnly && !(0, import_default_action_popup.isFlowSurfaceDefaultActionPopupBusinessField)(field)) {
18832
18991
  return [];
18833
18992
  }
18993
+ if ((0, import_relation_backing_foreign_key.isRelationBackingForeignKeyField)(collection, field) && !explicitDefaultFieldPaths.has(fieldName)) {
18994
+ return [];
18995
+ }
18834
18996
  if (input.mode === "table" && ((_a = field == null ? void 0 : field.options) == null ? void 0 : _a.treeChildren)) {
18835
18997
  return [];
18836
18998
  }
@@ -18918,6 +19080,9 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
18918
19080
  if (!targetFieldName) {
18919
19081
  continue;
18920
19082
  }
19083
+ if ((0, import_relation_backing_foreign_key.isRelationBackingForeignKeyField)(targetCollection, targetField) && !this.isCollectionTitleField(targetCollection, targetFieldName)) {
19084
+ continue;
19085
+ }
18921
19086
  nextCandidates.push({
18922
19087
  field: targetField,
18923
19088
  fieldPath: `${associationPathName}.${targetFieldName}`,
@@ -19092,7 +19257,7 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
19092
19257
  const getFields = (targetCollection) => (0, import_service_helpers.getCollectionFields)(targetCollection);
19093
19258
  const isFilterFieldVisible = (field) => (0, import_service_helpers.getFieldFilterable)(field) !== false && !!(0, import_service_helpers.getFieldInterface)(field);
19094
19259
  const directFields = getFields(collection).filter(
19095
- (field) => ["FilterFormBlockModel", "FilterFormGridModel", "FilterFormItemModel"].includes(input.ownerUse) ? isFilterFieldVisible(field) : !!(0, import_service_helpers.getFieldInterface)(field)
19260
+ (field) => !(0, import_relation_backing_foreign_key.isRelationBackingForeignKeyField)(collection, field) && (["FilterFormBlockModel", "FilterFormGridModel", "FilterFormItemModel"].includes(input.ownerUse) ? isFilterFieldVisible(field) : !!(0, import_service_helpers.getFieldInterface)(field))
19096
19261
  );
19097
19262
  if (!directFields.length && !collection) {
19098
19263
  return [];
@@ -19106,9 +19271,13 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
19106
19271
  if (!(0, import_service_helpers.isAssociationField)(field) || !targetCollection) {
19107
19272
  return [];
19108
19273
  }
19109
- return getFields(targetCollection).filter(
19110
- (targetField) => ["FilterFormBlockModel", "FilterFormGridModel", "FilterFormItemModel"].includes(input.ownerUse) ? isFilterFieldVisible(targetField) : !!(0, import_service_helpers.getFieldInterface)(targetField)
19111
- ).map((targetField) => ({
19274
+ return getFields(targetCollection).filter((targetField) => {
19275
+ const targetFieldName = (0, import_service_helpers.getFieldName)(targetField);
19276
+ if ((0, import_relation_backing_foreign_key.isRelationBackingForeignKeyField)(targetCollection, targetField) && !this.isCollectionTitleField(targetCollection, targetFieldName)) {
19277
+ return false;
19278
+ }
19279
+ return ["FilterFormBlockModel", "FilterFormGridModel", "FilterFormItemModel"].includes(input.ownerUse) ? isFilterFieldVisible(targetField) : !!(0, import_service_helpers.getFieldInterface)(targetField);
19280
+ }).map((targetField) => ({
19112
19281
  field: targetField,
19113
19282
  fieldPath: `${(0, import_service_helpers.getFieldName)(field)}.${(0, import_service_helpers.getFieldName)(targetField)}`,
19114
19283
  associationPathName: (0, import_service_helpers.getFieldName)(field),