@nocobase/plugin-flow-engine 2.1.0-alpha.45 → 2.1.0-alpha.46

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 (93) hide show
  1. package/dist/client/index.js +1 -1
  2. package/dist/externalVersion.js +9 -9
  3. package/dist/node_modules/@ant-design/icons-svg/package.json +1 -1
  4. package/dist/node_modules/acorn/package.json +1 -1
  5. package/dist/node_modules/acorn-jsx/package.json +1 -1
  6. package/dist/node_modules/acorn-walk/package.json +1 -1
  7. package/dist/node_modules/ses/package.json +1 -1
  8. package/dist/node_modules/zod/package.json +1 -1
  9. package/dist/server/flow-surfaces/apply/compiler.js +10 -11
  10. package/dist/server/flow-surfaces/authoring-validation.d.ts +1 -0
  11. package/dist/server/flow-surfaces/authoring-validation.js +773 -26
  12. package/dist/server/flow-surfaces/blueprint/normalize-document.js +5 -1
  13. package/dist/server/flow-surfaces/catalog.js +9 -5
  14. package/dist/server/flow-surfaces/chart-config.js +220 -16
  15. package/dist/server/flow-surfaces/contract-guard.js +40 -6
  16. package/dist/server/flow-surfaces/default-block-actions.js +2 -0
  17. package/dist/server/flow-surfaces/errors.d.ts +15 -0
  18. package/dist/server/flow-surfaces/errors.js +49 -3
  19. package/dist/server/flow-surfaces/event-flow-normalizer.d.ts +19 -0
  20. package/dist/server/flow-surfaces/event-flow-normalizer.js +128 -0
  21. package/dist/server/flow-surfaces/filter-group.d.ts +9 -1
  22. package/dist/server/flow-surfaces/filter-group.js +402 -3
  23. package/dist/server/flow-surfaces/public-data-surface-default-filter.js +2 -1
  24. package/dist/server/flow-surfaces/route-sync.js +19 -2
  25. package/dist/server/flow-surfaces/runjs-authoring/ast/bindings.d.ts +66 -0
  26. package/dist/server/flow-surfaces/runjs-authoring/ast/bindings.js +661 -0
  27. package/dist/server/flow-surfaces/runjs-authoring/ast/execution.d.ts +20 -0
  28. package/dist/server/flow-surfaces/runjs-authoring/ast/execution.js +275 -0
  29. package/dist/server/flow-surfaces/runjs-authoring/ast/parser.d.ts +16 -0
  30. package/dist/server/flow-surfaces/runjs-authoring/ast/parser.js +130 -0
  31. package/dist/server/flow-surfaces/runjs-authoring/ast/react-values.d.ts +20 -0
  32. package/dist/server/flow-surfaces/runjs-authoring/ast/react-values.js +401 -0
  33. package/dist/server/flow-surfaces/runjs-authoring/ast/request-config.d.ts +21 -0
  34. package/dist/server/flow-surfaces/runjs-authoring/ast/request-config.js +199 -0
  35. package/dist/server/flow-surfaces/runjs-authoring/ast/source.d.ts +70 -0
  36. package/dist/server/flow-surfaces/runjs-authoring/ast/source.js +895 -0
  37. package/dist/server/flow-surfaces/runjs-authoring/ast/static-bindings.d.ts +23 -0
  38. package/dist/server/flow-surfaces/runjs-authoring/ast/static-bindings.js +618 -0
  39. package/dist/server/flow-surfaces/runjs-authoring/ast/static-values.d.ts +196 -0
  40. package/dist/server/flow-surfaces/runjs-authoring/ast/static-values.js +1777 -0
  41. package/dist/server/flow-surfaces/runjs-authoring/ast/walk.d.ts +10 -0
  42. package/dist/server/flow-surfaces/runjs-authoring/ast/walk.js +55 -0
  43. package/dist/server/flow-surfaces/runjs-authoring/collectors.d.ts +12 -0
  44. package/dist/server/flow-surfaces/runjs-authoring/collectors.js +589 -0
  45. package/dist/server/flow-surfaces/runjs-authoring/index.d.ts +2 -25
  46. package/dist/server/flow-surfaces/runjs-authoring/index.js +5 -11138
  47. package/dist/server/flow-surfaces/runjs-authoring/inspect.d.ts +13 -0
  48. package/dist/server/flow-surfaces/runjs-authoring/inspect.js +149 -0
  49. package/dist/server/flow-surfaces/runjs-authoring/internal-types.d.ts +333 -0
  50. package/dist/server/flow-surfaces/runjs-authoring/internal-types.js +36 -0
  51. package/dist/server/flow-surfaces/runjs-authoring/rules.js +2 -0
  52. package/dist/server/flow-surfaces/runjs-authoring/runtime/constants.d.ts +67 -0
  53. package/dist/server/flow-surfaces/runjs-authoring/runtime/constants.js +757 -0
  54. package/dist/server/flow-surfaces/runjs-authoring/runtime/errors.d.ts +22 -0
  55. package/dist/server/flow-surfaces/runjs-authoring/runtime/errors.js +91 -0
  56. package/dist/server/flow-surfaces/runjs-authoring/runtime/source-budget.d.ts +16 -0
  57. package/dist/server/flow-surfaces/runjs-authoring/runtime/source-budget.js +115 -0
  58. package/dist/server/flow-surfaces/runjs-authoring/runtime/surface.d.ts +19 -0
  59. package/dist/server/flow-surfaces/runjs-authoring/runtime/surface.js +140 -0
  60. package/dist/server/flow-surfaces/runjs-authoring/runtime/types.d.ts +91 -0
  61. package/dist/server/flow-surfaces/runjs-authoring/runtime/types.js +24 -0
  62. package/dist/server/flow-surfaces/runjs-authoring/scan/ctx-api.d.ts +138 -0
  63. package/dist/server/flow-surfaces/runjs-authoring/scan/ctx-api.js +1779 -0
  64. package/dist/server/flow-surfaces/runjs-authoring/scan/filter.d.ts +10 -0
  65. package/dist/server/flow-surfaces/runjs-authoring/scan/filter.js +1583 -0
  66. package/dist/server/flow-surfaces/runjs-authoring/scan/index.d.ts +195 -0
  67. package/dist/server/flow-surfaces/runjs-authoring/scan/index.js +463 -0
  68. package/dist/server/flow-surfaces/runjs-authoring/scan/react-render.d.ts +48 -0
  69. package/dist/server/flow-surfaces/runjs-authoring/scan/react-render.js +379 -0
  70. package/dist/server/flow-surfaces/runjs-authoring/scan/react.d.ts +26 -0
  71. package/dist/server/flow-surfaces/runjs-authoring/scan/react.js +1441 -0
  72. package/dist/server/flow-surfaces/runjs-authoring/scan/resource.d.ts +23 -0
  73. package/dist/server/flow-surfaces/runjs-authoring/scan/resource.js +1427 -0
  74. package/dist/server/flow-surfaces/runjs-authoring/scan/source-patterns.d.ts +91 -0
  75. package/dist/server/flow-surfaces/runjs-authoring/scan/source-patterns.js +889 -0
  76. package/dist/server/flow-surfaces/runjs-authoring/types.d.ts +1 -1
  77. package/dist/server/flow-surfaces/runjs-authoring/unknown-global-stop/index.d.ts +10 -0
  78. package/dist/server/flow-surfaces/runjs-authoring/unknown-global-stop/index.js +40 -0
  79. package/dist/server/flow-surfaces/runjs-authoring/validators/index.d.ts +12 -0
  80. package/dist/server/flow-surfaces/runjs-authoring/validators/index.js +887 -0
  81. package/dist/server/flow-surfaces/service-helpers.d.ts +29 -0
  82. package/dist/server/flow-surfaces/service-helpers.js +105 -0
  83. package/dist/server/flow-surfaces/service-utils.d.ts +15 -3
  84. package/dist/server/flow-surfaces/service-utils.js +6 -5
  85. package/dist/server/flow-surfaces/service.d.ts +7 -1
  86. package/dist/server/flow-surfaces/service.js +488 -94
  87. package/dist/server/flow-surfaces/types.d.ts +3 -0
  88. package/dist/server/repository.d.ts +12 -1
  89. package/dist/server/repository.js +195 -23
  90. package/dist/swagger/flow-surfaces.d.ts +175 -0
  91. package/dist/swagger/flow-surfaces.js +130 -51
  92. package/dist/swagger/index.d.ts +175 -0
  93. package/package.json +2 -2
@@ -60,6 +60,7 @@ var import_association_interfaces = require("./association-interfaces");
60
60
  var import_defaults = require("./blueprint/defaults");
