@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
@@ -81,6 +81,7 @@ var import_placement = require("./placement");
81
81
  var import_route_sync = require("./route-sync");
82
82
  var import_surface_context = require("./surface-context");
83
83
  var import_context = require("./context");
84
+ var import_event_flow_normalizer = require("./event-flow-normalizer");
84
85
  var import_configure_options = require("./configure-options");
85
86
  var import_public_compatibility = require("./public-compatibility");
86
87
  var import_support_matrix = require("./support-matrix");
@@ -103,14 +104,38 @@ var import_template_service_utils = require("./template-service-utils");
103
104
  var import_hidden_popup_contract = require("./hidden-popup-contract");
104
105
  var import_hidden_popup_calendar = require("./hidden-popup-calendar");
105
106
  var import_hidden_popup_kanban = require("./hidden-popup-kanban");
106
- const FLOW_SURFACE_CHART_REPAIR_HINT = "This is a chart payload shape problem. Repair the current chart block payload 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. Do not drop or defer the chart. KPI / summary numbers should use jsBlock; charts are for trends, distributions, rankings, and visual analysis.";
107
+ const FLOW_SURFACE_CHART_REPAIR_HINT = "This is a chart payload shape problem. Keep using chart and repair the current chart block payload 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. Do not drop or defer the chart. KPI / summary numbers should use jsBlock; charts are for trends, distributions, rankings, and visual analysis.";
107
108
  const FLOW_SURFACE_CHART_REPAIR_STEPS = [
108
109
  "Keep the block type as chart.",
109
- "Define assets.charts.<key>.query and assets.charts.<key>.visual, or repair the localized settings.query/settings.visual on the existing chart block.",
110
+ "Define assets.charts.<key>.query and assets.charts.<key>.visual, or fill localized settings.query and settings.visual on the existing chart block.",
110
111
  "Reference the asset from the chart block with block.chart = <key> when using assets.charts.",
111
112
  "Retry the chart payload instead of replacing the chart with another block type, omitting it, or deferring it."
112
113
  ];
