@eventcatalog/cli 0.5.0 → 0.5.2
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/cli/index.js +128 -13
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +128 -13
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli-docs.js +1 -1
- package/dist/cli-docs.js.map +1 -1
- package/dist/cli-docs.mjs +1 -1
- package/dist/cli-docs.mjs.map +1 -1
- package/package.json +3 -3
package/dist/cli/index.js
CHANGED
|
@@ -1253,8 +1253,10 @@ var import_node_fs5 = __toESM(require("fs"));
|
|
|
1253
1253
|
var import_node_path4 = __toESM(require("path"));
|
|
1254
1254
|
var import_js_yaml = __toESM(require("js-yaml"));
|
|
1255
1255
|
var loadGovernanceConfig = (catalogDir) => {
|
|
1256
|
-
const
|
|
1257
|
-
|
|
1256
|
+
const yamlPath = import_node_path4.default.join(catalogDir, "governance.yaml");
|
|
1257
|
+
const ymlPath = import_node_path4.default.join(catalogDir, "governance.yml");
|
|
1258
|
+
const configPath = import_node_fs5.default.existsSync(yamlPath) ? yamlPath : import_node_fs5.default.existsSync(ymlPath) ? ymlPath : null;
|
|
1259
|
+
if (!configPath) {
|
|
1258
1260
|
return { rules: [] };
|
|
1259
1261
|
}
|
|
1260
1262
|
const content = import_node_fs5.default.readFileSync(configPath, "utf-8");
|
|
@@ -1285,17 +1287,82 @@ var buildServiceMessageSets = (snapshot2) => {
|
|
|
1285
1287
|
}
|
|
1286
1288
|
return { produces, consumes };
|
|
1287
1289
|
};
|
|
1288
|
-
var
|
|
1290
|
+
var matchesResourceId = (resourceId, serviceId, resources, messageSets) => {
|
|
1289
1291
|
return resources.some((r) => {
|
|
1290
1292
|
if (r === "*") return true;
|
|
1291
|
-
if (r.startsWith("service:"))
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1293
|
+
if (r.startsWith("service:")) {
|
|
1294
|
+
if (serviceId) return serviceId === r.slice(8);
|
|
1295
|
+
return messageSets?.produces.get(r.slice(8))?.has(resourceId) ?? false;
|
|
1296
|
+
}
|
|
1297
|
+
if (r.startsWith("message:")) return resourceId === r.slice(8);
|
|
1298
|
+
if (r.startsWith("produces:")) return messageSets?.produces.get(r.slice(9))?.has(resourceId) ?? false;
|
|
1299
|
+
if (r.startsWith("consumes:")) return messageSets?.consumes.get(r.slice(9))?.has(resourceId) ?? false;
|
|
1295
1300
|
return false;
|
|
1296
1301
|
});
|
|
1297
1302
|
};
|
|
1298
1303
|
var REMOVED_TRIGGERS = /* @__PURE__ */ new Set(["consumer_removed", "producer_removed"]);
|
|
1304
|
+
var MESSAGE_RESOURCE_TYPES = /* @__PURE__ */ new Set(["event", "command", "query"]);
|
|
1305
|
+
var buildMessageMap = (snapshot2) => {
|
|
1306
|
+
const map = /* @__PURE__ */ new Map();
|
|
1307
|
+
for (const msg of snapshot2.resources.messages.events) map.set(msg.id, msg);
|
|
1308
|
+
for (const msg of snapshot2.resources.messages.commands) map.set(msg.id, msg);
|
|
1309
|
+
for (const msg of snapshot2.resources.messages.queries) map.set(msg.id, msg);
|
|
1310
|
+
return map;
|
|
1311
|
+
};
|
|
1312
|
+
var buildProducerIndex = (snapshot2) => {
|
|
1313
|
+
const index = /* @__PURE__ */ new Map();
|
|
1314
|
+
for (const service of snapshot2.resources.services) {
|
|
1315
|
+
if (!service.sends) continue;
|
|
1316
|
+
for (const s of service.sends) {
|
|
1317
|
+
let producers = index.get(s.id);
|
|
1318
|
+
if (!producers) {
|
|
1319
|
+
producers = [];
|
|
1320
|
+
index.set(s.id, producers);
|
|
1321
|
+
}
|
|
1322
|
+
const entry = {
|
|
1323
|
+
id: service.id,
|
|
1324
|
+
version: service.version
|
|
1325
|
+
};
|
|
1326
|
+
if (service.owners && Array.isArray(service.owners) && service.owners.length > 0) {
|
|
1327
|
+
entry.owners = service.owners;
|
|
1328
|
+
}
|
|
1329
|
+
producers.push(entry);
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
return index;
|
|
1333
|
+
};
|
|
1334
|
+
var evaluateDeprecationRules = (diff, config, targetSnapshot, targetMessageSets, baseSnapshot) => {
|
|
1335
|
+
const deprecationRules = config.rules.filter((rule) => rule.when.includes("message_deprecated"));
|
|
1336
|
+
if (deprecationRules.length === 0) return [];
|
|
1337
|
+
const targetMessages = buildMessageMap(targetSnapshot);
|
|
1338
|
+
const baseMessages = baseSnapshot ? buildMessageMap(baseSnapshot) : void 0;
|
|
1339
|
+
const producerIndex = buildProducerIndex(targetSnapshot);
|
|
1340
|
+
const deprecatedResources = diff.resources.filter((rc) => {
|
|
1341
|
+
if (!MESSAGE_RESOURCE_TYPES.has(rc.type)) return false;
|
|
1342
|
+
if (!rc.changedFields?.includes("deprecated")) return false;
|
|
1343
|
+
const targetMessage = targetMessages.get(rc.resourceId);
|
|
1344
|
+
if (!targetMessage || !targetMessage.deprecated) return false;
|
|
1345
|
+
if (baseMessages) {
|
|
1346
|
+
const baseMessage = baseMessages.get(rc.resourceId);
|
|
1347
|
+
if (baseMessage && baseMessage.deprecated) return false;
|
|
1348
|
+
}
|
|
1349
|
+
return true;
|
|
1350
|
+
});
|
|
1351
|
+
if (deprecatedResources.length === 0) return [];
|
|
1352
|
+
const results = [];
|
|
1353
|
+
for (const rule of deprecationRules) {
|
|
1354
|
+
const matched = [];
|
|
1355
|
+
for (const rc of deprecatedResources) {
|
|
1356
|
+
if (!matchesResourceId(rc.resourceId, void 0, rule.resources, targetMessageSets)) continue;
|
|
1357
|
+
const producers = producerIndex.get(rc.resourceId) || [];
|
|
1358
|
+
matched.push({ resourceChange: rc, producerServices: producers });
|
|
1359
|
+
}
|
|
1360
|
+
if (matched.length > 0) {
|
|
1361
|
+
results.push({ rule, trigger: "message_deprecated", matchedChanges: [], deprecationChanges: matched });
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
return results;
|
|
1365
|
+
};
|
|
1299
1366
|
var evaluateGovernanceRules = (diff, config, targetSnapshot, baseSnapshot) => {
|
|
1300
1367
|
const results = [];
|
|
1301
1368
|
const targetMessageSets = targetSnapshot ? buildServiceMessageSets(targetSnapshot) : void 0;
|
|
@@ -1305,12 +1372,17 @@ var evaluateGovernanceRules = (diff, config, targetSnapshot, baseSnapshot) => {
|
|
|
1305
1372
|
const filter = TRIGGER_FILTERS[trigger];
|
|
1306
1373
|
if (!filter) continue;
|
|
1307
1374
|
const messageSets = REMOVED_TRIGGERS.has(trigger) && baseMessageSets ? baseMessageSets : targetMessageSets;
|
|
1308
|
-
const matchedChanges = diff.relationships.filter(
|
|
1375
|
+
const matchedChanges = diff.relationships.filter(
|
|
1376
|
+
(c2) => filter(c2) && matchesResourceId(c2.resourceId, c2.serviceId, rule.resources, messageSets)
|
|
1377
|
+
);
|
|
1309
1378
|
if (matchedChanges.length > 0) {
|
|
1310
1379
|
results.push({ rule, trigger, matchedChanges });
|
|
1311
1380
|
}
|
|
1312
1381
|
}
|
|
1313
1382
|
}
|
|
1383
|
+
if (targetSnapshot && targetMessageSets) {
|
|
1384
|
+
results.push(...evaluateDeprecationRules(diff, config, targetSnapshot, targetMessageSets, baseSnapshot));
|
|
1385
|
+
}
|
|
1314
1386
|
return results;
|
|
1315
1387
|
};
|
|
1316
1388
|
var PRODUCER_TRIGGERS = /* @__PURE__ */ new Set(["producer_added", "producer_removed"]);
|
|
@@ -1367,6 +1439,42 @@ var executeGovernanceActions = async (results, opts = {}) => {
|
|
|
1367
1439
|
headers[key] = resolveEnvVars(value);
|
|
1368
1440
|
}
|
|
1369
1441
|
}
|
|
1442
|
+
if (result.deprecationChanges && result.deprecationChanges.length > 0) {
|
|
1443
|
+
for (const dc of result.deprecationChanges) {
|
|
1444
|
+
const messageType = messageTypes?.get(dc.resourceChange.resourceId) || "message";
|
|
1445
|
+
const producers = dc.producerServices.length > 0 ? dc.producerServices : [{ id: "unknown", version: "unknown" }];
|
|
1446
|
+
for (const producer of producers) {
|
|
1447
|
+
const payload = {
|
|
1448
|
+
specversion: "1.0",
|
|
1449
|
+
type: `eventcatalog.governance.message_deprecated`,
|
|
1450
|
+
source: "eventcatalog/governance",
|
|
1451
|
+
id: (0, import_node_crypto2.randomUUID)(),
|
|
1452
|
+
time: now,
|
|
1453
|
+
datacontenttype: "application/json",
|
|
1454
|
+
data: {
|
|
1455
|
+
schemaVersion: 1,
|
|
1456
|
+
...status && { status },
|
|
1457
|
+
summary: `${dc.resourceChange.resourceId} (${messageType}) has been deprecated by ${producer.id}`,
|
|
1458
|
+
producer: {
|
|
1459
|
+
id: producer.id,
|
|
1460
|
+
version: producer.version,
|
|
1461
|
+
...producer.owners && { owners: producer.owners }
|
|
1462
|
+
},
|
|
1463
|
+
message: {
|
|
1464
|
+
id: dc.resourceChange.resourceId,
|
|
1465
|
+
version: dc.resourceChange.version,
|
|
1466
|
+
type: messageType
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
};
|
|
1470
|
+
webhookCalls.push({
|
|
1471
|
+
urlTemplate: action.url,
|
|
1472
|
+
request: fetch(url, { method: "POST", headers, body: JSON.stringify(payload) })
|
|
1473
|
+
});
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
continue;
|
|
1477
|
+
}
|
|
1370
1478
|
for (const change of result.matchedChanges) {
|
|
1371
1479
|
const verb = getChangeVerb(result.trigger, change.changeType);
|
|
1372
1480
|
const messageType = messageTypes?.get(change.resourceId) || "message";
|
|
@@ -1423,10 +1531,17 @@ var formatGovernanceOutput = (results) => {
|
|
|
1423
1531
|
const lines = ["Governance:", ""];
|
|
1424
1532
|
for (const result of results) {
|
|
1425
1533
|
lines.push(` Rule "${result.rule.name}" triggered (${result.trigger}):`);
|
|
1426
|
-
|
|
1427
|
-
const
|
|
1428
|
-
|
|
1429
|
-
|
|
1534
|
+
if (result.deprecationChanges && result.deprecationChanges.length > 0) {
|
|
1535
|
+
for (const dc of result.deprecationChanges) {
|
|
1536
|
+
const producers = dc.producerServices.length > 0 ? dc.producerServices.map((p) => p.id).join(", ") : "unknown producer";
|
|
1537
|
+
lines.push(` ! ${dc.resourceChange.resourceId} (${dc.resourceChange.type}) deprecated by ${producers}`);
|
|
1538
|
+
}
|
|
1539
|
+
} else {
|
|
1540
|
+
for (const change of result.matchedChanges) {
|
|
1541
|
+
const prefix = change.changeType === "added" ? "+" : "-";
|
|
1542
|
+
const verb = getChangeVerb(result.trigger, change.changeType);
|
|
1543
|
+
lines.push(` ${prefix} ${change.serviceId} is ${verb} ${change.resourceId}`);
|
|
1544
|
+
}
|
|
1430
1545
|
}
|
|
1431
1546
|
lines.push("");
|
|
1432
1547
|
}
|
|
@@ -1487,7 +1602,7 @@ var governanceCheck = async (opts) => {
|
|
|
1487
1602
|
const diff = await baseSDK.diffSnapshots(baseResult.filePath, targetResult.filePath);
|
|
1488
1603
|
const config = loadGovernanceConfig(dir);
|
|
1489
1604
|
if (config.rules.length === 0) {
|
|
1490
|
-
return "No governance.yaml found or no rules defined.";
|
|
1605
|
+
return "No governance.yaml (or governance.yml) found or no rules defined.";
|
|
1491
1606
|
}
|
|
1492
1607
|
const results = evaluateGovernanceRules(diff, config, targetResult.snapshot, baseResult.snapshot);
|
|
1493
1608
|
const messageTypes = buildMessageTypeMap(targetResult.snapshot);
|