61
61
  var import_runjs_authoring = require("./runjs-authoring");
62
62
  var import_configure_options = require("./configure-options");
63
+ var import_filter_group = require("./filter-group");
63
64
  const MAIN_BLOCK_UNSUPPORTED_SECTIONS = {
64
65
  calendar: ["fields", "fieldGroups", "recordActions", "fieldsLayout"],
65
66
  kanban: ["fieldGroups", "recordActions", "fieldsLayout"],
@@ -83,6 +84,13 @@ const VISIBLE_FIELD_REQUIRED_DATA_BLOCK_TYPES = /* @__PURE__ */ new Set([
83
84
  "kanban"
84
85
  ]);
85
86
  const VISIBLE_FIELD_MINIMUM_DATA_BLOCK_TYPES = /* @__PURE__ */ new Set(["table", "list", "gridCard", "details"]);
87
+ const IMPLICIT_RELATION_TITLE_FIELD_DISPLAY_BLOCK_TYPES = /* @__PURE__ */ new Set(["table", "list", "gridCard", "details"]);
88
+ const IMPLICIT_RELATION_TITLE_FIELD_CONTAINER_USE_BY_BLOCK_TYPE = {
89
+ details: "DetailsItemModel",
90
+ gridCard: "GridCardItemModel",
91
+ list: "ListItemModel",
92
+ table: "TableColumnModel"
93
+ };
86
94
  const RICH_COLLECTION_VISIBLE_FIELD_THRESHOLD = import_public_data_surface_default_filter.FLOW_SURFACE_DEFAULT_FILTER_REQUIRED_FIELD_COUNT * 2;
87
95
  const RICH_DATA_BLOCK_VISIBLE_FIELD_MINIMUM = 3;
88
96
  const NON_BUSINESS_VISIBLE_FIELD_NAMES = /* @__PURE__ */ new Set([
@@ -163,10 +171,36 @@ const JS_BLOCK_ALLOWED_SETTINGS_KEYS = /* @__PURE__ */ new Set(["title", "descri
163
171
  const JS_BLOCK_TOP_LEVEL_JS_KEYS = ["code", "version"];
164
172
  const JS_BLOCK_INTERNAL_AUTHORING_KEYS = ["props", "decoratorProps", "flowRegistry", "stepParams"];
165
173
  const JS_BLOCK_REPAIR_HINT = "This is a jsBlock payload shape problem. Repair this jsBlock using inline settings.code/settings.version, or applyBlueprint assets.scripts.<key>.code plus block.script. Do not change this block type to table, chart, actionPanel, gridCard, or another block type.";
166
- const CHART_REPAIR_HINT = "This is a chart payload shape problem. Repair this chart using assets.charts.<key>.query/visual plus block.chart, or localized settings.query/settings.visual. Do not change this block type to table, jsBlock, actionPanel, gridCard, or another block type, and do not drop or defer the chart. KPI / summary numbers should use jsBlock; charts are for trends, distributions, rankings, and visual analysis.";
174
+ const CHART_REPAIR_HINT = "This is a chart payload shape problem. Keep using chart and repair this chart using assets.charts.<key>.query/visual plus block.chart, or localized settings.query/settings.visual. Do not change this block type to table, jsBlock, actionPanel, gridCard, or another block type, and do not drop or defer the chart. KPI / summary numbers should use jsBlock; charts are for trends, distributions, rankings, and visual analysis.";
175
+ const REPAIR_ALL_ERRORS_AGENT_INSTRUCTION = "If this response contains errors[], fix every listed error in one payload revision before retrying the same write. Do not fix only this error and immediately retry.";
176
+ const JS_BLOCK_AGENT_INSTRUCTION = `${REPAIR_ALL_ERRORS_AGENT_INSTRUCTION} Do not skip, drop, defer, or replace this required jsBlock. Repair it as jsBlock.`;
177
+ const CHART_AGENT_INSTRUCTION = `${REPAIR_ALL_ERRORS_AGENT_INSTRUCTION} Do not skip, drop, defer, or replace this required chart. Repair it as chart.`;
178
+ const VISIBLE_DATA_BLOCK_FIELDS_REPAIR_HINT = "Add direct visible collection fields to this block. Do not rely on defaults.collections.*.fieldGroups, action-only fields, dividers, or generated popup/form defaults as a substitute for visible block fields.";
179
+ const JS_BLOCK_FORBIDDEN_FALLBACKS = [
180
+ "table",
181
+ "list",
182
+ "chart",
183
+ "actionPanel",
184
+ "gridCard",
185
+ "markdown",
186
+ "drop jsBlock",
187
+ "defer jsBlock"
188
+ ];
189
+ const CHART_FORBIDDEN_FALLBACKS = [
190
+ "table",
191
+ "list",
192
+ "jsBlock",
193
+ "actionPanel",
194
+ "gridCard",
195
+ "markdown",
196
+ "drop chart",
197
+ "defer chart"
198
+ ];
167
199
  const CHART_QUERY_MODE_SET = new Set(import_chart_config.CHART_QUERY_MODES);
168
200
  const CHART_VISUAL_MODE_SET = new Set(import_chart_config.CHART_VISUAL_MODES);
169
201
  const CHART_BASIC_VISUAL_TYPE_SET = new Set(import_chart_config.CHART_BASIC_VISUAL_TYPES);
202
+ const CHART_BASIC_VISUAL_TYPE_LIST = import_chart_config.CHART_BASIC_VISUAL_TYPES.join(", ");
203
+ const STRICT_LOCALIZED_CHART_ACTIONS = /* @__PURE__ */ new Set(["compose", "addBlocks"]);
170
204
  const CHART_VISUAL_LEGACY_BUILDER_KEYS = /* @__PURE__ */ new Set([
171
205
  "xField",
172
206
  "yField",
@@ -201,6 +235,7 @@ const CHART_SQL_QUERY_FORBIDDEN_KEYS = /* @__PURE__ */ new Set([
201
235
  "offset"
202
236
  ]);
203
237
  const CHART_CUSTOM_VISUAL_FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["type", "mappings", "style"]);
238
+ const CHART_DEFAULT_DATA_SOURCE_KEY = "main";
204
239
  const JS_ITEM_COLLECTION_ACTION_HOST_BLOCK_TYPES = /* @__PURE__ */ new Set(["table", "list", "gridCard", "calendar", "kanban"]);
205
240
  const JS_ITEM_RECORD_ACTION_HOST_BLOCK_TYPES = /* @__PURE__ */ new Set(["table", "details", "list", "gridCard"]);
206
241
  const JS_ITEM_FORM_ACTION_HOST_BLOCK_TYPES = /* @__PURE__ */ new Set(["createForm", "editForm"]);
@@ -396,6 +431,14 @@ async function collectFlowSurfaceAuthoringErrors(actionName, values, context = {
396
431
  if (!_.isPlainObject(values)) {
397
432
  return errors;
398
433
  }
434
+ validationContext.getDefaultFieldGroups = validationContext.getDefaultFieldGroups || ((dataSourceKey, collectionName) => {
435
+ var _a2;
436
+ return (_a2 = (0, import_defaults.resolveFlowSurfaceApplyBlueprintDefaultCollection)({
437
+ metadata: values == null ? void 0 : values.defaults,
438
+ dataSourceKey,
439
+ collectionName
440
+ }).collectionDefaults) == null ? void 0 : _a2.fieldGroups;
441
+ });
399
442
  if (actionName === "applyBlueprint" && _.isPlainObject((_a = values == null ? void 0 : values.assets) == null ? void 0 : _a.scripts)) {
400
443
  validationContext.applyBlueprintScriptAssets = values.assets.scripts;
401
444
  }
@@ -408,7 +451,7 @@ async function collectFlowSurfaceAuthoringErrors(actionName, values, context = {
408
451
  collectApplyBlueprintChartAssetErrors(actionName, values, validationContext, errors);
409
452
  if (actionName === "configure") {
410
453
  await collectConfigureErrors(values, errors, validationContext);
411
- errors.push(...(0, import_runjs_authoring.collectRunJsAuthoringErrors)(actionName, values, validationContext));
454
+ appendRunJsAuthoringErrors(actionName, values, validationContext, errors);
412
455
  if (!validationContext.skipGeneratedPopupDefaultFieldGroups) {
413
456
  collectGeneratedPopupDefaultFieldGroupErrors(actionName, values, validationContext, errors);
414
457
  }
@@ -429,9 +472,42 @@ async function collectFlowSurfaceAuthoringErrors(actionName, values, context = {
429
472
  if (!validationContext.skipGeneratedPopupDefaultFieldGroups) {
430
473
  collectGeneratedPopupDefaultFieldGroupErrors(actionName, values, validationContext, errors);
431
474
  }
432
- errors.push(...(0, import_runjs_authoring.collectRunJsAuthoringErrors)(actionName, values, validationContext));
475
+ appendRunJsAuthoringErrors(actionName, values, validationContext, errors);
433
476
  return errors;
434
477
  }
478
+ function appendRunJsAuthoringErrors(actionName, values, context, errors) {
479
+ try {
480
+ errors.push(...(0, import_runjs_authoring.collectRunJsAuthoringErrors)(actionName, values, context));
481
+ } catch (error) {
482
+ if (shouldKeepExistingChartAuthoringErrors(error, errors)) {
483
+ return;
484
+ }
485
+ if (isChartBadRequestError(error)) {
486
+ pushChartBadRequestAuthoringError(errors, error, actionName === "configure" ? "$.changes" : "$");
487
+ return;
488
+ }
489
+ throw error;
490
+ }
491
+ }
492
+ function isChartBadRequestError(error) {
493
+ return error instanceof import_errors.FlowSurfaceBadRequestError && String(error.message || "").startsWith("chart ");
494
+ }
495
+ function shouldKeepExistingChartAuthoringErrors(error, errors) {
496
+ return isChartBadRequestError(error) && errors.some((item) => {
497
+ var _a;
498
+ return ((_a = item.details) == null ? void 0 : _a.repairHint) === CHART_REPAIR_HINT;
499
+ });
500
+ }
501
+ function pushChartBadRequestAuthoringError(errors, error, fallbackPath) {
502
+ var _a, _b, _c;
503
+ const details = _.isPlainObject((_a = error.options) == null ? void 0 : _a.details) ? error.options.details : {};
504
+ pushAuthoringError(errors, {
505
+ path: typeof ((_b = error.options) == null ? void 0 : _b.path) === "string" && error.options.path ? error.options.path : fallbackPath,
506
+ ruleId: typeof ((_c = error.options) == null ? void 0 : _c.ruleId) === "string" && error.options.ruleId ? error.options.ruleId : "chart-configure-invalid",
507
+ message: error.message,
508
+ details: withChartRepairHint(details)
509
+ });
510
+ }
435
511
  async function collectNavigationGroupErrors(actionName, values, context, errors) {
436
512
  var _a;
437
513
  if (actionName !== "applyBlueprint" || (values == null ? void 0 : values.mode) !== "create" || !_.isPlainObject((_a = values == null ? void 0 : values.navigation) == null ? void 0 : _a.group)) {
@@ -644,13 +720,41 @@ function collectChartAssetBlockTreeErrors(block, path, chartAssets, errors) {
644
720
  function withJsBlockRepairHint(details = {}) {
645
721
  return {
646
722
  ...details,
647
- repairHint: JS_BLOCK_REPAIR_HINT
723
+ requiredBlockType: "jsBlock",
724
+ fixStrategy: "repair_same_block_type",
725
+ repairHint: JS_BLOCK_REPAIR_HINT,
726
+ agentInstruction: JS_BLOCK_AGENT_INSTRUCTION,
727
+ repairExample: {
728
+ inlineBlock: {
729
+ type: "jsBlock",
730
+ settings: {
731
+ code: 'ctx.render("Replace this with the required rendered UI");'
732
+ }
733
+ },
734
+ assetBlock: {
735
+ assets: {
736
+ scripts: {
737
+ scriptKey: {
738
+ code: 'ctx.render("Replace this with the required rendered UI");'
739
+ }
740
+ }
741
+ },
742
+ block: {
743
+ type: "jsBlock",
744
+ script: "scriptKey"
745
+ }
746
+ }
747
+ },
748
+ forbiddenFallbacks: JS_BLOCK_FORBIDDEN_FALLBACKS
648
749
  };
649
750
  }
650
751
  function withChartRepairHint(details = {}) {
651
752
  return {
652
753
  ...details,
754
+ requiredBlockType: "chart",
755
+ fixStrategy: "repair_same_block_type",
653
756
  repairHint: CHART_REPAIR_HINT,
757
+ agentInstruction: CHART_AGENT_INSTRUCTION,
654
758
  repairSteps: [
655
759
  "Keep the block type as chart.",
656
760
  "Define assets.charts.<key>.query and assets.charts.<key>.visual.",
@@ -658,6 +762,58 @@ function withChartRepairHint(details = {}) {
658
762
  "Retry the chart payload instead of replacing the chart with another block type or omitting it."
659
763
  ],
660
764
  expectedShape: {
765
+ settings: {
766
+ query: {
767
+ mode: "builder",
768
+ resource: {
769
+ dataSourceKey: "main",
770
+ collectionName: "employees"
771
+ },
772
+ measures: [
773
+ {
774
+ field: "id",
775
+ aggregation: "count",
776
+ alias: "employeeCount"
777
+ }
778
+ ]
779
+ },
780
+ visual: {
781
+ mode: "basic",
782
+ type: "bar",
783
+ mappings: {
784
+ x: "status",
785
+ y: "employeeCount"
786
+ }
787
+ }
788
+ },
789
+ legacySettings: {
790
+ configure: {
791
+ query: {
792
+ mode: "builder",
793
+ resource: {
794
+ dataSourceKey: "main",
795
+ collectionName: "employees"
796
+ },
797
+ measures: [
798
+ {
799
+ field: "id",
800
+ aggregation: "count",
801
+ alias: "employeeCount"
802
+ }
803
+ ]
804
+ },
805
+ chart: {
806
+ option: {
807
+ mode: "basic",
808
+ builder: {
809
+ type: "bar",
810
+ xField: "status",
811
+ yField: "employeeCount"
812
+ }
813
+ }
814
+ }
815
+ }
816
+ },
661
817
  assets: {
662
818
  charts: {
663
819
  chartKey: {
@@ -671,9 +827,245 @@ function withChartRepairHint(details = {}) {
671
827
  chart: "chartKey"
672
828
  }
673
829
  },
674
- forbiddenFallbacks: ["table", "jsBlock", "actionPanel", "gridCard", "drop chart", "defer chart"]
830
+ repairExample: {
831
+ settings: {
832
+ query: {
833
+ mode: "builder",
834
+ resource: {
835
+ dataSourceKey: "main",
836
+ collectionName: "<collectionName>"
837
+ },
838
+ measures: [
839
+ {
840
+ field: "id",
841
+ aggregation: "count",
842
+ alias: "recordCount"
843
+ }
844
+ ],
845
+ dimensions: [
846
+ {
847
+ field: "<dimensionField>"
848
+ }
849
+ ]
850
+ },
851
+ visual: {
852
+ mode: "basic",
853
+ type: "bar",
854
+ mappings: {
855
+ x: "<dimensionField>",
856
+ y: "recordCount"
857
+ }
858
+ }
859
+ },
860
+ assets: {
861
+ charts: {
862
+ chartKey: {
863
+ query: {
864
+ mode: "builder",
865
+ resource: {
866
+ dataSourceKey: "main",
867
+ collectionName: "<collectionName>"
868
+ },
869
+ measures: [
870
+ {
871
+ field: "id",
872
+ aggregation: "count",
873
+ alias: "recordCount"
874
+ }
875
+ ],
876
+ dimensions: [
877
+ {
878
+ field: "<dimensionField>"
879
+ }
880
+ ]
881
+ },
882
+ visual: {
883
+ mode: "basic",
884
+ type: "bar",
885
+ mappings: {
886
+ x: "<dimensionField>",
887
+ y: "recordCount"
888
+ }
889
+ }
890
+ }
891
+ }
892
+ },
893
+ block: {
894
+ type: "chart",
895
+ chart: "chartKey"
896
+ }
897
+ },
898
+ forbiddenFallbacks: CHART_FORBIDDEN_FALLBACKS
899
+ };
900
+ }
901
+ function withUnsupportedChartVisualTypeHint(details = {}) {
902
+ const jsBlockHint = `Supported basic chart visual types are: ${CHART_BASIC_VISUAL_TYPE_LIST}. If the required visualization cannot be represented by these chart types, use a jsBlock instead.`;
903
+ return {
904
+ ...details,
905
+ fixStrategy: "use_supported_chart_type_or_jsBlock",
906
+ repairHint: jsBlockHint,
907
+ agentInstruction: `${REPAIR_ALL_ERRORS_AGENT_INSTRUCTION} Use one of the supported chart visual types, or use a jsBlock when the requested visualization is outside the chart plugin capabilities.`,
908
+ supportedVisualTypes: [...import_chart_config.CHART_BASIC_VISUAL_TYPES],
909
+ alternativeBlockType: "jsBlock",
910
+ alternativeHint: jsBlockHint,
911
+ forbiddenFallbacks: CHART_FORBIDDEN_FALLBACKS.filter((item) => item !== "jsBlock")
912
+ };
913
+ }
914
+ function collectLocalizedChartSettingsErrors(block, blockType, path, errors, context) {
915
+ if (blockType !== "chart" || !STRICT_LOCALIZED_CHART_ACTIONS.has(context.authoringActionName)) {
916
+ return;
917
+ }
918
+ const settingsPath = `${path}.settings`;
919
+ if (!_.isUndefined(block.settings) && !_.isPlainObject(block.settings)) {
920
+ pushAuthoringError(errors, {
921
+ path: settingsPath,
922
+ ruleId: "chart-localized-settings-invalid",
923
+ message: `flowSurfaces authoring ${settingsPath} must be an object for compose/addBlocks chart blocks`,
924
+ details: withChartRepairHint()
925
+ });
926
+ return;
927
+ }
928
+ const settings = _.isPlainObject(block.settings) ? block.settings : {};
929
+ if (hasOwn(settings, "configure")) {
930
+ if (["query", "visual", "events"].some((key) => hasOwn(settings, key))) {
931
+ pushAuthoringError(errors, {
932
+ path: settingsPath,
933
+ ruleId: "chart-localized-settings-mixed-configure",
934
+ message: `flowSurfaces authoring ${settingsPath} cannot mix legacy configure with query/visual/events`,
935
+ details: withChartRepairHint()
936
+ });
937
+ return;
938
+ }
939
+ collectLocalizedLegacyChartConfigureErrors(settings.configure, `${settingsPath}.configure`, errors);
940
+ return;
941
+ }
942
+ if (!hasOwn(settings, "query") && !hasOwn(settings, "visual")) {
943
+ return;
944
+ }
945
+ collectChartAssetQueryErrors(settings, settingsPath, context, errors);
946
+ collectChartAssetVisualErrors(settings, settingsPath, errors);
947
+ }
948
+ function collectLocalizedLegacyChartConfigureErrors(configure, path, errors) {
949
+ if (!_.isPlainObject(configure)) {
950
+ pushAuthoringError(errors, {
951
+ path,
952
+ ruleId: "chart-configure-invalid",
953
+ message: `flowSurfaces authoring ${path} must be an object`,
954
+ details: withChartRepairHint()
955
+ });
956
+ return;
957
+ }
958
+ collectLegacyChartQueryCompatibilityErrors(configure.query, `${path}.query`, errors);
959
+ }
960
+ function collectLegacyChartQueryCompatibilityErrors(query, path, errors) {
961
+ if (!_.isPlainObject(query)) {
962
+ return;
963
+ }
964
+ collectChartQueryFilterOperatorErrors(query, path, errors);
965
+ const hasResource = hasOwn(query, "resource");
966
+ const hasCollectionPath = hasOwn(query, "collectionPath");
967
+ if (!hasResource && !hasCollectionPath) {
968
+ return;
969
+ }
970
+ const resource = hasResource ? normalizeLegacyChartResourceForValidation(query.resource, `${path}.resource`, errors) : void 0;
971
+ const collectionPathResource = hasCollectionPath ? normalizeLegacyChartCollectionPathResourceForValidation(query.collectionPath, `${path}.collectionPath`, errors) : void 0;
972
+ if (hasResource && hasCollectionPath && resource && collectionPathResource && !_.isEqual(resource, collectionPathResource)) {
973
+ pushAuthoringError(errors, {
974
+ path,
975
+ ruleId: "chart-legacy-query-resource-conflict",
976
+ message: `flowSurfaces authoring ${path}.resource and ${path}.collectionPath must reference the same collection`,
977
+ details: withChartRepairHint({
978
+ resource,
979
+ collectionPathResource
980
+ })
981
+ });
982
+ }
983
+ }
984
+ function normalizeLegacyChartCollectionPathResource(collectionPath) {
985
+ if (!Array.isArray(collectionPath)) {
986
+ return void 0;
987
+ }
988
+ const collectionName = normalizeLegacyChartRequiredString(collectionPath[1]);
989
+ if (!collectionName) {
990
+ return void 0;
991
+ }
992
+ const dataSourceKey = normalizeLegacyChartCollectionPathDataSourceKey(collectionPath[0]);
993
+ if (!dataSourceKey) {
994
+ return void 0;
995
+ }
996
+ return {
997
+ dataSourceKey,
998
+ collectionName
999
+ };
1000
+ }
1001
+ function normalizeLegacyChartResourceForValidation(resource, path, errors) {
1002
+ if (!_.isPlainObject(resource)) {
1003
+ pushAuthoringError(errors, {
1004
+ path,
1005
+ ruleId: "chart-legacy-query-resource-invalid",
1006
+ message: `flowSurfaces authoring ${path} must be an object with string collectionName`,
1007
+ details: withChartRepairHint()
1008
+ });
1009
+ return void 0;
1010
+ }
1011
+ const collectionName = normalizeLegacyChartRequiredString(resource.collectionName);
1012
+ if (!collectionName) {
1013
+ pushAuthoringError(errors, {
1014
+ path: `${path}.collectionName`,
1015
+ ruleId: "chart-legacy-query-resource-invalid",
1016
+ message: `flowSurfaces authoring ${path}.collectionName must be a non-empty string`,
1017
+ details: withChartRepairHint()
1018
+ });
1019
+ return void 0;
1020
+ }
1021
+ const dataSourceKey = normalizeLegacyChartResourceDataSourceKey(resource.dataSourceKey);
1022
+ if (!dataSourceKey) {
1023
+ pushAuthoringError(errors, {
1024
+ path: `${path}.dataSourceKey`,
1025
+ ruleId: "chart-legacy-query-resource-invalid",
1026
+ message: `flowSurfaces authoring ${path}.dataSourceKey must be a non-empty string when provided`,
1027
+ details: withChartRepairHint()
1028
+ });
1029
+ return void 0;
1030
+ }
1031
+ return {
1032
+ dataSourceKey,
1033
+ collectionName
675
1034
  };
676
1035
  }
1036
+ function normalizeLegacyChartCollectionPathResourceForValidation(collectionPath, path, errors) {
1037
+ const resource = normalizeLegacyChartCollectionPathResource(collectionPath);
1038
+ if (!resource) {
1039
+ pushAuthoringError(errors, {
1040
+ path,
1041
+ ruleId: "chart-legacy-query-collection-path-invalid",
1042
+ message: `flowSurfaces authoring ${path} must be [dataSourceKey, collectionName] with string values and a non-empty collectionName`,
1043
+ details: withChartRepairHint()
1044
+ });
1045
+ }
1046
+ return resource;
1047
+ }
1048
+ function normalizeLegacyChartRequiredString(input) {
1049
+ if (typeof input !== "string") {
1050
+ return void 0;
1051
+ }
1052
+ return input.trim() || void 0;
1053
+ }
1054
+ function normalizeLegacyChartResourceDataSourceKey(input) {
1055
+ if (_.isUndefined(input) || _.isNull(input)) {
1056
+ return CHART_DEFAULT_DATA_SOURCE_KEY;
1057
+ }
1058
+ return normalizeLegacyChartRequiredString(input);
1059
+ }
1060
+ function normalizeLegacyChartCollectionPathDataSourceKey(input) {
1061
+ if (_.isUndefined(input) || _.isNull(input)) {
1062
+ return CHART_DEFAULT_DATA_SOURCE_KEY;
1063
+ }
1064
+ if (typeof input === "string" && !input.trim()) {
1065
+ return CHART_DEFAULT_DATA_SOURCE_KEY;
1066
+ }
1067
+ return normalizeLegacyChartRequiredString(input);
1068
+ }
677
1069
  function collectChartBlockAssetReferenceErrors(block, path, chartAssets, errors) {
678
1070
  if (!CHART_BLOCK_TYPES.has(String((block == null ? void 0 : block.type) || "").trim())) {
679
1071
  return;
@@ -781,8 +1173,85 @@ function collectBuilderChartAssetQueryErrors(query, path, context, errors) {
781
1173
  errors,
782
1174
  withChartRepairHint()
783
1175
  );
1176
+ collectChartQueryFilterOperatorErrors(query, `${path}.query`, errors);
784
1177
  collectBuilderChartAssetFieldErrors(query, path, context, errors);
785
1178
  }
1179
+ function collectChartQueryFilterOperatorErrors(query, path, errors) {
1180
+ if (!_.isPlainObject(query) || !hasOwn(query, "filter")) {
1181
+ return;
1182
+ }
1183
+ collectChartFilterOperatorErrors(query.filter, `${path}.filter`, errors);
1184
+ }
1185
+ function collectChartFilterOperatorErrors(filter, path, errors) {
1186
+ if (_.isUndefined(filter) || _.isNull(filter) || !_.isPlainObject(filter)) {
1187
+ return;
1188
+ }
1189
+ if (Array.isArray(filter.items)) {
1190
+ collectChartFilterGroupOperatorErrors(filter.items, `${path}.items`, errors);
1191
+ return;
1192
+ }
1193
+ collectBackendQueryFilterOperatorErrors(filter, path, errors);
1194
+ }
1195
+ function collectChartFilterGroupOperatorErrors(items, path, errors) {
1196
+ items.forEach((item, index) => {
1197
+ const itemPath = `${path}[${index}]`;
1198
+ if (!_.isPlainObject(item)) {
1199
+ return;
1200
+ }
1201
+ if (Array.isArray(item.items)) {
1202
+ collectChartFilterGroupOperatorErrors(item.items, `${itemPath}.items`, errors);
1203
+ return;
1204
+ }
1205
+ if (hasOwn(item, "operator")) {
1206
+ collectChartFilterOperatorError(item.operator, `${itemPath}.operator`, errors);
1207
+ collectChartFilterDateValueError(item.operator, item.value, `${itemPath}.value`, errors);
1208
+ }
1209
+ });
1210
+ }
1211
+ function collectBackendQueryFilterOperatorErrors(filter, path, errors) {
1212
+ Object.entries(filter).forEach(([field, condition]) => {
1213
+ const fieldPath = `${path}.${field}`;
1214
+ if ((field === "$and" || field === "$or") && Array.isArray(condition)) {
1215
+ condition.forEach(
1216
+ (operand, index) => collectChartFilterOperatorErrors(operand, `${fieldPath}[${index}]`, errors)
1217
+ );
1218
+ return;
1219
+ }
1220
+ if (!_.isPlainObject(condition)) {
1221
+ return;
1222
+ }
1223
+ Object.keys(condition).forEach((operator) => {
1224
+ if (operator === "$and" || operator === "$or") {
1225
+ collectChartFilterOperatorErrors({ [operator]: condition[operator] }, fieldPath, errors);
1226
+ return;
1227
+ }
1228
+ collectChartFilterOperatorError(operator, `${fieldPath}.${operator}`, errors);
1229
+ collectChartFilterDateValueError(operator, condition[operator], `${fieldPath}.${operator}`, errors);
1230
+ });
1231
+ });
1232
+ }
1233
+ function collectChartFilterOperatorError(operator, path, errors) {
1234
+ try {
1235
+ (0, import_filter_group.assertFlowSurfaceFilterOperator)(operator, path);
1236
+ } catch (error) {
1237
+ if (error instanceof import_errors.FlowSurfaceBadRequestError) {
1238
+ pushChartBadRequestAuthoringError(errors, error, path);
1239
+ return;
1240
+ }
1241
+ throw error;
1242
+ }
1243
+ }
1244
+ function collectChartFilterDateValueError(operator, value, path, errors) {
1245
+ try {
1246
+ (0, import_filter_group.normalizeFlowSurfaceStrictFilterDateValue)(operator, value, path);
1247
+ } catch (error) {
1248
+ if (error instanceof import_errors.FlowSurfaceBadRequestError) {
1249
+ pushChartBadRequestAuthoringError(errors, error, path);
1250
+ return;
1251
+ }
1252
+ throw error;
1253
+ }
1254
+ }
786
1255
  function normalizeChartAssetFieldPath(input) {
787
1256
  if (Array.isArray(input)) {
788
1257
  return input.map((item) => String(item || "").trim()).filter(Boolean).join(".");
@@ -790,6 +1259,7 @@ function normalizeChartAssetFieldPath(input) {
790
1259
  return String(input || "").trim();
791
1260
  }
792
1261
  function collectBuilderChartAssetFieldErrors(query, path, context, errors) {
1262
+ var _a, _b, _c, _d, _e;
793
1263
  const resource = _.isPlainObject(query.resource) ? query.resource : null;
794
1264
  const collectionName = String((resource == null ? void 0 : resource.collectionName) || "").trim();
795
1265
  if (!collectionName || typeof context.getCollection !== "function") {
@@ -803,10 +1273,12 @@ function collectBuilderChartAssetFieldErrors(query, path, context, errors) {
803
1273
  const selections = [
804
1274
  ..._.castArray(query.measures || []).map((selection, index) => ({
805
1275
  selection,
1276
+ kind: "measure",
806
1277
  fieldPath: `${path}.query.measures[${index}].field`
807
1278
  })),
808
1279
  ..._.castArray(query.dimensions || []).map((selection, index) => ({
809
1280
  selection,
1281
+ kind: "dimension",
810
1282
  fieldPath: `${path}.query.dimensions[${index}].field`
811
1283
  }))
812
1284
  ];
@@ -818,24 +1290,80 @@ function collectBuilderChartAssetFieldErrors(query, path, context, errors) {
818
1290
  if (!fieldPath) {
819
1291
  continue;
820
1292
  }
1293
+ const fieldPathParts = fieldPath.split(".").filter(Boolean);
1294
+ const isCountMeasureSelection = item.kind === "measure" && String(((_a = item.selection) == null ? void 0 : _a.aggregation) || "").trim() === "count" && !((_b = item.selection) == null ? void 0 : _b.distinct);
1295
+ if (fieldPathParts.length > 1 && !isCountMeasureSelection) {
1296
+ const directAssociationPath = fieldPathParts[0];
1297
+ const directAssociationField = (0, import_service_helpers.resolveFieldFromCollection)(collection, directAssociationPath);
1298
+ const directAssociationTargetCollection = directAssociationField && (0, import_service_helpers.isAssociationField)(directAssociationField) ? (0, import_service_helpers.resolveFieldTargetCollection)(
1299
+ directAssociationField,
1300
+ dataSourceKey,
1301
+ (resolvedDataSourceKey, targetCollection) => {
1302
+ var _a2;
1303
+ return (_a2 = context.getCollection) == null ? void 0 : _a2.call(context, resolvedDataSourceKey, targetCollection);
1304
+ }
1305
+ ) : null;
1306
+ const invalidDirectSubfield = directAssociationTargetCollection ? (0, import_service_helpers.getInvalidChartBuilderRelationDirectSubfieldDetails)({
1307
+ associationPathName: directAssociationPath,
1308
+ selectedSubfieldPath: fieldPathParts.slice(1).join("."),
1309
+ targetCollection: directAssociationTargetCollection
1310
+ }) : null;
1311
+ if (invalidDirectSubfield) {
1312
+ pushAuthoringError(errors, {
1313
+ path: item.fieldPath,
1314
+ ruleId: "chart-builder-query-relation-direct-subfield-required",
1315
+ message: `flowSurfaces authoring ${item.fieldPath} must reference a direct scalar child field under relation '${invalidDirectSubfield.associationPath}'. ${(0, import_service_helpers.formatChartBuilderSupportedRelationSubfields)(
1316
+ invalidDirectSubfield.associationPath,
1317
+ invalidDirectSubfield.supportedFields
1318
+ )}`,
1319
+ details: withChartRepairHint({
1320
+ fieldPath,
1321
+ dataSourceKey,
1322
+ collectionName,
1323
+ ...invalidDirectSubfield
1324
+ })
1325
+ });
1326
+ continue;
1327
+ }
1328
+ }
821
1329
  const field = (0, import_service_helpers.resolveFieldFromCollection)(collection, fieldPath);
1330
+ const associationPath = fieldPath.includes(".") ? fieldPath.split(".").slice(0, -1).join(".") : "";
1331
+ const leafFieldName = fieldPath.split(".").slice(-1)[0];
1332
+ const associationField = associationPath ? (0, import_service_helpers.resolveFieldFromCollection)(collection, associationPath) : null;
1333
+ const associationTargetCollection = associationField && (0, import_service_helpers.isAssociationField)(associationField) ? (0, import_service_helpers.resolveFieldTargetCollection)(
1334
+ associationField,
1335
+ dataSourceKey,
1336
+ (resolvedDataSourceKey, targetCollection) => {
1337
+ var _a2;
1338
+ return (_a2 = context.getCollection) == null ? void 0 : _a2.call(context, resolvedDataSourceKey, targetCollection);
1339
+ }
1340
+ ) : null;
1341
+ const leafModelAttributes = (0, import_service_helpers.getCollectionModelAttributes)(associationTargetCollection || collection);
1342
+ const hasLeafModelAttribute = Object.prototype.hasOwnProperty.call(leafModelAttributes, leafFieldName);
1343
+ const isCountMeasureRelationSubfield = item.kind === "measure" && String(((_c = item.selection) == null ? void 0 : _c.aggregation) || "").trim() === "count" && !((_d = item.selection) == null ? void 0 : _d.distinct) && associationField && (0, import_service_helpers.isAssociationField)(associationField);
1344
+ const unsupportedRelationSubfield = associationTargetCollection ? (0, import_service_helpers.getUnsupportedChartBuilderRelationSubfieldDetails)({
1345
+ associationPathName: associationPath,
1346
+ leafFieldName,
1347
+ leafField: field,
1348
+ targetCollection: associationTargetCollection
1349
+ }) : null;
822
1350
  if (!field) {
823
- if (collectionHasConcreteField(collection, fieldPath)) {
1351
+ const hasConcreteField = associationTargetCollection ? hasLeafModelAttribute || collectionHasConcreteField(associationTargetCollection, leafFieldName) : collectionHasConcreteField(collection, fieldPath);
1352
+ if (!hasConcreteField) {
1353
+ pushAuthoringError(errors, {
1354
+ path: item.fieldPath,
1355
+ ruleId: "chart-builder-query-field-unknown",
1356
+ message: `flowSurfaces authoring ${item.fieldPath} references unknown field '${fieldPath}' on collection '${dataSourceKey}.${collectionName}'`,
1357
+ details: withChartRepairHint({
1358
+ fieldPath,
1359
+ dataSourceKey,
1360
+ collectionName
1361
+ })
1362
+ });
824
1363
  continue;
825
1364
  }
826
- pushAuthoringError(errors, {
827
- path: item.fieldPath,
828
- ruleId: "chart-builder-query-field-unknown",
829
- message: `flowSurfaces authoring ${item.fieldPath} references unknown field '${fieldPath}' on collection '${dataSourceKey}.${collectionName}'`,
830
- details: withChartRepairHint({
831
- fieldPath,
832
- dataSourceKey,
833
- collectionName
834
- })
835
- });
836
- continue;
837
1365
  }
838
- if (!fieldPath.includes(".") && (0, import_service_helpers.isAssociationField)(field)) {
1366
+ if (!fieldPath.includes(".") && field && (0, import_service_helpers.isAssociationField)(field)) {
839
1367
  const suggestion = resolveChartBuilderAssociationSubfieldSuggestion(
840
1368
  fieldPath,
841
1369
  field,
@@ -854,6 +1382,43 @@ function collectBuilderChartAssetFieldErrors(query, path, context, errors) {
854
1382
  })
855
1383
  });
856
1384
  }
1385
+ if (isCountMeasureRelationSubfield) {
1386
+ pushAuthoringError(errors, {
1387
+ path: item.fieldPath,
1388
+ ruleId: "chart-builder-query-count-measure-relation-subfield",
1389
+ message: `flowSurfaces authoring ${item.fieldPath} counts relation subfield '${fieldPath}'; count a scalar base field such as 'id' and keep '${fieldPath}' as a dimension`,
1390
+ details: withChartRepairHint({
1391
+ fieldPath,
1392
+ dataSourceKey,
1393
+ collectionName,
1394
+ suggestedMeasure: {
1395
+ field: "id",
1396
+ aggregation: "count",
1397
+ alias: String(((_e = item.selection) == null ? void 0 : _e.alias) || "").trim() || "recordCount"
1398
+ },
1399
+ suggestedDimension: {
1400
+ field: fieldPath
1401
+ }
1402
+ })
1403
+ });
1404
+ continue;
1405
+ }
1406
+ if (unsupportedRelationSubfield) {
1407
+ pushAuthoringError(errors, {
1408
+ path: item.fieldPath,
1409
+ ruleId: "chart-builder-query-relation-subfield-column-unsupported",
1410
+ message: `flowSurfaces authoring ${item.fieldPath} references relation subfield '${fieldPath}', but current chart builder SQL generation cannot query relation subfield '${unsupportedRelationSubfield.leafFieldName}' because its database column is '${unsupportedRelationSubfield.columnName}'. ${(0, import_service_helpers.formatChartBuilderSupportedRelationSubfields)(
1411
+ associationPath,
1412
+ unsupportedRelationSubfield.supportedFields
1413
+ )}`,
1414
+ details: withChartRepairHint({
1415
+ fieldPath,
1416
+ dataSourceKey,
1417
+ collectionName,
1418
+ ...unsupportedRelationSubfield
1419
+ })
1420
+ });
1421
+ }
857
1422
  }
858
1423
  }
859
1424
  function resolveChartBuilderAssociationSubfieldSuggestion(fieldPath, field, dataSourceKey, getCollection) {
@@ -953,8 +1518,8 @@ function collectChartAssetVisualErrors(asset, path, errors) {
953
1518
  pushAuthoringError(errors, {
954
1519
  path: `${path}.visual.type`,
955
1520
  ruleId: "chart-visual-type-unsupported",
956
- message: `flowSurfaces authoring ${path}.visual.type '${type}' is not supported`,
957
- details: withChartRepairHint({
1521
+ message: `flowSurfaces authoring ${path}.visual.type '${type}' is not supported. Supported basic chart visual types: ${CHART_BASIC_VISUAL_TYPE_LIST}. If these types do not satisfy the requirement, use a jsBlock instead.`,
1522
+ details: withUnsupportedChartVisualTypeHint({
958
1523
  type
959
1524
  })
960
1525
  });
@@ -3385,10 +3950,13 @@ function collectBlockErrors(block, path, errors, localKeys, context) {
3385
3950
  collectVisibleDataBlockFieldErrors(block, blockType, path, errors, context);
3386
3951
  collectCommentsBlockErrors(block, blockType, path, errors, context);
3387
3952
  collectRecordHistoryBlockErrors(block, blockType, path, errors, context);
3953
+ collectLocalizedChartSettingsErrors(block, blockType, path, errors, context);
3388
3954
  collectChartDisplayTitleErrors(block, blockType, path, errors);
3389
3955
  collectTreeTableExplicitFieldsErrors(block, blockType, path, errors, context);
3390
3956
  collectTreeConnectFieldsErrors((_a = block.settings) == null ? void 0 : _a.connectFields, `${path}.settings.connectFields`, errors);
3391
- collectTableSettingsErrors(block, blockType, path, errors);
3957
+ collectTableSettingsErrors(block, blockType, path, errors, {
3958
+ deferPublicDataScopeErrors: context.authoringActionName === "addBlocks"
3959
+ });
3392
3960
  collectGridCardSettingsErrors(block, blockType, path, errors);
3393
3961
  const descendantContext = getBlockDescendantValidationContext(block, context);
3394
3962
  collectActionListErrors(block.actions, `${path}.actions`, errors, block, descendantContext, "actions");
@@ -3646,6 +4214,7 @@ function collectFieldGroupsShapeErrors(fieldGroups, blockPath, errors, block, co
3646
4214
  if (fieldPath) {
3647
4215
  collectUnknownFieldPathError(fieldPath, itemPath, block, context, errors);
3648
4216
  }
4217
+ collectImplicitRelationTitleFieldErrors(field, itemPath, block, context, errors);
3649
4218
  if (!_.isPlainObject(field)) {
3650
4219
  return;
3651
4220
  }
@@ -3695,6 +4264,7 @@ async function collectConfigureErrors(values, errors, context) {
3695
4264
  collectCommentsBlockErrors(changesBlock, hostBlockType, "$.changes", errors, context);
3696
4265
  collectRecordHistoryBlockErrors(changesBlock, hostBlockType, "$.changes", errors, context);
3697
4266
  collectChartDisplayTitleErrors(changes, hostBlockType, "$.changes", errors);
4267
+ collectChartConfigureFilterOperatorErrors(changes, hostBlockType, "$.changes", errors);
3698
4268
  collectTableSettingsErrors(changes, hostBlockType, "$.changes", errors, { directSettings: true });
3699
4269
  collectGridCardSettingsErrors(changes, hostBlockType, "$.changes", errors, { directSettings: true });
3700
4270
  collectAssignValuesErrors(changes.assignValues, "$.changes.assignValues", errors, changesBlock, context);
@@ -3783,6 +4353,23 @@ function collectUnsupportedDefaultFilterOperatorError(operator, path, errors) {
3783
4353
  }
3784
4354
  });
3785
4355
  }
4356
+ function collectDefaultFilterDateValueError(operator, value, path, errors) {
4357
+ var _a, _b, _c;
4358
+ try {
4359
+ (0, import_filter_group.normalizeFlowSurfaceStrictFilterDateValue)(operator, value, path);
4360
+ } catch (error) {
4361
+ if (!(error instanceof import_errors.FlowSurfaceBadRequestError)) {
4362
+ throw error;
4363
+ }
4364
+ const details = _.isPlainObject((_a = error.options) == null ? void 0 : _a.details) ? error.options.details : {};
4365
+ pushAuthoringError(errors, {
4366
+ path: typeof ((_b = error.options) == null ? void 0 : _b.path) === "string" && error.options.path ? error.options.path : path,
4367
+ ruleId: typeof ((_c = error.options) == null ? void 0 : _c.ruleId) === "string" && error.options.ruleId ? error.options.ruleId : "filter-group-date-value-invalid",
4368
+ message: error.message,
4369
+ details
4370
+ });
4371
+ }
4372
+ }
3786
4373
  function collectTopLevelLayoutErrors(actionName, values, errors) {
3787
4374
  if (actionName !== "applyBlueprint") {
3788
4375
  return;
@@ -4377,6 +4964,8 @@ function collectVisibleDataBlockFieldErrors(block, blockType, path, errors, cont
4377
4964
  blockType,
4378
4965
  collection: getBlockCollectionName(block, context),
4379
4966
  fieldCount: fieldEntries.length,
4967
+ repairHint: VISIBLE_DATA_BLOCK_FIELDS_REPAIR_HINT,
4968
+ agentInstruction: REPAIR_ALL_ERRORS_AGENT_INSTRUCTION,
4380
4969
  ...suggestedFields.length ? { suggestion: { fields: suggestedFields } } : {}
4381
4970
  }
4382
4971
  });
@@ -4410,6 +4999,8 @@ function collectVisibleDataBlockFieldErrors(block, blockType, path, errors, cont
4410
4999
  fieldCount: validBusinessFieldNames.length,
4411
5000
  requiredFieldCount,
4412
5001
  eligibleBusinessFieldCount: eligibleBusinessFields.length,
5002
+ repairHint: VISIBLE_DATA_BLOCK_FIELDS_REPAIR_HINT,
5003
+ agentInstruction: REPAIR_ALL_ERRORS_AGENT_INSTRUCTION,
4413
5004
  suggestion: {
4414
5005
  fields: eligibleBusinessFields.slice(0, requiredFieldCount)
4415
5006
  }
@@ -4783,6 +5374,15 @@ function collectChartDisplayTitleErrors(block, blockType, blockPath, errors) {
4783
5374
  message: "Chart block settings do not support displayTitle in the current flowSurfaces runtime; keep settings.title and omit displayTitle."
4784
5375
  });
4785
5376
  }
5377
+ function collectChartConfigureFilterOperatorErrors(changes, hostBlockType, path, errors) {
5378
+ if (hostBlockType !== "chart" || !_.isPlainObject(changes)) {
5379
+ return;
5380
+ }
5381
+ collectChartQueryFilterOperatorErrors(changes.query, `${path}.query`, errors);
5382
+ if (_.isPlainObject(changes.configure)) {
5383
+ collectChartQueryFilterOperatorErrors(changes.configure.query, `${path}.configure.query`, errors);
5384
+ }
5385
+ }
4786
5386
  function visitFilterItems(value, path, errors, block, context = {}) {
4787
5387
  if (Array.isArray(value)) {
4788
5388
  value.forEach((item, index) => visitFilterItems(item, `${path}[${index}]`, errors, block, context));
@@ -4797,6 +5397,7 @@ function visitFilterItems(value, path, errors, block, context = {}) {
4797
5397
  }
4798
5398
  if (typeof value.operator === "string") {
4799
5399
  collectUnsupportedDefaultFilterOperatorError(value.operator, `${path}.operator`, errors);
5400
+ collectDefaultFilterDateValueError(value.operator, value.value, `${path}.value`, errors);
4800
5401
  }
4801
5402
  const filterItems = value.items;
4802
5403
  if (Array.isArray(filterItems)) {
@@ -4820,8 +5421,9 @@ function visitFilterItems(value, path, errors, block, context = {}) {
4820
5421
  }
4821
5422
  collectDefaultFilterFieldPathError(key, `${path}.${key}`, block, context, errors);
4822
5423
  if (_.isPlainObject(child)) {
4823
- Object.keys(child).forEach((operator) => {
5424
+ Object.entries(child).forEach(([operator, operatorValue]) => {
4824
5425
  collectUnsupportedDefaultFilterOperatorError(operator, `${path}.${key}.${operator}`, errors);
5426
+ collectDefaultFilterDateValueError(operator, operatorValue, `${path}.${key}.${operator}`, errors);
4825
5427
  });
4826
5428
  }
4827
5429
  });
@@ -5198,6 +5800,9 @@ function collectTableSettingsErrors(block, blockType, blockPath, errors, options
5198
5800
  }
5199
5801
  pushTableSettingsUnsupportedError(errors, `${settingsPath}.${key}`, key);
5200
5802
  });
5803
+ if (!shouldDeferPublicDataScopeErrorsToBatchItem(blockPath, errors, options)) {
5804
+ collectPublicDataScopeErrors(settings.dataScope, `${settingsPath}.dataScope`, errors);
5805
+ }
5201
5806
  }
5202
5807
  function pushTableSettingsUnsupportedError(errors, path, key) {
5203
5808
  pushAuthoringError(errors, {
@@ -5211,6 +5816,47 @@ function pushTableSettingsUnsupportedError(errors, path, key) {
5211
5816
  }
5212
5817
  });
5213
5818
  }
5819
+ function collectPublicDataScopeErrors(value, path, errors) {
5820
+ if (_.isUndefined(value)) {
5821
+ return;
5822
+ }
5823
+ if (value === null || _.isPlainObject(value) && !Object.keys(value).length) {
5824
+ return;
5825
+ }
5826
+ const validationValue = normalizePublicDataScopeValueForValidation(value);
5827
+ try {
5828
+ (0, import_filter_group.assertFlowSurfaceFilterGroupShape)(validationValue);
5829
+ } catch (error) {
5830
+ const reason = error instanceof Error ? error.message : String(error);
5831
+ pushAuthoringError(errors, {
5832
+ path,
5833
+ ruleId: "dataScope-filter-group-invalid-shape",
5834
+ message: `flowSurfaces authoring ${path} expects FilterGroup like ${import_filter_group.FLOW_SURFACE_FILTER_GROUP_EXAMPLE}: ${reason}`,
5835
+ details: {
5836
+ repairHint: 'Use settings.dataScope with logic/items, for example {"logic":"$and","items":[{"path":"status","operator":"$eq","value":"Active"}]}; do not use a field-name map.'
5837
+ }
5838
+ });
5839
+ }
5840
+ }
5841
+ function shouldDeferPublicDataScopeErrorsToBatchItem(blockPath, errors, options) {
5842
+ if (options.deferPublicDataScopeErrors !== true) {
5843
+ return false;
5844
+ }
5845
+ if (!/^\$\.blocks\[\d+\]$/.test(blockPath)) {
5846
+ return false;
5847
+ }
5848
+ return !errors.some((error) => error.path === `${blockPath}.settings.dataScope`);
5849
+ }
5850
+ function normalizePublicDataScopeValueForValidation(value) {
5851
+ if (!_.isPlainObject(value)) {
5852
+ return value;
5853
+ }
5854
+ const keys = Object.keys(value);
5855
+ if (keys.length === 1 && keys[0] === "filter") {
5856
+ return value.filter;
5857
+ }
5858
+ return value;
5859
+ }
5214
5860
  function collectGridCardSettingsErrors(block, blockType, blockPath, errors, options = {}) {
5215
5861
  const hasSettings = _.isPlainObject(block == null ? void 0 : block.settings);
5216
5862
  if (!hasSettings && options.directSettings !== true) {
@@ -5851,6 +6497,7 @@ function collectFieldListErrors(fields, path, errors, localKeys, context, block)
5851
6497
  if (fieldPath) {
5852
6498
  collectUnknownFieldPathError(fieldPath, `${path}[${index}]`, block, context, errors);
5853
6499
  }
6500
+ collectImplicitRelationTitleFieldErrors(field, `${path}[${index}]`, block, context, errors);
5854
6501
  if (!_.isPlainObject(field)) {
5855
6502
  return;
5856
6503
  }
@@ -6171,6 +6818,106 @@ function collectRelationTitleFieldErrors(fieldSpec, path, block, context, errors
6171
6818
  })
6172
6819
  });
6173
6820
  }
6821
+ function collectImplicitRelationTitleFieldErrors(fieldSpec, path, block, context, errors) {
6822
+ var _a;
6823
+ if (context.authoringActionName !== "applyBlueprint") {
6824
+ return;
6825
+ }
6826
+ const hostBlockType = String((block == null ? void 0 : block.type) || "").trim();
6827
+ if (!IMPLICIT_RELATION_TITLE_FIELD_DISPLAY_BLOCK_TYPES.has(hostBlockType)) {
6828
+ return;
6829
+ }
6830
+ if (_.isPlainObject(fieldSpec) && fieldSpec.__autoPopupForRelationField === true) {
6831
+ return;
6832
+ }
6833
+ if (_.isPlainObject(fieldSpec) && Object.prototype.hasOwnProperty.call(fieldSpec, "titleField")) {
6834
+ return;
6835
+ }
6836
+ const fieldPath = getFieldPathInput(fieldSpec);
6837
+ if (!fieldPath || fieldPath.includes(".")) {
6838
+ return;
6839
+ }
6840
+ const collection = getBlockCollection(block, context);
6841
+ if (!collection || !context.getCollection) {
6842
+ return;
6843
+ }
6844
+ const resolvedField = (0, import_service_helpers.resolveFieldFromCollection)(collection, (0, import_service_helpers.normalizeFieldPath)(fieldPath));
6845
+ if (!resolvedField || !(0, import_service_helpers.isAssociationField)(resolvedField)) {
6846
+ return;
6847
+ }
6848
+ const dataSourceKey = getBlockDataSourceKey(block, context);
6849
+ if (hasUsableDefaultFieldGroupRelationTitleField({
6850
+ fieldGroups: (_a = context.getDefaultFieldGroups) == null ? void 0 : _a.call(context, dataSourceKey, getBlockCollectionName(block, context)),
6851
+ fieldPath,
6852
+ field: resolvedField,
6853
+ dataSourceKey,
6854
+ context
6855
+ })) {
6856
+ return;
6857
+ }
6858
+ const registeredBinding = (0, import_field_binding_registry.resolveRegisteredFieldBinding)({
6859
+ containerUse: IMPLICIT_RELATION_TITLE_FIELD_CONTAINER_USE_BY_BLOCK_TYPE[hostBlockType],
6860
+ field: resolvedField,
6861
+ dataSourceKey,
6862
+ enabledPackages: context.enabledPackages,
6863
+ getCollection: (resolvedDataSourceKey, targetCollectionName) => {
6864
+ var _a2;
6865
+ return (_a2 = context.getCollection) == null ? void 0 : _a2.call(context, resolvedDataSourceKey, targetCollectionName);
6866
+ },
6867
+ useStrictOnly: true
6868
+ });
6869
+ if (registeredBinding == null ? void 0 : registeredBinding.modelClassName) {
6870
+ return;
6871
+ }
6872
+ try {
6873
+ const resolvedTitleField = (0, import_association_title_field.resolveAssociationSafeTitleField)(resolvedField, dataSourceKey, context.getCollection, {
6874
+ action: context.authoringActionName,
6875
+ path: `${path}.titleField`,
6876
+ fieldPath
6877
+ });
6878
+ if (!(resolvedTitleField == null ? void 0 : resolvedTitleField.fieldName)) {
6879
+ pushAuthoringError(errors, {
6880
+ path: `${path}.titleField`,
6881
+ ruleId: "relation-titleField-unavailable",
6882
+ message: `flowSurfaces authoring ${path} relation field '${fieldPath}' requires an explicit readable titleField`,
6883
+ details: {
6884
+ fieldPath,
6885
+ repairHint: `Use object field form such as {"field":"${fieldPath}","titleField":"<readable target field>"}.`
6886
+ }
6887
+ });
6888
+ }
6889
+ } catch (error) {
6890
+ if (!(error instanceof import_errors.FlowSurfaceBadRequestError)) {
6891
+ throw error;
6892
+ }
6893
+ pushAuthoringError(errors, {
6894
+ path: `${path}.titleField`,
6895
+ ruleId: error.options.ruleId || "relation-titleField-unavailable",
6896
+ message: `flowSurfaces authoring ${path} relation field '${fieldPath}' requires an explicit readable titleField`,
6897
+ details: {
6898
+ ...error.options.details || {},
6899
+ fieldPath,
6900
+ repairHint: `Use object field form such as {"field":"${fieldPath}","titleField":"<readable target field>"}.`
6901
+ }
6902
+ });
6903
+ }
6904
+ }
6905
+ function hasUsableDefaultFieldGroupRelationTitleField(input) {
6906
+ const titleField = (0, import_defaults.getFlowSurfaceDefaultFieldGroupRelationTitleFieldOverride)(input.fieldGroups, input.fieldPath);
6907
+ if (!titleField || titleField === "id" || !input.context.getCollection) {
6908
+ return false;
6909
+ }
6910
+ const targetCollection = (0, import_service_helpers.resolveFieldTargetCollection)(
6911
+ input.field,
6912
+ input.dataSourceKey,
6913
+ (dataSourceKey, collectionName) => {
6914
+ var _a, _b;
6915
+ return (_b = (_a = input.context).getCollection) == null ? void 0 : _b.call(_a, dataSourceKey, collectionName);
6916
+ }
6917
+ );
6918
+ const targetField = targetCollection ? (0, import_service_helpers.resolveFieldFromCollection)(targetCollection, titleField) : void 0;
6919
+ return !!targetField && !(0, import_service_helpers.isAssociationField)(targetField);
6920
+ }
6174
6921
  function getRelationTitleFieldInvalidReason(titleField, targetField) {
6175
6922
  if (titleField === "id") {
6176
6923
  return "id";
@@ -6204,18 +6951,18 @@ function getRecordHistoryDeclaredFilterTargetKey(collection) {
6204
6951
  return String(raw || "").trim();
6205
6952
  }
6206
6953
  function collectionHasConcreteField(collection, fieldName) {
6207
- var _a, _b, _c, _d, _e, _f;
6954
+ var _a, _b, _c;
6208
6955
  const normalized = String(fieldName || "").trim();
6209
6956
  if (!normalized) {
6210
6957
  return false;
6211
6958
  }
6212
- const modelAttributes = (typeof ((_a = collection == null ? void 0 : collection.model) == null ? void 0 : _a.getAttributes) === "function" ? collection.model.getAttributes() : null) || ((_b = collection == null ? void 0 : collection.model) == null ? void 0 : _b.rawAttributes) || ((_c = collection == null ? void 0 : collection.model) == null ? void 0 : _c.attributes) || {};
6959
+ const modelAttributes = (0, import_service_helpers.getCollectionModelAttributes)(collection);
6213
6960
  const primaryKeyAttributes = _.castArray(
6214
- ((_d = collection == null ? void 0 : collection.model) == null ? void 0 : _d.primaryKeyAttributes) || ((_e = collection == null ? void 0 : collection.model) == null ? void 0 : _e.primaryKeyAttribute) || []
6961
+ ((_a = collection == null ? void 0 : collection.model) == null ? void 0 : _a.primaryKeyAttributes) || ((_b = collection == null ? void 0 : collection.model) == null ? void 0 : _b.primaryKeyAttribute) || []
6215
6962
  );
6216
6963
  const modelAttribute = modelAttributes == null ? void 0 : modelAttributes[normalized];
6217
6964
  const isModelPrimaryKey = primaryKeyAttributes.includes(normalized) || !!(modelAttribute == null ? void 0 : modelAttribute.primaryKey);
6218
- return !!((0, import_service_helpers.resolveFieldFromCollection)(collection, normalized) || ((_f = collection == null ? void 0 : collection.getField) == null ? void 0 : _f.call(collection, normalized)) || (0, import_service_helpers.getCollectionFields)(collection).some((field) => (0, import_service_helpers.getFieldName)(field) === normalized) || isModelPrimaryKey);
6965
+ return !!((0, import_service_helpers.resolveFieldFromCollection)(collection, normalized) || ((_c = collection == null ? void 0 : collection.getField) == null ? void 0 : _c.call(collection, normalized)) || (0, import_service_helpers.getCollectionFields)(collection).some((field) => (0, import_service_helpers.getFieldName)(field) === normalized) || isModelPrimaryKey);
6219
6966
  }
6220
6967
  function collectDefaultFilterFieldPathError(rawFieldPath, path, block, context, errors) {
6221
6968
  const fieldPath = String(rawFieldPath || "").trim();