@nocobase/plugin-flow-engine 2.1.0-beta.37 → 2.1.0-beta.38
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.
- package/dist/externalVersion.js +9 -9
- package/dist/node_modules/@ant-design/icons-svg/package.json +1 -1
- package/dist/node_modules/acorn/package.json +1 -1
- package/dist/node_modules/acorn-jsx/package.json +1 -1
- package/dist/node_modules/acorn-walk/package.json +1 -1
- package/dist/node_modules/ses/package.json +1 -1
- package/dist/node_modules/zod/package.json +1 -1
- package/dist/server/flow-surfaces/apply/compiler.js +18 -3
- package/dist/server/flow-surfaces/apply/matching.js +2 -0
- package/dist/server/flow-surfaces/authoring-validation.js +621 -66
- package/dist/server/flow-surfaces/blueprint/compile-blocks.js +21 -3
- package/dist/server/flow-surfaces/blueprint/compile-plan.js +9 -9
- package/dist/server/flow-surfaces/catalog.js +3 -0
- package/dist/server/flow-surfaces/chart-config.js +14 -1
- package/dist/server/flow-surfaces/compose-compiler.d.ts +2 -0
- package/dist/server/flow-surfaces/compose-compiler.js +2 -0
- package/dist/server/flow-surfaces/compose-runtime.js +4 -7
- package/dist/server/flow-surfaces/configure-options.js +18 -7
- package/dist/server/flow-surfaces/locator.js +16 -2
- package/dist/server/flow-surfaces/runjs-authoring/index.js +5909 -2214
- package/dist/server/flow-surfaces/service-utils.d.ts +2 -0
- package/dist/server/flow-surfaces/service-utils.js +8 -0
- package/dist/server/flow-surfaces/service.d.ts +22 -0
- package/dist/server/flow-surfaces/service.js +722 -59
- package/dist/server/flow-surfaces/template-service-utils.d.ts +1 -0
- package/dist/swagger/flow-surfaces.d.ts +4 -2
- package/dist/swagger/flow-surfaces.examples.d.ts +6 -17
- package/dist/swagger/flow-surfaces.examples.js +5 -5
- package/dist/swagger/flow-surfaces.js +5 -3
- package/dist/swagger/index.d.ts +4 -2
- package/package.json +2 -2
|
@@ -59,6 +59,7 @@ var import_template_reference = require("./template-reference");
|
|
|
59
59
|
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
|
+
var import_configure_options = require("./configure-options");
|
|
62
63
|
const MAIN_BLOCK_UNSUPPORTED_SECTIONS = {
|
|
63
64
|
calendar: ["fields", "fieldGroups", "recordActions", "fieldsLayout"],
|
|
64
65
|
kanban: ["fieldGroups", "recordActions", "fieldsLayout"],
|
|
@@ -71,6 +72,55 @@ const SORTABLE_BLOCK_TYPES = /* @__PURE__ */ new Set(["table", "details", "list"
|
|
|
71
72
|
const CHART_BLOCK_TYPES = /* @__PURE__ */ new Set(["chart"]);
|
|
72
73
|
const COMMENTS_PAGE_SIZE_VALUES = /* @__PURE__ */ new Set([5, 10, 20, 50, 100, 200]);
|
|
73
74
|
const RECORD_HISTORY_INTERNAL_COLLECTIONS = /* @__PURE__ */ new Set(["recordHistories", "recordFieldHistories"]);
|
|
75
|
+
const VISIBLE_FIELD_REQUIRED_DATA_BLOCK_TYPES = /* @__PURE__ */ new Set([
|
|
76
|
+
"table",
|
|
77
|
+
"list",
|
|
78
|
+
"gridCard",
|
|
79
|
+
"details",
|
|
80
|
+
"createForm",
|
|
81
|
+
"editForm",
|
|
82
|
+
"filterForm",
|
|
83
|
+
"kanban"
|
|
84
|
+
]);
|
|
85
|
+
const VISIBLE_FIELD_MINIMUM_DATA_BLOCK_TYPES = /* @__PURE__ */ new Set(["table", "list", "gridCard", "details"]);
|
|
86
|
+
const RICH_COLLECTION_VISIBLE_FIELD_THRESHOLD = import_public_data_surface_default_filter.FLOW_SURFACE_DEFAULT_FILTER_REQUIRED_FIELD_COUNT * 2;
|
|
87
|
+
const RICH_DATA_BLOCK_VISIBLE_FIELD_MINIMUM = 3;
|
|
88
|
+
const NON_BUSINESS_VISIBLE_FIELD_NAMES = /* @__PURE__ */ new Set([
|
|
89
|
+
"id",
|
|
90
|
+
"uid",
|
|
91
|
+
"createdAt",
|
|
92
|
+
"updatedAt",
|
|
93
|
+
"deletedAt",
|
|
94
|
+
"createdBy",
|
|
95
|
+
"updatedBy",
|
|
96
|
+
"deletedBy",
|
|
97
|
+
"createdById",
|
|
98
|
+
"updatedById",
|
|
99
|
+
"deletedById",
|
|
100
|
+
"created_at",
|
|
101
|
+
"updated_at",
|
|
102
|
+
"deleted_at",
|
|
103
|
+
"created_by",
|
|
104
|
+
"updated_by",
|
|
105
|
+
"deleted_by"
|
|
106
|
+
]);
|
|
107
|
+
const NON_BUSINESS_VISIBLE_FIELD_INTERFACES = /* @__PURE__ */ new Set([
|
|
108
|
+
"id",
|
|
109
|
+
"createdAt",
|
|
110
|
+
"updatedAt",
|
|
111
|
+
"createdBy",
|
|
112
|
+
"updatedBy",
|
|
113
|
+
"sort"
|
|
114
|
+
]);
|
|
115
|
+
const NON_BUSINESS_VISIBLE_FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
116
|
+
"action",
|
|
117
|
+
"actions",
|
|
118
|
+
"button",
|
|
119
|
+
"divider",
|
|
120
|
+
"operation",
|
|
121
|
+
"operations",
|
|
122
|
+
"sort"
|
|
123
|
+
]);
|
|
74
124
|
const ANT_DESIGN_ICON_NAMES = new Set(Object.keys(antDesignIconAsn || {}));
|
|
75
125
|
const PUBLIC_BLOCK_TYPE_BY_MODEL_USE = {
|
|
76
126
|
TableBlockModel: "table",
|
|
@@ -106,9 +156,14 @@ const GRID_CARD_ALLOWED_SETTINGS_KEYS = /* @__PURE__ */ new Set([
|
|
|
106
156
|
"sorting",
|
|
107
157
|
"layout"
|
|
108
158
|
]);
|
|
159
|
+
const TABLE_ALLOWED_SETTINGS_KEYS = /* @__PURE__ */ new Set([...(0, import_configure_options.getConfigureOptionKeysForUse)("TableBlockModel"), "sort"]);
|
|
160
|
+
const TABLE_INTERNAL_AUTHORING_KEYS = ["tableSettings", "defaultSorting", "stepParams"];
|
|
161
|
+
const TABLE_SETTINGS_REPAIR_HINT = "Use public table settings keys such as settings.pageSize, settings.sorting, settings.dataScope, settings.density, settings.showRowNumbers, settings.treeTable, settings.dragSort, and settings.dragSortBy. Do not nest persisted tableSettings/defaultSorting/stepParams payloads.";
|
|
109
162
|
const JS_BLOCK_ALLOWED_SETTINGS_KEYS = /* @__PURE__ */ new Set(["title", "description", "className", "code", "version"]);
|
|
110
163
|
const JS_BLOCK_TOP_LEVEL_JS_KEYS = ["code", "version"];
|
|
111
164
|
const JS_BLOCK_INTERNAL_AUTHORING_KEYS = ["props", "decoratorProps", "flowRegistry", "stepParams"];
|
|
165
|
+
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.";
|
|
112
167
|
const CHART_QUERY_MODE_SET = new Set(import_chart_config.CHART_QUERY_MODES);
|
|
113
168
|
const CHART_VISUAL_MODE_SET = new Set(import_chart_config.CHART_VISUAL_MODES);
|
|
114
169
|
const CHART_BASIC_VISUAL_TYPE_SET = new Set(import_chart_config.CHART_BASIC_VISUAL_TYPES);
|
|
@@ -264,6 +319,67 @@ const DEFAULT_POPUPS_ALLOWED_KEYS = ["view", "addNew", "edit", "associations"];
|
|
|
264
319
|
const DEFAULT_POPUP_ACTION_ALLOWED_KEYS = ["name", "description"];
|
|
265
320
|
const DEFAULT_POPUP_ASSOCIATION_ALLOWED_KEYS = ["view", "addNew", "edit"];
|
|
266
321
|
const DEFAULT_POPUP_ACTIONS = ["view", "addNew", "edit"];
|
|
322
|
+
const AUTHORING_AI_EMPLOYEE_WORK_CONTEXT_PUBLIC_KEYS = ["type", "uid", "target"];
|
|
323
|
+
const AUTHORING_AI_EMPLOYEE_TASK_PUBLIC_SETTING_KEYS = [
|
|
324
|
+
"title",
|
|
325
|
+
"message",
|
|
326
|
+
"autoSend",
|
|
327
|
+
"skillSettings",
|
|
328
|
+
"model",
|
|
329
|
+
"webSearch"
|
|
330
|
+
];
|
|
331
|
+
const AUTHORING_AI_EMPLOYEE_TASK_MESSAGE_PUBLIC_KEYS = ["system", "user", "workContext"];
|
|
332
|
+
const AUTHORING_AI_EMPLOYEE_TASK_MODEL_PUBLIC_KEYS = ["llmService", "model"];
|
|
333
|
+
const AUTHORING_AI_EMPLOYEE_SKILL_SETTINGS_PUBLIC_KEYS = ["skills", "tools", "skillsVersion", "toolsVersion"];
|
|
334
|
+
const AUTHORING_AI_EMPLOYEE_STYLE_PUBLIC_KEYS = ["size", "mask"];
|
|
335
|
+
const AUTHORING_AI_EMPLOYEE_DEFAULT_STYLE = {
|
|
336
|
+
size: 40,
|
|
337
|
+
mask: false
|
|
338
|
+
};
|
|
339
|
+
function buildCalendarMainBlockRepairDetails(section) {
|
|
340
|
+
const popupSectionHint = section === "fieldGroups" || section === "recordActions" || section === "fieldsLayout" ? " Put event form/details content under settings.quickCreatePopup or settings.eventPopup instead of on the calendar main block." : "";
|
|
341
|
+
return {
|
|
342
|
+
repairHint: "Calendar main block payload shape issue. Put event bindings under settings.titleField, settings.startField, settings.endField, and optional settings.colorField; do not put collection fields in block fields. Keep block type calendar and repair this payload." + popupSectionHint,
|
|
343
|
+
example: {
|
|
344
|
+
type: "calendar",
|
|
345
|
+
collection: "tasks",
|
|
346
|
+
settings: {
|
|
347
|
+
titleField: "title",
|
|
348
|
+
startField: "startAt",
|
|
349
|
+
endField: "endAt"
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
function buildKanbanMainBlockRepairDetails(section) {
|
|
355
|
+
return {
|
|
356
|
+
repairHint: "Kanban main block payload shape issue. Put card display fields in block fields, grouping in settings.groupField, and quick-create/card details under settings.quickCreatePopup or settings.cardPopup. Keep block type kanban and repair this payload.",
|
|
357
|
+
section,
|
|
358
|
+
example: {
|
|
359
|
+
type: "kanban",
|
|
360
|
+
collection: "tasks",
|
|
361
|
+
fields: ["title", "priority"],
|
|
362
|
+
settings: {
|
|
363
|
+
groupField: "status"
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
function buildTwoColumnLayoutRepairDetails() {
|
|
369
|
+
return {
|
|
370
|
+
repairHint: "When multiple non-filter blocks should share a row, put them in the same layout row. Do not place every block on a separate row.",
|
|
371
|
+
example: {
|
|
372
|
+
layout: {
|
|
373
|
+
rows: [
|
|
374
|
+
[
|
|
375
|
+
{ key: "calendar", span: 12 },
|
|
376
|
+
{ key: "kanban", span: 12 }
|
|
377
|
+
]
|
|
378
|
+
]
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
};
|
|
382
|
+
}
|
|
267
383
|
async function assertFlowSurfaceAuthoringPayload(actionName, values, context = {}) {
|
|
268
384
|
const errors = await collectFlowSurfaceAuthoringErrors(actionName, values, context);
|
|
269
385
|
if (errors.length) {
|
|
@@ -329,38 +445,43 @@ async function collectNavigationGroupErrors(actionName, values, context, errors)
|
|
|
329
445
|
return;
|
|
330
446
|
}
|
|
331
447
|
const matchedRoutes = await context.findMenuGroupRoutesByTitle(groupTitle, context.transaction);
|
|
332
|
-
|
|
448
|
+
const rootMatchedRoutes = filterRootMenuGroupRoutes(matchedRoutes);
|
|
449
|
+
if (rootMatchedRoutes.length <= 1) {
|
|
333
450
|
return;
|
|
334
451
|
}
|
|
335
452
|
pushAuthoringError(errors, {
|
|
336
453
|
path: "$.navigation.group.title",
|
|
337
454
|
ruleId: "navigation-group-title-ambiguous",
|
|
338
|
-
message: `flowSurfaces authoring $.navigation.group.title '${groupTitle}' matches ${
|
|
455
|
+
message: `flowSurfaces authoring $.navigation.group.title '${groupTitle}' matches ${rootMatchedRoutes.length} existing root menu groups; pass navigation.group.routeId explicitly`,
|
|
339
456
|
details: {
|
|
340
457
|
title: groupTitle,
|
|
341
|
-
|
|
458
|
+
parentMenuRouteId: null,
|
|
459
|
+
matches: rootMatchedRoutes.length
|
|
342
460
|
}
|
|
343
461
|
});
|
|
344
462
|
}
|
|
345
463
|
async function collectNavigationIconErrors(actionName, values, context, errors) {
|
|
346
|
-
var _a, _b;
|
|
464
|
+
var _a, _b, _c;
|
|
347
465
|
if (actionName !== "applyBlueprint" || (values == null ? void 0 : values.mode) !== "create") {
|
|
348
466
|
return;
|
|
349
467
|
}
|
|
350
468
|
const group = _.isPlainObject((_a = values == null ? void 0 : values.navigation) == null ? void 0 : _a.group) ? values.navigation.group : null;
|
|
351
469
|
const groupRouteId = String((group == null ? void 0 : group.routeId) || "").trim();
|
|
352
|
-
if (group && !groupRouteId) {
|
|
470
|
+
if (group && !groupRouteId && group.hideInMenu !== true) {
|
|
353
471
|
const groupIcon = String(group.icon || "").trim();
|
|
354
472
|
if (!groupIcon && await shouldRequireNewNavigationGroupIcon(group, context)) {
|
|
355
473
|
pushAuthoringError(errors, {
|
|
356
474
|
path: "$.navigation.group.icon",
|
|
357
|
-
ruleId: "
|
|
358
|
-
message: "flowSurfaces authoring $.navigation.group.icon is required when creating a
|
|
475
|
+
ruleId: "navigation-icon-required",
|
|
476
|
+
message: "flowSurfaces authoring $.navigation.group.icon is required when creating a visible navigation group",
|
|
477
|
+
details: {
|
|
478
|
+
repairHint: "Pass a valid Ant Design icon name such as AppstoreOutlined, DashboardOutlined, or FolderOpenOutlined."
|
|
479
|
+
}
|
|
359
480
|
});
|
|
360
481
|
} else if (groupIcon && !isValidAntDesignIconName(groupIcon)) {
|
|
361
482
|
pushAuthoringError(errors, {
|
|
362
483
|
path: "$.navigation.group.icon",
|
|
363
|
-
ruleId: "
|
|
484
|
+
ruleId: "navigation-icon-unknown",
|
|
364
485
|
message: "flowSurfaces authoring $.navigation.group.icon must be a valid Ant Design icon name",
|
|
365
486
|
details: {
|
|
366
487
|
icon: groupIcon
|
|
@@ -370,7 +491,7 @@ async function collectNavigationIconErrors(actionName, values, context, errors)
|
|
|
370
491
|
} else if (group && String(group.icon || "").trim() && !isValidAntDesignIconName(group.icon)) {
|
|
371
492
|
pushAuthoringError(errors, {
|
|
372
493
|
path: "$.navigation.group.icon",
|
|
373
|
-
ruleId: "
|
|
494
|
+
ruleId: "navigation-icon-unknown",
|
|
374
495
|
message: "flowSurfaces authoring $.navigation.group.icon must be a valid Ant Design icon name",
|
|
375
496
|
details: {
|
|
376
497
|
icon: String(group.icon || "").trim()
|
|
@@ -382,13 +503,24 @@ async function collectNavigationIconErrors(actionName, values, context, errors)
|
|
|
382
503
|
if (itemIcon && !isValidAntDesignIconName(itemIcon)) {
|
|
383
504
|
pushAuthoringError(errors, {
|
|
384
505
|
path: "$.navigation.item.icon",
|
|
385
|
-
ruleId: "
|
|
506
|
+
ruleId: "navigation-icon-unknown",
|
|
386
507
|
message: "flowSurfaces authoring $.navigation.item.icon must be a valid Ant Design icon name",
|
|
387
508
|
details: {
|
|
388
509
|
icon: itemIcon
|
|
389
510
|
}
|
|
390
511
|
});
|
|
391
512
|
}
|
|
513
|
+
const pageIcon = String(((_c = values == null ? void 0 : values.page) == null ? void 0 : _c.icon) || "").trim();
|
|
514
|
+
if (pageIcon && !isValidAntDesignIconName(pageIcon)) {
|
|
515
|
+
pushAuthoringError(errors, {
|
|
516
|
+
path: "$.page.icon",
|
|
517
|
+
ruleId: "navigation-icon-unknown",
|
|
518
|
+
message: "flowSurfaces authoring $.page.icon must be a valid Ant Design icon name when used as the create-mode page route icon",
|
|
519
|
+
details: {
|
|
520
|
+
icon: pageIcon
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
}
|
|
392
524
|
}
|
|
393
525
|
async function shouldRequireNewNavigationGroupIcon(group, context) {
|
|
394
526
|
const groupTitle = String((group == null ? void 0 : group.title) || "").trim();
|
|
@@ -396,7 +528,22 @@ async function shouldRequireNewNavigationGroupIcon(group, context) {
|
|
|
396
528
|
return true;
|
|
397
529
|
}
|
|
398
530
|
const matchedRoutes = await context.findMenuGroupRoutesByTitle(groupTitle, context.transaction);
|
|
399
|
-
return matchedRoutes.length === 0;
|
|
531
|
+
return filterRootMenuGroupRoutes(matchedRoutes).length === 0;
|
|
532
|
+
}
|
|
533
|
+
function filterRootMenuGroupRoutes(routes) {
|
|
534
|
+
return _.castArray(routes || []).filter(
|
|
535
|
+
(route) => routeParentIdMatches(readAuthoringRouteField(route, "parentId"), null)
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
function readAuthoringRouteField(route, key) {
|
|
539
|
+
var _a;
|
|
540
|
+
return ((_a = route == null ? void 0 : route.get) == null ? void 0 : _a.call(route, key)) ?? (route == null ? void 0 : route[key]);
|
|
541
|
+
}
|
|
542
|
+
function routeParentIdMatches(routeParentId, parentId) {
|
|
543
|
+
if (_.isNil(routeParentId) && _.isNil(parentId)) {
|
|
544
|
+
return true;
|
|
545
|
+
}
|
|
546
|
+
return String(routeParentId ?? "") === String(parentId ?? "");
|
|
400
547
|
}
|
|
401
548
|
function isValidAntDesignIconName(value) {
|
|
402
549
|
const normalized = String(value || "").trim();
|
|
@@ -494,6 +641,39 @@ function collectChartAssetBlockTreeErrors(block, path, chartAssets, errors) {
|
|
|
494
641
|
);
|
|
495
642
|
});
|
|
496
643
|
}
|
|
644
|
+
function withJsBlockRepairHint(details = {}) {
|
|
645
|
+
return {
|
|
646
|
+
...details,
|
|
647
|
+
repairHint: JS_BLOCK_REPAIR_HINT
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
function withChartRepairHint(details = {}) {
|
|
651
|
+
return {
|
|
652
|
+
...details,
|
|
653
|
+
repairHint: CHART_REPAIR_HINT,
|
|
654
|
+
repairSteps: [
|
|
655
|
+
"Keep the block type as chart.",
|
|
656
|
+
"Define assets.charts.<key>.query and assets.charts.<key>.visual.",
|
|
657
|
+
"Reference that asset from the chart block with block.chart = <key>.",
|
|
658
|
+
"Retry the chart payload instead of replacing the chart with another block type or omitting it."
|
|
659
|
+
],
|
|
660
|
+
expectedShape: {
|
|
661
|
+
assets: {
|
|
662
|
+
charts: {
|
|
663
|
+
chartKey: {
|
|
664
|
+
query: "builder/sql query configuration",
|
|
665
|
+
visual: "basic/custom visual configuration"
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
},
|
|
669
|
+
block: {
|
|
670
|
+
type: "chart",
|
|
671
|
+
chart: "chartKey"
|
|
672
|
+
}
|
|
673
|
+
},
|
|
674
|
+
forbiddenFallbacks: ["table", "jsBlock", "actionPanel", "gridCard", "drop chart", "defer chart"]
|
|
675
|
+
};
|
|
676
|
+
}
|
|
497
677
|
function collectChartBlockAssetReferenceErrors(block, path, chartAssets, errors) {
|
|
498
678
|
if (!CHART_BLOCK_TYPES.has(String((block == null ? void 0 : block.type) || "").trim())) {
|
|
499
679
|
return;
|
|
@@ -502,7 +682,8 @@ function collectChartBlockAssetReferenceErrors(block, path, chartAssets, errors)
|
|
|
502
682
|
pushAuthoringError(errors, {
|
|
503
683
|
path: `${path}.stepParams`,
|
|
504
684
|
ruleId: "chart-block-step-params-unsupported",
|
|
505
|
-
message: `flowSurfaces authoring ${path}.stepParams is not accepted on public chart blocks; put chart configuration under assets.charts and reference it with block.chart
|
|
685
|
+
message: `flowSurfaces authoring ${path}.stepParams is not accepted on public chart blocks; put chart configuration under assets.charts and reference it with block.chart`,
|
|
686
|
+
details: withChartRepairHint()
|
|
506
687
|
});
|
|
507
688
|
}
|
|
508
689
|
const chartKey = String(block.chart || "").trim();
|
|
@@ -510,7 +691,8 @@ function collectChartBlockAssetReferenceErrors(block, path, chartAssets, errors)
|
|
|
510
691
|
pushAuthoringError(errors, {
|
|
511
692
|
path: `${path}.chart`,
|
|
512
693
|
ruleId: "chart-block-asset-reference-required",
|
|
513
|
-
message: `flowSurfaces authoring ${path}.chart must reference one key from assets.charts
|
|
694
|
+
message: `flowSurfaces authoring ${path}.chart must reference one key from assets.charts`,
|
|
695
|
+
details: withChartRepairHint()
|
|
514
696
|
});
|
|
515
697
|
return;
|
|
516
698
|
}
|
|
@@ -519,9 +701,9 @@ function collectChartBlockAssetReferenceErrors(block, path, chartAssets, errors)
|
|
|
519
701
|
path: `${path}.chart`,
|
|
520
702
|
ruleId: "chart-block-asset-reference-missing",
|
|
521
703
|
message: `flowSurfaces authoring ${path}.chart references missing chart asset '${chartKey}'`,
|
|
522
|
-
details: {
|
|
704
|
+
details: withChartRepairHint({
|
|
523
705
|
chartKey
|
|
524
|
-
}
|
|
706
|
+
})
|
|
525
707
|
});
|
|
526
708
|
}
|
|
527
709
|
}
|
|
@@ -535,7 +717,8 @@ function collectChartAssetRegistryErrors(charts, path, context, errors) {
|
|
|
535
717
|
pushAuthoringError(errors, {
|
|
536
718
|
path: assetPath,
|
|
537
719
|
ruleId: "chart-asset-invalid",
|
|
538
|
-
message: `flowSurfaces authoring ${assetPath} must be an object
|
|
720
|
+
message: `flowSurfaces authoring ${assetPath} must be an object`,
|
|
721
|
+
details: withChartRepairHint()
|
|
539
722
|
});
|
|
540
723
|
return;
|
|
541
724
|
}
|
|
@@ -549,7 +732,8 @@ function collectChartAssetQueryErrors(asset, path, context, errors) {
|
|
|
549
732
|
pushAuthoringError(errors, {
|
|
550
733
|
path: `${path}.query`,
|
|
551
734
|
ruleId: "chart-query-missing",
|
|
552
|
-
message: `flowSurfaces authoring ${path}.query is required
|
|
735
|
+
message: `flowSurfaces authoring ${path}.query is required`,
|
|
736
|
+
details: withChartRepairHint()
|
|
553
737
|
});
|
|
554
738
|
return;
|
|
555
739
|
}
|
|
@@ -559,9 +743,9 @@ function collectChartAssetQueryErrors(asset, path, context, errors) {
|
|
|
559
743
|
path: `${path}.query.mode`,
|
|
560
744
|
ruleId: "chart-query-mode-unsupported",
|
|
561
745
|
message: `flowSurfaces authoring ${path}.query.mode '${mode}' is not supported`,
|
|
562
|
-
details: {
|
|
746
|
+
details: withChartRepairHint({
|
|
563
747
|
mode
|
|
564
|
-
}
|
|
748
|
+
})
|
|
565
749
|
});
|
|
566
750
|
return;
|
|
567
751
|
}
|
|
@@ -577,14 +761,16 @@ function collectBuilderChartAssetQueryErrors(query, path, context, errors) {
|
|
|
577
761
|
pushAuthoringError(errors, {
|
|
578
762
|
path: `${path}.query.resource`,
|
|
579
763
|
ruleId: "chart-builder-query-resource-missing",
|
|
580
|
-
message: `flowSurfaces authoring ${path}.query.resource.collectionName is required for builder chart assets
|
|
764
|
+
message: `flowSurfaces authoring ${path}.query.resource.collectionName is required for builder chart assets`,
|
|
765
|
+
details: withChartRepairHint()
|
|
581
766
|
});
|
|
582
767
|
}
|
|
583
768
|
if (!Array.isArray(query.measures) || !query.measures.length) {
|
|
584
769
|
pushAuthoringError(errors, {
|
|
585
770
|
path: `${path}.query.measures`,
|
|
586
771
|
ruleId: "chart-builder-query-measures-missing",
|
|
587
|
-
message: `flowSurfaces authoring ${path}.query.measures must include at least one measure
|
|
772
|
+
message: `flowSurfaces authoring ${path}.query.measures must include at least one measure`,
|
|
773
|
+
details: withChartRepairHint()
|
|
588
774
|
});
|
|
589
775
|
}
|
|
590
776
|
collectForbiddenObjectKeyErrors(
|
|
@@ -592,7 +778,8 @@ function collectBuilderChartAssetQueryErrors(query, path, context, errors) {
|
|
|
592
778
|
`${path}.query`,
|
|
593
779
|
CHART_BUILDER_QUERY_FORBIDDEN_KEYS,
|
|
594
780
|
"chart-builder-query-forbidden-keys",
|
|
595
|
-
errors
|
|
781
|
+
errors,
|
|
782
|
+
withChartRepairHint()
|
|
596
783
|
);
|
|
597
784
|
collectBuilderChartAssetFieldErrors(query, path, context, errors);
|
|
598
785
|
}
|
|
@@ -640,11 +827,11 @@ function collectBuilderChartAssetFieldErrors(query, path, context, errors) {
|
|
|
640
827
|
path: item.fieldPath,
|
|
641
828
|
ruleId: "chart-builder-query-field-unknown",
|
|
642
829
|
message: `flowSurfaces authoring ${item.fieldPath} references unknown field '${fieldPath}' on collection '${dataSourceKey}.${collectionName}'`,
|
|
643
|
-
details: {
|
|
830
|
+
details: withChartRepairHint({
|
|
644
831
|
fieldPath,
|
|
645
832
|
dataSourceKey,
|
|
646
833
|
collectionName
|
|
647
|
-
}
|
|
834
|
+
})
|
|
648
835
|
});
|
|
649
836
|
continue;
|
|
650
837
|
}
|
|
@@ -659,12 +846,12 @@ function collectBuilderChartAssetFieldErrors(query, path, context, errors) {
|
|
|
659
846
|
path: item.fieldPath,
|
|
660
847
|
ruleId: "chart-builder-query-association-field-requires-subfield",
|
|
661
848
|
message: `flowSurfaces authoring ${item.fieldPath} references association field '${fieldPath}' directly; use scalar subfield '${suggestion.suggestedFieldPath}' for builder charts`,
|
|
662
|
-
details: {
|
|
849
|
+
details: withChartRepairHint({
|
|
663
850
|
fieldPath,
|
|
664
851
|
dataSourceKey,
|
|
665
852
|
collectionName,
|
|
666
853
|
...suggestion
|
|
667
|
-
}
|
|
854
|
+
})
|
|
668
855
|
});
|
|
669
856
|
}
|
|
670
857
|
}
|
|
@@ -691,7 +878,8 @@ function collectSqlChartAssetQueryErrors(query, path, errors) {
|
|
|
691
878
|
pushAuthoringError(errors, {
|
|
692
879
|
path: `${path}.query.sql`,
|
|
693
880
|
ruleId: "chart-sql-query-text-missing",
|
|
694
|
-
message: `flowSurfaces authoring ${path}.query.sql must be a non-empty string
|
|
881
|
+
message: `flowSurfaces authoring ${path}.query.sql must be a non-empty string`,
|
|
882
|
+
details: withChartRepairHint()
|
|
695
883
|
});
|
|
696
884
|
}
|
|
697
885
|
collectForbiddenObjectKeyErrors(
|
|
@@ -699,7 +887,8 @@ function collectSqlChartAssetQueryErrors(query, path, errors) {
|
|
|
699
887
|
`${path}.query`,
|
|
700
888
|
CHART_SQL_QUERY_FORBIDDEN_KEYS,
|
|
701
889
|
"chart-sql-query-forbidden-builder-keys",
|
|
702
|
-
errors
|
|
890
|
+
errors,
|
|
891
|
+
withChartRepairHint()
|
|
703
892
|
);
|
|
704
893
|
}
|
|
705
894
|
function collectChartAssetVisualErrors(asset, path, errors) {
|
|
@@ -708,7 +897,8 @@ function collectChartAssetVisualErrors(asset, path, errors) {
|
|
|
708
897
|
pushAuthoringError(errors, {
|
|
709
898
|
path: `${path}.visual`,
|
|
710
899
|
ruleId: "chart-visual-missing",
|
|
711
|
-
message: `flowSurfaces authoring ${path}.visual is required
|
|
900
|
+
message: `flowSurfaces authoring ${path}.visual is required`,
|
|
901
|
+
details: withChartRepairHint()
|
|
712
902
|
});
|
|
713
903
|
return;
|
|
714
904
|
}
|
|
@@ -717,7 +907,8 @@ function collectChartAssetVisualErrors(asset, path, errors) {
|
|
|
717
907
|
`${path}.visual`,
|
|
718
908
|
CHART_VISUAL_LEGACY_BUILDER_KEYS,
|
|
719
909
|
"chart-visual-legacy-builder-keys-unsupported",
|
|
720
|
-
errors
|
|
910
|
+
errors,
|
|
911
|
+
withChartRepairHint()
|
|
721
912
|
);
|
|
722
913
|
const mode = String(visual.mode || "basic").trim();
|
|
723
914
|
if (!CHART_VISUAL_MODE_SET.has(mode)) {
|
|
@@ -725,9 +916,9 @@ function collectChartAssetVisualErrors(asset, path, errors) {
|
|
|
725
916
|
path: `${path}.visual.mode`,
|
|
726
917
|
ruleId: "chart-visual-mode-unsupported",
|
|
727
918
|
message: `flowSurfaces authoring ${path}.visual.mode '${mode}' is not supported`,
|
|
728
|
-
details: {
|
|
919
|
+
details: withChartRepairHint({
|
|
729
920
|
mode
|
|
730
|
-
}
|
|
921
|
+
})
|
|
731
922
|
});
|
|
732
923
|
return;
|
|
733
924
|
}
|
|
@@ -736,7 +927,8 @@ function collectChartAssetVisualErrors(asset, path, errors) {
|
|
|
736
927
|
pushAuthoringError(errors, {
|
|
737
928
|
path: `${path}.visual.raw`,
|
|
738
929
|
ruleId: "chart-custom-visual-raw-missing",
|
|
739
|
-
message: `flowSurfaces authoring ${path}.visual.raw is required for custom chart assets
|
|
930
|
+
message: `flowSurfaces authoring ${path}.visual.raw is required for custom chart assets`,
|
|
931
|
+
details: withChartRepairHint()
|
|
740
932
|
});
|
|
741
933
|
}
|
|
742
934
|
collectForbiddenObjectKeyErrors(
|
|
@@ -744,7 +936,8 @@ function collectChartAssetVisualErrors(asset, path, errors) {
|
|
|
744
936
|
`${path}.visual`,
|
|
745
937
|
CHART_CUSTOM_VISUAL_FORBIDDEN_KEYS,
|
|
746
938
|
"chart-custom-visual-public-keys-unsupported",
|
|
747
|
-
errors
|
|
939
|
+
errors,
|
|
940
|
+
withChartRepairHint()
|
|
748
941
|
);
|
|
749
942
|
return;
|
|
750
943
|
}
|
|
@@ -753,23 +946,25 @@ function collectChartAssetVisualErrors(asset, path, errors) {
|
|
|
753
946
|
pushAuthoringError(errors, {
|
|
754
947
|
path: `${path}.visual.type`,
|
|
755
948
|
ruleId: "chart-visual-type-missing",
|
|
756
|
-
message: `flowSurfaces authoring ${path}.visual.type is required for basic chart assets
|
|
949
|
+
message: `flowSurfaces authoring ${path}.visual.type is required for basic chart assets`,
|
|
950
|
+
details: withChartRepairHint()
|
|
757
951
|
});
|
|
758
952
|
} else if (!CHART_BASIC_VISUAL_TYPE_SET.has(type)) {
|
|
759
953
|
pushAuthoringError(errors, {
|
|
760
954
|
path: `${path}.visual.type`,
|
|
761
955
|
ruleId: "chart-visual-type-unsupported",
|
|
762
956
|
message: `flowSurfaces authoring ${path}.visual.type '${type}' is not supported`,
|
|
763
|
-
details: {
|
|
957
|
+
details: withChartRepairHint({
|
|
764
958
|
type
|
|
765
|
-
}
|
|
959
|
+
})
|
|
766
960
|
});
|
|
767
961
|
}
|
|
768
962
|
if (!_.isPlainObject(visual.mappings)) {
|
|
769
963
|
pushAuthoringError(errors, {
|
|
770
964
|
path: `${path}.visual.mappings`,
|
|
771
965
|
ruleId: "chart-visual-mappings-missing",
|
|
772
|
-
message: `flowSurfaces authoring ${path}.visual.mappings is required for basic chart assets
|
|
966
|
+
message: `flowSurfaces authoring ${path}.visual.mappings is required for basic chart assets`,
|
|
967
|
+
details: withChartRepairHint()
|
|
773
968
|
});
|
|
774
969
|
return;
|
|
775
970
|
}
|
|
@@ -781,14 +976,14 @@ function collectChartAssetVisualErrors(asset, path, errors) {
|
|
|
781
976
|
path: `${path}.visual.mappings`,
|
|
782
977
|
ruleId: "chart-visual-required-mappings-missing",
|
|
783
978
|
message: `flowSurfaces authoring ${path}.visual.mappings is missing required keys: ${missingMappings.join(", ")}`,
|
|
784
|
-
details: {
|
|
979
|
+
details: withChartRepairHint({
|
|
785
980
|
type,
|
|
786
981
|
missingMappings
|
|
787
|
-
}
|
|
982
|
+
})
|
|
788
983
|
});
|
|
789
984
|
}
|
|
790
985
|
}
|
|
791
|
-
function collectForbiddenObjectKeyErrors(value, path, forbiddenKeys, ruleId, errors) {
|
|
986
|
+
function collectForbiddenObjectKeyErrors(value, path, forbiddenKeys, ruleId, errors, details = {}) {
|
|
792
987
|
if (!_.isPlainObject(value)) {
|
|
793
988
|
return;
|
|
794
989
|
}
|
|
@@ -801,6 +996,7 @@ function collectForbiddenObjectKeyErrors(value, path, forbiddenKeys, ruleId, err
|
|
|
801
996
|
ruleId,
|
|
802
997
|
message: `flowSurfaces authoring ${path} does not accept keys: ${keys.join(", ")}`,
|
|
803
998
|
details: {
|
|
999
|
+
...details,
|
|
804
1000
|
keys
|
|
805
1001
|
}
|
|
806
1002
|
});
|
|
@@ -3186,11 +3382,13 @@ function collectBlockErrors(block, path, errors, localKeys, context) {
|
|
|
3186
3382
|
context
|
|
3187
3383
|
);
|
|
3188
3384
|
collectSemanticBindingErrors(block, blockType, path, errors, context);
|
|
3385
|
+
collectVisibleDataBlockFieldErrors(block, blockType, path, errors, context);
|
|
3189
3386
|
collectCommentsBlockErrors(block, blockType, path, errors, context);
|
|
3190
3387
|
collectRecordHistoryBlockErrors(block, blockType, path, errors, context);
|
|
3191
3388
|
collectChartDisplayTitleErrors(block, blockType, path, errors);
|
|
3192
3389
|
collectTreeTableExplicitFieldsErrors(block, blockType, path, errors, context);
|
|
3193
3390
|
collectTreeConnectFieldsErrors((_a = block.settings) == null ? void 0 : _a.connectFields, `${path}.settings.connectFields`, errors);
|
|
3391
|
+
collectTableSettingsErrors(block, blockType, path, errors);
|
|
3194
3392
|
collectGridCardSettingsErrors(block, blockType, path, errors);
|
|
3195
3393
|
const descendantContext = getBlockDescendantValidationContext(block, context);
|
|
3196
3394
|
collectActionListErrors(block.actions, `${path}.actions`, errors, block, descendantContext, "actions");
|
|
@@ -3214,7 +3412,8 @@ function collectJsBlockPublicContractErrors(block, path, errors, context) {
|
|
|
3214
3412
|
pushAuthoringError(errors, {
|
|
3215
3413
|
path: `${path}.type`,
|
|
3216
3414
|
ruleId: "jsBlock-type-alias-unsupported",
|
|
3217
|
-
message: `flowSurfaces authoring ${path}.type must be "jsBlock"; "js" is only an action type and is not a public JSBlock block alias. Use ${path}.settings.code for inline JSBlock code
|
|
3415
|
+
message: `flowSurfaces authoring ${path}.type must be "jsBlock"; "js" is only an action type and is not a public JSBlock block alias. Use ${path}.settings.code for inline JSBlock code`,
|
|
3416
|
+
details: withJsBlockRepairHint()
|
|
3218
3417
|
});
|
|
3219
3418
|
return;
|
|
3220
3419
|
}
|
|
@@ -3228,7 +3427,8 @@ function collectJsBlockPublicContractErrors(block, path, errors, context) {
|
|
|
3228
3427
|
pushAuthoringError(errors, {
|
|
3229
3428
|
path: `${path}.${key}`,
|
|
3230
3429
|
ruleId: `jsBlock-top-level-${key}-unsupported`,
|
|
3231
|
-
message: `flowSurfaces authoring ${path}.${key} is not accepted on public jsBlock blocks; use ${path}.settings.code and ${path}.settings.version for inline JS code
|
|
3430
|
+
message: `flowSurfaces authoring ${path}.${key} is not accepted on public jsBlock blocks; use ${path}.settings.code and ${path}.settings.version for inline JS code`,
|
|
3431
|
+
details: withJsBlockRepairHint({ key })
|
|
3232
3432
|
});
|
|
3233
3433
|
});
|
|
3234
3434
|
JS_BLOCK_INTERNAL_AUTHORING_KEYS.forEach((key) => {
|
|
@@ -3239,16 +3439,17 @@ function collectJsBlockPublicContractErrors(block, path, errors, context) {
|
|
|
3239
3439
|
path: `${path}.${key}`,
|
|
3240
3440
|
ruleId: key === "stepParams" ? "jsBlock-stepParams-unsupported" : "jsBlock-internal-field-unsupported",
|
|
3241
3441
|
message: `flowSurfaces authoring ${path}.${key} is not accepted on public jsBlock blocks; use ${path}.settings.code and ${path}.settings.version instead of internal persisted fields`,
|
|
3242
|
-
details: {
|
|
3442
|
+
details: withJsBlockRepairHint({
|
|
3243
3443
|
key
|
|
3244
|
-
}
|
|
3444
|
+
})
|
|
3245
3445
|
});
|
|
3246
3446
|
});
|
|
3247
3447
|
if (hasOwn(block, "script") && context.authoringActionName !== "applyBlueprint") {
|
|
3248
3448
|
pushAuthoringError(errors, {
|
|
3249
3449
|
path: `${path}.script`,
|
|
3250
3450
|
ruleId: "jsBlock-script-unsupported",
|
|
3251
|
-
message: `flowSurfaces authoring ${path}.script is only supported by applyBlueprint assets.scripts; use ${path}.settings.code for localized jsBlock inline JS code
|
|
3451
|
+
message: `flowSurfaces authoring ${path}.script is only supported by applyBlueprint assets.scripts; use ${path}.settings.code for localized jsBlock inline JS code`,
|
|
3452
|
+
details: withJsBlockRepairHint()
|
|
3252
3453
|
});
|
|
3253
3454
|
}
|
|
3254
3455
|
const settings = _.isPlainObject(block.settings) ? block.settings : void 0;
|
|
@@ -3261,10 +3462,10 @@ function collectJsBlockPublicContractErrors(block, path, errors, context) {
|
|
|
3261
3462
|
path: `${path}.settings.${key}`,
|
|
3262
3463
|
ruleId: "jsBlock-settings-unsupported-key",
|
|
3263
3464
|
message: `flowSurfaces authoring ${path}.settings.${key} is not part of the public jsBlock contract; use ${path}.settings.code and ${path}.settings.version for inline JS code`,
|
|
3264
|
-
details: {
|
|
3465
|
+
details: withJsBlockRepairHint({
|
|
3265
3466
|
key,
|
|
3266
3467
|
allowedKeys: Array.from(JS_BLOCK_ALLOWED_SETTINGS_KEYS)
|
|
3267
|
-
}
|
|
3468
|
+
})
|
|
3268
3469
|
});
|
|
3269
3470
|
});
|
|
3270
3471
|
}
|
|
@@ -3274,9 +3475,9 @@ function collectJsBlockPublicContractErrors(block, path, errors, context) {
|
|
|
3274
3475
|
path: `${path}.script`,
|
|
3275
3476
|
ruleId: "jsBlock-mixed-inline-and-script",
|
|
3276
3477
|
message: `flowSurfaces authoring ${path} cannot combine script asset references with ${inlineKeys.map((key) => `settings.${key}`).join(", ")}; use either applyBlueprint assets.scripts + block.script or inline ${path}.settings.code`,
|
|
3277
|
-
details: {
|
|
3478
|
+
details: withJsBlockRepairHint({
|
|
3278
3479
|
inlineKeys
|
|
3279
|
-
}
|
|
3480
|
+
})
|
|
3280
3481
|
});
|
|
3281
3482
|
}
|
|
3282
3483
|
const hasInlineCode = typeof (settings == null ? void 0 : settings.code) === "string" && !!settings.code.trim();
|
|
@@ -3286,7 +3487,8 @@ function collectJsBlockPublicContractErrors(block, path, errors, context) {
|
|
|
3286
3487
|
pushAuthoringError(errors, {
|
|
3287
3488
|
path,
|
|
3288
3489
|
ruleId: "jsBlock-source-required",
|
|
3289
|
-
message: `flowSurfaces authoring ${path} jsBlock must include inline ${path}.settings.code or, for applyBlueprint only, a block.script asset reference
|
|
3490
|
+
message: `flowSurfaces authoring ${path} jsBlock must include inline ${path}.settings.code or, for applyBlueprint only, a block.script asset reference`,
|
|
3491
|
+
details: withJsBlockRepairHint()
|
|
3290
3492
|
});
|
|
3291
3493
|
}
|
|
3292
3494
|
}
|
|
@@ -3302,16 +3504,17 @@ function collectJsBlockConfigurePublicContractErrors(changes, path, errors) {
|
|
|
3302
3504
|
path: `${path}.${key}`,
|
|
3303
3505
|
ruleId: key === "stepParams" ? "jsBlock-stepParams-unsupported" : "jsBlock-internal-field-unsupported",
|
|
3304
3506
|
message: `flowSurfaces authoring ${path}.${key} is not accepted on public jsBlock configure changes; use ${path}.code and ${path}.version instead of internal persisted fields`,
|
|
3305
|
-
details: {
|
|
3507
|
+
details: withJsBlockRepairHint({
|
|
3306
3508
|
key
|
|
3307
|
-
}
|
|
3509
|
+
})
|
|
3308
3510
|
});
|
|
3309
3511
|
});
|
|
3310
3512
|
if (hasOwn(changes, "script")) {
|
|
3311
3513
|
pushAuthoringError(errors, {
|
|
3312
3514
|
path: `${path}.script`,
|
|
3313
3515
|
ruleId: "jsBlock-script-unsupported",
|
|
3314
|
-
message: `flowSurfaces authoring ${path}.script is only supported by applyBlueprint assets.scripts; use ${path}.code for localized jsBlock configure JS code
|
|
3516
|
+
message: `flowSurfaces authoring ${path}.script is only supported by applyBlueprint assets.scripts; use ${path}.code for localized jsBlock configure JS code`,
|
|
3517
|
+
details: withJsBlockRepairHint()
|
|
3315
3518
|
});
|
|
3316
3519
|
}
|
|
3317
3520
|
const inlineKeys = JS_BLOCK_TOP_LEVEL_JS_KEYS.filter((key) => hasOwn(changes, key));
|
|
@@ -3320,9 +3523,9 @@ function collectJsBlockConfigurePublicContractErrors(changes, path, errors) {
|
|
|
3320
3523
|
path: `${path}.script`,
|
|
3321
3524
|
ruleId: "jsBlock-mixed-inline-and-script",
|
|
3322
3525
|
message: `flowSurfaces authoring ${path} cannot combine script asset references with ${inlineKeys.map((key) => `${path}.${key}`).join(", ")}; use either applyBlueprint assets.scripts + block.script or localized ${path}.code`,
|
|
3323
|
-
details: {
|
|
3526
|
+
details: withJsBlockRepairHint({
|
|
3324
3527
|
inlineKeys
|
|
3325
|
-
}
|
|
3528
|
+
})
|
|
3326
3529
|
});
|
|
3327
3530
|
}
|
|
3328
3531
|
if (!hasOwn(changes, "settings")) {
|
|
@@ -3333,7 +3536,8 @@ function collectJsBlockConfigurePublicContractErrors(changes, path, errors) {
|
|
|
3333
3536
|
pushAuthoringError(errors, {
|
|
3334
3537
|
path: `${path}.settings`,
|
|
3335
3538
|
ruleId: "jsBlock-settings-unsupported-key",
|
|
3336
|
-
message: `flowSurfaces authoring ${path}.settings is not part of the public jsBlock configure contract; use ${path}.code and ${path}.version
|
|
3539
|
+
message: `flowSurfaces authoring ${path}.settings is not part of the public jsBlock configure contract; use ${path}.code and ${path}.version`,
|
|
3540
|
+
details: withJsBlockRepairHint()
|
|
3337
3541
|
});
|
|
3338
3542
|
return;
|
|
3339
3543
|
}
|
|
@@ -3342,9 +3546,9 @@ function collectJsBlockConfigurePublicContractErrors(changes, path, errors) {
|
|
|
3342
3546
|
path: `${path}.settings.${key}`,
|
|
3343
3547
|
ruleId: "jsBlock-settings-unsupported-key",
|
|
3344
3548
|
message: `flowSurfaces authoring ${path}.settings.${key} is not part of the public jsBlock configure contract; use ${path}.${key}`,
|
|
3345
|
-
details: {
|
|
3549
|
+
details: withJsBlockRepairHint({
|
|
3346
3550
|
key
|
|
3347
|
-
}
|
|
3551
|
+
})
|
|
3348
3552
|
});
|
|
3349
3553
|
});
|
|
3350
3554
|
}
|
|
@@ -3376,7 +3580,8 @@ function collectUnsupportedMainBlockSectionErrors(block, blockType, path, errors
|
|
|
3376
3580
|
pushAuthoringError(errors, {
|
|
3377
3581
|
path: `${path}.${section}`,
|
|
3378
3582
|
ruleId: `${blockType}-main-block-unsupported-${section}`,
|
|
3379
|
-
message: `flowSurfaces authoring ${path} ${blockType} main blocks do not support ${section}
|
|
3583
|
+
message: `flowSurfaces authoring ${path} ${blockType} main blocks do not support ${section}`,
|
|
3584
|
+
details: blockType === "calendar" ? buildCalendarMainBlockRepairDetails(section) : blockType === "kanban" ? buildKanbanMainBlockRepairDetails(section) : void 0
|
|
3380
3585
|
});
|
|
3381
3586
|
});
|
|
3382
3587
|
}
|
|
@@ -3393,7 +3598,8 @@ function collectApplyBlueprintKanbanFieldLimitErrors(block, blockType, path, err
|
|
|
3393
3598
|
message: `flowSurfaces authoring ${path}.fields supports at most 2 fields for applyBlueprint kanban main blocks`,
|
|
3394
3599
|
details: {
|
|
3395
3600
|
max: 2,
|
|
3396
|
-
count: block.fields.length
|
|
3601
|
+
count: block.fields.length,
|
|
3602
|
+
repairHint: "Kanban main block fields controls compact card display only. Keep at most 2 fields in applyBlueprint kanban fields, move richer card details to settings.cardPopup, and keep block type kanban."
|
|
3397
3603
|
}
|
|
3398
3604
|
});
|
|
3399
3605
|
}
|
|
@@ -3489,6 +3695,7 @@ async function collectConfigureErrors(values, errors, context) {
|
|
|
3489
3695
|
collectCommentsBlockErrors(changesBlock, hostBlockType, "$.changes", errors, context);
|
|
3490
3696
|
collectRecordHistoryBlockErrors(changesBlock, hostBlockType, "$.changes", errors, context);
|
|
3491
3697
|
collectChartDisplayTitleErrors(changes, hostBlockType, "$.changes", errors);
|
|
3698
|
+
collectTableSettingsErrors(changes, hostBlockType, "$.changes", errors, { directSettings: true });
|
|
3492
3699
|
collectGridCardSettingsErrors(changes, hostBlockType, "$.changes", errors, { directSettings: true });
|
|
3493
3700
|
collectAssignValuesErrors(changes.assignValues, "$.changes.assignValues", errors, changesBlock, context);
|
|
3494
3701
|
collectTriggerWorkflowsErrors(changes.triggerWorkflows, "$.changes.triggerWorkflows", errors);
|
|
@@ -3531,9 +3738,18 @@ function pushAuthoringError(errors, error) {
|
|
|
3531
3738
|
type: "bad_request",
|
|
3532
3739
|
code: "FLOW_SURFACE_AUTHORING_VALIDATION_ERROR",
|
|
3533
3740
|
status: 400,
|
|
3534
|
-
...error
|
|
3741
|
+
...error,
|
|
3742
|
+
message: appendRepairHintToAuthoringMessage(error)
|
|
3535
3743
|
});
|
|
3536
3744
|
}
|
|
3745
|
+
function appendRepairHintToAuthoringMessage(error) {
|
|
3746
|
+
var _a;
|
|
3747
|
+
const repairHint = typeof ((_a = error.details) == null ? void 0 : _a.repairHint) === "string" ? error.details.repairHint.trim() : "";
|
|
3748
|
+
if (!repairHint || error.message.includes(repairHint)) {
|
|
3749
|
+
return error.message;
|
|
3750
|
+
}
|
|
3751
|
+
return `${error.message}. ${repairHint}`;
|
|
3752
|
+
}
|
|
3537
3753
|
function hasOwnDefined(value, key) {
|
|
3538
3754
|
return _.isPlainObject(value) && Object.prototype.hasOwnProperty.call(value, key) && !_.isUndefined(value[key]);
|
|
3539
3755
|
}
|
|
@@ -3696,7 +3912,8 @@ function collectPublicLayoutErrors(layout, layoutPath, knownEntries, kind, error
|
|
|
3696
3912
|
pushAuthoringError(errors, {
|
|
3697
3913
|
path: `${layoutPath}.rows`,
|
|
3698
3914
|
ruleId: "block-layout-single-column",
|
|
3699
|
-
message: `flowSurfaces authoring ${layoutPath}.rows must not place every non-filter block on its own row
|
|
3915
|
+
message: `flowSurfaces authoring ${layoutPath}.rows must not place every non-filter block on its own row`,
|
|
3916
|
+
details: buildTwoColumnLayoutRepairDetails()
|
|
3700
3917
|
});
|
|
3701
3918
|
}
|
|
3702
3919
|
}
|
|
@@ -4140,6 +4357,195 @@ function doesBlockConsumeDefaultFilterAction(block) {
|
|
|
4140
4357
|
const blockType = String((block == null ? void 0 : block.type) || "").trim();
|
|
4141
4358
|
return (0, import_public_data_surface_default_filter.isFlowSurfacePublicDataSurfaceBlockType)(blockType) && !(0, import_template_reference.hasFlowSurfaceTemplateDocument)(block == null ? void 0 : block.template);
|
|
4142
4359
|
}
|
|
4360
|
+
function collectVisibleDataBlockFieldErrors(block, blockType, path, errors, context) {
|
|
4361
|
+
if (!VISIBLE_FIELD_REQUIRED_DATA_BLOCK_TYPES.has(blockType) || (0, import_template_reference.hasFlowSurfaceTemplateReference)(block == null ? void 0 : block.template)) {
|
|
4362
|
+
return;
|
|
4363
|
+
}
|
|
4364
|
+
const fieldEntries = collectVisibleDataBlockFieldEntries(block, path);
|
|
4365
|
+
const validBusinessFieldNames = collectVisibleDataBlockValidBusinessFieldNames(block, context, fieldEntries);
|
|
4366
|
+
if (!fieldEntries.length || !validBusinessFieldNames.length) {
|
|
4367
|
+
const hasBlockFields2 = Array.isArray(block == null ? void 0 : block.fields);
|
|
4368
|
+
const hasBlockFieldGroups2 = Array.isArray(block == null ? void 0 : block.fieldGroups);
|
|
4369
|
+
const fieldConfigPath2 = !hasBlockFields2 && hasBlockFieldGroups2 ? `${path}.fieldGroups` : `${path}.fields`;
|
|
4370
|
+
const fieldConfigLabel2 = !hasBlockFields2 && hasBlockFieldGroups2 ? `${path}.fieldGroups[].fields` : `${path}.fields`;
|
|
4371
|
+
const suggestedFields = pickVisibleDataBlockFieldSuggestions(block, context);
|
|
4372
|
+
pushAuthoringError(errors, {
|
|
4373
|
+
path: fieldConfigPath2,
|
|
4374
|
+
ruleId: "data-block-visible-fields-required",
|
|
4375
|
+
message: `flowSurfaces authoring ${path} ${blockType} block has no valid business fields. Add collection field names to ${fieldConfigLabel2}; defaults.collections.*.fieldGroups only configures generated popups/forms and is not a substitute for visible block columns.`,
|
|
4376
|
+
details: {
|
|
4377
|
+
blockType,
|
|
4378
|
+
collection: getBlockCollectionName(block, context),
|
|
4379
|
+
fieldCount: fieldEntries.length,
|
|
4380
|
+
...suggestedFields.length ? { suggestion: { fields: suggestedFields } } : {}
|
|
4381
|
+
}
|
|
4382
|
+
});
|
|
4383
|
+
return;
|
|
4384
|
+
}
|
|
4385
|
+
if (!VISIBLE_FIELD_MINIMUM_DATA_BLOCK_TYPES.has(blockType)) {
|
|
4386
|
+
return;
|
|
4387
|
+
}
|
|
4388
|
+
if (hasUnknownVisibleDataBlockFieldPath(block, context, fieldEntries)) {
|
|
4389
|
+
return;
|
|
4390
|
+
}
|
|
4391
|
+
const eligibleBusinessFields = collectVisibleDataBlockEligibleBusinessFieldNames(block, context);
|
|
4392
|
+
if (eligibleBusinessFields.length < RICH_COLLECTION_VISIBLE_FIELD_THRESHOLD) {
|
|
4393
|
+
return;
|
|
4394
|
+
}
|
|
4395
|
+
const requiredFieldCount = Math.min(RICH_DATA_BLOCK_VISIBLE_FIELD_MINIMUM, eligibleBusinessFields.length);
|
|
4396
|
+
if (validBusinessFieldNames.length >= requiredFieldCount) {
|
|
4397
|
+
return;
|
|
4398
|
+
}
|
|
4399
|
+
const hasBlockFields = Array.isArray(block == null ? void 0 : block.fields);
|
|
4400
|
+
const hasBlockFieldGroups = Array.isArray(block == null ? void 0 : block.fieldGroups);
|
|
4401
|
+
const fieldConfigPath = !hasBlockFields && hasBlockFieldGroups ? `${path}.fieldGroups` : `${path}.fields`;
|
|
4402
|
+
const fieldConfigLabel = !hasBlockFields && hasBlockFieldGroups ? `${path}.fieldGroups[].fields` : `${path}.fields`;
|
|
4403
|
+
pushAuthoringError(errors, {
|
|
4404
|
+
path: fieldConfigPath,
|
|
4405
|
+
ruleId: "data-block-visible-fields-minimum",
|
|
4406
|
+
message: `flowSurfaces authoring ${path} ${blockType} block only has ${validBusinessFieldNames.length} valid business field(s). Add at least ${requiredFieldCount} collection field names to ${fieldConfigLabel}; defaults.collections.*.fieldGroups only configures generated popups/forms and is not a substitute for visible block columns.`,
|
|
4407
|
+
details: {
|
|
4408
|
+
blockType,
|
|
4409
|
+
collection: getBlockCollectionName(block, context),
|
|
4410
|
+
fieldCount: validBusinessFieldNames.length,
|
|
4411
|
+
requiredFieldCount,
|
|
4412
|
+
eligibleBusinessFieldCount: eligibleBusinessFields.length,
|
|
4413
|
+
suggestion: {
|
|
4414
|
+
fields: eligibleBusinessFields.slice(0, requiredFieldCount)
|
|
4415
|
+
}
|
|
4416
|
+
}
|
|
4417
|
+
});
|
|
4418
|
+
}
|
|
4419
|
+
function collectVisibleDataBlockFieldEntries(block, path) {
|
|
4420
|
+
const entries = [];
|
|
4421
|
+
if (Array.isArray(block == null ? void 0 : block.fields)) {
|
|
4422
|
+
block.fields.forEach((field, index) => {
|
|
4423
|
+
entries.push({ field, path: `${path}.fields[${index}]` });
|
|
4424
|
+
});
|
|
4425
|
+
}
|
|
4426
|
+
if (Array.isArray(block == null ? void 0 : block.fieldGroups)) {
|
|
4427
|
+
block.fieldGroups.forEach((group, groupIndex) => {
|
|
4428
|
+
if (!Array.isArray(group == null ? void 0 : group.fields)) {
|
|
4429
|
+
return;
|
|
4430
|
+
}
|
|
4431
|
+
group.fields.forEach((field, fieldIndex) => {
|
|
4432
|
+
entries.push({
|
|
4433
|
+
field,
|
|
4434
|
+
path: `${path}.fieldGroups[${groupIndex}].fields[${fieldIndex}]`
|
|
4435
|
+
});
|
|
4436
|
+
});
|
|
4437
|
+
});
|
|
4438
|
+
}
|
|
4439
|
+
return entries;
|
|
4440
|
+
}
|
|
4441
|
+
function collectVisibleDataBlockValidBusinessFieldNames(block, context, fieldEntries) {
|
|
4442
|
+
const names = /* @__PURE__ */ new Set();
|
|
4443
|
+
fieldEntries.forEach((entry) => {
|
|
4444
|
+
const fieldPath = getAssociationAwareFieldPathInput(entry.field);
|
|
4445
|
+
if (!fieldPath || fieldPath.startsWith("$") || fieldPath.startsWith("{{")) {
|
|
4446
|
+
return;
|
|
4447
|
+
}
|
|
4448
|
+
if (!isVisibleDataBlockBusinessField(entry.field, block, context)) {
|
|
4449
|
+
return;
|
|
4450
|
+
}
|
|
4451
|
+
names.add((0, import_service_helpers.normalizeFieldPath)(fieldPath));
|
|
4452
|
+
});
|
|
4453
|
+
return Array.from(names);
|
|
4454
|
+
}
|
|
4455
|
+
function hasUnknownVisibleDataBlockFieldPath(block, context, fieldEntries) {
|
|
4456
|
+
const collection = getBlockCollection(block, context);
|
|
4457
|
+
if (!collection) {
|
|
4458
|
+
return false;
|
|
4459
|
+
}
|
|
4460
|
+
return fieldEntries.some((entry) => {
|
|
4461
|
+
const fieldPath = getAssociationAwareFieldPathInput(entry.field);
|
|
4462
|
+
if (!fieldPath || fieldPath.startsWith("$") || fieldPath.startsWith("{{")) {
|
|
4463
|
+
return false;
|
|
4464
|
+
}
|
|
4465
|
+
return !(0, import_service_helpers.resolveFieldFromCollection)(collection, (0, import_service_helpers.normalizeFieldPath)(fieldPath));
|
|
4466
|
+
});
|
|
4467
|
+
}
|
|
4468
|
+
function collectVisibleDataBlockEligibleBusinessFieldNames(block, context) {
|
|
4469
|
+
const collection = getBlockCollection(block, context);
|
|
4470
|
+
if (!collection) {
|
|
4471
|
+
return [];
|
|
4472
|
+
}
|
|
4473
|
+
return (0, import_service_helpers.getCollectionFields)(collection).map((field) => {
|
|
4474
|
+
const name = String((0, import_service_helpers.getFieldName)(field) || "").trim();
|
|
4475
|
+
if (!name || !isVisibleDataBlockMinimumCandidateResolvedField(field, name)) {
|
|
4476
|
+
return "";
|
|
4477
|
+
}
|
|
4478
|
+
return name;
|
|
4479
|
+
}).filter(Boolean);
|
|
4480
|
+
}
|
|
4481
|
+
function isVisibleDataBlockMinimumCandidateResolvedField(field, fieldName) {
|
|
4482
|
+
if (!isVisibleDataBlockBusinessResolvedField(field, fieldName)) {
|
|
4483
|
+
return false;
|
|
4484
|
+
}
|
|
4485
|
+
if ((0, import_service_helpers.isAssociationField)(field)) {
|
|
4486
|
+
return false;
|
|
4487
|
+
}
|
|
4488
|
+
if (/Id$/.test(fieldName)) {
|
|
4489
|
+
return false;
|
|
4490
|
+
}
|
|
4491
|
+
return true;
|
|
4492
|
+
}
|
|
4493
|
+
function isVisibleDataBlockBusinessField(field, block, context) {
|
|
4494
|
+
const fieldPath = getAssociationAwareFieldPathInput(field);
|
|
4495
|
+
if (!fieldPath || fieldPath.startsWith("$") || fieldPath.startsWith("{{")) {
|
|
4496
|
+
return false;
|
|
4497
|
+
}
|
|
4498
|
+
if (_.isPlainObject(field)) {
|
|
4499
|
+
if (field.hidden === true || field.internal === true || field.synthetic === true || field.actionOnly === true) {
|
|
4500
|
+
return false;
|
|
4501
|
+
}
|
|
4502
|
+
const semanticType = String(field.type || field.fieldType || field.interface || "").trim();
|
|
4503
|
+
if (semanticType && NON_BUSINESS_VISIBLE_FIELD_TYPES.has(semanticType)) {
|
|
4504
|
+
return false;
|
|
4505
|
+
}
|
|
4506
|
+
}
|
|
4507
|
+
const collection = getBlockCollection(block, context);
|
|
4508
|
+
if (!collection) {
|
|
4509
|
+
return true;
|
|
4510
|
+
}
|
|
4511
|
+
const resolvedField = (0, import_service_helpers.resolveFieldFromCollection)(collection, (0, import_service_helpers.normalizeFieldPath)(fieldPath));
|
|
4512
|
+
if (!resolvedField) {
|
|
4513
|
+
return true;
|
|
4514
|
+
}
|
|
4515
|
+
const fieldName = (0, import_service_helpers.getFieldName)(resolvedField) || fieldPath;
|
|
4516
|
+
return isVisibleDataBlockBusinessResolvedField(resolvedField, fieldName);
|
|
4517
|
+
}
|
|
4518
|
+
function pickVisibleDataBlockFieldSuggestions(block, context) {
|
|
4519
|
+
const collection = getBlockCollection(block, context);
|
|
4520
|
+
if (!collection) {
|
|
4521
|
+
return [];
|
|
4522
|
+
}
|
|
4523
|
+
return (0, import_service_helpers.getCollectionFields)(collection).map((field) => {
|
|
4524
|
+
const name = String((0, import_service_helpers.getFieldName)(field) || "").trim();
|
|
4525
|
+
if (!name || !isVisibleDataBlockBusinessResolvedField(field, name)) {
|
|
4526
|
+
return "";
|
|
4527
|
+
}
|
|
4528
|
+
return name;
|
|
4529
|
+
}).filter(Boolean).slice(0, 3);
|
|
4530
|
+
}
|
|
4531
|
+
function isVisibleDataBlockBusinessResolvedField(field, fieldName) {
|
|
4532
|
+
var _a;
|
|
4533
|
+
if (NON_BUSINESS_VISIBLE_FIELD_NAMES.has(fieldName)) {
|
|
4534
|
+
return false;
|
|
4535
|
+
}
|
|
4536
|
+
const fieldInterface = String((0, import_service_helpers.getFieldInterface)(field) || "").trim();
|
|
4537
|
+
if (NON_BUSINESS_VISIBLE_FIELD_INTERFACES.has(fieldInterface)) {
|
|
4538
|
+
return false;
|
|
4539
|
+
}
|
|
4540
|
+
const fieldType = String((0, import_service_helpers.getFieldType)(field) || "").trim();
|
|
4541
|
+
if (NON_BUSINESS_VISIBLE_FIELD_TYPES.has(fieldType)) {
|
|
4542
|
+
return false;
|
|
4543
|
+
}
|
|
4544
|
+
if ((field == null ? void 0 : field.hidden) === true || ((_a = field == null ? void 0 : field.options) == null ? void 0 : _a.hidden) === true) {
|
|
4545
|
+
return false;
|
|
4546
|
+
}
|
|
4547
|
+
return true;
|
|
4548
|
+
}
|
|
4143
4549
|
function hasConcreteFilterItem(value) {
|
|
4144
4550
|
if (!_.isPlainObject(value)) {
|
|
4145
4551
|
return false;
|
|
@@ -4768,6 +5174,43 @@ function getCollectionFilterTargetKey(collection) {
|
|
|
4768
5174
|
function normalizeDataSourceKey(value) {
|
|
4769
5175
|
return String(value || "main").trim() || "main";
|
|
4770
5176
|
}
|
|
5177
|
+
function collectTableSettingsErrors(block, blockType, blockPath, errors, options = {}) {
|
|
5178
|
+
if (blockType !== "table" || !_.isPlainObject(block)) {
|
|
5179
|
+
return;
|
|
5180
|
+
}
|
|
5181
|
+
TABLE_INTERNAL_AUTHORING_KEYS.forEach((key) => {
|
|
5182
|
+
if (Object.prototype.hasOwnProperty.call(block, key)) {
|
|
5183
|
+
pushTableSettingsUnsupportedError(errors, `${blockPath}.${key}`, key);
|
|
5184
|
+
}
|
|
5185
|
+
});
|
|
5186
|
+
const hasSettings = _.isPlainObject(block == null ? void 0 : block.settings);
|
|
5187
|
+
if (!hasSettings) {
|
|
5188
|
+
return;
|
|
5189
|
+
}
|
|
5190
|
+
const settings = block.settings;
|
|
5191
|
+
const settingsPath = `${blockPath}.settings`;
|
|
5192
|
+
Object.keys(settings).forEach((key) => {
|
|
5193
|
+
if (TABLE_ALLOWED_SETTINGS_KEYS.has(key) && options.directSettings !== true) {
|
|
5194
|
+
return;
|
|
5195
|
+
}
|
|
5196
|
+
if (options.directSettings === true && !TABLE_INTERNAL_AUTHORING_KEYS.includes(key)) {
|
|
5197
|
+
return;
|
|
5198
|
+
}
|
|
5199
|
+
pushTableSettingsUnsupportedError(errors, `${settingsPath}.${key}`, key);
|
|
5200
|
+
});
|
|
5201
|
+
}
|
|
5202
|
+
function pushTableSettingsUnsupportedError(errors, path, key) {
|
|
5203
|
+
pushAuthoringError(errors, {
|
|
5204
|
+
path,
|
|
5205
|
+
ruleId: "table-settings-unsupported-key",
|
|
5206
|
+
message: `flowSurfaces authoring ${path} is not part of the public table settings contract`,
|
|
5207
|
+
details: {
|
|
5208
|
+
key,
|
|
5209
|
+
allowedKeys: Array.from(TABLE_ALLOWED_SETTINGS_KEYS),
|
|
5210
|
+
repairHint: TABLE_SETTINGS_REPAIR_HINT
|
|
5211
|
+
}
|
|
5212
|
+
});
|
|
5213
|
+
}
|
|
4771
5214
|
function collectGridCardSettingsErrors(block, blockType, blockPath, errors, options = {}) {
|
|
4772
5215
|
const hasSettings = _.isPlainObject(block == null ? void 0 : block.settings);
|
|
4773
5216
|
if (!hasSettings && options.directSettings !== true) {
|
|
@@ -4853,8 +5296,115 @@ function collectActionListErrors(actions, path, errors, block, context = {}, slo
|
|
|
4853
5296
|
if (!Array.isArray(actions)) {
|
|
4854
5297
|
return;
|
|
4855
5298
|
}
|
|
5299
|
+
collectDuplicateAIEmployeeActionErrors(actions, path, errors, block);
|
|
4856
5300
|
actions.forEach((action, index) => collectActionErrors(action, `${path}[${index}]`, errors, block, context, slot));
|
|
4857
5301
|
}
|
|
5302
|
+
function collectDuplicateAIEmployeeActionErrors(actions, path, errors, block) {
|
|
5303
|
+
const seen = /* @__PURE__ */ new Map();
|
|
5304
|
+
actions.forEach((action, index) => {
|
|
5305
|
+
const actionType = resolveAuthoringActionType(action, block);
|
|
5306
|
+
if (actionType !== "aiEmployee" || !_.isPlainObject(action)) {
|
|
5307
|
+
return;
|
|
5308
|
+
}
|
|
5309
|
+
const identity = buildAuthoringAIEmployeeActionIdentity(action.settings);
|
|
5310
|
+
if (!identity) {
|
|
5311
|
+
return;
|
|
5312
|
+
}
|
|
5313
|
+
const currentPath = `${path}[${index}]`;
|
|
5314
|
+
const previousPath = seen.get(identity);
|
|
5315
|
+
if (previousPath) {
|
|
5316
|
+
pushAuthoringError(errors, {
|
|
5317
|
+
path: currentPath,
|
|
5318
|
+
ruleId: "duplicate-ai-employee-action",
|
|
5319
|
+
message: `flowSurfaces authoring ${currentPath} duplicates an existing AI employee action in the same action container; reuse or update the existing button instead of appending another identical AI employee action.`,
|
|
5320
|
+
details: {
|
|
5321
|
+
duplicateOf: previousPath,
|
|
5322
|
+
repairHint: "Remove the duplicate aiEmployee action, or change username, task title/key, or workContext if this is a genuinely different AI employee action."
|
|
5323
|
+
}
|
|
5324
|
+
});
|
|
5325
|
+
return;
|
|
5326
|
+
}
|
|
5327
|
+
seen.set(identity, currentPath);
|
|
5328
|
+
});
|
|
5329
|
+
}
|
|
5330
|
+
function buildAuthoringAIEmployeeActionIdentity(settings) {
|
|
5331
|
+
if (!_.isPlainObject(settings)) {
|
|
5332
|
+
return "";
|
|
5333
|
+
}
|
|
5334
|
+
const username = String(settings.username || "").trim();
|
|
5335
|
+
if (!username) {
|
|
5336
|
+
return "";
|
|
5337
|
+
}
|
|
5338
|
+
return stableSerializeAuthoringValue(normalizeAuthoringAIEmployeePublicSettingsForIdentity(settings));
|
|
5339
|
+
}
|
|
5340
|
+
function normalizeAuthoringAIEmployeePublicSettingsForIdentity(settings) {
|
|
5341
|
+
return {
|
|
5342
|
+
username: String(settings.username || "").trim(),
|
|
5343
|
+
auto: typeof settings.auto === "boolean" ? settings.auto : false,
|
|
5344
|
+
workContext: Object.prototype.hasOwnProperty.call(settings, "workContext") ? normalizeAuthoringAIEmployeeWorkContextForIdentity(settings.workContext) : [{ type: "flow-model", target: "self" }],
|
|
5345
|
+
tasks: normalizeAuthoringAIEmployeeTasksForIdentity(settings.tasks),
|
|
5346
|
+
style: {
|
|
5347
|
+
...AUTHORING_AI_EMPLOYEE_DEFAULT_STYLE,
|
|
5348
|
+
..._.isPlainObject(settings.style) ? _.pick(settings.style, AUTHORING_AI_EMPLOYEE_STYLE_PUBLIC_KEYS) : {}
|
|
5349
|
+
}
|
|
5350
|
+
};
|
|
5351
|
+
}
|
|
5352
|
+
function normalizeAuthoringAIEmployeeWorkContextForIdentity(value) {
|
|
5353
|
+
return _.castArray(value || []).map((item) => {
|
|
5354
|
+
if (!_.isPlainObject(item)) {
|
|
5355
|
+
return item;
|
|
5356
|
+
}
|
|
5357
|
+
const output = _.pick(item, AUTHORING_AI_EMPLOYEE_WORK_CONTEXT_PUBLIC_KEYS);
|
|
5358
|
+
if (!Object.prototype.hasOwnProperty.call(output, "type") || _.isUndefined(output.type) || output.type === null) {
|
|
5359
|
+
output.type = "flow-model";
|
|
5360
|
+
}
|
|
5361
|
+
return output;
|
|
5362
|
+
});
|
|
5363
|
+
}
|
|
5364
|
+
function normalizeAuthoringAIEmployeeTasksForIdentity(value) {
|
|
5365
|
+
return _.castArray(value || []).map((task) => {
|
|
5366
|
+
if (!_.isPlainObject(task)) {
|
|
5367
|
+
return task;
|
|
5368
|
+
}
|
|
5369
|
+
const output = _.pick(task, AUTHORING_AI_EMPLOYEE_TASK_PUBLIC_SETTING_KEYS);
|
|
5370
|
+
if (_.isPlainObject(output.message)) {
|
|
5371
|
+
output.message = _.pick(output.message, AUTHORING_AI_EMPLOYEE_TASK_MESSAGE_PUBLIC_KEYS);
|
|
5372
|
+
if (_.isPlainObject(output.message.workContext)) {
|
|
5373
|
+
output.message.workContext = normalizeAuthoringAIEmployeeWorkContextForIdentity(output.message.workContext);
|
|
5374
|
+
} else if (Array.isArray(output.message.workContext)) {
|
|
5375
|
+
output.message.workContext = normalizeAuthoringAIEmployeeWorkContextForIdentity(output.message.workContext);
|
|
5376
|
+
}
|
|
5377
|
+
}
|
|
5378
|
+
if (Object.prototype.hasOwnProperty.call(task, "prompt") && !Object.prototype.hasOwnProperty.call(output.message || {}, "user")) {
|
|
5379
|
+
output.message = {
|
|
5380
|
+
..._.isPlainObject(output.message) ? output.message : {},
|
|
5381
|
+
user: task.prompt
|
|
5382
|
+
};
|
|
5383
|
+
}
|
|
5384
|
+
if (_.isPlainObject(output.model)) {
|
|
5385
|
+
output.model = _.pick(output.model, AUTHORING_AI_EMPLOYEE_TASK_MODEL_PUBLIC_KEYS);
|
|
5386
|
+
}
|
|
5387
|
+
if (_.isPlainObject(output.skillSettings)) {
|
|
5388
|
+
output.skillSettings = _.pick(output.skillSettings, AUTHORING_AI_EMPLOYEE_SKILL_SETTINGS_PUBLIC_KEYS);
|
|
5389
|
+
if (Array.isArray(output.skillSettings.skills) && !Object.prototype.hasOwnProperty.call(output.skillSettings, "skillsVersion")) {
|
|
5390
|
+
output.skillSettings.skillsVersion = 2;
|
|
5391
|
+
}
|
|
5392
|
+
if (Array.isArray(output.skillSettings.tools) && !Object.prototype.hasOwnProperty.call(output.skillSettings, "toolsVersion")) {
|
|
5393
|
+
output.skillSettings.toolsVersion = 2;
|
|
5394
|
+
}
|
|
5395
|
+
}
|
|
5396
|
+
return output;
|
|
5397
|
+
});
|
|
5398
|
+
}
|
|
5399
|
+
function stableSerializeAuthoringValue(value) {
|
|
5400
|
+
if (Array.isArray(value)) {
|
|
5401
|
+
return `[${value.map((item) => stableSerializeAuthoringValue(item)).join(",")}]`;
|
|
5402
|
+
}
|
|
5403
|
+
if (_.isPlainObject(value)) {
|
|
5404
|
+
return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableSerializeAuthoringValue(value[key])}`).join(",")}}`;
|
|
5405
|
+
}
|
|
5406
|
+
return JSON.stringify(value);
|
|
5407
|
+
}
|
|
4858
5408
|
function resolveAuthoringActionType(action, block) {
|
|
4859
5409
|
const rawType = typeof action === "string" ? action : _.isPlainObject(action) ? action.type : "";
|
|
4860
5410
|
const normalized = String(rawType || "").trim().toLowerCase();
|
|
@@ -5388,7 +5938,8 @@ function collectApplyBlueprintScriptAssetReferenceErrors(spec, path, errors, con
|
|
|
5388
5938
|
pushAuthoringError(errors, {
|
|
5389
5939
|
path: `${path}.script`,
|
|
5390
5940
|
ruleId: "apply-blueprint-script-asset-key-invalid",
|
|
5391
|
-
message: `flowSurfaces applyBlueprint ${publicPath}.script must be a non-empty string asset key; use settings.code for inline JS code
|
|
5941
|
+
message: `flowSurfaces applyBlueprint ${publicPath}.script must be a non-empty string asset key; use settings.code for inline JS code`,
|
|
5942
|
+
details: withJsBlockRepairHint()
|
|
5392
5943
|
});
|
|
5393
5944
|
return;
|
|
5394
5945
|
}
|
|
@@ -5399,14 +5950,18 @@ function collectApplyBlueprintScriptAssetReferenceErrors(spec, path, errors, con
|
|
|
5399
5950
|
pushAuthoringError(errors, {
|
|
5400
5951
|
path: `${path}.script`,
|
|
5401
5952
|
ruleId: "apply-blueprint-script-asset-code-required",
|
|
5402
|
-
message: `flowSurfaces applyBlueprint ${publicPath}.script references script asset '${scriptKey}' without non-empty code; use settings.code for inline JS code
|
|
5953
|
+
message: `flowSurfaces applyBlueprint ${publicPath}.script references script asset '${scriptKey}' without non-empty code; use settings.code for inline JS code`,
|
|
5954
|
+
details: withJsBlockRepairHint({
|
|
5955
|
+
scriptKey
|
|
5956
|
+
})
|
|
5403
5957
|
});
|
|
5404
5958
|
return;
|
|
5405
5959
|
}
|
|
5406
5960
|
pushAuthoringError(errors, {
|
|
5407
5961
|
path: `${path}.script`,
|
|
5408
5962
|
ruleId: "apply-blueprint-script-asset-key-invalid",
|
|
5409
|
-
message: `flowSurfaces applyBlueprint ${publicPath}.script must be a string asset key; use settings.code for inline JS code
|
|
5963
|
+
message: `flowSurfaces applyBlueprint ${publicPath}.script must be a string asset key; use settings.code for inline JS code`,
|
|
5964
|
+
details: withJsBlockRepairHint()
|
|
5410
5965
|
});
|
|
5411
5966
|
}
|
|
5412
5967
|
function hasApplyBlueprintRunnableScriptAssetReference(script, context) {
|