113
114
  const FLOW_SURFACE_CHART_EXPECTED_SHAPE = {
115
+ settings: {
116
+ query: {
117
+ mode: "builder",
118
+ resource: {
119
+ dataSourceKey: "main",
120
+ collectionName: "employees"
121
+ },
122
+ measures: [
123
+ {
124
+ field: "id",
125
+ aggregation: "count",
126
+ alias: "employeeCount"
127
+ }
128
+ ]
129
+ },
130
+ visual: {
131
+ mode: "basic",
132
+ type: "bar",
133
+ mappings: {
134
+ x: "status",
135
+ y: "employeeCount"
136
+ }
137
+ }
138
+ },
114
139
  assets: {
115
140
  charts: {
116
141
  chartKey: {
@@ -126,29 +151,80 @@ const FLOW_SURFACE_CHART_EXPECTED_SHAPE = {
126
151
  };
127
152
  const FLOW_SURFACE_CHART_FORBIDDEN_FALLBACKS = [
128
153
  "table",
154
+ "list",
129
155
  "jsBlock",
130
156
  "actionPanel",
131
157
  "gridCard",
158
+ "markdown",
132
159
  "drop chart",
133
160
  "defer chart"
134
161
  ];
162
+ const FLOW_SURFACE_CHART_REPAIR_EXAMPLE = {
163
+ settings: {
164
+ query: {
165
+ mode: "builder",
166
+ resource: {
167
+ dataSourceKey: "main",
168
+ collectionName: "<collectionName>"
169
+ },
170
+ measures: [
171
+ {
172
+ field: "id",
173
+ aggregation: "count",
174
+ alias: "recordCount"
175
+ }
176
+ ],
177
+ dimensions: [
178
+ {
179
+ field: "<dimensionField>"
180
+ }
181
+ ]
182
+ },
183
+ visual: {
184
+ mode: "basic",
185
+ type: "bar",
186
+ mappings: {
187
+ x: "<dimensionField>",
188
+ y: "recordCount"
189
+ }
190
+ }
191
+ }
192
+ };
135
193
  function withChartRepairMessage(message) {
136
194
  return `${message}. ${FLOW_SURFACE_CHART_REPAIR_HINT}`;
137
195
  }
138
196
  function withFlowSurfaceChartRepairDetails(details = {}) {
139
197
  return {
140
198
  ...details,
199
+ requiredBlockType: "chart",
200
+ fixStrategy: "repair_same_block_type",
141
201
  repairHint: FLOW_SURFACE_CHART_REPAIR_HINT,
142
202
  repairSteps: FLOW_SURFACE_CHART_REPAIR_STEPS,
143
203
  expectedShape: FLOW_SURFACE_CHART_EXPECTED_SHAPE,
204
+ repairExample: FLOW_SURFACE_CHART_REPAIR_EXAMPLE,
144
205
  forbiddenFallbacks: FLOW_SURFACE_CHART_FORBIDDEN_FALLBACKS
145
206
  };
146
207
  }
147
- function throwChartRepairBadRequest(message, details = {}) {
208
+ function throwChartRepairBadRequest(message, options = {}) {
209
+ const details = import_lodash.default.isPlainObject(options.details) ? options.details : {};
148
210
  (0, import_errors.throwBadRequest)(withChartRepairMessage(message), {
211
+ ...options,
149
212
  details: withFlowSurfaceChartRepairDetails(details)
150
213
  });
151
214
  }
215
+ function isChartConfigureBadRequestError(error) {
216
+ return error instanceof import_errors.FlowSurfaceBadRequestError && String(error.message || "").startsWith("chart ");
217
+ }
218
+ function buildChartConfigureFromSemanticChangesWithRepair(currentConfigure, changes) {
219
+ try {
220
+ return (0, import_chart_config.buildChartConfigureFromSemanticChanges)(currentConfigure, changes);
221
+ } catch (error) {
222
+ if (isChartConfigureBadRequestError(error)) {
223
+ throwChartRepairBadRequest(error.message, error.options);
224
+ }
225
+ throw error;
226
+ }
227
+ }
152
228
  function isFlowSurfaceChartRepairError(error) {
153
229
  var _a, _b;
154
230
  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;
@@ -1088,7 +1164,7 @@ class FlowSurfacesService {
1088
1164
  parentId: null,
1089
1165
  options: {
1090
1166
  documentTitle: values.tabDocumentTitle,
1091
- flowRegistry: values.tabFlowRegistry || {}
1167
+ flowRegistry: this.normalizeEventFlowRegistry("createMenu", values.tabFlowRegistry || {})
1092
1168
  }
1093
1169
  }
1094
1170
  ]
@@ -2819,7 +2895,7 @@ class FlowSurfacesService {
2819
2895
  use: "RootPageTabModel",
2820
2896
  props: import_lodash.default.omit(import_lodash.default.cloneDeep((currentNode == null ? void 0 : currentNode.props) || {}), ["route"]),
2821
2897
  decoratorProps: import_lodash.default.cloneDeep((currentNode == null ? void 0 : currentNode.decoratorProps) || {}),
2822
- flowRegistry: import_lodash.default.cloneDeep((currentNode == null ? void 0 : currentNode.flowRegistry) || {}),
2898
+ flowRegistry: this.getEventFlowRegistry(currentNode),
2823
2899
  stepParams: import_lodash.default.cloneDeep((values == null ? void 0 : values.stepParams) || (currentNode == null ? void 0 : currentNode.stepParams) || {})
2824
2900
  }),
2825
2901
  { transaction: options == null ? void 0 : options.transaction }
@@ -3040,7 +3116,7 @@ class FlowSurfacesService {
3040
3116
  continue;
3041
3117
  }
3042
3118
  (0, import_service_utils.assertSupportedSimpleChanges)("chart", chartAsset, (0, import_configure_options.getConfigureOptionKeysForUse)("ChartBlockModel"));
3043
- const nextConfigure = (0, import_chart_config.buildChartConfigureFromSemanticChanges)(void 0, chartAsset);
3119
+ const nextConfigure = buildChartConfigureFromSemanticChangesWithRepair(void 0, chartAsset);
3044
3120
  await this.validateChartConfigureForRuntime(
3045
3121
  `applyBlueprint assets.charts.${chartKey}`,
3046
3122
  nextConfigure,
@@ -3048,6 +3124,209 @@ class FlowSurfacesService {
3048
3124
  );
3049
3125
  }
3050
3126
  }
3127
+ composeChartBlockHasInlineConfig(block) {
3128
+ const settings = import_lodash.default.isPlainObject(block.settings) ? block.settings : {};
3129
+ return ["configure", "query", "visual", "events"].some(
3130
+ (key) => Object.prototype.hasOwnProperty.call(settings, key)
3131
+ );
3132
+ }
3133
+ prepareComposeChartAssetNestedPopupBlocks(input, path, chartAssets) {
3134
+ if (!import_lodash.default.isPlainObject(input)) {
3135
+ return { value: input, didResolveChartAsset: false };
3136
+ }
3137
+ let didResolveChartAsset = false;
3138
+ let nextInput = input;
3139
+ const ensureNextInput = () => {
3140
+ if (nextInput === input) {
3141
+ nextInput = { ...input };
3142
+ }
3143
+ return nextInput;
3144
+ };
3145
+ const preparePopupBlocks = (key) => {
3146
+ const popup = input[key];
3147
+ if (!import_lodash.default.isPlainObject(popup) || !Array.isArray(popup.blocks)) {
3148
+ return;
3149
+ }
3150
+ const prepared = this.prepareComposeChartAssetBlockList(popup.blocks, `${path}.${key}.blocks`, chartAssets);
3151
+ if (!prepared.didResolveChartAsset) {
3152
+ return;
3153
+ }
3154
+ ensureNextInput()[key] = {
3155
+ ...popup,
3156
+ blocks: prepared.blocks
3157
+ };
3158
+ didResolveChartAsset = true;
3159
+ };
3160
+ preparePopupBlocks("popup");
3161
+ preparePopupBlocks("openView");
3162
+ return {
3163
+ value: nextInput,
3164
+ didResolveChartAsset
3165
+ };
3166
+ }
3167
+ prepareComposeChartAssetBlockList(blocks, path, chartAssets) {
3168
+ const rawBlocks = import_lodash.default.castArray(blocks || []);
3169
+ if (!rawBlocks.length) {
3170
+ return { blocks: rawBlocks, didResolveChartAsset: false };
3171
+ }
3172
+ let didResolveChartAsset = false;
3173
+ const hiddenPopupKeys = [
3174
+ "quickCreatePopup",
3175
+ "eventPopup",
3176
+ "cardPopup",
3177
+ "quickCreatePopupSettings",
3178
+ "eventPopupSettings",
3179
+ "cardPopupSettings"
3180
+ ];
3181
+ const nextBlocks = rawBlocks.map((block, index) => {
3182
+ if (!import_lodash.default.isPlainObject(block)) {
3183
+ return block;
3184
+ }
3185
+ const blockPath = `${path}[${index}]`;
3186
+ let nextBlock = block;
3187
+ const ensureNextBlock = () => {
3188
+ if (nextBlock === block) {
3189
+ nextBlock = { ...block };
3190
+ }
3191
+ return nextBlock;
3192
+ };
3193
+ if (Array.isArray(block.blocks)) {
3194
+ const prepared = this.prepareComposeChartAssetBlockList(block.blocks, `${blockPath}.blocks`, chartAssets);
3195
+ if (prepared.didResolveChartAsset) {
3196
+ ensureNextBlock().blocks = prepared.blocks;
3197
+ didResolveChartAsset = true;
3198
+ }
3199
+ }
3200
+ for (const slot of ["actions", "recordActions", "fields"]) {
3201
+ if (!Array.isArray(block[slot])) {
3202
+ continue;
3203
+ }
3204
+ let didPrepareSlot = false;
3205
+ const nextItems = block[slot].map((item, itemIndex) => {
3206
+ const prepared = this.prepareComposeChartAssetNestedPopupBlocks(
3207
+ item,
3208
+ `${blockPath}.${slot}[${itemIndex}]`,
3209
+ chartAssets
3210
+ );
3211
+ didPrepareSlot = didPrepareSlot || prepared.didResolveChartAsset;
3212
+ return prepared.value;
3213
+ });
3214
+ if (didPrepareSlot) {
3215
+ ensureNextBlock()[slot] = nextItems;
3216
+ didResolveChartAsset = true;
3217
+ }
3218
+ }
3219
+ if (Array.isArray(block.fieldGroups)) {
3220
+ let didPrepareFieldGroups = false;
3221
+ const nextFieldGroups = block.fieldGroups.map((group, groupIndex) => {
3222
+ if (!import_lodash.default.isPlainObject(group) || !Array.isArray(group.fields)) {
3223
+ return group;
3224
+ }
3225
+ let didPrepareGroupFields = false;
3226
+ const nextFields = group.fields.map((field, fieldIndex) => {
3227
+ const prepared = this.prepareComposeChartAssetNestedPopupBlocks(
3228
+ field,
3229
+ `${blockPath}.fieldGroups[${groupIndex}].fields[${fieldIndex}]`,
3230
+ chartAssets
3231
+ );
3232
+ didPrepareGroupFields = didPrepareGroupFields || prepared.didResolveChartAsset;
3233
+ return prepared.value;
3234
+ });
3235
+ if (!didPrepareGroupFields) {
3236
+ return group;
3237
+ }
3238
+ didPrepareFieldGroups = true;
3239
+ return {
3240
+ ...group,
3241
+ fields: nextFields
3242
+ };
3243
+ });
3244
+ if (didPrepareFieldGroups) {
3245
+ ensureNextBlock().fieldGroups = nextFieldGroups;
3246
+ didResolveChartAsset = true;
3247
+ }
3248
+ }
3249
+ if (import_lodash.default.isPlainObject(block.popup) && Array.isArray(block.popup.blocks)) {
3250
+ const prepared = this.prepareComposeChartAssetBlockList(
3251
+ block.popup.blocks,
3252
+ `${blockPath}.popup.blocks`,
3253
+ chartAssets
3254
+ );
3255
+ if (prepared.didResolveChartAsset) {
3256
+ ensureNextBlock().popup = {
3257
+ ...block.popup,
3258
+ blocks: prepared.blocks
3259
+ };
3260
+ didResolveChartAsset = true;
3261
+ }
3262
+ }
3263
+ if (import_lodash.default.isPlainObject(block.settings)) {
3264
+ for (const key of hiddenPopupKeys) {
3265
+ const popup = block.settings[key];
3266
+ if (!import_lodash.default.isPlainObject(popup) || !Array.isArray(popup.blocks)) {
3267
+ continue;
3268
+ }
3269
+ const prepared = this.prepareComposeChartAssetBlockList(
3270
+ popup.blocks,
3271
+ `${blockPath}.settings.${key}.blocks`,
3272
+ chartAssets
3273
+ );
3274
+ if (!prepared.didResolveChartAsset) {
3275
+ continue;
3276
+ }
3277
+ ensureNextBlock().settings = {
3278
+ ...nextBlock.settings || {},
3279
+ [key]: {
3280
+ ...popup,
3281
+ blocks: prepared.blocks
3282
+ }
3283
+ };
3284
+ didResolveChartAsset = true;
3285
+ }
3286
+ }
3287
+ if (String(nextBlock.type || "").trim() !== "chart" || !Object.prototype.hasOwnProperty.call(nextBlock, "chart") || this.composeChartBlockHasInlineConfig(nextBlock)) {
3288
+ return nextBlock;
3289
+ }
3290
+ const chartKey = String(nextBlock.chart || "").trim();
3291
+ if (!chartKey) {
3292
+ throwChartRepairBadRequest(`${blockPath}.chart must reference one key from assets.charts`, {
3293
+ path: `${blockPath}.chart`,
3294
+ ruleId: "chart-block-asset-reference-required"
3295
+ });
3296
+ }
3297
+ const chartAsset = chartAssets[chartKey];
3298
+ if (!import_lodash.default.isPlainObject(chartAsset)) {
3299
+ throwChartRepairBadRequest(`${blockPath}.chart references missing chart asset '${chartKey}'`, {
3300
+ path: `${blockPath}.chart`,
3301
+ ruleId: "chart-block-asset-reference-missing",
3302
+ details: {
3303
+ chartKey
3304
+ }
3305
+ });
3306
+ }
3307
+ if (!import_lodash.default.isUndefined(nextBlock.settings) && !import_lodash.default.isPlainObject(nextBlock.settings)) {
3308
+ return nextBlock;
3309
+ }
3310
+ didResolveChartAsset = true;
3311
+ return {
3312
+ ...nextBlock,
3313
+ settings: import_lodash.default.merge({}, import_lodash.default.cloneDeep(nextBlock.settings || {}), import_lodash.default.cloneDeep(chartAsset))
3314
+ };
3315
+ });
3316
+ return {
3317
+ blocks: nextBlocks,
3318
+ didResolveChartAsset
3319
+ };
3320
+ }
3321
+ prepareComposeChartAssetSettings(values) {
3322
+ var _a;
3323
+ const chartAssets = import_lodash.default.isPlainObject((_a = values == null ? void 0 : values.assets) == null ? void 0 : _a.charts) ? values.assets.charts : {};
3324
+ const prepared = this.prepareComposeChartAssetBlockList(values == null ? void 0 : values.blocks, "$.blocks", chartAssets);
3325
+ return prepared.didResolveChartAsset ? {
3326
+ ...values,
3327
+ blocks: prepared.blocks
3328
+ } : values;
3329
+ }
3051
3330
  getApplyBlueprintKanbanBlockResourceObject(block) {
3052
3331
  return import_lodash.default.isPlainObject(block == null ? void 0 : block.resource) ? block.resource : {};
3053
3332
  }
@@ -3450,16 +3729,6 @@ class FlowSurfacesService {
3450
3729
  await this.assertApplyBlueprintAuthoringPayload(values, options);
3451
3730
  const document = (0, import_blueprint.prepareFlowSurfaceApplyBlueprintDocument)(values);
3452
3731
  await this.prevalidateApplyBlueprintChartAssets(document);
3453
- if (document.mode === "create") {
3454
- return await this.applyBlueprintWithTransaction(
3455
- values,
3456
- { ...options, skipAuthoringValidation: true },
3457
- createdKanbanSortFields,
3458
- {
3459
- readSurface: false
3460
- }
3461
- );
3462
- }
3463
3732
  return await this.transaction(
3464
3733
  (transaction) => this.applyBlueprintWithTransaction(
3465
3734
  values,
@@ -5132,12 +5401,13 @@ class FlowSurfacesService {
5132
5401
  async compose(values, options = {}) {
5133
5402
  var _a, _b, _c;
5134
5403
  const enabledPackages = await this.resolveEnabledPluginPackages(options);
5135
- const target = await this.prepareWriteTarget("compose", values == null ? void 0 : values.target, values, options);
5404
+ const composeValues = this.prepareComposeChartAssetSettings(values);
5405
+ const target = await this.prepareWriteTarget("compose", composeValues == null ? void 0 : composeValues.target, composeValues, options);
5136
5406
  const authoringContext = await this.buildTargetAuthoringContext({
5137
5407
  target,
5138
5408
  transaction: options.transaction
5139
5409
  });
5140
- await (0, import_authoring_validation.assertFlowSurfaceAuthoringPayload)("compose", values, {
5410
+ await (0, import_authoring_validation.assertFlowSurfaceAuthoringPayload)("compose", composeValues, {
5141
5411
  transaction: options.transaction,
5142
5412
  enabledPackages,
5143
5413
  skipGeneratedLayoutSingleColumnErrors: options.skipGeneratedLayoutSingleColumnErrors === true,
@@ -5150,12 +5420,17 @@ class FlowSurfacesService {
5150
5420
  ...options,
5151
5421
  popupTemplateTreeCache
5152
5422
  };
5153
- const mode = this.assertComposeMode(values == null ? void 0 : values.mode);
5154
- const popupDefaultsMetadata = this.buildPopupDefaultsMetadata(values == null ? void 0 : values.defaults);
5155
- const normalizedBlocks = this.normalizeComposeBlocks(values == null ? void 0 : values.blocks, enabledPackages, popupDefaultsMetadata, {
5156
- dataSourceKey: authoringContext.currentDataSourceKey,
5157
- collectionName: authoringContext.currentCollectionName
5158
- });
5423
+ const mode = this.assertComposeMode(composeValues == null ? void 0 : composeValues.mode);
5424
+ const popupDefaultsMetadata = this.buildPopupDefaultsMetadata(composeValues == null ? void 0 : composeValues.defaults);
5425
+ const normalizedBlocks = this.normalizeComposeBlocks(
5426
+ composeValues == null ? void 0 : composeValues.blocks,
5427
+ enabledPackages,
5428
+ popupDefaultsMetadata,
5429
+ {
5430
+ dataSourceKey: authoringContext.currentDataSourceKey,
5431
+ collectionName: authoringContext.currentCollectionName
5432
+ }
5433
+ );
5159
5434
  this.validateComposePopupTemplateAliases(normalizedBlocks, popupTemplateAliasSession);
5160
5435
  const blockParent = await this.surfaceContext.resolveBlockParent(target, options.transaction);
5161
5436
  const gridUid = blockParent.parentUid;
@@ -5181,7 +5456,7 @@ class FlowSurfacesService {
5181
5456
  mode,
5182
5457
  normalizedBlocks,
5183
5458
  existingItemUids: existingItems.map((item) => item.uid),
5184
- layout: values.layout
5459
+ layout: composeValues.layout
5185
5460
  });
5186
5461
  const generatedDefaultFilterByComposeBlockUid = /* @__PURE__ */ new Map();
5187
5462
  const result = await (0, import_compose_runtime.executeComposeRuntime)(plan, {
@@ -5216,7 +5491,7 @@ class FlowSurfacesService {
5216
5491
  {
5217
5492
  ...payload,
5218
5493
  ...Object.keys(hiddenPopupSettings).length ? { settings: hiddenPopupSettings } : {},
5219
- ...values.defaults ? { defaults: values.defaults } : {}
5494
+ ...composeValues.defaults ? { defaults: composeValues.defaults } : {}
5220
5495
  },
5221
5496
  {
5222
5497
  ...runtimeOptions,
@@ -5553,7 +5828,7 @@ class FlowSurfacesService {
5553
5828
  parentId: routeId,
5554
5829
  options: {
5555
5830
  documentTitle: values.tabDocumentTitle,
5556
- flowRegistry: values.tabFlowRegistry || {}
5831
+ flowRegistry: this.normalizeEventFlowRegistry("createPage", values.tabFlowRegistry || {})
5557
5832
  }
5558
5833
  },
5559
5834
  transaction
@@ -5572,7 +5847,10 @@ class FlowSurfacesService {
5572
5847
  options: {
5573
5848
  ...this.readRouteOptions(tabRoute),
5574
5849
  documentTitle: values.tabDocumentTitle ?? this.readRouteOptions(tabRoute).documentTitle,
5575
- flowRegistry: values.tabFlowRegistry || this.readRouteOptions(tabRoute).flowRegistry || {}
5850
+ flowRegistry: this.normalizeEventFlowRegistry(
5851
+ "createPage",
5852
+ values.tabFlowRegistry || this.readRouteOptions(tabRoute).flowRegistry || {}
5853
+ )
5576
5854
  }
5577
5855
  },
5578
5856
  transaction
@@ -5714,7 +5992,7 @@ class FlowSurfacesService {
5714
5992
  hidden: !pageRoute.get("enableTabs"),
5715
5993
  options: {
5716
5994
  documentTitle: values.documentTitle,
5717
- flowRegistry: values.flowRegistry || {}
5995
+ flowRegistry: this.normalizeEventFlowRegistry("addTab", values.flowRegistry || {})
5718
5996
  }
5719
5997
  },
5720
5998
  transaction: options.transaction
@@ -5762,7 +6040,7 @@ class FlowSurfacesService {
5762
6040
  )
5763
6041
  }
5764
6042
  } : void 0,
5765
- flowRegistry: !import_lodash.default.isUndefined(values.flowRegistry) ? values.flowRegistry : void 0
6043
+ flowRegistry: !import_lodash.default.isUndefined(values.flowRegistry) ? this.normalizeEventFlowRegistry("updateTab", values.flowRegistry) : void 0
5766
6044
  });
5767
6045
  await this.routeSync.persistTabSettings(target, current, nextPayload, options.transaction);
5768
6046
  return {
@@ -5878,7 +6156,7 @@ class FlowSurfacesService {
5878
6156
  title: values.title,
5879
6157
  icon: values.icon,
5880
6158
  documentTitle: values.documentTitle,
5881
- flowRegistry: values.flowRegistry
6159
+ flowRegistry: this.normalizeEventFlowRegistry("addPopupTab", values.flowRegistry)
5882
6160
  });
5883
6161
  await this.repository.upsertModel(
5884
6162
  {
@@ -5933,7 +6211,7 @@ class FlowSurfacesService {
5933
6211
  }
5934
6212
  }
5935
6213
  } : void 0,
5936
- flowRegistry: !import_lodash.default.isUndefined(values.flowRegistry) ? values.flowRegistry : void 0
6214
+ flowRegistry: !import_lodash.default.isUndefined(values.flowRegistry) ? this.normalizeEventFlowRegistry("updatePopupTab", values.flowRegistry) : void 0
5937
6215
  });
5938
6216
  if (Object.keys(nextPayload).length === 1) {
5939
6217
  return { uid: popupTab.uid };
@@ -6134,7 +6412,7 @@ class FlowSurfacesService {
6134
6412
  use: "ReferenceFormGridModel",
6135
6413
  props: currentGrid.props,
6136
6414
  decoratorProps: currentGrid.decoratorProps,
6137
- flowRegistry: currentGrid.flowRegistry,
6415
+ flowRegistry: this.getEventFlowRegistry(currentGrid),
6138
6416
  sortIndex: currentGrid.sortIndex,
6139
6417
  parentId: blockUid,
6140
6418
  subKey: "grid",
@@ -6380,7 +6658,8 @@ class FlowSurfacesService {
6380
6658
  if ((0, import_service_utils.hasOwnDefined)(normalizedSettings, "defaultFilter")) {
6381
6659
  normalizedSettings.defaultFilter = (0, import_filter_group.normalizeFlowSurfaceFilterGroupValue)(
6382
6660
  normalizedSettings.defaultFilter,
6383
- `flowSurfaces ${actionName} defaultActionSettings.filter.defaultFilter expects FilterGroup like ${import_filter_group.FLOW_SURFACE_FILTER_GROUP_EXAMPLE}`
6661
+ `flowSurfaces ${actionName} defaultActionSettings.filter.defaultFilter expects FilterGroup like ${import_filter_group.FLOW_SURFACE_FILTER_GROUP_EXAMPLE}`,
6662
+ { strictDateValues: true }
6384
6663
  );
6385
6664
  normalizedSettings.defaultFilter = this.normalizeEffectivePublicDataSurfaceDefaultFilter(
6386
6665
  normalizedSettings.defaultFilter,
@@ -7390,7 +7669,7 @@ class FlowSurfacesService {
7390
7669
  props: actionSettingsPayload.props,
7391
7670
  decoratorProps: values.decoratorProps,
7392
7671
  stepParams: actionSettingsPayload.stepParams,
7393
- flowRegistry: values.flowRegistry
7672
+ flowRegistry: this.normalizeEventFlowRegistry("addAction", values.flowRegistry)
7394
7673
  });
7395
7674
  this.contractGuard.validateNodeTreeAgainstContract(action);
7396
7675
  const created = await this.repository.upsertModel(
@@ -7517,7 +7796,7 @@ class FlowSurfacesService {
7517
7796
  props: actionSettingsPayload.props,
7518
7797
  decoratorProps: values.decoratorProps,
7519
7798
  stepParams: actionSettingsPayload.stepParams,
7520
- flowRegistry: values.flowRegistry
7799
+ flowRegistry: this.normalizeEventFlowRegistry("addRecordAction", values.flowRegistry)
7521
7800
  });
7522
7801
  this.contractGuard.validateNodeTreeAgainstContract(action);
7523
7802
  const created = await this.repository.upsertModel(
@@ -7569,7 +7848,8 @@ class FlowSurfacesService {
7569
7848
  },
7570
7849
  {
7571
7850
  ...options,
7572
- preserveSingleScopeDataBlockTitle
7851
+ preserveSingleScopeDataBlockTitle,
7852
+ skipAuthoringValidation: true
7573
7853
  }
7574
7854
  )
7575
7855
  });
@@ -11157,6 +11437,7 @@ class FlowSurfacesService {
11157
11437
  }
11158
11438
  if (domain === "flowRegistry") {
11159
11439
  this.assertNoTreeConnectFieldsFlowRegistry(current, normalizedValues[domain], "updateSettings");
11440
+ normalizedValues[domain] = this.normalizeEventFlowRegistry("updateSettings", normalizedValues[domain]);
11160
11441
  }
11161
11442
  if (!contract.editableDomains.includes(domain)) {
11162
11443
  (0, import_errors.throwBadRequest)(`flowSurfaces updateSettings domain '${domain}' is not editable`);
@@ -11173,6 +11454,9 @@ class FlowSurfacesService {
11173
11454
  current.use
11174
11455
  );
11175
11456
  });
11457
+ if (!import_lodash.default.isUndefined(nextPayload.flowRegistry)) {
11458
+ nextPayload.flowRegistry = this.normalizeEventFlowRegistry("updateSettings", nextPayload.flowRegistry);
11459
+ }
11176
11460
  this.replaceExplicitPopupStepParamSubtreesForUpdateSettings(
11177
11461
  current,
11178
11462
  normalizedValues,
@@ -11239,7 +11523,7 @@ class FlowSurfacesService {
11239
11523
  props: nextPayload.props ?? current.props,
11240
11524
  decoratorProps: nextPayload.decoratorProps ?? current.decoratorProps,
11241
11525
  stepParams: nextPayload.stepParams ?? current.stepParams,
11242
- flowRegistry: nextPayload.flowRegistry ?? current.flowRegistry
11526
+ flowRegistry: nextPayload.flowRegistry ?? this.getEventFlowRegistry(current)
11243
11527
  };
11244
11528
  const shouldValidateFlowRegistry = !import_lodash.default.isUndefined(nextPayload.flowRegistry) || !import_lodash.default.isUndefined(nextPayload.stepParams);
11245
11529
  assertNoFlowSurfaceIdTitleFieldSettings(import_lodash.default.pick(effectiveNode, ["props", "stepParams"]), {
@@ -11664,12 +11948,12 @@ class FlowSurfacesService {
11664
11948
  "flowSurfaces updateSettings filter action values 'props.defaultFilterValue/filterValue' and 'stepParams.filterSettings.defaultFilter.defaultFilter' must match"
11665
11949
  );
11666
11950
  }
11667
- const filterValue = this.normalizeEffectivePublicDataSurfaceDefaultFilter(
11668
- hasStepDefaultFilter ? nextStepFilter : nextPropFilter,
11669
- {
11670
- requiredFieldCount: options.requiredFieldCount
11671
- }
11951
+ const normalizedFilterValue = this.normalizeFilterActionDefaultFilterValue(
11952
+ hasStepDefaultFilter ? nextStepFilter : nextPropFilter
11672
11953
  );
11954
+ const filterValue = this.normalizeEffectivePublicDataSurfaceDefaultFilter(normalizedFilterValue, {
11955
+ requiredFieldCount: options.requiredFieldCount
11956
+ });
11673
11957
  if (!hasPropsFilterableFieldNames && !hasStepFilterableFieldNames) {
11674
11958
  const filterableFieldNames = (0, import_public_data_surface_default_filter.resolveFlowSurfaceDefaultFilterFieldNames)(filterValue);
11675
11959
  if (filterableFieldNames.length) {
@@ -12113,7 +12397,7 @@ class FlowSurfacesService {
12113
12397
  return String(input || "").trim();
12114
12398
  }
12115
12399
  validateBuilderChartFieldsForRuntime(actionName, configure) {
12116
- var _a, _b;
12400
+ var _a, _b, _c, _d, _e, _f, _g;
12117
12401
  const resourceInit = (0, import_chart_config.getChartBuilderResourceInit)(configure);
12118
12402
  if (!(resourceInit == null ? void 0 : resourceInit.collectionName)) {
12119
12403
  return;
@@ -12131,10 +12415,12 @@ class FlowSurfacesService {
12131
12415
  const selections = [
12132
12416
  ...import_lodash.default.castArray(state.query.measures || []).map((selection, index) => ({
12133
12417
  selection,
12418
+ kind: "measure",
12134
12419
  path: `chart query.measures[${index}].field`
12135
12420
  })),
12136
12421
  ...import_lodash.default.castArray(state.query.dimensions || []).map((selection, index) => ({
12137
12422
  selection,
12423
+ kind: "dimension",
12138
12424
  path: `chart query.dimensions[${index}].field`
12139
12425
  }))
12140
12426
  ];
@@ -12143,37 +12429,151 @@ class FlowSurfacesService {
12143
12429
  if (!fieldPath) {
12144
12430
  continue;
12145
12431
  }
12432
+ const fieldPathParts = fieldPath.split(".").filter(Boolean);
12433
+ const isCountMeasureSelection = item.kind === "measure" && String(((_c = item.selection) == null ? void 0 : _c.aggregation) || "").trim() === "count" && !((_d = item.selection) == null ? void 0 : _d.distinct);
12434
+ if (fieldPathParts.length > 1 && !isCountMeasureSelection) {
12435
+ const directAssociationPath = fieldPathParts[0];
12436
+ const directAssociationField = (0, import_service_helpers.resolveFieldFromCollection)(collection, directAssociationPath);
12437
+ const directAssociationTargetCollection = directAssociationField && (0, import_service_helpers.isAssociationField)(directAssociationField) ? (0, import_service_helpers.resolveFieldTargetCollection)(
12438
+ directAssociationField,
12439
+ dataSourceKey,
12440
+ (resolvedDataSourceKey, targetCollection) => this.getCollection(resolvedDataSourceKey, targetCollection)
12441
+ ) : null;
12442
+ const invalidDirectSubfield = directAssociationTargetCollection ? (0, import_service_helpers.getInvalidChartBuilderRelationDirectSubfieldDetails)({
12443
+ associationPathName: directAssociationPath,
12444
+ selectedSubfieldPath: fieldPathParts.slice(1).join("."),
12445
+ targetCollection: directAssociationTargetCollection
12446
+ }) : null;
12447
+ if (invalidDirectSubfield) {
12448
+ (0, import_errors.throwBadRequest)(
12449
+ withChartRepairMessage(
12450
+ `flowSurfaces ${actionName} ${item.path} '${fieldPath}' must reference a direct scalar child field under relation '${invalidDirectSubfield.associationPath}'. ${(0, import_service_helpers.formatChartBuilderSupportedRelationSubfields)(
12451
+ invalidDirectSubfield.associationPath,
12452
+ invalidDirectSubfield.supportedFields
12453
+ )}`
12454
+ ),
12455
+ {
12456
+ path: item.path,
12457
+ ruleId: "chart-builder-query-relation-direct-subfield-required",
12458
+ details: withFlowSurfaceChartRepairDetails({
12459
+ fieldPath,
12460
+ dataSourceKey,
12461
+ collectionName,
12462
+ ...invalidDirectSubfield
12463
+ })
12464
+ }
12465
+ );
12466
+ }
12467
+ }
12146
12468
  const parsed = this.parseFieldPath(collection, fieldPath, void 0, dataSourceKey, collectionName);
12469
+ if (parsed.associationPathName) {
12470
+ const associationField = parsed.associationField;
12471
+ const associationTargetCollection = associationField && (0, import_service_helpers.isAssociationField)(associationField) ? (0, import_service_helpers.resolveFieldTargetCollection)(
12472
+ associationField,
12473
+ dataSourceKey,
12474
+ (resolvedDataSourceKey, targetCollection) => this.getCollection(resolvedDataSourceKey, targetCollection)
12475
+ ) : null;
12476
+ if (!associationField || !(0, import_service_helpers.isAssociationField)(associationField) || !associationTargetCollection) {
12477
+ (0, import_errors.throwBadRequest)(
12478
+ withChartRepairMessage(
12479
+ `flowSurfaces ${actionName} ${item.path} '${fieldPath}' uses invalid association path '${parsed.associationPathName}' for builder charts`
12480
+ ),
12481
+ {
12482
+ path: item.path,
12483
+ ruleId: "chart-builder-query-association-path-invalid",
12484
+ details: withFlowSurfaceChartRepairDetails({
12485
+ fieldPath,
12486
+ associationPath: parsed.associationPathName,
12487
+ dataSourceKey,
12488
+ collectionName
12489
+ })
12490
+ }
12491
+ );
12492
+ }
12493
+ }
12147
12494
  const field = (0, import_service_helpers.resolveFieldFromCollection)(parsed.leafCollection, parsed.leafFieldPath);
12495
+ const leafModelAttributes = (0, import_service_helpers.getCollectionModelAttributes)(parsed.leafCollection);
12496
+ const hasLeafModelAttribute = Object.prototype.hasOwnProperty.call(leafModelAttributes, parsed.leafFieldPath);
12497
+ const isCountMeasureRelationSubfield = item.kind === "measure" && String(((_e = item.selection) == null ? void 0 : _e.aggregation) || "").trim() === "count" && !((_f = item.selection) == null ? void 0 : _f.distinct) && parsed.associationField && (0, import_service_helpers.isAssociationField)(parsed.associationField);
12498
+ const unsupportedRelationSubfield = parsed.associationField && (0, import_service_helpers.isAssociationField)(parsed.associationField) ? (0, import_service_helpers.getUnsupportedChartBuilderRelationSubfieldDetails)({
12499
+ associationPathName: parsed.associationPathName,
12500
+ leafFieldName: parsed.leafFieldPath,
12501
+ leafField: field,
12502
+ targetCollection: parsed.leafCollection
12503
+ }) : null;
12148
12504
  if (!field) {
12149
- if (this.collectionHasConcreteField(parsed.leafCollection, parsed.leafFieldPath)) {
12150
- continue;
12505
+ const hasConcreteField = hasLeafModelAttribute || this.collectionHasConcreteField(parsed.leafCollection, parsed.leafFieldPath);
12506
+ if (!hasConcreteField) {
12507
+ (0, import_errors.throwBadRequest)(
12508
+ withChartRepairMessage(
12509
+ `flowSurfaces ${actionName} ${item.path} '${fieldPath}' does not exist on collection '${dataSourceKey}.${collectionName}'`
12510
+ ),
12511
+ {
12512
+ details: withFlowSurfaceChartRepairDetails({
12513
+ fieldPath,
12514
+ dataSourceKey,
12515
+ collectionName
12516
+ })
12517
+ }
12518
+ );
12151
12519
  }
12520
+ }
12521
+ if (!fieldPath.includes(".") && field && (0, import_service_helpers.isAssociationField)(field)) {
12522
+ const suggestion = this.resolveBuilderChartAssociationSubfieldSuggestion(fieldPath, field, dataSourceKey);
12152
12523
  (0, import_errors.throwBadRequest)(
12153
12524
  withChartRepairMessage(
12154
- `flowSurfaces ${actionName} ${item.path} '${fieldPath}' does not exist on collection '${dataSourceKey}.${collectionName}'`
12525
+ `flowSurfaces ${actionName} ${item.path} '${fieldPath}' references an association field directly; use scalar subfield '${suggestion.suggestedFieldPath}' for builder charts`
12155
12526
  ),
12156
12527
  {
12157
12528
  details: withFlowSurfaceChartRepairDetails({
12158
12529
  fieldPath,
12159
12530
  dataSourceKey,
12160
- collectionName
12531
+ collectionName,
12532
+ ...suggestion
12161
12533
  })
12162
12534
  }
12163
12535
  );
12164
12536
  }
12165
- if (!fieldPath.includes(".") && (0, import_service_helpers.isAssociationField)(field)) {
12166
- const suggestion = this.resolveBuilderChartAssociationSubfieldSuggestion(fieldPath, field, dataSourceKey);
12537
+ if (isCountMeasureRelationSubfield) {
12167
12538
  (0, import_errors.throwBadRequest)(
12168
12539
  withChartRepairMessage(
12169
- `flowSurfaces ${actionName} ${item.path} '${fieldPath}' references an association field directly; use scalar subfield '${suggestion.suggestedFieldPath}' for builder charts`
12540
+ `flowSurfaces ${actionName} ${item.path} '${fieldPath}' counts a relation subfield; count a scalar base field such as 'id' and keep '${fieldPath}' as a dimension`
12170
12541
  ),
12171
12542
  {
12543
+ path: item.path,
12544
+ ruleId: "chart-builder-query-count-measure-relation-subfield",
12172
12545
  details: withFlowSurfaceChartRepairDetails({
12173
12546
  fieldPath,
12174
12547
  dataSourceKey,
12175
12548
  collectionName,
12176
- ...suggestion
12549
+ suggestedMeasure: {
12550
+ field: "id",
12551
+ aggregation: "count",
12552
+ alias: String(((_g = item.selection) == null ? void 0 : _g.alias) || "").trim() || "recordCount"
12553
+ },
12554
+ suggestedDimension: {
12555
+ field: fieldPath
12556
+ }
12557
+ })
12558
+ }
12559
+ );
12560
+ }
12561
+ if (unsupportedRelationSubfield) {
12562
+ (0, import_errors.throwBadRequest)(
12563
+ withChartRepairMessage(
12564
+ `flowSurfaces ${actionName} ${item.path} '${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)(
12565
+ unsupportedRelationSubfield.associationPath,
12566
+ unsupportedRelationSubfield.supportedFields
12567
+ )}`
12568
+ ),
12569
+ {
12570
+ path: item.path,
12571
+ ruleId: "chart-builder-query-relation-subfield-column-unsupported",
12572
+ details: withFlowSurfaceChartRepairDetails({
12573
+ fieldPath,
12574
+ dataSourceKey,
12575
+ collectionName,
12576
+ ...unsupportedRelationSubfield
12177
12577
  })
12178
12578
  }
12179
12579
  );
@@ -12448,6 +12848,8 @@ class FlowSurfacesService {
12448
12848
  options
12449
12849
  );
12450
12850
  const flowRegistry = this.getEventFlowRegistry(current);
12851
+ const directEvents = import_lodash.default.cloneDeep(((_a = contract.eventCapabilities) == null ? void 0 : _a.direct) || []);
12852
+ const objectEvents = import_lodash.default.uniq([...import_lodash.default.cloneDeep(((_b = contract.eventCapabilities) == null ? void 0 : _b.object) || []), ...directEvents]);
12451
12853
  return {
12452
12854
  target: {
12453
12855
  uid: target.uid,
@@ -12456,8 +12858,8 @@ class FlowSurfacesService {
12456
12858
  },
12457
12859
  flowRegistry,
12458
12860
  events: {
12459
- direct: import_lodash.default.cloneDeep(((_a = contract.eventCapabilities) == null ? void 0 : _a.direct) || []),
12460
- object: import_lodash.default.cloneDeep(((_b = contract.eventCapabilities) == null ? void 0 : _b.object) || [])
12861
+ direct: directEvents,
12862
+ object: objectEvents
12461
12863
  },
12462
12864
  phases: {
12463
12865
  supported: ["beforeAllFlows", "afterAllFlows", "beforeFlow", "afterFlow", "beforeStep", "afterStep"],
@@ -12492,13 +12894,12 @@ class FlowSurfacesService {
12492
12894
  if (phase !== "beforeAllFlows") {
12493
12895
  (0, import_errors.throwBadRequest)(`flowSurfaces addEventFlow only supports phase 'beforeAllFlows'`);
12494
12896
  }
12495
- const flow = this.normalizeAddEventFlowInput(key, values, phase);
12496
- const nextFlowRegistry = {
12897
+ const nextFlowRegistry = this.normalizeEventFlowRegistry("addEventFlow", {
12497
12898
  ...flowRegistry,
12498
- [key]: flow
12499
- };
12899
+ [key]: this.normalizeAddEventFlowInput(key, values, phase)
12900
+ });
12500
12901
  await this.persistEventFlowRegistry("addEventFlow", target, current, nextFlowRegistry, options);
12501
- return this.buildEventFlowWriteResult(target, key, flow, nextFlowRegistry);
12902
+ return this.buildEventFlowWriteResult(target, key, nextFlowRegistry[key], nextFlowRegistry);
12502
12903
  }
12503
12904
  async setEventFlow(values, options = {}) {
12504
12905
  var _a;
@@ -12512,13 +12913,12 @@ class FlowSurfacesService {
12512
12913
  const key = this.normalizeEventFlowKey("setEventFlow", (values == null ? void 0 : values.key) ?? ((_a = values == null ? void 0 : values.flow) == null ? void 0 : _a.key));
12513
12914
  this.assertEventFlowFingerprint("setEventFlow", values == null ? void 0 : values.expectedFingerprint, flowRegistry);
12514
12915
  const flowInput = import_lodash.default.isPlainObject(values == null ? void 0 : values.flow) ? values.flow : values;
12515
- const flow = this.normalizeEventFlowObject("setEventFlow", key, flowInput);
12516
- const nextFlowRegistry = {
12916
+ const nextFlowRegistry = this.normalizeEventFlowRegistry("setEventFlow", {
12517
12917
  ...flowRegistry,
12518
- [key]: flow
12519
- };
12918
+ [key]: this.normalizeEventFlowObject("setEventFlow", key, flowInput)
12919
+ });
12520
12920
  await this.persistEventFlowRegistry("setEventFlow", target, current, nextFlowRegistry, options);
12521
- return this.buildEventFlowWriteResult(target, key, flow, nextFlowRegistry);
12921
+ return this.buildEventFlowWriteResult(target, key, nextFlowRegistry[key], nextFlowRegistry);
12522
12922
  }
12523
12923
  async removeEventFlow(values, options = {}) {
12524
12924
  (0, import_payload_shape.validateFlowSurfacePayloadShape)("removeEventFlow", values, "values");
@@ -12533,14 +12933,14 @@ class FlowSurfacesService {
12533
12933
  (0, import_errors.throwBadRequest)(`flowSurfaces removeEventFlow flow '${key}' does not exist`);
12534
12934
  }
12535
12935
  this.assertEventFlowFingerprint("removeEventFlow", values == null ? void 0 : values.expectedFingerprint, flowRegistry);
12536
- const nextFlowRegistry = import_lodash.default.omit(flowRegistry, [key]);
12936
+ const nextFlowRegistry = this.normalizeEventFlowRegistry("removeEventFlow", import_lodash.default.omit(flowRegistry, [key]));
12537
12937
  await this.persistEventFlowRegistry("removeEventFlow", target, current, nextFlowRegistry, options);
12538
12938
  return this.buildEventFlowWriteResult(target, key, void 0, nextFlowRegistry);
12539
12939
  }
12540
12940
  async setEventFlows(values, options = {}) {
12541
12941
  (0, import_payload_shape.validateFlowSurfacePayloadShape)("setEventFlows", values, "values");
12542
12942
  const { target, current } = await this.resolveEventFlowTarget("setEventFlows", values == null ? void 0 : values.target, values, options);
12543
- const flows = values.flowRegistry || values.flows || {};
12943
+ const flows = this.normalizeEventFlowRegistry("setEventFlows", values.flowRegistry || values.flows || {});
12544
12944
  await this.persistEventFlowRegistry("setEventFlows", target, current, flows, options);
12545
12945
  return {
12546
12946
  uid: target.uid,
@@ -12566,7 +12966,10 @@ class FlowSurfacesService {
12566
12966
  };
12567
12967
  }
12568
12968
  getEventFlowRegistry(node) {
12569
- return import_lodash.default.isPlainObject(node == null ? void 0 : node.flowRegistry) ? import_lodash.default.cloneDeep(node.flowRegistry) : {};
12969
+ return import_lodash.default.isPlainObject(node == null ? void 0 : node.flowRegistry) ? this.normalizeEventFlowRegistry("getEventFlowRegistry", node.flowRegistry) : {};
12970
+ }
12971
+ normalizeEventFlowRegistry(actionName, flowRegistry) {
12972
+ return (0, import_event_flow_normalizer.normalizeFlowSurfaceEventFlowRegistry)(actionName, flowRegistry);
12570
12973
  }
12571
12974
  buildEventFlowFingerprint(flowRegistry) {
12572
12975
  return this.buildSurfaceFingerprint({
@@ -12604,7 +13007,9 @@ class FlowSurfacesService {
12604
13007
  normalizeAddEventFlowInput(key, values, phase) {
12605
13008
  var _a, _b, _c;
12606
13009
  const flow = import_lodash.default.isPlainObject(values.flow) ? import_lodash.default.cloneDeep(values.flow) : {};
12607
- const eventName = String(values.eventName ?? ((_a = flow == null ? void 0 : flow.on) == null ? void 0 : _a.eventName) ?? "").trim();
13010
+ const eventName = String(
13011
+ values.eventName ?? (typeof flow.on === "string" ? flow.on : (_a = flow == null ? void 0 : flow.on) == null ? void 0 : _a.eventName) ?? ""
13012
+ ).trim();
12608
13013
  if (!eventName) {
12609
13014
  (0, import_errors.throwBadRequest)(`flowSurfaces addEventFlow requires eventName`);
12610
13015
  }
@@ -12627,25 +13032,7 @@ class FlowSurfacesService {
12627
13032
  });
12628
13033
  }
12629
13034
  normalizeEventFlowObject(actionName, key, flowInput) {
12630
- if (!import_lodash.default.isPlainObject(flowInput)) {
12631
- (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} flow '${key}' must be an object`);
12632
- }
12633
- const flow = import_lodash.default.cloneDeep(flowInput);
12634
- flow.key = key;
12635
- if (import_lodash.default.isPlainObject(flow.on)) {
12636
- const eventName = String(flow.on.eventName || "").trim();
12637
- if (eventName) {
12638
- flow.on.eventName = eventName;
12639
- }
12640
- const phase = String(flow.on.phase || "").trim();
12641
- if (phase) {
12642
- flow.on.phase = phase;
12643
- }
12644
- }
12645
- if (import_lodash.default.isUndefined(flow.steps)) {
12646
- flow.steps = {};
12647
- }
12648
- return flow;
13035
+ return (0, import_event_flow_normalizer.normalizeFlowSurfaceEventFlow)(actionName, key, flowInput);
12649
13036
  }
12650
13037
  async persistEventFlowRegistry(actionName, target, current, flowRegistry, options = {}) {
12651
13038
  this.assertNoTreeConnectFieldsFlowRegistry(current, flowRegistry, actionName);
@@ -16037,7 +16424,10 @@ class FlowSurfacesService {
16037
16424
  const shouldLoadCurrent = shouldUpdateConfigure || shouldUpdateCardSettings;
16038
16425
  const resolved = shouldLoadCurrent ? await this.locator.resolve(target, options) : null;
16039
16426
  const current = resolved ? await this.loadResolvedNode(resolved, options.transaction) : null;
16040
- let nextConfigure = shouldUpdateConfigure ? (0, import_chart_config.buildChartConfigureFromSemanticChanges)(import_lodash.default.get(current, ["stepParams", "chartSettings", "configure"]), changes) : void 0;
16427
+ let nextConfigure = shouldUpdateConfigure ? buildChartConfigureFromSemanticChangesWithRepair(
16428
+ import_lodash.default.get(current, ["stepParams", "chartSettings", "configure"]),
16429
+ changes
16430
+ ) : void 0;
16041
16431
  if (shouldUpdateConfigure) {
16042
16432
  nextConfigure = await this.stripBasicSqlVisualWhenPreviewUnavailable(nextConfigure, changes, options.transaction);
16043
16433
  }
@@ -16165,18 +16555,18 @@ class FlowSurfacesService {
16165
16555
  return String(raw || "").trim();
16166
16556
  }
16167
16557
  collectionHasConcreteField(collection, fieldName) {
16168
- var _a, _b, _c, _d, _e, _f;
16558
+ var _a, _b, _c;
16169
16559
  const normalized = String(fieldName || "").trim();
16170
16560
  if (!normalized) {
16171
16561
  return false;
16172
16562
  }
16173
- 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) || {};
16563
+ const modelAttributes = (0, import_service_helpers.getCollectionModelAttributes)(collection);
16174
16564
  const primaryKeyAttributes = import_lodash.default.castArray(
16175
- ((_d = collection == null ? void 0 : collection.model) == null ? void 0 : _d.primaryKeyAttributes) || ((_e = collection == null ? void 0 : collection.model) == null ? void 0 : _e.primaryKeyAttribute) || []
16565
+ ((_a = collection == null ? void 0 : collection.model) == null ? void 0 : _a.primaryKeyAttributes) || ((_b = collection == null ? void 0 : collection.model) == null ? void 0 : _b.primaryKeyAttribute) || []
16176
16566
  );
16177
16567
  const modelAttribute = modelAttributes == null ? void 0 : modelAttributes[normalized];
16178
16568
  const isModelPrimaryKey = primaryKeyAttributes.includes(normalized) || !!(modelAttribute == null ? void 0 : modelAttribute.primaryKey);
16179
- 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);
16569
+ 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);
16180
16570
  }
16181
16571
  assertInitialBlockResourceCompatible(actionName, blockUse, resourceInit, popupProfile) {
16182
16572
  if (blockUse === "CommentsBlockModel") {
@@ -16987,7 +17377,11 @@ class FlowSurfacesService {
16987
17377
  items: []
16988
17378
  };
16989
17379
  }
16990
- return import_lodash.default.cloneDeep(value);
17380
+ return (0, import_filter_group.normalizeFlowSurfaceFilterGroupValue)(
17381
+ value,
17382
+ `flowSurfaces configure action defaultFilter expects FilterGroup like ${import_filter_group.FLOW_SURFACE_FILTER_GROUP_EXAMPLE}`,
17383
+ { strictDateValues: true }
17384
+ );
16991
17385
  }
16992
17386
  normalizeActionAssignValues(actionName, value) {
16993
17387
  if (!import_lodash.default.isPlainObject(value)) {
@@ -21637,7 +22031,7 @@ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROM
21637
22031
  (value) => !import_lodash.default.isUndefined(value)
21638
22032
  ),
21639
22033
  decoratorProps: import_lodash.default.cloneDeep(innerField.decoratorProps || {}),
21640
- flowRegistry: import_lodash.default.cloneDeep(innerField.flowRegistry || {}),
22034
+ flowRegistry: this.getEventFlowRegistry(innerField),
21641
22035
  stepParams: import_lodash.default.merge({}, innerField.stepParams || {}, {
21642
22036
  fieldBinding: {
21643
22037
  use: normalizedTargetUse