nexarch 0.9.17 → 0.9.20
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.
|
@@ -909,6 +909,9 @@ function pickRelationshipType(toEntityTypeCode, toEntitySubtypeCode, _fromEntity
|
|
|
909
909
|
// managed services — integrates_with is the semantically correct relationship.
|
|
910
910
|
// Other platform_component subtypes (platform_runtime, platform_control_plane) use depends_on.
|
|
911
911
|
return toEntitySubtypeCode === "platform_service" ? "integrates_with" : "depends_on";
|
|
912
|
+
case "application":
|
|
913
|
+
// Application-to-application: a hard runtime dependency, not a peer integration concern.
|
|
914
|
+
return "depends_on";
|
|
912
915
|
case "skill":
|
|
913
916
|
return "uses";
|
|
914
917
|
case "technology_component":
|
|
@@ -1349,10 +1352,23 @@ export async function initProject(args) {
|
|
|
1349
1352
|
if (r.normalised && r.canonicalExternalRef)
|
|
1350
1353
|
resolvedByInput.set(r.normalised, r);
|
|
1351
1354
|
}
|
|
1355
|
+
// Build intra-monorepo lookup: normalised package name → sub-package externalKey + entityType.
|
|
1356
|
+
// Used to detect workspace deps between applications in the same repo (e.g. "workspace:*" refs
|
|
1357
|
+
// that won't resolve against the global reference library but should still be wired).
|
|
1358
|
+
const intraMonorepoByName = new Map();
|
|
1359
|
+
for (const sp of subPackages) {
|
|
1360
|
+
if (!sp.externalKey)
|
|
1361
|
+
continue;
|
|
1362
|
+
intraMonorepoByName.set(sp.name.toLowerCase(), { externalKey: sp.externalKey, entityType: sp.entityType });
|
|
1363
|
+
const norm = normalizeToken(sp.name);
|
|
1364
|
+
if (norm !== sp.name.toLowerCase())
|
|
1365
|
+
intraMonorepoByName.set(norm, { externalKey: sp.externalKey, entityType: sp.entityType });
|
|
1366
|
+
}
|
|
1352
1367
|
// Build relationships:
|
|
1353
1368
|
// - Root-level deps → wired to the top-level project entity
|
|
1354
1369
|
// - Sub-package deps → wired to each sub-package entity
|
|
1355
1370
|
// - Sub-packages that are apps → part_of the top-level project
|
|
1371
|
+
// - Sub-package deps that resolve to another sub-package → integrates_with
|
|
1356
1372
|
const relationships = [];
|
|
1357
1373
|
const seenRelPairs = new Set();
|
|
1358
1374
|
let relationshipAddAttempts = 0;
|
|
@@ -1385,20 +1401,43 @@ export async function initProject(args) {
|
|
|
1385
1401
|
if (!sp.externalKey || seenSubKeys.has(`rel:${sp.externalKey}`))
|
|
1386
1402
|
continue;
|
|
1387
1403
|
seenSubKeys.add(`rel:${sp.externalKey}`);
|
|
1388
|
-
//
|
|
1404
|
+
// Wire structural relationship to the top-level project entity:
|
|
1405
|
+
// - application_component → part_of → root (component within a single deployable app)
|
|
1406
|
+
// - application → root:
|
|
1407
|
+
// product root: root composes sub-app (product is composed of its constituent apps)
|
|
1408
|
+
// application root: sub-app part_of root (treat as a bounded sub-application)
|
|
1389
1409
|
if (sp.entityType === "application_component") {
|
|
1390
1410
|
addRel("part_of", sp.externalKey, projectExternalKey);
|
|
1391
1411
|
}
|
|
1412
|
+
else if (sp.entityType === "application") {
|
|
1413
|
+
if (entityTypeOverride === "product") {
|
|
1414
|
+
addRel("composes", projectExternalKey, sp.externalKey);
|
|
1415
|
+
}
|
|
1416
|
+
else {
|
|
1417
|
+
addRel("part_of", sp.externalKey, projectExternalKey);
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1392
1420
|
// Wire each sub-package's resolved deps to itself
|
|
1393
1421
|
for (const dep of sp.depSpecs) {
|
|
1394
1422
|
const r = resolvedByInput.get(dep.name);
|
|
1395
|
-
if (
|
|
1423
|
+
if (r?.canonicalExternalRef && r.entityTypeCode) {
|
|
1424
|
+
addRel(pickRelationshipType(r.entityTypeCode, r.entitySubtypeCode, sp.entityType), sp.externalKey, r.canonicalExternalRef, 0.9, {
|
|
1425
|
+
source: dep.source,
|
|
1426
|
+
detected_at: nowIso,
|
|
1427
|
+
...buildVersionAttributes(dep.versionRaw, dep.source),
|
|
1428
|
+
});
|
|
1396
1429
|
continue;
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1430
|
+
}
|
|
1431
|
+
// Check if the dep resolves to another sub-package in the same monorepo.
|
|
1432
|
+
// This catches workspace:* references and local inter-app dependencies.
|
|
1433
|
+
const intra = intraMonorepoByName.get(dep.name.toLowerCase())
|
|
1434
|
+
?? intraMonorepoByName.get(normalizeToken(dep.name));
|
|
1435
|
+
if (intra && intra.externalKey !== sp.externalKey) {
|
|
1436
|
+
addRel("depends_on", sp.externalKey, intra.externalKey, 0.85, {
|
|
1437
|
+
source: dep.source,
|
|
1438
|
+
detected_at: nowIso,
|
|
1439
|
+
});
|
|
1440
|
+
}
|
|
1402
1441
|
}
|
|
1403
1442
|
}
|
|
1404
1443
|
// Company org is accountable_for the top-level project entity
|
|
@@ -1406,7 +1445,7 @@ export async function initProject(args) {
|
|
|
1406
1445
|
try {
|
|
1407
1446
|
const orgRaw = await callMcpProfiled("nexarch_list_entities", { entityTypeCode: "organisation", status: "active", limit: 1, companyId: creds.companyId }, { entityTypeCode: "organisation", limit: 1 });
|
|
1408
1447
|
const orgData = parseToolText(orgRaw);
|
|
1409
|
-
const org = (orgData.entities ?? [])
|
|
1448
|
+
const org = (orgData.entities ?? []).find((e) => e.entityTypeCode === "organisation");
|
|
1410
1449
|
if (org?.entityRef || org?.externalKey)
|
|
1411
1450
|
orgExternalKey = (org.entityRef ?? org.externalKey);
|
|
1412
1451
|
}
|