@servicenow/sdk-build-plugins 4.6.1 → 4.7.0
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/acl-plugin.js +0 -3
- package/dist/acl-plugin.js.map +1 -1
- package/dist/applicability-plugin.js +0 -2
- package/dist/applicability-plugin.js.map +1 -1
- package/dist/application-menu-plugin.js +0 -2
- package/dist/application-menu-plugin.js.map +1 -1
- package/dist/arrow-function-plugin.js +0 -1
- package/dist/arrow-function-plugin.js.map +1 -1
- package/dist/atf/test-plugin.js +0 -2
- package/dist/atf/test-plugin.js.map +1 -1
- package/dist/basic-syntax-plugin.js +0 -1
- package/dist/basic-syntax-plugin.js.map +1 -1
- package/dist/business-rule-plugin.js +0 -1
- package/dist/business-rule-plugin.js.map +1 -1
- package/dist/call-expression-plugin.js +0 -1
- package/dist/call-expression-plugin.js.map +1 -1
- package/dist/claims-plugin.js +0 -1
- package/dist/claims-plugin.js.map +1 -1
- package/dist/client-script-plugin.js +0 -1
- package/dist/client-script-plugin.js.map +1 -1
- package/dist/column-plugin.js +24 -7
- package/dist/column-plugin.js.map +1 -1
- package/dist/cross-scope-privilege-plugin.js +0 -1
- package/dist/cross-scope-privilege-plugin.js.map +1 -1
- package/dist/dashboard/dashboard-plugin.js +0 -2
- package/dist/dashboard/dashboard-plugin.js.map +1 -1
- package/dist/data-plugin.js +0 -1
- package/dist/data-plugin.js.map +1 -1
- package/dist/data-policy-plugin.d.ts +2 -0
- package/dist/data-policy-plugin.js +276 -0
- package/dist/data-policy-plugin.js.map +1 -0
- package/dist/email-notification-plugin.js +2 -3
- package/dist/email-notification-plugin.js.map +1 -1
- package/dist/flow/flow-logic/flow-logic-constants.d.ts +2 -0
- package/dist/flow/flow-logic/flow-logic-constants.js +6 -1
- package/dist/flow/flow-logic/flow-logic-constants.js.map +1 -1
- package/dist/flow/flow-logic/flow-logic-diagnostics.js +192 -56
- package/dist/flow/flow-logic/flow-logic-diagnostics.js.map +1 -1
- package/dist/flow/flow-logic/flow-logic-plugin-helpers.d.ts +2 -1
- package/dist/flow/flow-logic/flow-logic-plugin-helpers.js +44 -5
- package/dist/flow/flow-logic/flow-logic-plugin-helpers.js.map +1 -1
- package/dist/flow/flow-logic/flow-logic-plugin.js +279 -29
- package/dist/flow/flow-logic/flow-logic-plugin.js.map +1 -1
- package/dist/flow/flow-logic/flow-logic-shapes.d.ts +15 -0
- package/dist/flow/flow-logic/flow-logic-shapes.js +25 -1
- package/dist/flow/flow-logic/flow-logic-shapes.js.map +1 -1
- package/dist/flow/plugins/approval-rules-plugin.js +0 -1
- package/dist/flow/plugins/approval-rules-plugin.js.map +1 -1
- package/dist/flow/plugins/flow-action-definition-plugin.js +804 -205
- package/dist/flow/plugins/flow-action-definition-plugin.js.map +1 -1
- package/dist/flow/plugins/flow-data-pill-plugin.js +3 -5
- package/dist/flow/plugins/flow-data-pill-plugin.js.map +1 -1
- package/dist/flow/plugins/flow-definition-plugin.js +84 -17
- package/dist/flow/plugins/flow-definition-plugin.js.map +1 -1
- package/dist/flow/plugins/flow-diagnostics-plugin.js +65 -3
- package/dist/flow/plugins/flow-diagnostics-plugin.js.map +1 -1
- package/dist/flow/plugins/flow-instance-plugin.js +13 -5
- package/dist/flow/plugins/flow-instance-plugin.js.map +1 -1
- package/dist/flow/plugins/flow-trigger-instance-plugin.js +0 -1
- package/dist/flow/plugins/flow-trigger-instance-plugin.js.map +1 -1
- package/dist/flow/plugins/inline-script-plugin.js +0 -1
- package/dist/flow/plugins/inline-script-plugin.js.map +1 -1
- package/dist/flow/plugins/step-definition-plugin.js +0 -2
- package/dist/flow/plugins/step-definition-plugin.js.map +1 -1
- package/dist/flow/plugins/step-instance-plugin.js +216 -77
- package/dist/flow/plugins/step-instance-plugin.js.map +1 -1
- package/dist/flow/plugins/trigger-plugin.js +0 -2
- package/dist/flow/plugins/trigger-plugin.js.map +1 -1
- package/dist/flow/plugins/wfa-datapill-plugin.js +0 -1
- package/dist/flow/plugins/wfa-datapill-plugin.js.map +1 -1
- package/dist/flow/utils/datapill-transformer.js +9 -5
- package/dist/flow/utils/datapill-transformer.js.map +1 -1
- package/dist/flow/utils/flow-constants.d.ts +12 -0
- package/dist/flow/utils/flow-constants.js +17 -3
- package/dist/flow/utils/flow-constants.js.map +1 -1
- package/dist/flow/utils/flow-io-to-record.d.ts +1 -1
- package/dist/flow/utils/flow-io-to-record.js +21 -13
- package/dist/flow/utils/flow-io-to-record.js.map +1 -1
- package/dist/flow/utils/flow-pill-utils.d.ts +26 -0
- package/dist/flow/utils/flow-pill-utils.js +50 -0
- package/dist/flow/utils/flow-pill-utils.js.map +1 -0
- package/dist/flow/utils/flow-stage-processor.d.ts +138 -0
- package/dist/flow/utils/flow-stage-processor.js +665 -0
- package/dist/flow/utils/flow-stage-processor.js.map +1 -0
- package/dist/flow/utils/pill-string-parser.js +28 -43
- package/dist/flow/utils/pill-string-parser.js.map +1 -1
- package/dist/flow/utils/utils.d.ts +11 -6
- package/dist/flow/utils/utils.js +37 -28
- package/dist/flow/utils/utils.js.map +1 -1
- package/dist/form-plugin.js +4 -14
- package/dist/form-plugin.js.map +1 -1
- package/dist/html-import-plugin.js +0 -1
- package/dist/html-import-plugin.js.map +1 -1
- package/dist/import-sets-plugin.js +0 -2
- package/dist/import-sets-plugin.js.map +1 -1
- package/dist/inbound-email-action-plugin.js +0 -1
- package/dist/inbound-email-action-plugin.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/instance-scan-plugin.js +0 -7
- package/dist/instance-scan-plugin.js.map +1 -1
- package/dist/json-plugin.js +0 -1
- package/dist/json-plugin.js.map +1 -1
- package/dist/list-plugin.js +4 -1
- package/dist/list-plugin.js.map +1 -1
- package/dist/now-attach-plugin.js +0 -1
- package/dist/now-attach-plugin.js.map +1 -1
- package/dist/now-config-plugin.js +0 -1
- package/dist/now-config-plugin.js.map +1 -1
- package/dist/now-id-plugin.js +0 -1
- package/dist/now-id-plugin.js.map +1 -1
- package/dist/now-include-plugin.js +0 -1
- package/dist/now-include-plugin.js.map +1 -1
- package/dist/now-ref-plugin.js +0 -1
- package/dist/now-ref-plugin.js.map +1 -1
- package/dist/now-unresolved-plugin.js +0 -1
- package/dist/now-unresolved-plugin.js.map +1 -1
- package/dist/package-json-plugin.js +3 -2
- package/dist/package-json-plugin.js.map +1 -1
- package/dist/property-plugin.js +0 -2
- package/dist/property-plugin.js.map +1 -1
- package/dist/record-plugin.d.ts +2 -0
- package/dist/record-plugin.js +2 -2
- package/dist/record-plugin.js.map +1 -1
- package/dist/repack/lint/Rules.d.ts +1 -2
- package/dist/rest-api-plugin.js +6 -5
- package/dist/rest-api-plugin.js.map +1 -1
- package/dist/role-plugin.js +0 -1
- package/dist/role-plugin.js.map +1 -1
- package/dist/schedule-script/scheduled-script-plugin.js +5 -4
- package/dist/schedule-script/scheduled-script-plugin.js.map +1 -1
- package/dist/script-action-plugin.js +0 -2
- package/dist/script-action-plugin.js.map +1 -1
- package/dist/script-include-plugin.js +0 -4
- package/dist/script-include-plugin.js.map +1 -1
- package/dist/server-module-plugin/index.js +2 -3
- package/dist/server-module-plugin/index.js.map +1 -1
- package/dist/service-catalog/catalog-clientscript-plugin.js +0 -2
- package/dist/service-catalog/catalog-clientscript-plugin.js.map +1 -1
- package/dist/service-catalog/catalog-item-plugin.js +0 -2
- package/dist/service-catalog/catalog-item-plugin.js.map +1 -1
- package/dist/service-catalog/catalog-ui-policy-plugin.js +0 -2
- package/dist/service-catalog/catalog-ui-policy-plugin.js.map +1 -1
- package/dist/service-catalog/sc-record-producer-plugin.js +0 -2
- package/dist/service-catalog/sc-record-producer-plugin.js.map +1 -1
- package/dist/service-catalog/variable-set-plugin.js +0 -2
- package/dist/service-catalog/variable-set-plugin.js.map +1 -1
- package/dist/service-portal/angular-provider-plugin.js +0 -2
- package/dist/service-portal/angular-provider-plugin.js.map +1 -1
- package/dist/service-portal/dependency-plugin.js +3 -5
- package/dist/service-portal/dependency-plugin.js.map +1 -1
- package/dist/service-portal/header-footer-plugin.js +3 -5
- package/dist/service-portal/header-footer-plugin.js.map +1 -1
- package/dist/service-portal/menu-plugin.js +0 -1
- package/dist/service-portal/menu-plugin.js.map +1 -1
- package/dist/service-portal/page-plugin.js +0 -1
- package/dist/service-portal/page-plugin.js.map +1 -1
- package/dist/service-portal/page-route-map-plugin.js +0 -1
- package/dist/service-portal/page-route-map-plugin.js.map +1 -1
- package/dist/service-portal/portal-plugin.js +0 -2
- package/dist/service-portal/portal-plugin.js.map +1 -1
- package/dist/service-portal/theme-plugin.js +0 -2
- package/dist/service-portal/theme-plugin.js.map +1 -1
- package/dist/service-portal/widget-plugin.js +3 -5
- package/dist/service-portal/widget-plugin.js.map +1 -1
- package/dist/sla-plugin.js +0 -2
- package/dist/sla-plugin.js.map +1 -1
- package/dist/static-content-plugin.js +32 -3
- package/dist/static-content-plugin.js.map +1 -1
- package/dist/table-plugin.js +102 -11
- package/dist/table-plugin.js.map +1 -1
- package/dist/ui-action-plugin.js +26 -17
- package/dist/ui-action-plugin.js.map +1 -1
- package/dist/ui-page-plugin.js +159 -17
- package/dist/ui-page-plugin.js.map +1 -1
- package/dist/ui-policy-plugin.js +0 -1
- package/dist/ui-policy-plugin.js.map +1 -1
- package/dist/user-preference-plugin.js +0 -2
- package/dist/user-preference-plugin.js.map +1 -1
- package/dist/utils.d.ts +1 -9
- package/dist/utils.js +0 -14
- package/dist/utils.js.map +1 -1
- package/dist/ux-list-menu-config-plugin.js +0 -2
- package/dist/ux-list-menu-config-plugin.js.map +1 -1
- package/dist/view-plugin.js +0 -1
- package/dist/view-plugin.js.map +1 -1
- package/dist/workspace-plugin.js +0 -2
- package/dist/workspace-plugin.js.map +1 -1
- package/package.json +6 -6
- package/src/acl-plugin.ts +1 -4
- package/src/applicability-plugin.ts +0 -2
- package/src/application-menu-plugin.ts +0 -2
- package/src/arrow-function-plugin.ts +0 -1
- package/src/atf/test-plugin.ts +0 -2
- package/src/basic-syntax-plugin.ts +0 -1
- package/src/business-rule-plugin.ts +1 -2
- package/src/call-expression-plugin.ts +0 -1
- package/src/claims-plugin.ts +0 -1
- package/src/client-script-plugin.ts +1 -2
- package/src/column-plugin.ts +29 -9
- package/src/cross-scope-privilege-plugin.ts +1 -2
- package/src/dashboard/dashboard-plugin.ts +0 -2
- package/src/data-plugin.ts +0 -1
- package/src/data-policy-plugin.ts +333 -0
- package/src/email-notification-plugin.ts +8 -4
- package/src/flow/flow-logic/flow-logic-constants.ts +6 -0
- package/src/flow/flow-logic/flow-logic-diagnostics.ts +236 -58
- package/src/flow/flow-logic/flow-logic-plugin-helpers.ts +59 -6
- package/src/flow/flow-logic/flow-logic-plugin.ts +368 -38
- package/src/flow/flow-logic/flow-logic-shapes.ts +25 -0
- package/src/flow/plugins/approval-rules-plugin.ts +0 -1
- package/src/flow/plugins/flow-action-definition-plugin.ts +940 -208
- package/src/flow/plugins/flow-data-pill-plugin.ts +3 -5
- package/src/flow/plugins/flow-definition-plugin.ts +159 -26
- package/src/flow/plugins/flow-diagnostics-plugin.ts +89 -3
- package/src/flow/plugins/flow-instance-plugin.ts +26 -12
- package/src/flow/plugins/flow-trigger-instance-plugin.ts +0 -1
- package/src/flow/plugins/inline-script-plugin.ts +0 -1
- package/src/flow/plugins/step-definition-plugin.ts +0 -2
- package/src/flow/plugins/step-instance-plugin.ts +259 -65
- package/src/flow/plugins/trigger-plugin.ts +0 -2
- package/src/flow/plugins/wfa-datapill-plugin.ts +0 -1
- package/src/flow/utils/datapill-transformer.ts +13 -5
- package/src/flow/utils/flow-constants.ts +19 -1
- package/src/flow/utils/flow-io-to-record.ts +29 -19
- package/src/flow/utils/flow-pill-utils.ts +48 -0
- package/src/flow/utils/flow-stage-processor.ts +831 -0
- package/src/flow/utils/pill-string-parser.ts +29 -47
- package/src/flow/utils/utils.ts +39 -35
- package/src/form-plugin.ts +5 -15
- package/src/html-import-plugin.ts +0 -1
- package/src/import-sets-plugin.ts +0 -2
- package/src/inbound-email-action-plugin.ts +1 -2
- package/src/index.ts +7 -1
- package/src/instance-scan-plugin.ts +0 -7
- package/src/json-plugin.ts +0 -1
- package/src/list-plugin.ts +6 -2
- package/src/now-attach-plugin.ts +0 -1
- package/src/now-config-plugin.ts +0 -1
- package/src/now-id-plugin.ts +0 -1
- package/src/now-include-plugin.ts +0 -1
- package/src/now-ref-plugin.ts +0 -1
- package/src/now-unresolved-plugin.ts +0 -1
- package/src/package-json-plugin.ts +8 -3
- package/src/property-plugin.ts +0 -2
- package/src/record-plugin.ts +3 -3
- package/src/repack/lint/Rules.ts +1 -1
- package/src/rest-api-plugin.ts +7 -6
- package/src/role-plugin.ts +1 -2
- package/src/schedule-script/scheduled-script-plugin.ts +11 -5
- package/src/script-action-plugin.ts +0 -2
- package/src/script-include-plugin.ts +0 -4
- package/src/server-module-plugin/index.ts +2 -3
- package/src/service-catalog/catalog-clientscript-plugin.ts +0 -2
- package/src/service-catalog/catalog-item-plugin.ts +0 -2
- package/src/service-catalog/catalog-ui-policy-plugin.ts +0 -2
- package/src/service-catalog/sc-record-producer-plugin.ts +0 -2
- package/src/service-catalog/variable-set-plugin.ts +0 -2
- package/src/service-portal/angular-provider-plugin.ts +0 -2
- package/src/service-portal/dependency-plugin.ts +0 -2
- package/src/service-portal/header-footer-plugin.ts +0 -2
- package/src/service-portal/menu-plugin.ts +1 -2
- package/src/service-portal/page-plugin.ts +1 -2
- package/src/service-portal/page-route-map-plugin.ts +1 -2
- package/src/service-portal/portal-plugin.ts +0 -2
- package/src/service-portal/theme-plugin.ts +0 -2
- package/src/service-portal/widget-plugin.ts +0 -2
- package/src/sla-plugin.ts +0 -2
- package/src/static-content-plugin.ts +37 -4
- package/src/table-plugin.ts +118 -16
- package/src/ui-action-plugin.ts +30 -17
- package/src/ui-page-plugin.ts +188 -20
- package/src/ui-policy-plugin.ts +1 -2
- package/src/user-preference-plugin.ts +0 -2
- package/src/utils.ts +0 -15
- package/src/ux-list-menu-config-plugin.ts +0 -2
- package/src/view-plugin.ts +0 -1
- package/src/workspace-plugin.ts +0 -2
|
@@ -0,0 +1,665 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.stageDurationToString = stageDurationToString;
|
|
4
|
+
exports.processHeaderStages = processHeaderStages;
|
|
5
|
+
exports.createSubflowStageRecords = createSubflowStageRecords;
|
|
6
|
+
exports.extractStageKey = extractStageKey;
|
|
7
|
+
exports.unwrapCall = unwrapCall;
|
|
8
|
+
exports.collectSubflowDefName = collectSubflowDefName;
|
|
9
|
+
exports.resolveNestedStagesInline = resolveNestedStagesInline;
|
|
10
|
+
exports.resolveNestedStagesForTryCatch = resolveNestedStagesForTryCatch;
|
|
11
|
+
exports.finalizeStageRecords = finalizeStageRecords;
|
|
12
|
+
exports.toSafeIdentifier = toSafeIdentifier;
|
|
13
|
+
exports.buildStageShapes = buildStageShapes;
|
|
14
|
+
exports.buildStageInsertionMap = buildStageInsertionMap;
|
|
15
|
+
exports.createStageCallShape = createStageCallShape;
|
|
16
|
+
exports.insertNestedStageShapes = insertNestedStageShapes;
|
|
17
|
+
const sdk_build_core_1 = require("@servicenow/sdk-build-core");
|
|
18
|
+
const arrow_function_plugin_1 = require("../../arrow-function-plugin");
|
|
19
|
+
const now_id_plugin_1 = require("../../now-id-plugin");
|
|
20
|
+
const flow_constants_1 = require("./flow-constants");
|
|
21
|
+
const flow_logic_constants_1 = require("../flow-logic/flow-logic-constants");
|
|
22
|
+
const utils_1 = require("./utils");
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Duration conversion (Fluent → XML)
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
/**
|
|
27
|
+
* Converts a `Duration({...})` CallExpressionShape from the Fluent API into the
|
|
28
|
+
* `YYYY-MM-DD HH:MM:SS` string stored in `sys_hub_flow_stage.duration`.
|
|
29
|
+
*
|
|
30
|
+
* `Duration()` is an identity function — ObjectShape.get() resolves it with
|
|
31
|
+
* resolve=true by default, but CallExpressionShape.resolve() returns itself
|
|
32
|
+
* (can't evaluate the body). We therefore read with resolve=false to get the
|
|
33
|
+
* raw CallExpressionShape, then delegate to DurationShape for formatting.
|
|
34
|
+
* Falls back to zero duration when absent or not a Duration() call.
|
|
35
|
+
*/
|
|
36
|
+
function stageDurationToString(stageConfig) {
|
|
37
|
+
const raw = stageConfig.get('duration', false);
|
|
38
|
+
const ce = raw.if(sdk_build_core_1.CallExpressionShape) ? raw.as(sdk_build_core_1.CallExpressionShape) : undefined;
|
|
39
|
+
if (ce && ce.getCallee() === sdk_build_core_1.DATA_HELPER_NAMES.DURATION) {
|
|
40
|
+
return new sdk_build_core_1.DurationShape({
|
|
41
|
+
source: raw.getSource(),
|
|
42
|
+
value: ce.getArgument(0).asObject(),
|
|
43
|
+
})
|
|
44
|
+
.toString()
|
|
45
|
+
.getValue();
|
|
46
|
+
}
|
|
47
|
+
return flow_constants_1.STAGE_DEFAULT_DURATION;
|
|
48
|
+
}
|
|
49
|
+
// camelCase API key → snake_case DB key for FlowStageStates fields
|
|
50
|
+
const STATE_KEY_MAP = {
|
|
51
|
+
pending: 'pending',
|
|
52
|
+
inProgress: 'in_progress',
|
|
53
|
+
complete: 'complete',
|
|
54
|
+
error: 'error',
|
|
55
|
+
skipped: 'skipped',
|
|
56
|
+
};
|
|
57
|
+
const DEFAULT_STATES = {
|
|
58
|
+
in_progress: 'In progress',
|
|
59
|
+
complete: 'Completed',
|
|
60
|
+
error: 'Error',
|
|
61
|
+
pending: 'Pending - has not started',
|
|
62
|
+
skipped: 'Skipped',
|
|
63
|
+
};
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
// Phase 1 — Header stage pre-creation
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
/**
|
|
68
|
+
* Reads the `stages: {}` config object from the Flow/Subflow first argument
|
|
69
|
+
* and creates `sys_hub_flow_stage` records for each declared stage.
|
|
70
|
+
*
|
|
71
|
+
* Records are created WITHOUT `component_indexes` — those are computed by
|
|
72
|
+
* `finalizeStageRecords` after the body loop has determined which actions
|
|
73
|
+
* each stage covers.
|
|
74
|
+
*
|
|
75
|
+
* `stage_id` is derived from the record's own coalesce-based sys_id (which the
|
|
76
|
+
* factory makes stable from `flow + value`), so it is deterministic across
|
|
77
|
+
* builds without requiring a separate hash.
|
|
78
|
+
*
|
|
79
|
+
* @returns Map keyed by the stages object property name (e.g. `'triage'`).
|
|
80
|
+
*/
|
|
81
|
+
async function processHeaderStages(flowConfiguration, flowDefinitionRecord, factory) {
|
|
82
|
+
const headerStageRecords = new Map();
|
|
83
|
+
if (!flowConfiguration.has('stages')) {
|
|
84
|
+
return headerStageRecords;
|
|
85
|
+
}
|
|
86
|
+
const stagesObj = flowConfiguration.get('stages').asObject();
|
|
87
|
+
for (const [key, stageVal] of stagesObj.entries()) {
|
|
88
|
+
const stageCE = stageVal.if(sdk_build_core_1.CallExpressionShape) ? stageVal.as(sdk_build_core_1.CallExpressionShape) : undefined;
|
|
89
|
+
if (!stageCE) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const stageConfig = stageCE.getArgument(0).asObject();
|
|
93
|
+
const stageValue = stageConfig.get('value').ifString()?.getValue() ?? '';
|
|
94
|
+
const statesArg = stageConfig.get('states').ifObject()?.asObject();
|
|
95
|
+
let statesJson;
|
|
96
|
+
if (statesArg) {
|
|
97
|
+
statesJson = {};
|
|
98
|
+
for (const [apiKey, dbKey] of Object.entries(STATE_KEY_MAP)) {
|
|
99
|
+
const val = statesArg.get(apiKey).ifString()?.getValue();
|
|
100
|
+
if (val) {
|
|
101
|
+
statesJson[dbKey] = val;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
statesJson = { ...DEFAULT_STATES };
|
|
107
|
+
}
|
|
108
|
+
const stageRecord = await factory.createRecord({
|
|
109
|
+
source: stageCE,
|
|
110
|
+
table: flow_constants_1.FLOW_STAGE_TABLE,
|
|
111
|
+
properties: {
|
|
112
|
+
flow: flowDefinitionRecord.getId().getValue(),
|
|
113
|
+
label: stageConfig.get('label').ifString()?.getValue() ?? '',
|
|
114
|
+
value: stageValue,
|
|
115
|
+
duration: stageDurationToString(stageConfig),
|
|
116
|
+
always_show: stageConfig.get('alwaysShow').ifBoolean()?.getValue() ?? false,
|
|
117
|
+
states: JSON.stringify(statesJson),
|
|
118
|
+
type: 'standard',
|
|
119
|
+
ancestor_array_position: 0,
|
|
120
|
+
ancestor_component_id: '',
|
|
121
|
+
ancestor_stage_id: '',
|
|
122
|
+
ancestral_if_else_logic: '',
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
// stage_id reuses the record's coalesce-based sys_id — stable across builds
|
|
126
|
+
// because sys_hub_flow_stage coalesces on ['flow', 'value'].
|
|
127
|
+
headerStageRecords.set(key, stageRecord.merge({ stage_id: (0, utils_1.sysIdToUuid)(String(stageRecord.getId().getValue())) }));
|
|
128
|
+
}
|
|
129
|
+
return headerStageRecords;
|
|
130
|
+
}
|
|
131
|
+
// ---------------------------------------------------------------------------
|
|
132
|
+
// Phase 2 — Subflow stage creation
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
/**
|
|
135
|
+
* Scans `relatedRecords` for subflow instances with `show_stages=true` and
|
|
136
|
+
* creates a separate `sys_hub_flow_stage` record with `type:'subflow'` for each.
|
|
137
|
+
*
|
|
138
|
+
* These differ from developer-declared stages:
|
|
139
|
+
* - `type` = `'subflow'` (not `'standard'`)
|
|
140
|
+
* - `value` = the subflow instance's `ui_id` (UUID)
|
|
141
|
+
* - `label` = the subflow definition's name (resolved via `subflowDefNames` map)
|
|
142
|
+
* - `component_indexes`= empty — the platform links via `value` (the UUID)
|
|
143
|
+
*
|
|
144
|
+
* @param pendingStagesLength Number of developer-declared stages — subflow stages
|
|
145
|
+
* are ordered after them.
|
|
146
|
+
* @param subflowDefNames Map of subflow definition sys_id → name, built by the
|
|
147
|
+
* caller from the original shapes.
|
|
148
|
+
*/
|
|
149
|
+
async function createSubflowStageRecords(relatedRecords, pendingStagesLength, flowDefinitionRecord, factory, subflowDefNames) {
|
|
150
|
+
const subflowStageRecords = [];
|
|
151
|
+
let subflowStageOrder = pendingStagesLength;
|
|
152
|
+
for (const rec of relatedRecords) {
|
|
153
|
+
if (rec.getTable() !== 'sys_hub_sub_flow_instance_v2') {
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
const showStages = rec.get('show_stages')?.getValue();
|
|
157
|
+
if (showStages !== true && showStages !== 'true') {
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
const uiId = String(rec.get('ui_id')?.getValue() ?? '');
|
|
161
|
+
if (!uiId) {
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const defSysId = String(rec.get('subflow')?.getValue() ?? '');
|
|
165
|
+
const label = subflowDefNames.get(defSysId) ?? '';
|
|
166
|
+
const stageRecord = await factory.createRecord({
|
|
167
|
+
source: flowDefinitionRecord,
|
|
168
|
+
table: flow_constants_1.FLOW_STAGE_TABLE,
|
|
169
|
+
properties: {
|
|
170
|
+
flow: flowDefinitionRecord.getId().getValue(),
|
|
171
|
+
type: 'subflow',
|
|
172
|
+
value: uiId,
|
|
173
|
+
label,
|
|
174
|
+
always_show: false,
|
|
175
|
+
states: '{}',
|
|
176
|
+
component_indexes: '',
|
|
177
|
+
order: subflowStageOrder,
|
|
178
|
+
ancestor_array_position: 0,
|
|
179
|
+
ancestor_component_id: '',
|
|
180
|
+
ancestor_stage_id: '',
|
|
181
|
+
ancestral_if_else_logic: '',
|
|
182
|
+
duration: flow_constants_1.STAGE_DEFAULT_DURATION,
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
// stage_id reuses the record's coalesce-based sys_id — stable because
|
|
186
|
+
// sys_hub_flow_stage coalesces on ['flow', 'value'] and value = uiId.
|
|
187
|
+
subflowStageRecords.push(stageRecord.merge({ stage_id: (0, utils_1.sysIdToUuid)(String(stageRecord.getId().getValue())) }));
|
|
188
|
+
subflowStageOrder++;
|
|
189
|
+
}
|
|
190
|
+
return subflowStageRecords;
|
|
191
|
+
}
|
|
192
|
+
// ---------------------------------------------------------------------------
|
|
193
|
+
// Body scanning — collect stage markers & subflow definition names
|
|
194
|
+
// ---------------------------------------------------------------------------
|
|
195
|
+
/**
|
|
196
|
+
* Extracts the stage key from a `wfa.stage(params.stages.<key>)` call.
|
|
197
|
+
* Returns `undefined` when the argument is not a PropertyAccessShape.
|
|
198
|
+
*/
|
|
199
|
+
function extractStageKey(callExpr) {
|
|
200
|
+
const arg = callExpr.getArgument(0, false);
|
|
201
|
+
if (!arg.if(sdk_build_core_1.PropertyAccessShape)) {
|
|
202
|
+
return undefined;
|
|
203
|
+
}
|
|
204
|
+
return arg.as(sdk_build_core_1.PropertyAccessShape).getLastElement().getName();
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Extracts the NowIdKey (`$id` value) from the config object of an instance call.
|
|
208
|
+
* Checks argument positions 0 and 1 (actions use position 1, flow logic uses 0).
|
|
209
|
+
*/
|
|
210
|
+
function extractNowIdKey(callExpr) {
|
|
211
|
+
for (const idx of [0, 1]) {
|
|
212
|
+
try {
|
|
213
|
+
const a = callExpr.getArgument(idx);
|
|
214
|
+
if (a?.if(sdk_build_core_1.ObjectShape)) {
|
|
215
|
+
const $id = a.as(sdk_build_core_1.ObjectShape).get('$id');
|
|
216
|
+
if ($id?.if(now_id_plugin_1.NowIdShape)) {
|
|
217
|
+
return String($id.as(now_id_plugin_1.NowIdShape).getValue());
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
/* skip */
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return undefined;
|
|
226
|
+
}
|
|
227
|
+
/** Unwrap a statement to the underlying CallExpressionShape if applicable. */
|
|
228
|
+
function unwrapCall(stmt) {
|
|
229
|
+
const inner = stmt instanceof sdk_build_core_1.VariableStatementShape ? stmt.getInitializer() : stmt;
|
|
230
|
+
return inner instanceof sdk_build_core_1.CallExpressionShape ? inner : undefined;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Collects subflow definition name from a `wfa.subflow(defRecord, ...)` call
|
|
234
|
+
* and stores it in the provided map.
|
|
235
|
+
*/
|
|
236
|
+
function collectSubflowDefName(callExpr, subflowDefNames) {
|
|
237
|
+
const defArg = callExpr.getArgument(0);
|
|
238
|
+
if (defArg?.isRecord()) {
|
|
239
|
+
const defRecord = defArg.as(sdk_build_core_1.Record);
|
|
240
|
+
const defSysId = String(defRecord.getId().getValue());
|
|
241
|
+
if (!subflowDefNames.has(defSysId)) {
|
|
242
|
+
subflowDefNames.set(defSysId, String(defRecord.get('name')?.getValue() ?? ''));
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Resolves nested stage indexes inline during the main instance loop.
|
|
248
|
+
*
|
|
249
|
+
* Called when a flow logic instance (if/elseIf/else) is encountered.
|
|
250
|
+
* Builds a local NowIdKey → order map from the flat records (whose orders
|
|
251
|
+
* are known: `baseOrder + index`), then recursively scans the body for
|
|
252
|
+
* `wfa.stage()` calls and pushes resolved entries directly into `pendingStages`.
|
|
253
|
+
*
|
|
254
|
+
* Also collects subflow definition names from nested `wfa.subflow()` calls.
|
|
255
|
+
*/
|
|
256
|
+
function resolveNestedStagesInline(callExpr, flatRecords, baseOrder, headerStageRecords, pendingStages, subflowDefNames, diagnostics) {
|
|
257
|
+
const bodyArg = callExpr.getArgument(1, false);
|
|
258
|
+
if (!bodyArg.if(arrow_function_plugin_1.ArrowFunctionShape)) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
// Build NowIdKey → order map for these flat records
|
|
262
|
+
const orderByNowIdKey = new Map();
|
|
263
|
+
flatRecords.forEach((rec, idx) => {
|
|
264
|
+
const nk = String(rec.getId().getNowIdKey() ?? '');
|
|
265
|
+
if (nk) {
|
|
266
|
+
orderByNowIdKey.set(nk, baseOrder + idx);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
resolveStagesInBody(bodyArg.as(arrow_function_plugin_1.ArrowFunctionShape), headerStageRecords, orderByNowIdKey, pendingStages, subflowDefNames, diagnostics);
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Resolves nested stages inside a `tryCatch(config, { try, catch })` call.
|
|
273
|
+
* Scans both the `try` and `catch` arrow function bodies for `wfa.stage()` calls.
|
|
274
|
+
*/
|
|
275
|
+
function resolveNestedStagesForTryCatch(callExpr, flatRecords, baseOrder, headerStageRecords, pendingStages, subflowDefNames, diagnostics) {
|
|
276
|
+
const handlersArg = callExpr.getArgument(1, false);
|
|
277
|
+
if (!handlersArg.if(sdk_build_core_1.ObjectShape)) {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
// Build NowIdKey → order map for these flat records
|
|
281
|
+
const orderByNowIdKey = new Map();
|
|
282
|
+
flatRecords.forEach((rec, idx) => {
|
|
283
|
+
const nk = String(rec.getId().getNowIdKey() ?? '');
|
|
284
|
+
if (nk) {
|
|
285
|
+
orderByNowIdKey.set(nk, baseOrder + idx);
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
const handlers = handlersArg.as(sdk_build_core_1.ObjectShape);
|
|
289
|
+
const tryHandler = handlers.get('try', false);
|
|
290
|
+
const catchHandler = handlers.get('catch', false);
|
|
291
|
+
if (tryHandler.if(arrow_function_plugin_1.ArrowFunctionShape)) {
|
|
292
|
+
resolveStagesInBody(tryHandler.as(arrow_function_plugin_1.ArrowFunctionShape), headerStageRecords, orderByNowIdKey, pendingStages, subflowDefNames, diagnostics);
|
|
293
|
+
}
|
|
294
|
+
if (catchHandler.if(arrow_function_plugin_1.ArrowFunctionShape)) {
|
|
295
|
+
resolveStagesInBody(catchHandler.as(arrow_function_plugin_1.ArrowFunctionShape), headerStageRecords, orderByNowIdKey, pendingStages, subflowDefNames, diagnostics);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Recursively scans an arrow-function body for:
|
|
300
|
+
* - `wfa.stage()` calls: resolves the order of the *next* non-stage instance
|
|
301
|
+
* from `orderByNowIdKey` and pushes directly to `pendingStages`.
|
|
302
|
+
* - `wfa.subflow()` calls: collects the definition name for showSubflowStage labels.
|
|
303
|
+
*/
|
|
304
|
+
function resolveStagesInBody(body, headerStageRecords, orderByNowIdKey, pendingStages, subflowDefNames, diagnostics) {
|
|
305
|
+
const stmts = body.getStatements();
|
|
306
|
+
for (let i = 0; i < stmts.length; i++) {
|
|
307
|
+
const inner = unwrapCall(stmts[i]);
|
|
308
|
+
if (!inner) {
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
const callee = inner.getCallee();
|
|
312
|
+
// Recurse into flow logic bodies (if / elseIf / else)
|
|
313
|
+
if (callee === flow_logic_constants_1.FLOW_LOGIC.IF || callee === flow_logic_constants_1.FLOW_LOGIC.ELSEIF || callee === flow_logic_constants_1.FLOW_LOGIC.ELSE) {
|
|
314
|
+
const bodyArg = inner.getArgument(1, false);
|
|
315
|
+
if (bodyArg.if(arrow_function_plugin_1.ArrowFunctionShape)) {
|
|
316
|
+
resolveStagesInBody(bodyArg.as(arrow_function_plugin_1.ArrowFunctionShape), headerStageRecords, orderByNowIdKey, pendingStages, subflowDefNames, diagnostics);
|
|
317
|
+
}
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
// Recurse into tryCatch try/catch handler bodies
|
|
321
|
+
if (callee === flow_logic_constants_1.FLOW_LOGIC.TRY_CATCH) {
|
|
322
|
+
const handlersArg = inner.getArgument(1, false);
|
|
323
|
+
if (handlersArg.if(sdk_build_core_1.ObjectShape)) {
|
|
324
|
+
const handlers = handlersArg.as(sdk_build_core_1.ObjectShape);
|
|
325
|
+
const tryHandler = handlers.get('try', false);
|
|
326
|
+
const catchHandler = handlers.get('catch', false);
|
|
327
|
+
if (tryHandler.if(arrow_function_plugin_1.ArrowFunctionShape)) {
|
|
328
|
+
resolveStagesInBody(tryHandler.as(arrow_function_plugin_1.ArrowFunctionShape), headerStageRecords, orderByNowIdKey, pendingStages, subflowDefNames, diagnostics);
|
|
329
|
+
}
|
|
330
|
+
if (catchHandler.if(arrow_function_plugin_1.ArrowFunctionShape)) {
|
|
331
|
+
resolveStagesInBody(catchHandler.as(arrow_function_plugin_1.ArrowFunctionShape), headerStageRecords, orderByNowIdKey, pendingStages, subflowDefNames, diagnostics);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
// Collect subflow definition names from nested bodies
|
|
337
|
+
if (callee === flow_constants_1.SUBFLOW_INSTANCE_API_NAME) {
|
|
338
|
+
collectSubflowDefName(inner, subflowDefNames);
|
|
339
|
+
}
|
|
340
|
+
if (callee !== flow_constants_1.STAGE_API_NAME) {
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
// Extract the stage key and resolve the order of the next non-stage instance
|
|
344
|
+
const key = extractStageKey(inner);
|
|
345
|
+
if (!key) {
|
|
346
|
+
diagnostics.error(inner, 'wfa.stage() argument must be a stage reference like params.stages.<key>.');
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
if (!headerStageRecords.has(key)) {
|
|
350
|
+
diagnostics.error(inner, `wfa.stage() references stage '${key}' which is not declared in the stages config.`);
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
for (let j = i + 1; j < stmts.length; j++) {
|
|
354
|
+
const next = unwrapCall(stmts[j]);
|
|
355
|
+
if (!next || next.getCallee() === flow_constants_1.STAGE_API_NAME) {
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
const nowIdKey = extractNowIdKey(next);
|
|
359
|
+
if (nowIdKey) {
|
|
360
|
+
const recOrder = orderByNowIdKey.get(nowIdKey);
|
|
361
|
+
if (recOrder != null) {
|
|
362
|
+
pendingStages.push({ startActionIndex: recOrder - 1, key });
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
// ---------------------------------------------------------------------------
|
|
370
|
+
// Header stage finalisation
|
|
371
|
+
// ---------------------------------------------------------------------------
|
|
372
|
+
/**
|
|
373
|
+
* Computes `component_indexes` for each developer-declared stage and merges it
|
|
374
|
+
* onto the pre-created header record.
|
|
375
|
+
*
|
|
376
|
+
* Matching is by **key name**: the `key` stored in each `pendingStage` entry is
|
|
377
|
+
* looked up in `headerStageRecords`. This is correct even when the order of
|
|
378
|
+
* `wfa.stage()` calls in the body differs from the declaration order in the
|
|
379
|
+
* stages config header.
|
|
380
|
+
*
|
|
381
|
+
* A stage may appear multiple times in `pendingStages` (e.g. inside both an
|
|
382
|
+
* `if` and an `elseIf` body). All indexes for the same key are collected and
|
|
383
|
+
* joined with `,` into a single `component_indexes` value on one record.
|
|
384
|
+
*
|
|
385
|
+
* @returns Array of finalised stage records ready to be added to `relatedRecords`.
|
|
386
|
+
*/
|
|
387
|
+
function finalizeStageRecords(pendingStages, headerStageRecords) {
|
|
388
|
+
// Group indexes by stage key, preserving encounter order for `order`.
|
|
389
|
+
const indexesByKey = new Map();
|
|
390
|
+
const keyOrder = [];
|
|
391
|
+
for (const entry of pendingStages) {
|
|
392
|
+
if (!entry) {
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
const existing = indexesByKey.get(entry.key);
|
|
396
|
+
if (existing) {
|
|
397
|
+
existing.push(entry.startActionIndex);
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
indexesByKey.set(entry.key, [entry.startActionIndex]);
|
|
401
|
+
keyOrder.push(entry.key);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
const finalised = [];
|
|
405
|
+
for (let i = 0; i < keyOrder.length; i++) {
|
|
406
|
+
const key = keyOrder[i];
|
|
407
|
+
const indexes = indexesByKey.get(key);
|
|
408
|
+
const headerRecord = headerStageRecords.get(key);
|
|
409
|
+
if (headerRecord) {
|
|
410
|
+
finalised.push(headerRecord.merge({ component_indexes: indexes.join(','), order: i }));
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
// Emit declared-but-never-activated stages with empty component_indexes.
|
|
414
|
+
// These are stages declared in the header config that have no wfa.stage()
|
|
415
|
+
// call anywhere in the flow body (e.g. a stage only activated inside a
|
|
416
|
+
// subflow). The platform still needs the sys_hub_flow_stage record so the
|
|
417
|
+
// stage tracker can display it.
|
|
418
|
+
const activatedKeys = new Set(keyOrder);
|
|
419
|
+
let nextOrder = keyOrder.length;
|
|
420
|
+
for (const [key, record] of headerStageRecords) {
|
|
421
|
+
if (!activatedKeys.has(key)) {
|
|
422
|
+
finalised.push(record.merge({ component_indexes: '', order: nextOrder++ }));
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
return finalised;
|
|
426
|
+
}
|
|
427
|
+
// ---------------------------------------------------------------------------
|
|
428
|
+
// toShape helpers — reconstruct stages from DB records back to Fluent shapes
|
|
429
|
+
// ---------------------------------------------------------------------------
|
|
430
|
+
// snake_case DB key → camelCase API key (reverse of STATE_KEY_MAP)
|
|
431
|
+
const REVERSE_STATE_KEY_MAP = {
|
|
432
|
+
pending: 'pending',
|
|
433
|
+
in_progress: 'inProgress',
|
|
434
|
+
complete: 'complete',
|
|
435
|
+
error: 'error',
|
|
436
|
+
skipped: 'skipped',
|
|
437
|
+
};
|
|
438
|
+
/**
|
|
439
|
+
* Converts a stage `value` string (which may contain spaces, dots, underscores
|
|
440
|
+
* etc.) into a valid camelCase JavaScript identifier suitable for use as an
|
|
441
|
+
* object property key and in `params.stages.<key>` property-access expressions.
|
|
442
|
+
*
|
|
443
|
+
* Examples:
|
|
444
|
+
* "Request Cancelled" → "requestCancelled"
|
|
445
|
+
* "Dept. Head Approval" → "deptHeadApproval"
|
|
446
|
+
* "CIO Approval" → "cioApproval"
|
|
447
|
+
* "manager_approval" → "managerApproval"
|
|
448
|
+
* "triage" → "triage"
|
|
449
|
+
*/
|
|
450
|
+
function toSafeIdentifier(value) {
|
|
451
|
+
const parts = value.split(/[^a-zA-Z0-9]+/).filter(Boolean);
|
|
452
|
+
if (parts.length === 0) {
|
|
453
|
+
return value;
|
|
454
|
+
}
|
|
455
|
+
const result = parts
|
|
456
|
+
.map((part, index) => {
|
|
457
|
+
const lower = part.toLowerCase();
|
|
458
|
+
if (index === 0) {
|
|
459
|
+
return lower;
|
|
460
|
+
}
|
|
461
|
+
return lower.charAt(0).toUpperCase() + lower.slice(1);
|
|
462
|
+
})
|
|
463
|
+
.join('');
|
|
464
|
+
// Prefix with underscore if starts with a digit
|
|
465
|
+
return /^\d/.test(result) ? `_${result}` : result;
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Builds `FlowStage()` CallExpressionShapes from `sys_hub_flow_stage` records
|
|
469
|
+
* for the header `stages: {}` config property.
|
|
470
|
+
*
|
|
471
|
+
* Only standard stages are included (type='subflow' stages are skipped).
|
|
472
|
+
*
|
|
473
|
+
* @returns Plain object keyed by stage `value` — e.g. `{ triage: FlowStage({...}) }`.
|
|
474
|
+
*/
|
|
475
|
+
function buildStageShapes(stageRecords) {
|
|
476
|
+
const shapes = {};
|
|
477
|
+
const sorted = [...stageRecords].sort((a, b) => Number(a.get('order')?.getValue() ?? 0) - Number(b.get('order')?.getValue() ?? 0));
|
|
478
|
+
for (const rec of sorted) {
|
|
479
|
+
if (rec.get('type')?.getValue() !== 'standard') {
|
|
480
|
+
continue;
|
|
481
|
+
}
|
|
482
|
+
const value = rec.get('value')?.ifString()?.getValue() ?? '';
|
|
483
|
+
if (!value) {
|
|
484
|
+
continue;
|
|
485
|
+
}
|
|
486
|
+
// Build config properties
|
|
487
|
+
const props = {
|
|
488
|
+
label: rec.get('label')?.ifString()?.getValue() ?? '',
|
|
489
|
+
value,
|
|
490
|
+
};
|
|
491
|
+
// Duration — only emit when not the default (zero duration)
|
|
492
|
+
const durationStr = rec.get('duration')?.ifString()?.getValue() ?? flow_constants_1.STAGE_DEFAULT_DURATION;
|
|
493
|
+
if (durationStr && durationStr !== flow_constants_1.STAGE_DEFAULT_DURATION) {
|
|
494
|
+
try {
|
|
495
|
+
props['duration'] = sdk_build_core_1.DurationShape.from(rec, sdk_build_core_1.Shape.from(rec, durationStr).asString());
|
|
496
|
+
}
|
|
497
|
+
catch {
|
|
498
|
+
/* keep default */
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
// alwaysShow
|
|
502
|
+
const alwaysShow = rec.get('always_show')?.getValue();
|
|
503
|
+
if (alwaysShow === true || alwaysShow === 'true') {
|
|
504
|
+
props['alwaysShow'] = true;
|
|
505
|
+
}
|
|
506
|
+
// states — only emit when they differ from platform defaults
|
|
507
|
+
const statesStr = rec.get('states')?.ifString()?.getValue();
|
|
508
|
+
if (statesStr) {
|
|
509
|
+
try {
|
|
510
|
+
const parsed = JSON.parse(statesStr);
|
|
511
|
+
const isDefault = Object.keys(parsed).length === Object.keys(DEFAULT_STATES).length &&
|
|
512
|
+
Object.entries(parsed).every(([k, v]) => DEFAULT_STATES[k] === v);
|
|
513
|
+
if (!isDefault) {
|
|
514
|
+
const stateProps = {};
|
|
515
|
+
for (const [dbKey, label] of Object.entries(parsed)) {
|
|
516
|
+
const apiKey = REVERSE_STATE_KEY_MAP[dbKey];
|
|
517
|
+
if (apiKey && label) {
|
|
518
|
+
stateProps[apiKey] = label;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
if (Object.keys(stateProps).length > 0) {
|
|
522
|
+
props['states'] = sdk_build_core_1.Shape.from(rec, stateProps).asObject();
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
catch {
|
|
527
|
+
/* skip malformed JSON */
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
let key = toSafeIdentifier(value);
|
|
531
|
+
if (key in shapes) {
|
|
532
|
+
let suffix = 2;
|
|
533
|
+
while (`${key}_${suffix}` in shapes) {
|
|
534
|
+
suffix++;
|
|
535
|
+
}
|
|
536
|
+
key = `${key}_${suffix}`;
|
|
537
|
+
}
|
|
538
|
+
shapes[key] = new sdk_build_core_1.CallExpressionShape({
|
|
539
|
+
source: rec,
|
|
540
|
+
callee: flow_constants_1.FLOW_STAGE_CALLEE,
|
|
541
|
+
args: [new sdk_build_core_1.ObjectShape({ source: rec, properties: props })],
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
return shapes;
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* Parses `component_indexes` from stage records and builds a map from
|
|
548
|
+
* action record order to the stage key(s) that should be inserted before it.
|
|
549
|
+
*
|
|
550
|
+
* component_index N means the stage belongs before the record with order = N + 1.
|
|
551
|
+
*/
|
|
552
|
+
function buildStageInsertionMap(stageRecords) {
|
|
553
|
+
const map = new Map();
|
|
554
|
+
for (const rec of stageRecords) {
|
|
555
|
+
if (rec.get('type')?.getValue() !== 'standard') {
|
|
556
|
+
continue;
|
|
557
|
+
}
|
|
558
|
+
const value = rec.get('value')?.ifString()?.getValue() ?? '';
|
|
559
|
+
if (!value) {
|
|
560
|
+
continue;
|
|
561
|
+
}
|
|
562
|
+
const indexes = rec.get('component_indexes')?.ifString()?.getValue() ?? '';
|
|
563
|
+
if (!indexes) {
|
|
564
|
+
continue;
|
|
565
|
+
}
|
|
566
|
+
for (const part of indexes.split(',')) {
|
|
567
|
+
const actionOrder = parseInt(part.trim(), 10) + 1;
|
|
568
|
+
if (isNaN(actionOrder)) {
|
|
569
|
+
continue;
|
|
570
|
+
}
|
|
571
|
+
const existing = map.get(actionOrder) ?? [];
|
|
572
|
+
existing.push(toSafeIdentifier(value));
|
|
573
|
+
map.set(actionOrder, existing);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
return map;
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* Creates a `wfa.stage(params.stages.<key>)` CallExpressionShape.
|
|
580
|
+
*/
|
|
581
|
+
function createStageCallShape(stageKey, paramName, source) {
|
|
582
|
+
return new sdk_build_core_1.CallExpressionShape({
|
|
583
|
+
source,
|
|
584
|
+
callee: flow_constants_1.STAGE_API_NAME,
|
|
585
|
+
args: [
|
|
586
|
+
new sdk_build_core_1.PropertyAccessShape({
|
|
587
|
+
source,
|
|
588
|
+
elements: [paramName, 'stages', stageKey],
|
|
589
|
+
}),
|
|
590
|
+
],
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Scans `stmts` for records whose order matches an entry in `stageInsertionMap`
|
|
595
|
+
* and splices `wfa.stage()` calls before them. Matched entries are removed from
|
|
596
|
+
* the map so they aren't inserted twice.
|
|
597
|
+
*/
|
|
598
|
+
function insertStagesIntoStatements(stmts, stageInsertionMap, paramName, source, orderFn) {
|
|
599
|
+
const insertions = [];
|
|
600
|
+
for (let i = 0; i < stmts.length; i++) {
|
|
601
|
+
const stmtSource = stmts[i].getSource();
|
|
602
|
+
if (!(stmtSource instanceof sdk_build_core_1.Record)) {
|
|
603
|
+
continue;
|
|
604
|
+
}
|
|
605
|
+
const recOrder = orderFn(stmtSource);
|
|
606
|
+
const keys = stageInsertionMap.get(recOrder);
|
|
607
|
+
if (keys && keys.length > 0) {
|
|
608
|
+
insertions.push({ before: i, keys });
|
|
609
|
+
stageInsertionMap.delete(recOrder);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
for (let j = insertions.length - 1; j >= 0; j--) {
|
|
613
|
+
const { before, keys } = insertions[j];
|
|
614
|
+
const stageCalls = keys.map((k) => createStageCallShape(k, paramName, source));
|
|
615
|
+
stmts.splice(before, 0, ...stageCalls);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* Walks through an array of body shapes and mutates flow logic bodies
|
|
620
|
+
* (if/elseIf/else/tryCatch) to insert `wfa.stage()` calls at positions identified
|
|
621
|
+
* by `stageInsertionMap`.
|
|
622
|
+
*
|
|
623
|
+
* Matched entries are removed from the map so they aren't inserted twice.
|
|
624
|
+
* Call this AFTER top-level stages have been handled.
|
|
625
|
+
*/
|
|
626
|
+
function insertNestedStageShapes(shapes, stageInsertionMap, paramName, orderFn) {
|
|
627
|
+
for (const shape of shapes) {
|
|
628
|
+
const callExpr = shape instanceof sdk_build_core_1.VariableStatementShape ? shape.getInitializer() : shape;
|
|
629
|
+
if (!(callExpr instanceof sdk_build_core_1.CallExpressionShape)) {
|
|
630
|
+
continue;
|
|
631
|
+
}
|
|
632
|
+
const callee = callExpr.getCallee();
|
|
633
|
+
// Recurse into tryCatch try/catch handler bodies
|
|
634
|
+
if (callee === flow_logic_constants_1.FLOW_LOGIC.TRY_CATCH) {
|
|
635
|
+
const handlersArg = callExpr.getArgument(1, false);
|
|
636
|
+
if (handlersArg.if(sdk_build_core_1.ObjectShape)) {
|
|
637
|
+
const handlers = handlersArg.as(sdk_build_core_1.ObjectShape);
|
|
638
|
+
for (const handlerKey of ['try', 'catch']) {
|
|
639
|
+
const handler = handlers.get(handlerKey, false);
|
|
640
|
+
if (handler.if(arrow_function_plugin_1.ArrowFunctionShape)) {
|
|
641
|
+
const handlerBody = handler.as(arrow_function_plugin_1.ArrowFunctionShape);
|
|
642
|
+
const handlerStmts = handlerBody.getStatements();
|
|
643
|
+
insertStagesIntoStatements(handlerStmts, stageInsertionMap, paramName, handlerBody.getSource(), orderFn);
|
|
644
|
+
insertNestedStageShapes(handlerStmts, stageInsertionMap, paramName, orderFn);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
continue;
|
|
649
|
+
}
|
|
650
|
+
// Only recurse into conditional bodies
|
|
651
|
+
if (callee !== flow_logic_constants_1.FLOW_LOGIC.IF && callee !== flow_logic_constants_1.FLOW_LOGIC.ELSEIF && callee !== flow_logic_constants_1.FLOW_LOGIC.ELSE) {
|
|
652
|
+
continue;
|
|
653
|
+
}
|
|
654
|
+
const bodyArg = callExpr.getArgument(1, false);
|
|
655
|
+
if (!bodyArg.if(arrow_function_plugin_1.ArrowFunctionShape)) {
|
|
656
|
+
continue;
|
|
657
|
+
}
|
|
658
|
+
const body = bodyArg.as(arrow_function_plugin_1.ArrowFunctionShape);
|
|
659
|
+
const stmts = body.getStatements(); // mutable reference
|
|
660
|
+
insertStagesIntoStatements(stmts, stageInsertionMap, paramName, body.getSource(), orderFn);
|
|
661
|
+
// Recurse into children for deeper nesting
|
|
662
|
+
insertNestedStageShapes(stmts, stageInsertionMap, paramName, orderFn);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
//# sourceMappingURL=flow-stage-processor.js.map
|