biz-a-cli 2.3.80-15227 → 2.3.80-15230
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/engine/bpm/bpm-agent.js
CHANGED
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
executeEffect,
|
|
3
3
|
executeTimerJob,
|
|
4
4
|
executeBackgroundTransition,
|
|
5
|
+
initiate,
|
|
5
6
|
} from "./workflow-runtime.js";
|
|
6
7
|
import {
|
|
7
8
|
queryData,
|
|
@@ -65,6 +66,18 @@ export function initBpmAgent(broker, services = "") {
|
|
|
65
66
|
}
|
|
66
67
|
});
|
|
67
68
|
|
|
69
|
+
broker.on("bpm:initiate", async (payload) => {
|
|
70
|
+
try {
|
|
71
|
+
const { entityType, entityId } = payload || {};
|
|
72
|
+
await initiate({ ...payload, apiConfig: getGlobalConfig() });
|
|
73
|
+
console.log(
|
|
74
|
+
`[BPM Agent] Initiated workflow for ${entityType} ${entityId}.`,
|
|
75
|
+
);
|
|
76
|
+
} catch (error) {
|
|
77
|
+
console.error(`[BPM Agent] Initiate Failed:`, error.message);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
68
81
|
broker.on("bpm:effect", async (payload, ackCallback) => {
|
|
69
82
|
if (!payload || (!payload.id && !payload.ID)) {
|
|
70
83
|
pollEffects();
|
|
@@ -1227,10 +1227,25 @@ export async function executeEffect(effectData) {
|
|
|
1227
1227
|
|
|
1228
1228
|
if (effectType === "CLI_SCRIPT") {
|
|
1229
1229
|
console.log(`[BPM Engine] Bridging Script: ${eventName}`);
|
|
1230
|
+
// Auto-inject the effect's own instanceId so the CLI script knows which workflow
|
|
1231
|
+
// instance triggered it (per the BPM spec's payload-injection contract). Without
|
|
1232
|
+
// this, a script that keys off scriptData.instanceId has no way to identify the
|
|
1233
|
+
// instance when the effect carries no payloadTemplate.
|
|
1234
|
+
const scriptData = Object.assign(
|
|
1235
|
+
{},
|
|
1236
|
+
parsedPayload && typeof parsedPayload === "object" && !Array.isArray(parsedPayload)
|
|
1237
|
+
? parsedPayload
|
|
1238
|
+
: {},
|
|
1239
|
+
{
|
|
1240
|
+
instanceId:
|
|
1241
|
+
effectData.sys$bpm_wf_instance_id ||
|
|
1242
|
+
effectData.SYS$BPM_WF_INSTANCE_ID,
|
|
1243
|
+
},
|
|
1244
|
+
);
|
|
1230
1245
|
const scriptResult = await execCLIScriptWorker(
|
|
1231
1246
|
apiConfig,
|
|
1232
1247
|
eventName,
|
|
1233
|
-
|
|
1248
|
+
scriptData,
|
|
1234
1249
|
);
|
|
1235
1250
|
|
|
1236
1251
|
// --- if cliScript of Effect need to run executeTransition ---
|
|
@@ -429,12 +429,10 @@ const isFirebird25NotNullCheckForColumn = (check, columnName) => {
|
|
|
429
429
|
.replace(/^CHECK\s*/i, "")
|
|
430
430
|
.replace(/"/g, "")
|
|
431
431
|
.replace(/\s+/g, "")
|
|
432
|
-
.toUpperCase()
|
|
432
|
+
.toUpperCase()
|
|
433
|
+
.replace(/^\(+|\)+$/g, "");
|
|
433
434
|
const normalizedColumnName = toConstraintIdentifierPart(columnName);
|
|
434
|
-
return
|
|
435
|
-
expression === `${normalizedColumnName}ISNOTNULL` ||
|
|
436
|
-
expression === `(${normalizedColumnName}ISNOTNULL)`
|
|
437
|
-
);
|
|
435
|
+
return expression === `${normalizedColumnName}ISNOTNULL`;
|
|
438
436
|
};
|
|
439
437
|
|
|
440
438
|
const resolveFirebird25NotNullCheckState = (tableName, columnName, actual) => {
|
|
@@ -451,6 +449,9 @@ const resolveFirebird25NotNullCheckState = (tableName, columnName, actual) => {
|
|
|
451
449
|
};
|
|
452
450
|
};
|
|
453
451
|
|
|
452
|
+
const getNotNullChecksForColumn = (actual, columnName) =>
|
|
453
|
+
(actual.checks ?? []).filter((check) => isFirebird25NotNullCheckForColumn(check, columnName));
|
|
454
|
+
|
|
454
455
|
const describeColumnDependency = (dependency) => {
|
|
455
456
|
const dependentName = dependency.dependentName || "unnamed object";
|
|
456
457
|
return `dependency ${dependentName} (type ${dependency.dependentType})`;
|
|
@@ -588,11 +589,34 @@ export const buildTableSyncPlan = (expected, actual, options) => {
|
|
|
588
589
|
const migrationMode = options?.migrationMode ?? "safe";
|
|
589
590
|
const allowDestructiveChanges = migrationMode === "aggressive";
|
|
590
591
|
const compare = compareTableStructure(expected, actual);
|
|
591
|
-
|
|
592
|
+
const expectedColumnsForCleanup = new Map(
|
|
593
|
+
(expected.columns ?? []).map((column) => [column.name.trim().toUpperCase(), column]),
|
|
594
|
+
);
|
|
595
|
+
const actualColumnsForCleanup = new Map(
|
|
596
|
+
(actual.columns ?? []).map((column) => [column.name.trim().toUpperCase(), column]),
|
|
597
|
+
);
|
|
598
|
+
const notNullChecksToDrop = [];
|
|
599
|
+
const seenNotNullChecks = new Set();
|
|
600
|
+
for (const [columnName, expectedColumn] of expectedColumnsForCleanup.entries()) {
|
|
601
|
+
if (expectedColumn.nullable === false || !actualColumnsForCleanup.has(columnName)) {
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
604
|
+
for (const check of getNotNullChecksForColumn(actual, expectedColumn.name)) {
|
|
605
|
+
const constraintName = String(check?.name ?? "").trim();
|
|
606
|
+
const constraintKey = constraintName.toUpperCase();
|
|
607
|
+
if (constraintName && !seenNotNullChecks.has(constraintKey)) {
|
|
608
|
+
seenNotNullChecks.add(constraintKey);
|
|
609
|
+
notNullChecksToDrop.push(constraintName);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
if (compare.isSame && notNullChecksToDrop.length === 0) {
|
|
592
614
|
return { statements: [], warnings: [], differences: [] };
|
|
593
615
|
}
|
|
594
616
|
|
|
595
|
-
const statements =
|
|
617
|
+
const statements = notNullChecksToDrop.map(
|
|
618
|
+
(constraintName) => `ALTER TABLE ${expected.name} DROP CONSTRAINT ${constraintName};`,
|
|
619
|
+
);
|
|
596
620
|
const warnings = [];
|
|
597
621
|
|
|
598
622
|
const expectedColumns = new Map();
|
|
@@ -1236,6 +1260,11 @@ const buildEntityTable = (entityName, entity, defaultDbIndex) => {
|
|
|
1236
1260
|
const columns = attributeEntries.map((entry) => entry.column);
|
|
1237
1261
|
ensureIdentityPrimaryColumn(columns, entity?.identity);
|
|
1238
1262
|
const primaryKey = resolvePrimaryKey(entity, columns);
|
|
1263
|
+
const identityPrimaryKey = toDbName(entity?.identity?.primaryKey ?? "");
|
|
1264
|
+
const identityColumn = columns.find((column) => column.name === identityPrimaryKey);
|
|
1265
|
+
if (identityColumn) {
|
|
1266
|
+
identityColumn.nullable = false;
|
|
1267
|
+
}
|
|
1239
1268
|
const uniqueKeys = buildUniqueKeys(tableName, attributeEntries, primaryKey);
|
|
1240
1269
|
const indexes = buildAttributeIndexes(tableName, attributeEntries, primaryKey, uniqueKeys);
|
|
1241
1270
|
|
|
@@ -627,18 +627,52 @@ export const publishApplicationConfig = async (payload = {}, argv = {}) => {
|
|
|
627
627
|
}
|
|
628
628
|
const parsedApplicationConfig = parseConfigData(appRow.data) ?? {};
|
|
629
629
|
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
630
|
+
/* An app bundle publish is a full replace (addApp() rebuilds the whole bundle from scratch every call), so
|
|
631
|
+
template.js scaffolding must be generated for EVERY domain registered in application.js's `domains` map, not
|
|
632
|
+
just whichever one this particular publish call cares about -- otherwise every other domain's screens silently
|
|
633
|
+
drop out of the bundle on the next publish. Real incident: Supertail's own runtime-domain publish passed only
|
|
634
|
+
`supertailruntime` as the domain to scan, which wiped out all 21 of supertailsetup's template files (they'd
|
|
635
|
+
only ever been generated because the Admin's own editor happened to have supertailsetup loaded). */
|
|
636
|
+
const domainMap =
|
|
637
|
+
parsedApplicationConfig?.domains && typeof parsedApplicationConfig.domains === "object" ? parsedApplicationConfig.domains : {};
|
|
638
|
+
const domainsToScan = new Map();
|
|
639
|
+
for (const [domainKey, domainDef] of Object.entries(domainMap)) {
|
|
640
|
+
const source = String(domainDef?.source ?? "").trim();
|
|
641
|
+
const [sourceName, sourceVersion] = source.split("@").map((part) => String(part ?? "").trim());
|
|
642
|
+
if (sourceName && sourceVersion) {
|
|
643
|
+
domainsToScan.set(domainKey, { domainConfigName: sourceName, domainConfigVersion: sourceVersion });
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
const explicitDomainConfigName = String(payload?.domainConfigName ?? "").trim();
|
|
647
|
+
const explicitDomainConfigVersion = String(payload?.domainConfigVersion ?? "").trim();
|
|
648
|
+
if (explicitDomainConfigName && explicitDomainConfigVersion && !domainsToScan.has(explicitDomainConfigName)) {
|
|
649
|
+
domainsToScan.set(explicitDomainConfigName, { domainConfigName: explicitDomainConfigName, domainConfigVersion: explicitDomainConfigVersion });
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
const mergedFileList = [];
|
|
653
|
+
const seenFileNames = new Set();
|
|
654
|
+
const addFilesToMergedList = (fileList) => {
|
|
655
|
+
for (const file of fileList) {
|
|
656
|
+
if (seenFileNames.has(file.name)) {
|
|
657
|
+
continue;
|
|
658
|
+
}
|
|
659
|
+
seenFileNames.add(file.name);
|
|
660
|
+
mergedFileList.push(file);
|
|
661
|
+
}
|
|
662
|
+
};
|
|
663
|
+
|
|
664
|
+
if (domainsToScan.size === 0) {
|
|
665
|
+
addFilesToMergedList(buildPublishBodyFromConfigs(parsedApplicationConfig, {}, "").fileList);
|
|
666
|
+
} else {
|
|
667
|
+
for (const [domainKey, { domainConfigName, domainConfigVersion }] of domainsToScan) {
|
|
668
|
+
const domainRows = await queryData(getConfigByNameVersionParameters(domainConfigName, domainConfigVersion), config);
|
|
669
|
+
const domainRow = domainRows?.[0];
|
|
670
|
+
const parsedDomainConfig = domainRow?.data ? (parseConfigData(domainRow.data) ?? {}) : {};
|
|
671
|
+
addFilesToMergedList(buildPublishBodyFromConfigs(parsedApplicationConfig, parsedDomainConfig, domainKey).fileList);
|
|
638
672
|
}
|
|
639
673
|
}
|
|
640
674
|
|
|
641
|
-
const publishBody =
|
|
675
|
+
const publishBody = { verbose: false, fileList: mergedFileList };
|
|
642
676
|
|
|
643
677
|
const response = await publishApp(
|
|
644
678
|
{
|