nexarch 0.1.24 → 0.1.25
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.
|
@@ -4,7 +4,7 @@ import { join } from "path";
|
|
|
4
4
|
import process from "process";
|
|
5
5
|
import { requireCredentials } from "../lib/credentials.js";
|
|
6
6
|
import { callMcpTool, mcpInitialize, mcpListTools } from "../lib/mcp.js";
|
|
7
|
-
const CLI_VERSION = "0.1.
|
|
7
|
+
const CLI_VERSION = "0.1.25";
|
|
8
8
|
const AGENT_ENTITY_TYPE = "agent";
|
|
9
9
|
const TECH_COMPONENT_ENTITY_TYPE = "technology_component";
|
|
10
10
|
function parseFlag(args, flag) {
|
|
@@ -115,6 +115,34 @@ function readRootPackage(pkgPath) {
|
|
|
115
115
|
return {};
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
|
+
// Guess entity type + subtype for a sub-package based on its path and package.json scripts.
|
|
119
|
+
function classifySubPackage(pkgPath, relativePath) {
|
|
120
|
+
const topDir = relativePath.split("/")[0] ?? "";
|
|
121
|
+
// packages/* → shared library/component
|
|
122
|
+
if (topDir === "packages") {
|
|
123
|
+
const name = relativePath.split("/")[1] ?? "";
|
|
124
|
+
if (name.includes("ui") || name.includes("components"))
|
|
125
|
+
return { entityType: "technology_component", subtype: "tech_framework" };
|
|
126
|
+
if (name.includes("types") || name.includes("shared"))
|
|
127
|
+
return { entityType: "technology_component", subtype: "tech_library" };
|
|
128
|
+
return { entityType: "technology_component", subtype: "tech_library" };
|
|
129
|
+
}
|
|
130
|
+
// apps/* or src/* → deployable application; check scripts
|
|
131
|
+
try {
|
|
132
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
133
|
+
const scripts = Object.keys(pkg.scripts ?? {});
|
|
134
|
+
const hasServer = scripts.some((s) => ["start", "dev", "serve", "build"].includes(s));
|
|
135
|
+
if (hasServer) {
|
|
136
|
+
const name = relativePath.toLowerCase();
|
|
137
|
+
if (name.includes("crawl") || name.includes("worker") || name.includes("job") || name.includes("etl")) {
|
|
138
|
+
return { entityType: "application", subtype: "app_integration_service" };
|
|
139
|
+
}
|
|
140
|
+
return { entityType: "application", subtype: "app_custom_built" };
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch { }
|
|
144
|
+
return { entityType: "technology_component", subtype: "tech_library" };
|
|
145
|
+
}
|
|
118
146
|
// Resolve workspace glob patterns (e.g. "apps/*", "packages/*") to actual directories.
|
|
119
147
|
// Handles the common case of a single wildcard — no full glob library needed.
|
|
120
148
|
function resolveWorkspaceDirs(rootDir, workspaces) {
|
|
@@ -219,11 +247,17 @@ function scanProject(dir) {
|
|
|
219
247
|
else {
|
|
220
248
|
// Record as a sub-package for enrichment task
|
|
221
249
|
const relativePath = pkgPath.replace(dir + "/", "").replace("/package.json", "");
|
|
250
|
+
const packageName = pkg.name ?? relativePath;
|
|
251
|
+
const { entityType, subtype } = classifySubPackage(pkgPath, relativePath);
|
|
252
|
+
const externalKey = `${entityType}:${slugify(packageName)}`;
|
|
222
253
|
subPackages.push({
|
|
223
|
-
name:
|
|
254
|
+
name: packageName,
|
|
224
255
|
relativePath,
|
|
225
256
|
packageJsonPath: pkgPath,
|
|
226
257
|
depNames: deps,
|
|
258
|
+
entityType,
|
|
259
|
+
subtype,
|
|
260
|
+
externalKey,
|
|
227
261
|
});
|
|
228
262
|
}
|
|
229
263
|
for (const dep of deps)
|
|
@@ -362,7 +396,22 @@ export async function initProject(args) {
|
|
|
362
396
|
confidence: 0.95,
|
|
363
397
|
});
|
|
364
398
|
}
|
|
365
|
-
//
|
|
399
|
+
// Auto-create stub entities for each sub-package
|
|
400
|
+
const seenSubKeys = new Set();
|
|
401
|
+
for (const sp of subPackages) {
|
|
402
|
+
if (seenSubKeys.has(sp.externalKey))
|
|
403
|
+
continue;
|
|
404
|
+
seenSubKeys.add(sp.externalKey);
|
|
405
|
+
entities.push({
|
|
406
|
+
externalKey: sp.externalKey,
|
|
407
|
+
entityTypeCode: sp.entityType,
|
|
408
|
+
entitySubtypeCode: sp.subtype,
|
|
409
|
+
name: sp.name,
|
|
410
|
+
confidence: 0.8,
|
|
411
|
+
attributes: { source_dir: `${dir}/${sp.relativePath}`, scanned_at: nowIso },
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
// Build a lookup from input name to resolved result for enrichment task and sub-app wiring
|
|
366
415
|
const resolvedByInput = new Map();
|
|
367
416
|
for (const r of resolvedItems) {
|
|
368
417
|
if (r.canonicalExternalRef)
|
|
@@ -370,27 +419,43 @@ export async function initProject(args) {
|
|
|
370
419
|
if (r.normalised && r.canonicalExternalRef)
|
|
371
420
|
resolvedByInput.set(r.normalised, r);
|
|
372
421
|
}
|
|
373
|
-
// Build relationships
|
|
374
|
-
//
|
|
422
|
+
// Build relationships:
|
|
423
|
+
// - Root-level deps → wired to the top-level project entity
|
|
424
|
+
// - Sub-package deps → wired to each sub-package entity
|
|
425
|
+
// - Sub-packages that are apps → part_of the top-level project
|
|
375
426
|
const relationships = [];
|
|
376
427
|
const seenRelPairs = new Set();
|
|
428
|
+
function addRel(type, from, to, confidence = 0.9) {
|
|
429
|
+
const key = `${type}::${from}::${to}`;
|
|
430
|
+
if (seenRelPairs.has(key))
|
|
431
|
+
return;
|
|
432
|
+
seenRelPairs.add(key);
|
|
433
|
+
relationships.push({ relationshipTypeCode: type, fromEntityExternalKey: from, toEntityExternalKey: to, confidence });
|
|
434
|
+
}
|
|
435
|
+
// Root-level deps → top-level project
|
|
377
436
|
for (const r of resolvedItems) {
|
|
378
437
|
if (!r.canonicalExternalRef || !r.entityTypeCode)
|
|
379
438
|
continue;
|
|
380
|
-
// Skip deps that don't belong to the root package — only wire root-level deps here
|
|
381
439
|
if (!rootDepNames.has(r.input) && !rootDepNames.has(r.normalised))
|
|
382
440
|
continue;
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
441
|
+
addRel(pickRelationshipType(r.entityTypeCode), projectExternalKey, r.canonicalExternalRef);
|
|
442
|
+
}
|
|
443
|
+
// Sub-package relationships
|
|
444
|
+
for (const sp of subPackages) {
|
|
445
|
+
if (!sp.externalKey || seenSubKeys.has(`rel:${sp.externalKey}`))
|
|
386
446
|
continue;
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
447
|
+
seenSubKeys.add(`rel:${sp.externalKey}`);
|
|
448
|
+
// Apps are part_of the top-level project
|
|
449
|
+
if (sp.entityType === "application") {
|
|
450
|
+
addRel("part_of", sp.externalKey, projectExternalKey);
|
|
451
|
+
}
|
|
452
|
+
// Wire each sub-package's resolved deps to itself
|
|
453
|
+
for (const depName of sp.depNames) {
|
|
454
|
+
const r = resolvedByInput.get(depName);
|
|
455
|
+
if (!r?.canonicalExternalRef || !r.entityTypeCode)
|
|
456
|
+
continue;
|
|
457
|
+
addRel(pickRelationshipType(r.entityTypeCode), sp.externalKey, r.canonicalExternalRef);
|
|
458
|
+
}
|
|
394
459
|
}
|
|
395
460
|
if (!asJson)
|
|
396
461
|
console.log(`\nWriting to graph…`);
|