@neat.is/core 0.7.6 → 0.7.7
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/{chunk-6H757ZNM.js → chunk-4GCV46AP.js} +2 -2
- package/dist/{chunk-XT4NNFH6.js → chunk-UI3AFJAF.js} +765 -216
- package/dist/chunk-UI3AFJAF.js.map +1 -0
- package/dist/{chunk-P2ZEKJ35.js → chunk-Y43UCVZS.js} +9 -6
- package/dist/chunk-Y43UCVZS.js.map +1 -0
- package/dist/{chunk-XHSK4BGL.js → chunk-YVZRBT4C.js} +3 -3
- package/dist/cli.cjs +1143 -590
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +4 -4
- package/dist/index.cjs +945 -392
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +4 -4
- package/dist/neatd.cjs +954 -401
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +3 -3
- package/dist/{otel-grpc-APVZSB6W.js → otel-grpc-DPSAGRUU.js} +3 -3
- package/dist/server.cjs +877 -324
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +3 -3
- package/package.json +2 -2
- package/dist/chunk-P2ZEKJ35.js.map +0 -1
- package/dist/chunk-XT4NNFH6.js.map +0 -1
- /package/dist/{chunk-6H757ZNM.js.map → chunk-4GCV46AP.js.map} +0 -0
- /package/dist/{chunk-XHSK4BGL.js.map → chunk-YVZRBT4C.js.map} +0 -0
- /package/dist/{otel-grpc-APVZSB6W.js.map → otel-grpc-DPSAGRUU.js.map} +0 -0
package/dist/cli.cjs
CHANGED
|
@@ -61,8 +61,8 @@ function mountBearerAuth(app, opts) {
|
|
|
61
61
|
]);
|
|
62
62
|
const publicRead = opts.publicRead === true;
|
|
63
63
|
app.addHook("preHandler", (req, reply, done) => {
|
|
64
|
-
const
|
|
65
|
-
if (exactUnauthPaths.has(
|
|
64
|
+
const path82 = (req.url.split("?")[0] ?? "").replace(/\/+$/, "");
|
|
65
|
+
if (exactUnauthPaths.has(path82) || PROJECT_SCOPED_UNAUTH_PATTERN.test(path82)) {
|
|
66
66
|
done();
|
|
67
67
|
return;
|
|
68
68
|
}
|
|
@@ -343,7 +343,7 @@ function pickEnv(spanAttrs, resourceAttrs) {
|
|
|
343
343
|
return ENV_FALLBACK;
|
|
344
344
|
}
|
|
345
345
|
function normalizeDbSystem(attrs) {
|
|
346
|
-
const raw = attrs["db.system"];
|
|
346
|
+
const raw = attrs["db.system"] ?? attrs["db.system.name"];
|
|
347
347
|
if (typeof raw !== "string") return void 0;
|
|
348
348
|
return raw === "mongoose" ? "mongodb" : raw;
|
|
349
349
|
}
|
|
@@ -415,8 +415,8 @@ function websocketChannelPathOf(attrs) {
|
|
|
415
415
|
const v = attrs[key];
|
|
416
416
|
if (typeof v === "string" && v.length > 0) {
|
|
417
417
|
const q = v.indexOf("?");
|
|
418
|
-
const
|
|
419
|
-
if (
|
|
418
|
+
const path82 = q === -1 ? v : v.slice(0, q);
|
|
419
|
+
if (path82.length > 0) return path82;
|
|
420
420
|
}
|
|
421
421
|
}
|
|
422
422
|
return void 0;
|
|
@@ -435,6 +435,9 @@ function parseOtlpRequest(body) {
|
|
|
435
435
|
for (const ss of rs.scopeSpans ?? []) {
|
|
436
436
|
for (const span of ss.spans ?? []) {
|
|
437
437
|
const attrs = attrsToRecord(span.attributes);
|
|
438
|
+
const dbSqlText = typeof attrs["db.statement"] === "string" ? attrs["db.statement"] : typeof attrs["db.query.text"] === "string" ? attrs["db.query.text"] : void 0;
|
|
439
|
+
const dbSystemName = normalizeDbSystem(attrs);
|
|
440
|
+
const directDbTable = typeof attrs["db.sql.table"] === "string" ? attrs["db.sql.table"] : dbSystemName !== "mongodb" && typeof attrs["db.collection.name"] === "string" ? attrs["db.collection.name"] : void 0;
|
|
438
441
|
const parsed = {
|
|
439
442
|
service,
|
|
440
443
|
resourceServiceNamePresent,
|
|
@@ -449,11 +452,11 @@ function parseOtlpRequest(body) {
|
|
|
449
452
|
durationNanos: durationNanos(span.startTimeUnixNano, span.endTimeUnixNano),
|
|
450
453
|
env: pickEnv(attrs, resourceAttrs),
|
|
451
454
|
attributes: attrs,
|
|
452
|
-
dbSystem:
|
|
455
|
+
dbSystem: dbSystemName,
|
|
453
456
|
dbName: typeof attrs["db.name"] === "string" ? attrs["db.name"] : void 0,
|
|
454
457
|
dbCollection: typeof attrs["db.collection.name"] === "string" ? attrs["db.collection.name"] : typeof attrs["db.mongodb.collection"] === "string" ? attrs["db.mongodb.collection"] : void 0,
|
|
455
|
-
dbTable:
|
|
456
|
-
dbColumns:
|
|
458
|
+
dbTable: directDbTable ?? (dbSqlText ? tableFromSqlStatement(dbSqlText) ?? void 0 : void 0),
|
|
459
|
+
dbColumns: dbSqlText ? columnsFromSqlStatement(dbSqlText) : void 0,
|
|
457
460
|
httpRoute: typeof attrs["http.route"] === "string" ? attrs["http.route"] : void 0,
|
|
458
461
|
httpMethod: typeof attrs["http.request.method"] === "string" ? attrs["http.request.method"] : typeof attrs["http.method"] === "string" ? attrs["http.method"] : void 0,
|
|
459
462
|
messagingSystem: typeof attrs["messaging.system"] === "string" ? attrs["messaging.system"] : void 0,
|
|
@@ -752,7 +755,7 @@ __export(cli_exports, {
|
|
|
752
755
|
});
|
|
753
756
|
module.exports = __toCommonJS(cli_exports);
|
|
754
757
|
init_cjs_shims();
|
|
755
|
-
var
|
|
758
|
+
var import_node_path81 = __toESM(require("path"), 1);
|
|
756
759
|
var import_node_os8 = __toESM(require("os"), 1);
|
|
757
760
|
var import_node_fs46 = require("fs");
|
|
758
761
|
|
|
@@ -1322,19 +1325,19 @@ function confidenceFromMix(edges, now = Date.now()) {
|
|
|
1322
1325
|
function longestIncomingWalk(graph, start, maxDepth) {
|
|
1323
1326
|
let best = { path: [start], edges: [] };
|
|
1324
1327
|
const visited = /* @__PURE__ */ new Set([start]);
|
|
1325
|
-
function step(node,
|
|
1326
|
-
if (
|
|
1327
|
-
best = { path: [...
|
|
1328
|
+
function step(node, path82, edges) {
|
|
1329
|
+
if (path82.length > best.path.length) {
|
|
1330
|
+
best = { path: [...path82], edges: [...edges] };
|
|
1328
1331
|
}
|
|
1329
|
-
if (
|
|
1332
|
+
if (path82.length - 1 >= maxDepth) return;
|
|
1330
1333
|
const incoming = bestEdgeBySource(graph, graph.inboundEdges(node));
|
|
1331
1334
|
for (const [srcId, edge] of incoming) {
|
|
1332
1335
|
if (visited.has(srcId)) continue;
|
|
1333
1336
|
visited.add(srcId);
|
|
1334
|
-
|
|
1337
|
+
path82.push(srcId);
|
|
1335
1338
|
edges.push(edge);
|
|
1336
|
-
step(srcId,
|
|
1337
|
-
|
|
1339
|
+
step(srcId, path82, edges);
|
|
1340
|
+
path82.pop();
|
|
1338
1341
|
edges.pop();
|
|
1339
1342
|
visited.delete(srcId);
|
|
1340
1343
|
}
|
|
@@ -1342,11 +1345,11 @@ function longestIncomingWalk(graph, start, maxDepth) {
|
|
|
1342
1345
|
step(start, [start], []);
|
|
1343
1346
|
return best;
|
|
1344
1347
|
}
|
|
1345
|
-
function databaseRootCauseShape(graph, origin,
|
|
1348
|
+
function databaseRootCauseShape(graph, origin, walk9) {
|
|
1346
1349
|
const targetDb = origin;
|
|
1347
1350
|
const candidatePairs = compatPairs().filter((p) => p.engine === targetDb.engine);
|
|
1348
1351
|
if (candidatePairs.length === 0) return null;
|
|
1349
|
-
for (const id of
|
|
1352
|
+
for (const id of walk9.path) {
|
|
1350
1353
|
const owner = resolveOwningService(graph, id);
|
|
1351
1354
|
if (!owner) continue;
|
|
1352
1355
|
const { id: serviceId9, svc } = owner;
|
|
@@ -1373,8 +1376,8 @@ function databaseRootCauseShape(graph, origin, walk8) {
|
|
|
1373
1376
|
}
|
|
1374
1377
|
return null;
|
|
1375
1378
|
}
|
|
1376
|
-
function serviceRootCauseShape(graph, _origin,
|
|
1377
|
-
for (const id of
|
|
1379
|
+
function serviceRootCauseShape(graph, _origin, walk9) {
|
|
1380
|
+
for (const id of walk9.path) {
|
|
1378
1381
|
const owner = resolveOwningService(graph, id);
|
|
1379
1382
|
if (!owner) continue;
|
|
1380
1383
|
const { id: serviceId9, svc } = owner;
|
|
@@ -1410,15 +1413,15 @@ function serviceRootCauseShape(graph, _origin, walk8) {
|
|
|
1410
1413
|
}
|
|
1411
1414
|
return null;
|
|
1412
1415
|
}
|
|
1413
|
-
function fileRootCauseShape(graph, origin,
|
|
1416
|
+
function fileRootCauseShape(graph, origin, walk9) {
|
|
1414
1417
|
const owner = resolveOwningService(graph, origin.id);
|
|
1415
1418
|
if (!owner) return null;
|
|
1416
|
-
return serviceRootCauseShape(graph, owner.svc,
|
|
1419
|
+
return serviceRootCauseShape(graph, owner.svc, walk9);
|
|
1417
1420
|
}
|
|
1418
|
-
function symbolRootCauseShape(graph, origin,
|
|
1421
|
+
function symbolRootCauseShape(graph, origin, walk9) {
|
|
1419
1422
|
const owner = resolveOwningService(graph, origin.id);
|
|
1420
1423
|
if (!owner) return null;
|
|
1421
|
-
return serviceRootCauseShape(graph, owner.svc,
|
|
1424
|
+
return serviceRootCauseShape(graph, owner.svc, walk9);
|
|
1422
1425
|
}
|
|
1423
1426
|
var rootCauseShapes = {
|
|
1424
1427
|
[import_types.NodeType.DatabaseNode]: databaseRootCauseShape,
|
|
@@ -1431,16 +1434,16 @@ function getRootCause(graph, errorNodeId, errorEvent, incidents) {
|
|
|
1431
1434
|
const origin = graph.getNodeAttributes(errorNodeId);
|
|
1432
1435
|
const shape = rootCauseShapes[origin.type];
|
|
1433
1436
|
if (shape) {
|
|
1434
|
-
const
|
|
1435
|
-
const match = shape(graph, origin,
|
|
1437
|
+
const walk9 = longestIncomingWalk(graph, errorNodeId, ROOT_CAUSE_MAX_DEPTH);
|
|
1438
|
+
const match = shape(graph, origin, walk9);
|
|
1436
1439
|
if (match) {
|
|
1437
1440
|
const reason = errorEvent ? `${match.rootCauseReason} (observed error: ${errorEvent.errorMessage})` : match.rootCauseReason;
|
|
1438
1441
|
return import_types.RootCauseResultSchema.parse({
|
|
1439
1442
|
rootCauseNode: match.rootCauseNode,
|
|
1440
1443
|
rootCauseReason: reason,
|
|
1441
|
-
traversalPath:
|
|
1442
|
-
edgeProvenances:
|
|
1443
|
-
confidence: confidenceFromMix(
|
|
1444
|
+
traversalPath: walk9.path,
|
|
1445
|
+
edgeProvenances: walk9.edges.map((e) => e.provenance),
|
|
1446
|
+
confidence: confidenceFromMix(walk9.edges),
|
|
1444
1447
|
fixRecommendation: match.fixRecommendation
|
|
1445
1448
|
});
|
|
1446
1449
|
}
|
|
@@ -1541,26 +1544,26 @@ function dominantFailingCall(graph, serviceId9, visited) {
|
|
|
1541
1544
|
return best;
|
|
1542
1545
|
}
|
|
1543
1546
|
function followFailingCallChain(graph, originServiceId, maxDepth) {
|
|
1544
|
-
const
|
|
1547
|
+
const path82 = [originServiceId];
|
|
1545
1548
|
const edges = [];
|
|
1546
1549
|
const visited = /* @__PURE__ */ new Set([originServiceId]);
|
|
1547
1550
|
let current = originServiceId;
|
|
1548
1551
|
for (let depth = 0; depth < maxDepth; depth++) {
|
|
1549
1552
|
const hop = dominantFailingCall(graph, current, visited);
|
|
1550
1553
|
if (!hop) break;
|
|
1551
|
-
|
|
1554
|
+
path82.push(hop.nextService);
|
|
1552
1555
|
edges.push(hop.edge);
|
|
1553
1556
|
visited.add(hop.nextService);
|
|
1554
1557
|
current = hop.nextService;
|
|
1555
1558
|
}
|
|
1556
1559
|
if (edges.length === 0) return null;
|
|
1557
|
-
return { path:
|
|
1560
|
+
return { path: path82, edges, culprit: current };
|
|
1558
1561
|
}
|
|
1559
1562
|
function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
1560
1563
|
const chain = followFailingCallChain(graph, originId, ROOT_CAUSE_MAX_DEPTH);
|
|
1561
1564
|
if (!chain) return null;
|
|
1562
1565
|
const culprit = chain.culprit;
|
|
1563
|
-
const
|
|
1566
|
+
const path82 = [...chain.path];
|
|
1564
1567
|
const edgeProvenances = chain.edges.map((e) => e.provenance);
|
|
1565
1568
|
const baseConfidence = confidenceFromMix(chain.edges);
|
|
1566
1569
|
const confidence = Math.max(0, Math.min(1, baseConfidence * INCIDENT_ROOT_CAUSE_CONFIDENCE));
|
|
@@ -1568,14 +1571,14 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
|
1568
1571
|
if (loc) {
|
|
1569
1572
|
let rootCauseNode = culprit;
|
|
1570
1573
|
if (loc.fileNode) {
|
|
1571
|
-
|
|
1574
|
+
path82.push(loc.fileNode);
|
|
1572
1575
|
edgeProvenances.push(import_types.Provenance.OBSERVED);
|
|
1573
1576
|
rootCauseNode = loc.fileNode;
|
|
1574
1577
|
}
|
|
1575
1578
|
return import_types.RootCauseResultSchema.parse({
|
|
1576
1579
|
rootCauseNode,
|
|
1577
1580
|
rootCauseReason: loc.rootCauseReason,
|
|
1578
|
-
traversalPath:
|
|
1581
|
+
traversalPath: path82,
|
|
1579
1582
|
edgeProvenances,
|
|
1580
1583
|
confidence,
|
|
1581
1584
|
...loc.fixRecommendation ? { fixRecommendation: loc.fixRecommendation } : {}
|
|
@@ -1587,7 +1590,7 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
|
1587
1590
|
return import_types.RootCauseResultSchema.parse({
|
|
1588
1591
|
rootCauseNode: culprit,
|
|
1589
1592
|
rootCauseReason: `${culpritName} is failing downstream calls (${errs} observed error${errs === 1 ? "" : "s"})`,
|
|
1590
|
-
traversalPath:
|
|
1593
|
+
traversalPath: path82,
|
|
1591
1594
|
edgeProvenances,
|
|
1592
1595
|
confidence,
|
|
1593
1596
|
fixRecommendation: `Inspect ${culpritName}'s failing handler`
|
|
@@ -2534,14 +2537,14 @@ function buildServiceHostIndex(services) {
|
|
|
2534
2537
|
}
|
|
2535
2538
|
async function walkSourceFiles(dir) {
|
|
2536
2539
|
const out = [];
|
|
2537
|
-
async function
|
|
2540
|
+
async function walk9(current) {
|
|
2538
2541
|
const entries = await import_node_fs6.promises.readdir(current, { withFileTypes: true }).catch(() => []);
|
|
2539
2542
|
for (const entry2 of entries) {
|
|
2540
2543
|
const full = import_node_path6.default.join(current, entry2.name);
|
|
2541
2544
|
if (entry2.isDirectory()) {
|
|
2542
2545
|
if (IGNORED_DIRS.has(entry2.name)) continue;
|
|
2543
2546
|
if (await isPythonVenvDir(full)) continue;
|
|
2544
|
-
await
|
|
2547
|
+
await walk9(full);
|
|
2545
2548
|
} else if (entry2.isFile() && SERVICE_FILE_EXTENSIONS.has(import_node_path6.default.extname(entry2.name)) && // Skip NEAT's own generated `otel-init.*` bootstrap — extracting it
|
|
2546
2549
|
// would attribute our instrumentation imports to the user's service.
|
|
2547
2550
|
!isNeatAuthoredSourceFile(entry2.name)) {
|
|
@@ -2549,7 +2552,7 @@ async function walkSourceFiles(dir) {
|
|
|
2549
2552
|
}
|
|
2550
2553
|
}
|
|
2551
2554
|
}
|
|
2552
|
-
await
|
|
2555
|
+
await walk9(dir);
|
|
2553
2556
|
return out;
|
|
2554
2557
|
}
|
|
2555
2558
|
async function loadSourceFiles(dir) {
|
|
@@ -3063,7 +3066,7 @@ var ROUTER_METHODS = /* @__PURE__ */ new Set([
|
|
|
3063
3066
|
]);
|
|
3064
3067
|
var NEXT_APP_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
|
|
3065
3068
|
var JS_ROUTE_EXTENSIONS = /* @__PURE__ */ new Set([".js", ".jsx", ".mjs", ".cjs", ".ts", ".tsx"]);
|
|
3066
|
-
function
|
|
3069
|
+
function goRouterRoutesFromSource(source, parser, framework) {
|
|
3067
3070
|
const tree = parseSource2(parser, source);
|
|
3068
3071
|
const prefixes = /* @__PURE__ */ new Map();
|
|
3069
3072
|
const out = [];
|
|
@@ -3073,10 +3076,12 @@ function ginRoutesFromSource(source, parser) {
|
|
|
3073
3076
|
const value = node.childForFieldName("right")?.namedChild(0) ?? node.childForFieldName("value");
|
|
3074
3077
|
if (name && value?.type === "call_expression") {
|
|
3075
3078
|
const fn2 = value.childForFieldName("function");
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3079
|
+
if (fn2?.childForFieldName("field")?.text === "Group") {
|
|
3080
|
+
const leaf2 = goStringLiteral(value.childForFieldName("arguments")?.namedChild(0));
|
|
3081
|
+
if (leaf2 !== null) {
|
|
3082
|
+
const parent = fn2.childForFieldName("operand")?.text ?? "";
|
|
3083
|
+
prefixes.set(name, (prefixes.get(parent) ?? "") + leaf2);
|
|
3084
|
+
}
|
|
3080
3085
|
}
|
|
3081
3086
|
}
|
|
3082
3087
|
return;
|
|
@@ -3087,18 +3092,32 @@ function ginRoutesFromSource(source, parser) {
|
|
|
3087
3092
|
const method = fn.childForFieldName("field")?.text?.toUpperCase();
|
|
3088
3093
|
if (!method || !ROUTER_METHODS.has(method.toLowerCase())) return;
|
|
3089
3094
|
const receiver = fn.childForFieldName("operand")?.text ?? "";
|
|
3090
|
-
const
|
|
3091
|
-
if (
|
|
3092
|
-
const leaf = first.text.slice(1, -1);
|
|
3095
|
+
const leaf = goStringLiteral(node.childForFieldName("arguments")?.namedChild(0));
|
|
3096
|
+
if (leaf === null) return;
|
|
3093
3097
|
out.push({
|
|
3094
|
-
method
|
|
3098
|
+
method,
|
|
3095
3099
|
pathTemplate: canonicalizeTemplate((prefixes.get(receiver) ?? "") + leaf),
|
|
3096
3100
|
line: node.startPosition.row + 1,
|
|
3097
|
-
framework
|
|
3101
|
+
framework
|
|
3098
3102
|
});
|
|
3099
3103
|
});
|
|
3100
3104
|
return out;
|
|
3101
3105
|
}
|
|
3106
|
+
function goStringLiteral(node) {
|
|
3107
|
+
if (node?.type === "interpreted_string_literal" || node?.type === "raw_string_literal") {
|
|
3108
|
+
return node.text.slice(1, -1);
|
|
3109
|
+
}
|
|
3110
|
+
return null;
|
|
3111
|
+
}
|
|
3112
|
+
function ginRoutesFromSource(source, parser) {
|
|
3113
|
+
return goRouterRoutesFromSource(source, parser, "gin");
|
|
3114
|
+
}
|
|
3115
|
+
function echoRoutesFromSource(source, parser) {
|
|
3116
|
+
return goRouterRoutesFromSource(source, parser, "echo");
|
|
3117
|
+
}
|
|
3118
|
+
function fiberRoutesFromSource(source, parser) {
|
|
3119
|
+
return goRouterRoutesFromSource(source, parser, "fiber");
|
|
3120
|
+
}
|
|
3102
3121
|
var FASTAPI_METHODS = /* @__PURE__ */ new Set(["get", "post", "put", "patch", "delete", "options", "head", "trace"]);
|
|
3103
3122
|
var NESTJS_METHODS = /* @__PURE__ */ new Map([
|
|
3104
3123
|
["Get", "GET"],
|
|
@@ -3683,9 +3702,9 @@ function rubyRocketRoute(args) {
|
|
|
3683
3702
|
if (!pair || pair.type !== "pair") continue;
|
|
3684
3703
|
const k = pair.childForFieldName("key");
|
|
3685
3704
|
if (k?.type !== "string") continue;
|
|
3686
|
-
const
|
|
3687
|
-
if (
|
|
3688
|
-
return { path:
|
|
3705
|
+
const path82 = rubyLiteral(k);
|
|
3706
|
+
if (path82 === null) continue;
|
|
3707
|
+
return { path: path82, target: rubyLiteral(pair.childForFieldName("value")) };
|
|
3689
3708
|
}
|
|
3690
3709
|
return null;
|
|
3691
3710
|
}
|
|
@@ -4362,9 +4381,11 @@ async function addRoutes(graph, services) {
|
|
|
4362
4381
|
const hasFlask = deps["flask"] !== void 0;
|
|
4363
4382
|
const hasDjango = deps["django"] !== void 0;
|
|
4364
4383
|
const hasGin = deps["github.com/gin-gonic/gin"] !== void 0;
|
|
4384
|
+
const hasEcho = deps["github.com/labstack/echo/v4"] !== void 0 || deps["github.com/labstack/echo"] !== void 0;
|
|
4385
|
+
const hasFiber = deps["github.com/gofiber/fiber/v2"] !== void 0 || deps["github.com/gofiber/fiber/v3"] !== void 0;
|
|
4365
4386
|
const hasRails = deps["rails"] !== void 0;
|
|
4366
4387
|
const hasLaravel = deps["laravel/framework"] !== void 0;
|
|
4367
|
-
if (!hasExpress && !hasFastify && !hasHono && !hasNext && !hasNestjs && !hasFastapi && !hasFlask && !hasDjango && !hasGin && !hasRails && !hasLaravel)
|
|
4388
|
+
if (!hasExpress && !hasFastify && !hasHono && !hasNext && !hasNestjs && !hasFastapi && !hasFlask && !hasDjango && !hasGin && !hasEcho && !hasFiber && !hasRails && !hasLaravel)
|
|
4368
4389
|
continue;
|
|
4369
4390
|
const files = await loadSourceFiles(service.dir);
|
|
4370
4391
|
const mountPrefixes = hasExpress ? await expressMountPrefixes(files, service.dir, await loadTsPathConfig(service.dir)) : /* @__PURE__ */ new Map();
|
|
@@ -4388,7 +4409,10 @@ async function addRoutes(graph, services) {
|
|
|
4388
4409
|
} else if (isRb) {
|
|
4389
4410
|
routes = hasRails && relFile === "config/routes.rb" ? railsRoutesFromSource(file.content, rubyParser) : [];
|
|
4390
4411
|
} else if (isGo) {
|
|
4391
|
-
routes =
|
|
4412
|
+
if (hasGin) routes = ginRoutesFromSource(file.content, goParser);
|
|
4413
|
+
else if (hasEcho) routes = echoRoutesFromSource(file.content, goParser);
|
|
4414
|
+
else if (hasFiber) routes = fiberRoutesFromSource(file.content, goParser);
|
|
4415
|
+
else routes = [];
|
|
4392
4416
|
} else if (isPy) {
|
|
4393
4417
|
routes = hasFastapi || hasFlask ? pythonRoutesFromSource(file.content, pyParser, hasFastapi ? "fastapi" : "flask") : [];
|
|
4394
4418
|
if (hasDjango) routes = routes.concat(djangoRoutesFromSource(file.content, pyParser));
|
|
@@ -5998,6 +6022,12 @@ function parseGoMod(source) {
|
|
|
5998
6022
|
}
|
|
5999
6023
|
return { module: module2, ...goVersion ? { goVersion } : {}, dependencies };
|
|
6000
6024
|
}
|
|
6025
|
+
function goFramework(deps) {
|
|
6026
|
+
if (deps["github.com/gin-gonic/gin"]) return "gin";
|
|
6027
|
+
if (deps["github.com/labstack/echo/v4"] || deps["github.com/labstack/echo"]) return "echo";
|
|
6028
|
+
if (deps["github.com/gofiber/fiber/v2"] || deps["github.com/gofiber/fiber/v3"]) return "fiber";
|
|
6029
|
+
return void 0;
|
|
6030
|
+
}
|
|
6001
6031
|
async function discoverGoService(scanPath, dir) {
|
|
6002
6032
|
let raw;
|
|
6003
6033
|
try {
|
|
@@ -6009,6 +6039,7 @@ async function discoverGoService(scanPath, dir) {
|
|
|
6009
6039
|
if (!mod) return null;
|
|
6010
6040
|
const name = mod.module.split("/").filter(Boolean).pop() ?? mod.module;
|
|
6011
6041
|
const pkg = { name, dependencies: mod.dependencies };
|
|
6042
|
+
const framework = goFramework(mod.dependencies);
|
|
6012
6043
|
const node = {
|
|
6013
6044
|
id: (0, import_types9.serviceId)(name),
|
|
6014
6045
|
type: import_types9.NodeType.ServiceNode,
|
|
@@ -6016,7 +6047,7 @@ async function discoverGoService(scanPath, dir) {
|
|
|
6016
6047
|
language: "go",
|
|
6017
6048
|
dependencies: mod.dependencies,
|
|
6018
6049
|
repoPath: import_node_path11.default.relative(scanPath, dir),
|
|
6019
|
-
...
|
|
6050
|
+
...framework ? { framework } : {}
|
|
6020
6051
|
};
|
|
6021
6052
|
return { pkg, dir, node };
|
|
6022
6053
|
}
|
|
@@ -6916,7 +6947,7 @@ async function addSymbolEdges(graph, services) {
|
|
|
6916
6947
|
return best;
|
|
6917
6948
|
};
|
|
6918
6949
|
const requests = [];
|
|
6919
|
-
const
|
|
6950
|
+
const walk9 = (node) => {
|
|
6920
6951
|
if (node.type === "class_declaration" || node.type === "abstract_class_declaration" || node.type === "class") {
|
|
6921
6952
|
const self = localBySpan.get(`${node.startPosition.row + 1}:${node.endPosition.row + 1}`);
|
|
6922
6953
|
if (self && self.kind === "class") {
|
|
@@ -6962,10 +6993,10 @@ async function addSymbolEdges(graph, services) {
|
|
|
6962
6993
|
}
|
|
6963
6994
|
for (let i = 0; i < node.namedChildCount; i++) {
|
|
6964
6995
|
const child = node.namedChild(i);
|
|
6965
|
-
if (child)
|
|
6996
|
+
if (child) walk9(child);
|
|
6966
6997
|
}
|
|
6967
6998
|
};
|
|
6968
|
-
|
|
6999
|
+
walk9(root);
|
|
6969
7000
|
for (const req of requests) {
|
|
6970
7001
|
const targetSid = resolveTarget(req.targetName, req.wantKind);
|
|
6971
7002
|
if (!targetSid) continue;
|
|
@@ -7978,20 +8009,20 @@ var import_node_path29 = __toESM(require("path"), 1);
|
|
|
7978
8009
|
var import_types18 = require("@neat.is/types");
|
|
7979
8010
|
async function walkConfigFiles(dir) {
|
|
7980
8011
|
const out = [];
|
|
7981
|
-
async function
|
|
8012
|
+
async function walk9(current) {
|
|
7982
8013
|
const entries = await import_node_fs17.promises.readdir(current, { withFileTypes: true });
|
|
7983
8014
|
for (const entry2 of entries) {
|
|
7984
8015
|
const full = import_node_path29.default.join(current, entry2.name);
|
|
7985
8016
|
if (entry2.isDirectory()) {
|
|
7986
8017
|
if (IGNORED_DIRS.has(entry2.name)) continue;
|
|
7987
8018
|
if (await isPythonVenvDir(full)) continue;
|
|
7988
|
-
await
|
|
8019
|
+
await walk9(full);
|
|
7989
8020
|
} else if (entry2.isFile() && isConfigFile(entry2.name).match) {
|
|
7990
8021
|
out.push(full);
|
|
7991
8022
|
}
|
|
7992
8023
|
}
|
|
7993
8024
|
}
|
|
7994
|
-
await
|
|
8025
|
+
await walk9(dir);
|
|
7995
8026
|
return out;
|
|
7996
8027
|
}
|
|
7997
8028
|
async function addConfigNodes(graph, services, scanPath) {
|
|
@@ -8081,20 +8112,20 @@ function grpcMethodsFromProto(content, fqPackage) {
|
|
|
8081
8112
|
}
|
|
8082
8113
|
async function walkProtoFiles(dir) {
|
|
8083
8114
|
const out = [];
|
|
8084
|
-
async function
|
|
8115
|
+
async function walk9(current) {
|
|
8085
8116
|
const entries = await import_node_fs18.promises.readdir(current, { withFileTypes: true }).catch(() => []);
|
|
8086
8117
|
for (const entry2 of entries) {
|
|
8087
8118
|
const full = import_node_path30.default.join(current, entry2.name);
|
|
8088
8119
|
if (entry2.isDirectory()) {
|
|
8089
8120
|
if (IGNORED_DIRS.has(entry2.name)) continue;
|
|
8090
8121
|
if (await isPythonVenvDir(full)) continue;
|
|
8091
|
-
await
|
|
8122
|
+
await walk9(full);
|
|
8092
8123
|
} else if (entry2.isFile() && import_node_path30.default.extname(entry2.name) === PROTO_EXTENSION) {
|
|
8093
8124
|
out.push(full);
|
|
8094
8125
|
}
|
|
8095
8126
|
}
|
|
8096
8127
|
}
|
|
8097
|
-
await
|
|
8128
|
+
await walk9(dir);
|
|
8098
8129
|
return out;
|
|
8099
8130
|
}
|
|
8100
8131
|
async function addGrpcMethods(graph, services) {
|
|
@@ -8162,7 +8193,7 @@ async function addGrpcMethods(graph, services) {
|
|
|
8162
8193
|
|
|
8163
8194
|
// src/extract/calls/index.ts
|
|
8164
8195
|
init_cjs_shims();
|
|
8165
|
-
var
|
|
8196
|
+
var import_types37 = require("@neat.is/types");
|
|
8166
8197
|
|
|
8167
8198
|
// src/extract/calls/http.ts
|
|
8168
8199
|
init_cjs_shims();
|
|
@@ -8916,7 +8947,7 @@ function isFirestoreClientFactory(node) {
|
|
|
8916
8947
|
}
|
|
8917
8948
|
function firestoreClientVars(root) {
|
|
8918
8949
|
const vars = /* @__PURE__ */ new Set();
|
|
8919
|
-
const
|
|
8950
|
+
const walk9 = (node) => {
|
|
8920
8951
|
if (node.type === "variable_declarator") {
|
|
8921
8952
|
const name = node.childForFieldName("name");
|
|
8922
8953
|
let value = node.childForFieldName("value");
|
|
@@ -8925,9 +8956,9 @@ function firestoreClientVars(root) {
|
|
|
8925
8956
|
vars.add(name.text);
|
|
8926
8957
|
}
|
|
8927
8958
|
}
|
|
8928
|
-
for (const c of namedChildren(node))
|
|
8959
|
+
for (const c of namedChildren(node)) walk9(c);
|
|
8929
8960
|
};
|
|
8930
|
-
|
|
8961
|
+
walk9(root);
|
|
8931
8962
|
return vars;
|
|
8932
8963
|
}
|
|
8933
8964
|
function isClientExpr(node, clientVars) {
|
|
@@ -9082,7 +9113,7 @@ function firestoreEndpointsFromFile(file, serviceDir) {
|
|
|
9082
9113
|
}
|
|
9083
9114
|
s.add(field);
|
|
9084
9115
|
};
|
|
9085
|
-
const
|
|
9116
|
+
const walk9 = (node) => {
|
|
9086
9117
|
if (node.type === "call_expression") {
|
|
9087
9118
|
const fn = node.childForFieldName("function");
|
|
9088
9119
|
const line = node.startPosition.row + 1;
|
|
@@ -9122,9 +9153,9 @@ function firestoreEndpointsFromFile(file, serviceDir) {
|
|
|
9122
9153
|
}
|
|
9123
9154
|
}
|
|
9124
9155
|
}
|
|
9125
|
-
for (const c of namedChildren(node))
|
|
9156
|
+
for (const c of namedChildren(node)) walk9(c);
|
|
9126
9157
|
};
|
|
9127
|
-
|
|
9158
|
+
walk9(tree.rootNode);
|
|
9128
9159
|
const out = [];
|
|
9129
9160
|
for (const [collPath, line] of collLine) {
|
|
9130
9161
|
const byField = writes.get(collPath);
|
|
@@ -9919,7 +9950,7 @@ function drizzleEndpointsFromFile(file, serviceDir) {
|
|
|
9919
9950
|
const tree = parseSource3(parserForExt2(import_node_path42.default.extname(file.path)), file.content);
|
|
9920
9951
|
const out = [];
|
|
9921
9952
|
const seen = /* @__PURE__ */ new Set();
|
|
9922
|
-
const
|
|
9953
|
+
const walk9 = (node) => {
|
|
9923
9954
|
if (node.type === "call_expression") {
|
|
9924
9955
|
const fn = node.childForFieldName("function");
|
|
9925
9956
|
if (fn?.type === "identifier" && TABLE_BUILDERS.has(fn.text)) {
|
|
@@ -9947,9 +9978,9 @@ function drizzleEndpointsFromFile(file, serviceDir) {
|
|
|
9947
9978
|
}
|
|
9948
9979
|
}
|
|
9949
9980
|
}
|
|
9950
|
-
for (const c of namedChildren4(node))
|
|
9981
|
+
for (const c of namedChildren4(node)) walk9(c);
|
|
9951
9982
|
};
|
|
9952
|
-
|
|
9983
|
+
walk9(tree.rootNode);
|
|
9953
9984
|
return out;
|
|
9954
9985
|
}
|
|
9955
9986
|
function enclosingVarName(call) {
|
|
@@ -9971,7 +10002,7 @@ function enclosingVarName(call) {
|
|
|
9971
10002
|
function collectDrizzleTables(root) {
|
|
9972
10003
|
const tables = [];
|
|
9973
10004
|
const varToTable = /* @__PURE__ */ new Map();
|
|
9974
|
-
const
|
|
10005
|
+
const walk9 = (node) => {
|
|
9975
10006
|
if (node.type === "call_expression") {
|
|
9976
10007
|
const fn = node.childForFieldName("function");
|
|
9977
10008
|
if (fn?.type === "identifier" && TABLE_BUILDERS.has(fn.text)) {
|
|
@@ -9986,9 +10017,9 @@ function collectDrizzleTables(root) {
|
|
|
9986
10017
|
}
|
|
9987
10018
|
}
|
|
9988
10019
|
}
|
|
9989
|
-
for (const c of namedChildren4(node))
|
|
10020
|
+
for (const c of namedChildren4(node)) walk9(c);
|
|
9990
10021
|
};
|
|
9991
|
-
|
|
10022
|
+
walk9(root);
|
|
9992
10023
|
return { tables, varToTable };
|
|
9993
10024
|
}
|
|
9994
10025
|
function referencesTargetVar(call) {
|
|
@@ -10011,7 +10042,7 @@ function drizzleForeignKeys(file, serviceDir) {
|
|
|
10011
10042
|
const seen = /* @__PURE__ */ new Set();
|
|
10012
10043
|
for (const table of tables) {
|
|
10013
10044
|
if (!table.object) continue;
|
|
10014
|
-
const
|
|
10045
|
+
const walk9 = (node) => {
|
|
10015
10046
|
if (node.type === "call_expression") {
|
|
10016
10047
|
const targetVar = referencesTargetVar(node);
|
|
10017
10048
|
const parentTable = targetVar ? varToTable.get(targetVar) : void 0;
|
|
@@ -10032,9 +10063,9 @@ function drizzleForeignKeys(file, serviceDir) {
|
|
|
10032
10063
|
}
|
|
10033
10064
|
}
|
|
10034
10065
|
}
|
|
10035
|
-
for (const c of namedChildren4(node))
|
|
10066
|
+
for (const c of namedChildren4(node)) walk9(c);
|
|
10036
10067
|
};
|
|
10037
|
-
|
|
10068
|
+
walk9(table.object);
|
|
10038
10069
|
}
|
|
10039
10070
|
return out;
|
|
10040
10071
|
}
|
|
@@ -11114,15 +11145,531 @@ function goSqlEndpointsFromFile(file, serviceDir) {
|
|
|
11114
11145
|
return out;
|
|
11115
11146
|
}
|
|
11116
11147
|
|
|
11148
|
+
// src/extract/calls/gorm.ts
|
|
11149
|
+
init_cjs_shims();
|
|
11150
|
+
var import_node_path49 = __toESM(require("path"), 1);
|
|
11151
|
+
var import_tree_sitter15 = __toESM(require("tree-sitter"), 1);
|
|
11152
|
+
var import_tree_sitter_go4 = __toESM(require("tree-sitter-go"), 1);
|
|
11153
|
+
var import_types36 = require("@neat.is/types");
|
|
11154
|
+
var GORM_IMPORT_RE = /gorm\.io\/gorm/;
|
|
11155
|
+
var PARSE_CHUNK11 = 16384;
|
|
11156
|
+
function makeGoParser3() {
|
|
11157
|
+
const p = new import_tree_sitter15.default();
|
|
11158
|
+
p.setLanguage(import_tree_sitter_go4.default);
|
|
11159
|
+
return p;
|
|
11160
|
+
}
|
|
11161
|
+
function parseSource10(parser, source) {
|
|
11162
|
+
return parser.parse(
|
|
11163
|
+
(index) => index >= source.length ? "" : source.slice(index, index + PARSE_CHUNK11)
|
|
11164
|
+
);
|
|
11165
|
+
}
|
|
11166
|
+
function walk8(node, visit) {
|
|
11167
|
+
visit(node);
|
|
11168
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
11169
|
+
const c = node.namedChild(i);
|
|
11170
|
+
if (c) walk8(c, visit);
|
|
11171
|
+
}
|
|
11172
|
+
}
|
|
11173
|
+
var COMMON_INITIALISMS = [
|
|
11174
|
+
"ASCII",
|
|
11175
|
+
"HTTPS",
|
|
11176
|
+
"UTF8",
|
|
11177
|
+
"XSRF",
|
|
11178
|
+
"HTML",
|
|
11179
|
+
"HTTP",
|
|
11180
|
+
"JSON",
|
|
11181
|
+
"UUID",
|
|
11182
|
+
"XMPP",
|
|
11183
|
+
"ACL",
|
|
11184
|
+
"API",
|
|
11185
|
+
"CPU",
|
|
11186
|
+
"CSS",
|
|
11187
|
+
"DNS",
|
|
11188
|
+
"EOF",
|
|
11189
|
+
"GUID",
|
|
11190
|
+
"LHS",
|
|
11191
|
+
"QPS",
|
|
11192
|
+
"RAM",
|
|
11193
|
+
"RHS",
|
|
11194
|
+
"RPC",
|
|
11195
|
+
"SLA",
|
|
11196
|
+
"SQL",
|
|
11197
|
+
"SSH",
|
|
11198
|
+
"TCP",
|
|
11199
|
+
"TLS",
|
|
11200
|
+
"TTL",
|
|
11201
|
+
"UDP",
|
|
11202
|
+
"UID",
|
|
11203
|
+
"URI",
|
|
11204
|
+
"URL",
|
|
11205
|
+
"UID",
|
|
11206
|
+
"XSS",
|
|
11207
|
+
"ID",
|
|
11208
|
+
"IP",
|
|
11209
|
+
"UI",
|
|
11210
|
+
"VM",
|
|
11211
|
+
"XML"
|
|
11212
|
+
].sort((a, b) => b.length - a.length);
|
|
11213
|
+
function titleCase(word) {
|
|
11214
|
+
return word.charAt(0) + word.slice(1).toLowerCase();
|
|
11215
|
+
}
|
|
11216
|
+
function replaceInitialisms(name) {
|
|
11217
|
+
let out = "";
|
|
11218
|
+
let i = 0;
|
|
11219
|
+
while (i < name.length) {
|
|
11220
|
+
let matched = false;
|
|
11221
|
+
for (const init of COMMON_INITIALISMS) {
|
|
11222
|
+
if (name.startsWith(init, i)) {
|
|
11223
|
+
out += titleCase(init);
|
|
11224
|
+
i += init.length;
|
|
11225
|
+
matched = true;
|
|
11226
|
+
break;
|
|
11227
|
+
}
|
|
11228
|
+
}
|
|
11229
|
+
if (!matched) {
|
|
11230
|
+
out += name[i];
|
|
11231
|
+
i++;
|
|
11232
|
+
}
|
|
11233
|
+
}
|
|
11234
|
+
return out;
|
|
11235
|
+
}
|
|
11236
|
+
var isUpper = (c) => c >= "A" && c <= "Z";
|
|
11237
|
+
var isDigit = (c) => c >= "0" && c <= "9";
|
|
11238
|
+
function toDBName(name) {
|
|
11239
|
+
if (name === "") return "";
|
|
11240
|
+
const value = replaceInitialisms(name);
|
|
11241
|
+
if (value.length === 1) return value.toLowerCase();
|
|
11242
|
+
let buf = "";
|
|
11243
|
+
let lastCase = false;
|
|
11244
|
+
let curCase = isUpper(value[0]);
|
|
11245
|
+
for (let i = 0; i < value.length - 1; i++) {
|
|
11246
|
+
const v = value[i];
|
|
11247
|
+
const nextCase = isUpper(value[i + 1]);
|
|
11248
|
+
const nextNumber = isDigit(value[i + 1]);
|
|
11249
|
+
if (curCase) {
|
|
11250
|
+
if (lastCase && (nextCase || nextNumber)) {
|
|
11251
|
+
buf += v.toLowerCase();
|
|
11252
|
+
} else {
|
|
11253
|
+
if (i > 0 && value[i - 1] !== "_" && lastCase !== curCase) buf += "_";
|
|
11254
|
+
buf += v.toLowerCase();
|
|
11255
|
+
}
|
|
11256
|
+
} else {
|
|
11257
|
+
buf += v;
|
|
11258
|
+
}
|
|
11259
|
+
lastCase = curCase;
|
|
11260
|
+
curCase = nextCase;
|
|
11261
|
+
}
|
|
11262
|
+
const last = value[value.length - 1];
|
|
11263
|
+
if (curCase) {
|
|
11264
|
+
if (!lastCase && value.length > 1) buf += "_";
|
|
11265
|
+
buf += last.toLowerCase();
|
|
11266
|
+
} else {
|
|
11267
|
+
buf += last;
|
|
11268
|
+
}
|
|
11269
|
+
return buf;
|
|
11270
|
+
}
|
|
11271
|
+
var UNCOUNTABLE = /* @__PURE__ */ new Set([
|
|
11272
|
+
"equipment",
|
|
11273
|
+
"information",
|
|
11274
|
+
"rice",
|
|
11275
|
+
"money",
|
|
11276
|
+
"species",
|
|
11277
|
+
"series",
|
|
11278
|
+
"fish",
|
|
11279
|
+
"sheep",
|
|
11280
|
+
"jeans",
|
|
11281
|
+
"police"
|
|
11282
|
+
]);
|
|
11283
|
+
var IRREGULAR = [
|
|
11284
|
+
["person", "people"],
|
|
11285
|
+
["man", "men"],
|
|
11286
|
+
["child", "children"],
|
|
11287
|
+
["sex", "sexes"],
|
|
11288
|
+
["move", "moves"]
|
|
11289
|
+
];
|
|
11290
|
+
var PLURAL_RULES = [
|
|
11291
|
+
[/(quiz)$/i, "$1zes"],
|
|
11292
|
+
[/^(ox)$/i, "$1en"],
|
|
11293
|
+
[/([ml])ouse$/i, "$1ice"],
|
|
11294
|
+
[/(matr|vert|ind)(?:ix|ex)$/i, "$1ices"],
|
|
11295
|
+
[/(x|ch|ss|sh)$/i, "$1es"],
|
|
11296
|
+
[/([^aeiouy]|qu)y$/i, "$1ies"],
|
|
11297
|
+
[/(hive)$/i, "$1s"],
|
|
11298
|
+
[/(?:([^f])fe|([lr])f)$/i, "$1$2ves"],
|
|
11299
|
+
[/sis$/i, "ses"],
|
|
11300
|
+
[/([ti])um$/i, "$1a"],
|
|
11301
|
+
[/([ti])a$/i, "$1a"],
|
|
11302
|
+
[/(buffal|tomat)o$/i, "$1oes"],
|
|
11303
|
+
[/(bu)s$/i, "$1ses"],
|
|
11304
|
+
[/(alias|status)$/i, "$1es"],
|
|
11305
|
+
[/(octop|vir)i$/i, "$1i"],
|
|
11306
|
+
[/(octop|vir)us$/i, "$1i"],
|
|
11307
|
+
[/(ax|test)is$/i, "$1es"],
|
|
11308
|
+
[/s$/i, "s"]
|
|
11309
|
+
];
|
|
11310
|
+
function pluralize3(word) {
|
|
11311
|
+
if (word === "") return word;
|
|
11312
|
+
const lower = word.toLowerCase();
|
|
11313
|
+
for (const u of UNCOUNTABLE) {
|
|
11314
|
+
if (lower === u || lower.endsWith("_" + u)) return word;
|
|
11315
|
+
}
|
|
11316
|
+
for (const [sing, plur] of IRREGULAR) {
|
|
11317
|
+
const re = new RegExp(sing + "$", "i");
|
|
11318
|
+
if (re.test(word)) return word.replace(re, plur);
|
|
11319
|
+
}
|
|
11320
|
+
for (const [re, rep] of PLURAL_RULES) {
|
|
11321
|
+
if (re.test(word)) return word.replace(re, rep);
|
|
11322
|
+
}
|
|
11323
|
+
return word + "s";
|
|
11324
|
+
}
|
|
11325
|
+
function deriveTableName(structName) {
|
|
11326
|
+
return pluralize3(toDBName(structName));
|
|
11327
|
+
}
|
|
11328
|
+
function stringLiteralValue(node) {
|
|
11329
|
+
if (!node) return null;
|
|
11330
|
+
if (node.type === "interpreted_string_literal" || node.type === "raw_string_literal") {
|
|
11331
|
+
const t = node.text;
|
|
11332
|
+
return t.length >= 2 ? t.slice(1, -1) : "";
|
|
11333
|
+
}
|
|
11334
|
+
return null;
|
|
11335
|
+
}
|
|
11336
|
+
function parseGormTag(tagNode) {
|
|
11337
|
+
const tag = {};
|
|
11338
|
+
if (!tagNode) return tag;
|
|
11339
|
+
let inner = tagNode.text;
|
|
11340
|
+
if (inner.length >= 2) inner = inner.slice(1, -1);
|
|
11341
|
+
if (tagNode.type === "interpreted_string_literal") inner = inner.replace(/\\"/g, '"');
|
|
11342
|
+
const m = inner.match(/gorm:"([^"]*)"/);
|
|
11343
|
+
if (!m) return tag;
|
|
11344
|
+
for (const part of m[1].split(";")) {
|
|
11345
|
+
if (part === "") continue;
|
|
11346
|
+
const idx = part.indexOf(":");
|
|
11347
|
+
const key = (idx >= 0 ? part.slice(0, idx) : part).trim().toLowerCase();
|
|
11348
|
+
const value = idx >= 0 ? part.slice(idx + 1).trim() : "";
|
|
11349
|
+
if (key === "-") tag.skip = true;
|
|
11350
|
+
else if (key === "column") tag.column = value;
|
|
11351
|
+
else if (key === "primarykey" || key === "primary_key") tag.primaryKey = true;
|
|
11352
|
+
else if (key === "foreignkey") tag.foreignKey = value;
|
|
11353
|
+
else if (key === "many2many") tag.many2many = value;
|
|
11354
|
+
else if (key === "embedded") tag.embedded = true;
|
|
11355
|
+
else if (key === "embeddedprefix") tag.embeddedPrefix = value;
|
|
11356
|
+
}
|
|
11357
|
+
return tag;
|
|
11358
|
+
}
|
|
11359
|
+
function unwrapType(typeNode) {
|
|
11360
|
+
let isSlice = false;
|
|
11361
|
+
let isPointer = false;
|
|
11362
|
+
let n = typeNode;
|
|
11363
|
+
while (n && (n.type === "slice_type" || n.type === "array_type" || n.type === "pointer_type")) {
|
|
11364
|
+
if (n.type === "slice_type" || n.type === "array_type") isSlice = true;
|
|
11365
|
+
if (n.type === "pointer_type") isPointer = true;
|
|
11366
|
+
n = n.childForFieldName("element") ?? n.namedChild(n.namedChildCount - 1);
|
|
11367
|
+
}
|
|
11368
|
+
if (!n) return { name: null, qualifier: null, isSlice, isPointer, isQualified: false };
|
|
11369
|
+
if (n.type === "type_identifier") {
|
|
11370
|
+
return { name: n.text, qualifier: null, isSlice, isPointer, isQualified: false };
|
|
11371
|
+
}
|
|
11372
|
+
if (n.type === "qualified_type") {
|
|
11373
|
+
const pkg = n.childForFieldName("package")?.text ?? n.namedChild(0)?.text ?? null;
|
|
11374
|
+
const nm = n.childForFieldName("name")?.text ?? n.namedChild(1)?.text ?? null;
|
|
11375
|
+
return { name: nm, qualifier: pkg, isSlice, isPointer, isQualified: true };
|
|
11376
|
+
}
|
|
11377
|
+
return { name: null, qualifier: null, isSlice, isPointer, isQualified: false };
|
|
11378
|
+
}
|
|
11379
|
+
function readField(fieldDecl) {
|
|
11380
|
+
const names = [];
|
|
11381
|
+
let tagNode = null;
|
|
11382
|
+
for (let i = 0; i < fieldDecl.namedChildCount; i++) {
|
|
11383
|
+
const c = fieldDecl.namedChild(i);
|
|
11384
|
+
if (!c) continue;
|
|
11385
|
+
if (c.type === "field_identifier") names.push(c.text);
|
|
11386
|
+
else if (c.type === "raw_string_literal" || c.type === "interpreted_string_literal") tagNode = c;
|
|
11387
|
+
}
|
|
11388
|
+
const typeNode = fieldDecl.childForFieldName("type");
|
|
11389
|
+
const t = unwrapType(typeNode);
|
|
11390
|
+
return {
|
|
11391
|
+
names,
|
|
11392
|
+
typeName: t.name,
|
|
11393
|
+
qualifier: t.qualifier,
|
|
11394
|
+
isSlice: t.isSlice,
|
|
11395
|
+
isPointer: t.isPointer,
|
|
11396
|
+
isQualified: t.isQualified,
|
|
11397
|
+
tag: parseGormTag(tagNode),
|
|
11398
|
+
line: fieldDecl.startPosition.row + 1
|
|
11399
|
+
};
|
|
11400
|
+
}
|
|
11401
|
+
function collectStructs(tree) {
|
|
11402
|
+
const structs = /* @__PURE__ */ new Map();
|
|
11403
|
+
walk8(tree.rootNode, (node) => {
|
|
11404
|
+
if (node.type !== "type_spec") return;
|
|
11405
|
+
const nameNode = node.childForFieldName("name");
|
|
11406
|
+
const typeNode = node.childForFieldName("type");
|
|
11407
|
+
if (!nameNode || typeNode?.type !== "struct_type") return;
|
|
11408
|
+
const list = typeNode.childForFieldName("body") ?? typeNode.namedChild(0);
|
|
11409
|
+
const fields = [];
|
|
11410
|
+
if (list && list.type === "field_declaration_list") {
|
|
11411
|
+
for (let i = 0; i < list.namedChildCount; i++) {
|
|
11412
|
+
const fd = list.namedChild(i);
|
|
11413
|
+
if (fd?.type === "field_declaration") fields.push(readField(fd));
|
|
11414
|
+
}
|
|
11415
|
+
}
|
|
11416
|
+
structs.set(nameNode.text, {
|
|
11417
|
+
name: nameNode.text,
|
|
11418
|
+
fields,
|
|
11419
|
+
line: node.startPosition.row + 1
|
|
11420
|
+
});
|
|
11421
|
+
});
|
|
11422
|
+
return structs;
|
|
11423
|
+
}
|
|
11424
|
+
var GORM_MODEL_METHODS = /* @__PURE__ */ new Set([
|
|
11425
|
+
"AutoMigrate",
|
|
11426
|
+
"Model",
|
|
11427
|
+
"Create",
|
|
11428
|
+
"Find",
|
|
11429
|
+
"First",
|
|
11430
|
+
"Take",
|
|
11431
|
+
"Last",
|
|
11432
|
+
"Save",
|
|
11433
|
+
"Delete",
|
|
11434
|
+
"Where",
|
|
11435
|
+
"FirstOrCreate",
|
|
11436
|
+
"FirstOrInit"
|
|
11437
|
+
]);
|
|
11438
|
+
function compositeStructName(arg) {
|
|
11439
|
+
let n = arg;
|
|
11440
|
+
if (n.type === "unary_expression") n = n.childForFieldName("operand") ?? n.namedChild(0);
|
|
11441
|
+
if (!n || n.type !== "composite_literal") return null;
|
|
11442
|
+
const typeNode = n.childForFieldName("type");
|
|
11443
|
+
if (!typeNode) return null;
|
|
11444
|
+
if (typeNode.type === "type_identifier") return typeNode.text;
|
|
11445
|
+
if (typeNode.type === "qualified_type") {
|
|
11446
|
+
return typeNode.childForFieldName("name")?.text ?? typeNode.namedChild(1)?.text ?? null;
|
|
11447
|
+
}
|
|
11448
|
+
return null;
|
|
11449
|
+
}
|
|
11450
|
+
function collectCallModels(tree) {
|
|
11451
|
+
const models = /* @__PURE__ */ new Set();
|
|
11452
|
+
walk8(tree.rootNode, (node) => {
|
|
11453
|
+
if (node.type !== "call_expression") return;
|
|
11454
|
+
const fn = node.childForFieldName("function");
|
|
11455
|
+
if (fn?.type !== "selector_expression") return;
|
|
11456
|
+
const method = fn.childForFieldName("field")?.text;
|
|
11457
|
+
if (!method || !GORM_MODEL_METHODS.has(method)) return;
|
|
11458
|
+
const args = node.childForFieldName("arguments");
|
|
11459
|
+
if (!args) return;
|
|
11460
|
+
for (let i = 0; i < args.namedChildCount; i++) {
|
|
11461
|
+
const arg = args.namedChild(i);
|
|
11462
|
+
if (!arg) continue;
|
|
11463
|
+
const name = compositeStructName(arg);
|
|
11464
|
+
if (name) models.add(name);
|
|
11465
|
+
}
|
|
11466
|
+
});
|
|
11467
|
+
return models;
|
|
11468
|
+
}
|
|
11469
|
+
function collectTableNameOverrides(tree) {
|
|
11470
|
+
const overrides = /* @__PURE__ */ new Map();
|
|
11471
|
+
const declarers = /* @__PURE__ */ new Set();
|
|
11472
|
+
walk8(tree.rootNode, (node) => {
|
|
11473
|
+
if (node.type !== "method_declaration") return;
|
|
11474
|
+
if (node.childForFieldName("name")?.text !== "TableName") return;
|
|
11475
|
+
const receiver = node.childForFieldName("receiver");
|
|
11476
|
+
if (!receiver) return;
|
|
11477
|
+
let recvType = null;
|
|
11478
|
+
for (let i = 0; i < receiver.namedChildCount; i++) {
|
|
11479
|
+
const pd = receiver.namedChild(i);
|
|
11480
|
+
if (pd?.type !== "parameter_declaration") continue;
|
|
11481
|
+
const t = unwrapType(pd.childForFieldName("type"));
|
|
11482
|
+
recvType = t.name;
|
|
11483
|
+
}
|
|
11484
|
+
if (!recvType) return;
|
|
11485
|
+
declarers.add(recvType);
|
|
11486
|
+
const body = node.childForFieldName("body");
|
|
11487
|
+
if (!body) return;
|
|
11488
|
+
let literal = null;
|
|
11489
|
+
walk8(body, (n) => {
|
|
11490
|
+
if (literal !== null) return;
|
|
11491
|
+
if (n.type !== "return_statement") return;
|
|
11492
|
+
const exprList = n.namedChild(0);
|
|
11493
|
+
const first = exprList?.namedChild(0) ?? exprList;
|
|
11494
|
+
const v = stringLiteralValue(first);
|
|
11495
|
+
if (v) literal = v;
|
|
11496
|
+
});
|
|
11497
|
+
if (literal !== null) overrides.set(recvType, literal);
|
|
11498
|
+
});
|
|
11499
|
+
return { overrides, declarers };
|
|
11500
|
+
}
|
|
11501
|
+
function isRelationField(field, structs) {
|
|
11502
|
+
if (field.names.length === 0) return false;
|
|
11503
|
+
if (field.isQualified) return false;
|
|
11504
|
+
if (!field.typeName) return false;
|
|
11505
|
+
return structs.has(field.typeName);
|
|
11506
|
+
}
|
|
11507
|
+
function isGormModelEmbed(field) {
|
|
11508
|
+
return field.names.length === 0 && field.qualifier === "gorm" && field.typeName === "Model";
|
|
11509
|
+
}
|
|
11510
|
+
function analyze(tree) {
|
|
11511
|
+
const structs = collectStructs(tree);
|
|
11512
|
+
const { overrides, declarers } = collectTableNameOverrides(tree);
|
|
11513
|
+
const callModels = collectCallModels(tree);
|
|
11514
|
+
const models = /* @__PURE__ */ new Set();
|
|
11515
|
+
for (const [name, info] of structs) {
|
|
11516
|
+
if (info.fields.some(isGormModelEmbed)) models.add(name);
|
|
11517
|
+
}
|
|
11518
|
+
for (const name of callModels) if (structs.has(name)) models.add(name);
|
|
11519
|
+
for (const name of declarers) if (structs.has(name)) models.add(name);
|
|
11520
|
+
let grew = true;
|
|
11521
|
+
while (grew) {
|
|
11522
|
+
grew = false;
|
|
11523
|
+
for (const name of Array.from(models)) {
|
|
11524
|
+
const info = structs.get(name);
|
|
11525
|
+
if (!info) continue;
|
|
11526
|
+
for (const field of info.fields) {
|
|
11527
|
+
if (!isRelationField(field, structs)) continue;
|
|
11528
|
+
const target = field.typeName;
|
|
11529
|
+
if (!models.has(target) && structs.has(target)) {
|
|
11530
|
+
models.add(target);
|
|
11531
|
+
grew = true;
|
|
11532
|
+
}
|
|
11533
|
+
}
|
|
11534
|
+
}
|
|
11535
|
+
}
|
|
11536
|
+
const tableFor = (structName) => overrides.get(structName) ?? deriveTableName(structName);
|
|
11537
|
+
return { structs, models, tableFor };
|
|
11538
|
+
}
|
|
11539
|
+
function collectColumns(struct, structs, seen, prefix, out, emitted) {
|
|
11540
|
+
if (seen.has(struct.name)) return;
|
|
11541
|
+
seen.add(struct.name);
|
|
11542
|
+
const add = (col) => {
|
|
11543
|
+
const full = prefix + col;
|
|
11544
|
+
if (!emitted.has(full)) {
|
|
11545
|
+
emitted.add(full);
|
|
11546
|
+
out.push(full);
|
|
11547
|
+
}
|
|
11548
|
+
};
|
|
11549
|
+
for (const field of struct.fields) {
|
|
11550
|
+
if (field.tag.skip) continue;
|
|
11551
|
+
if (field.names.length === 0) {
|
|
11552
|
+
if (isGormModelEmbed(field)) {
|
|
11553
|
+
add("id");
|
|
11554
|
+
add("created_at");
|
|
11555
|
+
add("updated_at");
|
|
11556
|
+
add("deleted_at");
|
|
11557
|
+
} else if (!field.isQualified && field.typeName && structs.has(field.typeName)) {
|
|
11558
|
+
collectColumns(structs.get(field.typeName), structs, seen, prefix, out, emitted);
|
|
11559
|
+
}
|
|
11560
|
+
continue;
|
|
11561
|
+
}
|
|
11562
|
+
if (field.tag.embedded && !field.isQualified && field.typeName && structs.has(field.typeName)) {
|
|
11563
|
+
collectColumns(
|
|
11564
|
+
structs.get(field.typeName),
|
|
11565
|
+
structs,
|
|
11566
|
+
seen,
|
|
11567
|
+
prefix + (field.tag.embeddedPrefix ?? ""),
|
|
11568
|
+
out,
|
|
11569
|
+
emitted
|
|
11570
|
+
);
|
|
11571
|
+
continue;
|
|
11572
|
+
}
|
|
11573
|
+
if (isRelationField(field, structs)) continue;
|
|
11574
|
+
if (field.names.length === 1 && field.tag.column) {
|
|
11575
|
+
add(field.tag.column);
|
|
11576
|
+
} else {
|
|
11577
|
+
for (const n of field.names) add(toDBName(n));
|
|
11578
|
+
}
|
|
11579
|
+
}
|
|
11580
|
+
seen.delete(struct.name);
|
|
11581
|
+
}
|
|
11582
|
+
function gormEndpointsFromFile(file, serviceDir) {
|
|
11583
|
+
if (import_node_path49.default.extname(file.path) !== ".go") return [];
|
|
11584
|
+
if (!GORM_IMPORT_RE.test(file.content)) return [];
|
|
11585
|
+
const tree = parseSource10(makeGoParser3(), file.content);
|
|
11586
|
+
const { structs, models, tableFor } = analyze(tree);
|
|
11587
|
+
const out = [];
|
|
11588
|
+
const seenTables = /* @__PURE__ */ new Set();
|
|
11589
|
+
for (const name of models) {
|
|
11590
|
+
const struct = structs.get(name);
|
|
11591
|
+
if (!struct) continue;
|
|
11592
|
+
const table = tableFor(name);
|
|
11593
|
+
if (seenTables.has(table)) continue;
|
|
11594
|
+
seenTables.add(table);
|
|
11595
|
+
const columns = [];
|
|
11596
|
+
collectColumns(struct, structs, /* @__PURE__ */ new Set(), "", columns, /* @__PURE__ */ new Set());
|
|
11597
|
+
out.push({
|
|
11598
|
+
infraId: (0, import_types36.infraId)("sql-table", table),
|
|
11599
|
+
name: table,
|
|
11600
|
+
kind: "sql-table",
|
|
11601
|
+
edgeType: "CALLS",
|
|
11602
|
+
confidenceKind: "structural",
|
|
11603
|
+
...columns.length > 0 ? { columns } : {},
|
|
11604
|
+
evidence: {
|
|
11605
|
+
file: toPosix(import_node_path49.default.relative(serviceDir, file.path)),
|
|
11606
|
+
line: struct.line,
|
|
11607
|
+
snippet: snippet(file.content, struct.line)
|
|
11608
|
+
}
|
|
11609
|
+
});
|
|
11610
|
+
}
|
|
11611
|
+
return out;
|
|
11612
|
+
}
|
|
11613
|
+
function gormForeignKeys(file, serviceDir) {
|
|
11614
|
+
if (import_node_path49.default.extname(file.path) !== ".go") return [];
|
|
11615
|
+
if (!GORM_IMPORT_RE.test(file.content)) return [];
|
|
11616
|
+
const tree = parseSource10(makeGoParser3(), file.content);
|
|
11617
|
+
const { structs, models, tableFor } = analyze(tree);
|
|
11618
|
+
const out = [];
|
|
11619
|
+
const seen = /* @__PURE__ */ new Set();
|
|
11620
|
+
const emit = (childTable, parentTable, line) => {
|
|
11621
|
+
if (!childTable || !parentTable || childTable === parentTable) return;
|
|
11622
|
+
const key = `${childTable}->${parentTable}`;
|
|
11623
|
+
if (seen.has(key)) return;
|
|
11624
|
+
seen.add(key);
|
|
11625
|
+
out.push({
|
|
11626
|
+
childTable,
|
|
11627
|
+
parentTable,
|
|
11628
|
+
evidence: {
|
|
11629
|
+
file: toPosix(import_node_path49.default.relative(serviceDir, file.path)),
|
|
11630
|
+
line,
|
|
11631
|
+
snippet: snippet(file.content, line)
|
|
11632
|
+
}
|
|
11633
|
+
});
|
|
11634
|
+
};
|
|
11635
|
+
for (const name of models) {
|
|
11636
|
+
const struct = structs.get(name);
|
|
11637
|
+
if (!struct) continue;
|
|
11638
|
+
const thisTable = tableFor(name);
|
|
11639
|
+
const scalarNames = new Set(
|
|
11640
|
+
struct.fields.filter((f) => f.names.length > 0 && !isRelationField(f, structs)).flatMap((f) => f.names)
|
|
11641
|
+
);
|
|
11642
|
+
for (const field of struct.fields) {
|
|
11643
|
+
if (field.tag.skip) continue;
|
|
11644
|
+
if (!isRelationField(field, structs)) continue;
|
|
11645
|
+
const relTable = tableFor(field.typeName);
|
|
11646
|
+
if (field.tag.many2many) {
|
|
11647
|
+
emit(field.tag.many2many, thisTable, field.line);
|
|
11648
|
+
emit(field.tag.many2many, relTable, field.line);
|
|
11649
|
+
continue;
|
|
11650
|
+
}
|
|
11651
|
+
if (field.isSlice) {
|
|
11652
|
+
emit(relTable, thisTable, field.line);
|
|
11653
|
+
continue;
|
|
11654
|
+
}
|
|
11655
|
+
const convFk = field.names[0] + "ID";
|
|
11656
|
+
const belongsTo = scalarNames.has(convFk) || (field.tag.foreignKey ? scalarNames.has(field.tag.foreignKey) : false);
|
|
11657
|
+
if (belongsTo) emit(thisTable, relTable, field.line);
|
|
11658
|
+
else emit(relTable, thisTable, field.line);
|
|
11659
|
+
}
|
|
11660
|
+
}
|
|
11661
|
+
return out;
|
|
11662
|
+
}
|
|
11663
|
+
|
|
11117
11664
|
// src/extract/calls/index.ts
|
|
11118
11665
|
function edgeTypeFromEndpoint(ep) {
|
|
11119
11666
|
switch (ep.edgeType) {
|
|
11120
11667
|
case "PUBLISHES_TO":
|
|
11121
|
-
return
|
|
11668
|
+
return import_types37.EdgeType.PUBLISHES_TO;
|
|
11122
11669
|
case "CONSUMES_FROM":
|
|
11123
|
-
return
|
|
11670
|
+
return import_types37.EdgeType.CONSUMES_FROM;
|
|
11124
11671
|
default:
|
|
11125
|
-
return
|
|
11672
|
+
return import_types37.EdgeType.CALLS;
|
|
11126
11673
|
}
|
|
11127
11674
|
}
|
|
11128
11675
|
function isAwsKind(kind) {
|
|
@@ -11155,6 +11702,11 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
11155
11702
|
} catch (err) {
|
|
11156
11703
|
recordExtractionError("go SQL call extraction", file.path, err);
|
|
11157
11704
|
}
|
|
11705
|
+
try {
|
|
11706
|
+
endpoints.push(...gormEndpointsFromFile(file, service.dir));
|
|
11707
|
+
} catch (err) {
|
|
11708
|
+
recordExtractionError("gorm data-axis extraction", file.path, err);
|
|
11709
|
+
}
|
|
11158
11710
|
try {
|
|
11159
11711
|
endpoints.push(...railsSchemaEndpointsFromFile(file, service.dir));
|
|
11160
11712
|
endpoints.push(...railsModelEndpointsFromFile(file, service.dir));
|
|
@@ -11177,7 +11729,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
11177
11729
|
if (!graph.hasNode(ep.infraId)) {
|
|
11178
11730
|
const node = {
|
|
11179
11731
|
id: ep.infraId,
|
|
11180
|
-
type:
|
|
11732
|
+
type: import_types37.NodeType.InfraNode,
|
|
11181
11733
|
name: ep.name,
|
|
11182
11734
|
// #238 — `aws-*` covers AWS-SDK client kinds (aws-s3, aws-dynamodb,
|
|
11183
11735
|
// aws-cognito-identity-provider, …); `s3-` / `dynamodb-` cover the
|
|
@@ -11190,21 +11742,21 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
11190
11742
|
}
|
|
11191
11743
|
if (ep.columns && ep.columns.length > 0) {
|
|
11192
11744
|
const node = graph.getNodeAttributes(ep.infraId);
|
|
11193
|
-
if (node.type ===
|
|
11745
|
+
if (node.type === import_types37.NodeType.InfraNode) {
|
|
11194
11746
|
graph.replaceNodeAttributes(ep.infraId, {
|
|
11195
11747
|
...node,
|
|
11196
11748
|
columns: foldColumns(
|
|
11197
11749
|
node.columns,
|
|
11198
11750
|
ep.columns,
|
|
11199
|
-
|
|
11200
|
-
(0,
|
|
11751
|
+
import_types37.Provenance.EXTRACTED,
|
|
11752
|
+
(0, import_types37.confidenceForExtracted)(ep.confidenceKind)
|
|
11201
11753
|
)
|
|
11202
11754
|
});
|
|
11203
11755
|
}
|
|
11204
11756
|
}
|
|
11205
11757
|
if (ep.sdkWrites && Object.keys(ep.sdkWrites).length > 0) {
|
|
11206
11758
|
const node = graph.getNodeAttributes(ep.infraId);
|
|
11207
|
-
if (node.type ===
|
|
11759
|
+
if (node.type === import_types37.NodeType.InfraNode) {
|
|
11208
11760
|
graph.replaceNodeAttributes(ep.infraId, {
|
|
11209
11761
|
...node,
|
|
11210
11762
|
columns: foldSdkWrites(node.columns, ep.sdkWrites)
|
|
@@ -11212,7 +11764,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
11212
11764
|
}
|
|
11213
11765
|
}
|
|
11214
11766
|
const edgeType = edgeTypeFromEndpoint(ep);
|
|
11215
|
-
const confidence = (0,
|
|
11767
|
+
const confidence = (0, import_types37.confidenceForExtracted)(ep.confidenceKind);
|
|
11216
11768
|
const relFile = toPosix(ep.evidence.file);
|
|
11217
11769
|
const { fileNodeId, nodesAdded: n, edgesAdded: e } = ensureFileNode(
|
|
11218
11770
|
graph,
|
|
@@ -11222,7 +11774,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
11222
11774
|
);
|
|
11223
11775
|
nodesAdded += n;
|
|
11224
11776
|
edgesAdded += e;
|
|
11225
|
-
if (!(0,
|
|
11777
|
+
if (!(0, import_types37.passesExtractedFloor)(confidence)) {
|
|
11226
11778
|
noteExtractedDropped({
|
|
11227
11779
|
source: fileNodeId,
|
|
11228
11780
|
target: ep.infraId,
|
|
@@ -11242,7 +11794,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
11242
11794
|
source: fileNodeId,
|
|
11243
11795
|
target: ep.infraId,
|
|
11244
11796
|
type: edgeType,
|
|
11245
|
-
provenance:
|
|
11797
|
+
provenance: import_types37.Provenance.EXTRACTED,
|
|
11246
11798
|
confidence,
|
|
11247
11799
|
evidence: ep.evidence
|
|
11248
11800
|
};
|
|
@@ -11265,7 +11817,7 @@ async function addCallEdges(graph, services) {
|
|
|
11265
11817
|
|
|
11266
11818
|
// src/extract/table-edges.ts
|
|
11267
11819
|
init_cjs_shims();
|
|
11268
|
-
var
|
|
11820
|
+
var import_types38 = require("@neat.is/types");
|
|
11269
11821
|
async function addTableEdges(graph, services) {
|
|
11270
11822
|
let nodesAdded = 0;
|
|
11271
11823
|
let edgesAdded = 0;
|
|
@@ -11279,6 +11831,7 @@ async function addTableEdges(graph, services) {
|
|
|
11279
11831
|
refs.push(...sqlalchemyForeignKeys(file, service.dir));
|
|
11280
11832
|
refs.push(...railsSchemaForeignKeys(file, service.dir));
|
|
11281
11833
|
refs.push(...laravelMigrationForeignKeys(file, service.dir));
|
|
11834
|
+
refs.push(...gormForeignKeys(file, service.dir));
|
|
11282
11835
|
modelRefs.push(...railsModelForeignKeys(file, service.dir));
|
|
11283
11836
|
modelRefs.push(...laravelModelForeignKeys(file, service.dir));
|
|
11284
11837
|
} catch (err) {
|
|
@@ -11292,20 +11845,20 @@ async function addTableEdges(graph, services) {
|
|
|
11292
11845
|
}
|
|
11293
11846
|
refs.push(...modelRefs);
|
|
11294
11847
|
for (const ref of refs) {
|
|
11295
|
-
const childId = (0,
|
|
11296
|
-
const parentId = (0,
|
|
11848
|
+
const childId = (0, import_types38.infraId)("sql-table", ref.childTable);
|
|
11849
|
+
const parentId = (0, import_types38.infraId)("sql-table", ref.parentTable);
|
|
11297
11850
|
if (childId === parentId) continue;
|
|
11298
11851
|
nodesAdded += ensureTableNode(graph, childId, ref.childTable);
|
|
11299
11852
|
nodesAdded += ensureTableNode(graph, parentId, ref.parentTable);
|
|
11300
|
-
const edgeId = (0,
|
|
11853
|
+
const edgeId = (0, import_types38.extractedEdgeId)(childId, parentId, import_types38.EdgeType.REFERENCES);
|
|
11301
11854
|
if (graph.hasEdge(edgeId)) continue;
|
|
11302
11855
|
const edge = {
|
|
11303
11856
|
id: edgeId,
|
|
11304
11857
|
source: childId,
|
|
11305
11858
|
target: parentId,
|
|
11306
|
-
type:
|
|
11307
|
-
provenance:
|
|
11308
|
-
confidence: (0,
|
|
11859
|
+
type: import_types38.EdgeType.REFERENCES,
|
|
11860
|
+
provenance: import_types38.Provenance.EXTRACTED,
|
|
11861
|
+
confidence: (0, import_types38.confidenceForExtracted)("structural"),
|
|
11309
11862
|
evidence: ref.evidence
|
|
11310
11863
|
};
|
|
11311
11864
|
graph.addEdgeWithKey(edgeId, childId, parentId, edge);
|
|
@@ -11318,7 +11871,7 @@ function ensureTableNode(graph, id, name) {
|
|
|
11318
11871
|
if (graph.hasNode(id)) return 0;
|
|
11319
11872
|
const node = {
|
|
11320
11873
|
id,
|
|
11321
|
-
type:
|
|
11874
|
+
type: import_types38.NodeType.InfraNode,
|
|
11322
11875
|
name,
|
|
11323
11876
|
provider: "self",
|
|
11324
11877
|
kind: "sql-table"
|
|
@@ -11332,16 +11885,16 @@ init_cjs_shims();
|
|
|
11332
11885
|
|
|
11333
11886
|
// src/extract/infra/docker-compose.ts
|
|
11334
11887
|
init_cjs_shims();
|
|
11335
|
-
var
|
|
11336
|
-
var
|
|
11888
|
+
var import_node_path50 = __toESM(require("path"), 1);
|
|
11889
|
+
var import_types40 = require("@neat.is/types");
|
|
11337
11890
|
|
|
11338
11891
|
// src/extract/infra/shared.ts
|
|
11339
11892
|
init_cjs_shims();
|
|
11340
|
-
var
|
|
11893
|
+
var import_types39 = require("@neat.is/types");
|
|
11341
11894
|
function makeInfraNode(kind, name, provider = "self", extras) {
|
|
11342
11895
|
return {
|
|
11343
|
-
id: (0,
|
|
11344
|
-
type:
|
|
11896
|
+
id: (0, import_types39.infraId)(kind, name),
|
|
11897
|
+
type: import_types39.NodeType.InfraNode,
|
|
11345
11898
|
name,
|
|
11346
11899
|
provider,
|
|
11347
11900
|
kind,
|
|
@@ -11385,8 +11938,8 @@ function emitPlatformResourceEdge(graph, anchorId, edgeType, kind, name, provide
|
|
|
11385
11938
|
source: anchorId,
|
|
11386
11939
|
target: node.id,
|
|
11387
11940
|
type: edgeType,
|
|
11388
|
-
provenance:
|
|
11389
|
-
confidence: (0,
|
|
11941
|
+
provenance: import_types39.Provenance.EXTRACTED,
|
|
11942
|
+
confidence: (0, import_types39.confidenceForExtracted)("structural"),
|
|
11390
11943
|
evidence: { file: evidenceFile, ...line !== void 0 ? { line } : {} }
|
|
11391
11944
|
};
|
|
11392
11945
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -11403,7 +11956,7 @@ function dependsOnList(value) {
|
|
|
11403
11956
|
}
|
|
11404
11957
|
function serviceNameToServiceNode(name, services) {
|
|
11405
11958
|
for (const s of services) {
|
|
11406
|
-
if (s.node.name === name ||
|
|
11959
|
+
if (s.node.name === name || import_node_path50.default.basename(s.dir) === name) return s.node.id;
|
|
11407
11960
|
}
|
|
11408
11961
|
return null;
|
|
11409
11962
|
}
|
|
@@ -11412,7 +11965,7 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
11412
11965
|
let edgesAdded = 0;
|
|
11413
11966
|
let composePath = null;
|
|
11414
11967
|
for (const name of ["docker-compose.yml", "docker-compose.yaml"]) {
|
|
11415
|
-
const abs =
|
|
11968
|
+
const abs = import_node_path50.default.join(scanPath, name);
|
|
11416
11969
|
if (await exists(abs)) {
|
|
11417
11970
|
composePath = abs;
|
|
11418
11971
|
break;
|
|
@@ -11425,13 +11978,13 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
11425
11978
|
} catch (err) {
|
|
11426
11979
|
recordExtractionError(
|
|
11427
11980
|
"infra docker-compose",
|
|
11428
|
-
|
|
11981
|
+
import_node_path50.default.relative(scanPath, composePath),
|
|
11429
11982
|
err
|
|
11430
11983
|
);
|
|
11431
11984
|
return { nodesAdded, edgesAdded };
|
|
11432
11985
|
}
|
|
11433
11986
|
if (!compose?.services) return { nodesAdded, edgesAdded };
|
|
11434
|
-
const evidenceFile =
|
|
11987
|
+
const evidenceFile = import_node_path50.default.relative(scanPath, composePath).split(import_node_path50.default.sep).join("/");
|
|
11435
11988
|
const composeNameToNodeId = /* @__PURE__ */ new Map();
|
|
11436
11989
|
for (const [composeName, svc] of Object.entries(compose.services)) {
|
|
11437
11990
|
const matchedServiceId = serviceNameToServiceNode(composeName, services);
|
|
@@ -11453,15 +12006,15 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
11453
12006
|
for (const dep of dependsOnList(svc.depends_on)) {
|
|
11454
12007
|
const targetId = composeNameToNodeId.get(dep);
|
|
11455
12008
|
if (!targetId) continue;
|
|
11456
|
-
const edgeId = (0, import_types3.extractedEdgeId)(sourceId, targetId,
|
|
12009
|
+
const edgeId = (0, import_types3.extractedEdgeId)(sourceId, targetId, import_types40.EdgeType.DEPENDS_ON);
|
|
11457
12010
|
if (graph.hasEdge(edgeId)) continue;
|
|
11458
12011
|
const edge = {
|
|
11459
12012
|
id: edgeId,
|
|
11460
12013
|
source: sourceId,
|
|
11461
12014
|
target: targetId,
|
|
11462
|
-
type:
|
|
11463
|
-
provenance:
|
|
11464
|
-
confidence: (0,
|
|
12015
|
+
type: import_types40.EdgeType.DEPENDS_ON,
|
|
12016
|
+
provenance: import_types40.Provenance.EXTRACTED,
|
|
12017
|
+
confidence: (0, import_types40.confidenceForExtracted)("structural"),
|
|
11465
12018
|
evidence: { file: evidenceFile }
|
|
11466
12019
|
};
|
|
11467
12020
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -11473,9 +12026,9 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
11473
12026
|
|
|
11474
12027
|
// src/extract/infra/dockerfile.ts
|
|
11475
12028
|
init_cjs_shims();
|
|
11476
|
-
var
|
|
12029
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
11477
12030
|
var import_node_fs19 = require("fs");
|
|
11478
|
-
var
|
|
12031
|
+
var import_types41 = require("@neat.is/types");
|
|
11479
12032
|
function readDockerfile(content) {
|
|
11480
12033
|
let image = null;
|
|
11481
12034
|
const ports = [];
|
|
@@ -11504,7 +12057,7 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
11504
12057
|
let nodesAdded = 0;
|
|
11505
12058
|
let edgesAdded = 0;
|
|
11506
12059
|
for (const service of services) {
|
|
11507
|
-
const dockerfilePath =
|
|
12060
|
+
const dockerfilePath = import_node_path51.default.join(service.dir, "Dockerfile");
|
|
11508
12061
|
if (!await exists(dockerfilePath)) continue;
|
|
11509
12062
|
let content;
|
|
11510
12063
|
try {
|
|
@@ -11512,7 +12065,7 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
11512
12065
|
} catch (err) {
|
|
11513
12066
|
recordExtractionError(
|
|
11514
12067
|
"infra dockerfile",
|
|
11515
|
-
|
|
12068
|
+
import_node_path51.default.relative(scanPath, dockerfilePath),
|
|
11516
12069
|
err
|
|
11517
12070
|
);
|
|
11518
12071
|
continue;
|
|
@@ -11524,8 +12077,8 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
11524
12077
|
graph.addNode(node.id, node);
|
|
11525
12078
|
nodesAdded++;
|
|
11526
12079
|
}
|
|
11527
|
-
const relDockerfile = toPosix(
|
|
11528
|
-
const evidenceFile = toPosix(
|
|
12080
|
+
const relDockerfile = toPosix(import_node_path51.default.relative(service.dir, dockerfilePath));
|
|
12081
|
+
const evidenceFile = toPosix(import_node_path51.default.relative(scanPath, dockerfilePath));
|
|
11529
12082
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
11530
12083
|
graph,
|
|
11531
12084
|
service.pkg.name,
|
|
@@ -11534,15 +12087,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
11534
12087
|
);
|
|
11535
12088
|
nodesAdded += fn;
|
|
11536
12089
|
edgesAdded += fe;
|
|
11537
|
-
const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, node.id,
|
|
12090
|
+
const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, node.id, import_types41.EdgeType.RUNS_ON);
|
|
11538
12091
|
if (!graph.hasEdge(edgeId)) {
|
|
11539
12092
|
const edge = {
|
|
11540
12093
|
id: edgeId,
|
|
11541
12094
|
source: fileNodeId,
|
|
11542
12095
|
target: node.id,
|
|
11543
|
-
type:
|
|
11544
|
-
provenance:
|
|
11545
|
-
confidence: (0,
|
|
12096
|
+
type: import_types41.EdgeType.RUNS_ON,
|
|
12097
|
+
provenance: import_types41.Provenance.EXTRACTED,
|
|
12098
|
+
confidence: (0, import_types41.confidenceForExtracted)("structural"),
|
|
11546
12099
|
evidence: {
|
|
11547
12100
|
file: evidenceFile,
|
|
11548
12101
|
...facts.entrypoint ? { snippet: facts.entrypoint.slice(0, 120) } : {}
|
|
@@ -11557,15 +12110,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
11557
12110
|
graph.addNode(portNode.id, portNode);
|
|
11558
12111
|
nodesAdded++;
|
|
11559
12112
|
}
|
|
11560
|
-
const portEdgeId = (0, import_types3.extractedEdgeId)(fileNodeId, portNode.id,
|
|
12113
|
+
const portEdgeId = (0, import_types3.extractedEdgeId)(fileNodeId, portNode.id, import_types41.EdgeType.CONNECTS_TO);
|
|
11561
12114
|
if (graph.hasEdge(portEdgeId)) continue;
|
|
11562
12115
|
const portEdge = {
|
|
11563
12116
|
id: portEdgeId,
|
|
11564
12117
|
source: fileNodeId,
|
|
11565
12118
|
target: portNode.id,
|
|
11566
|
-
type:
|
|
11567
|
-
provenance:
|
|
11568
|
-
confidence: (0,
|
|
12119
|
+
type: import_types41.EdgeType.CONNECTS_TO,
|
|
12120
|
+
provenance: import_types41.Provenance.EXTRACTED,
|
|
12121
|
+
confidence: (0, import_types41.confidenceForExtracted)("structural"),
|
|
11569
12122
|
evidence: { file: evidenceFile, snippet: `EXPOSE ${port}` }
|
|
11570
12123
|
};
|
|
11571
12124
|
graph.addEdgeWithKey(portEdgeId, portEdge.source, portEdge.target, portEdge);
|
|
@@ -11578,8 +12131,8 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
11578
12131
|
// src/extract/infra/terraform.ts
|
|
11579
12132
|
init_cjs_shims();
|
|
11580
12133
|
var import_node_fs20 = require("fs");
|
|
11581
|
-
var
|
|
11582
|
-
var
|
|
12134
|
+
var import_node_path52 = __toESM(require("path"), 1);
|
|
12135
|
+
var import_types42 = require("@neat.is/types");
|
|
11583
12136
|
var RESOURCE_RE = /resource\s+"(aws_[A-Za-z0-9_]+)"\s+"([A-Za-z0-9_-]+)"/g;
|
|
11584
12137
|
var REFERENCE_RE = /(?<![\w.])(aws_[A-Za-z0-9_]+)\.([A-Za-z0-9_-]+)/g;
|
|
11585
12138
|
async function walkTfFiles(start, depth = 0, max = 5) {
|
|
@@ -11589,11 +12142,11 @@ async function walkTfFiles(start, depth = 0, max = 5) {
|
|
|
11589
12142
|
for (const entry2 of entries) {
|
|
11590
12143
|
if (entry2.isDirectory()) {
|
|
11591
12144
|
if (IGNORED_DIRS.has(entry2.name) || entry2.name === ".terraform") continue;
|
|
11592
|
-
const child =
|
|
12145
|
+
const child = import_node_path52.default.join(start, entry2.name);
|
|
11593
12146
|
if (await isPythonVenvDir(child)) continue;
|
|
11594
12147
|
out.push(...await walkTfFiles(child, depth + 1, max));
|
|
11595
12148
|
} else if (entry2.isFile() && entry2.name.endsWith(".tf")) {
|
|
11596
|
-
out.push(
|
|
12149
|
+
out.push(import_node_path52.default.join(start, entry2.name));
|
|
11597
12150
|
}
|
|
11598
12151
|
}
|
|
11599
12152
|
return out;
|
|
@@ -11625,7 +12178,7 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
11625
12178
|
const files = await walkTfFiles(scanPath);
|
|
11626
12179
|
for (const file of files) {
|
|
11627
12180
|
const content = await import_node_fs20.promises.readFile(file, "utf8");
|
|
11628
|
-
const evidenceFile = toPosix(
|
|
12181
|
+
const evidenceFile = toPosix(import_node_path52.default.relative(scanPath, file));
|
|
11629
12182
|
const resources = [];
|
|
11630
12183
|
const byKey = /* @__PURE__ */ new Map();
|
|
11631
12184
|
RESOURCE_RE.lastIndex = 0;
|
|
@@ -11660,16 +12213,16 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
11660
12213
|
if (!target) continue;
|
|
11661
12214
|
if (seen.has(target.nodeId)) continue;
|
|
11662
12215
|
seen.add(target.nodeId);
|
|
11663
|
-
const edgeId = (0, import_types3.extractedEdgeId)(resource.nodeId, target.nodeId,
|
|
12216
|
+
const edgeId = (0, import_types3.extractedEdgeId)(resource.nodeId, target.nodeId, import_types42.EdgeType.DEPENDS_ON);
|
|
11664
12217
|
if (graph.hasEdge(edgeId)) continue;
|
|
11665
12218
|
const line = lineAt2(content, resource.bodyOffset + ref.index);
|
|
11666
12219
|
const edge = {
|
|
11667
12220
|
id: edgeId,
|
|
11668
12221
|
source: resource.nodeId,
|
|
11669
12222
|
target: target.nodeId,
|
|
11670
|
-
type:
|
|
11671
|
-
provenance:
|
|
11672
|
-
confidence: (0,
|
|
12223
|
+
type: import_types42.EdgeType.DEPENDS_ON,
|
|
12224
|
+
provenance: import_types42.Provenance.EXTRACTED,
|
|
12225
|
+
confidence: (0, import_types42.confidenceForExtracted)("structural"),
|
|
11673
12226
|
evidence: { file: evidenceFile, line, snippet: key }
|
|
11674
12227
|
};
|
|
11675
12228
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -11683,7 +12236,7 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
11683
12236
|
// src/extract/infra/k8s.ts
|
|
11684
12237
|
init_cjs_shims();
|
|
11685
12238
|
var import_node_fs21 = require("fs");
|
|
11686
|
-
var
|
|
12239
|
+
var import_node_path53 = __toESM(require("path"), 1);
|
|
11687
12240
|
var import_yaml3 = require("yaml");
|
|
11688
12241
|
var K8S_KIND_TO_INFRA_KIND = {
|
|
11689
12242
|
Service: "k8s-service",
|
|
@@ -11701,11 +12254,11 @@ async function walkYamlFiles2(start, depth = 0, max = 5) {
|
|
|
11701
12254
|
for (const entry2 of entries) {
|
|
11702
12255
|
if (entry2.isDirectory()) {
|
|
11703
12256
|
if (IGNORED_DIRS.has(entry2.name)) continue;
|
|
11704
|
-
const child =
|
|
12257
|
+
const child = import_node_path53.default.join(start, entry2.name);
|
|
11705
12258
|
if (await isPythonVenvDir(child)) continue;
|
|
11706
12259
|
out.push(...await walkYamlFiles2(child, depth + 1, max));
|
|
11707
|
-
} else if (entry2.isFile() && CONFIG_FILE_EXTENSIONS.has(
|
|
11708
|
-
out.push(
|
|
12260
|
+
} else if (entry2.isFile() && CONFIG_FILE_EXTENSIONS.has(import_node_path53.default.extname(entry2.name))) {
|
|
12261
|
+
out.push(import_node_path53.default.join(start, entry2.name));
|
|
11709
12262
|
}
|
|
11710
12263
|
}
|
|
11711
12264
|
return out;
|
|
@@ -11739,13 +12292,13 @@ async function addK8sResources(graph, scanPath) {
|
|
|
11739
12292
|
// src/extract/infra/cloudflare.ts
|
|
11740
12293
|
init_cjs_shims();
|
|
11741
12294
|
var import_node_fs22 = require("fs");
|
|
11742
|
-
var
|
|
12295
|
+
var import_node_path54 = __toESM(require("path"), 1);
|
|
11743
12296
|
var import_smol_toml2 = require("smol-toml");
|
|
11744
|
-
var
|
|
12297
|
+
var import_types43 = require("@neat.is/types");
|
|
11745
12298
|
var WRANGLER_FILENAMES = ["wrangler.toml", "wrangler.jsonc", "wrangler.json"];
|
|
11746
12299
|
async function readWranglerConfig(dir) {
|
|
11747
12300
|
for (const filename of WRANGLER_FILENAMES) {
|
|
11748
|
-
const abs =
|
|
12301
|
+
const abs = import_node_path54.default.join(dir, filename);
|
|
11749
12302
|
if (!await exists(abs)) continue;
|
|
11750
12303
|
const raw = await import_node_fs22.promises.readFile(abs, "utf8");
|
|
11751
12304
|
const config = filename === "wrangler.toml" ? (0, import_smol_toml2.parse)(raw) : JSON.parse(maskCommentsInSource(raw));
|
|
@@ -11789,8 +12342,8 @@ function addResourceEdge(graph, anchorId, edgeType, kind, name, evidenceFile, li
|
|
|
11789
12342
|
source: anchorId,
|
|
11790
12343
|
target: node.id,
|
|
11791
12344
|
type: edgeType,
|
|
11792
|
-
provenance:
|
|
11793
|
-
confidence: (0,
|
|
12345
|
+
provenance: import_types43.Provenance.EXTRACTED,
|
|
12346
|
+
confidence: (0, import_types43.confidenceForExtracted)("structural"),
|
|
11794
12347
|
evidence: { file: evidenceFile, ...line !== void 0 ? { line } : {} }
|
|
11795
12348
|
};
|
|
11796
12349
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -11808,11 +12361,11 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
11808
12361
|
try {
|
|
11809
12362
|
read = await readWranglerConfig(service.dir);
|
|
11810
12363
|
} catch (err) {
|
|
11811
|
-
recordExtractionError("infra cloudflare",
|
|
12364
|
+
recordExtractionError("infra cloudflare", import_node_path54.default.relative(scanPath, service.dir), err);
|
|
11812
12365
|
continue;
|
|
11813
12366
|
}
|
|
11814
12367
|
if (!read || !read.config.name) continue;
|
|
11815
|
-
const evidenceFile = toPosix(
|
|
12368
|
+
const evidenceFile = toPosix(import_node_path54.default.relative(scanPath, import_node_path54.default.join(service.dir, read.relFile)));
|
|
11816
12369
|
discovered.push({ service, config: read.config, relFile: read.relFile, raw: read.raw, evidenceFile });
|
|
11817
12370
|
}
|
|
11818
12371
|
for (const worker of discovered) {
|
|
@@ -11824,7 +12377,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
11824
12377
|
}
|
|
11825
12378
|
let anchorId = service.node.id;
|
|
11826
12379
|
if (config.main) {
|
|
11827
|
-
const entryRelPath = toPosix(
|
|
12380
|
+
const entryRelPath = toPosix(import_node_path54.default.normalize(config.main));
|
|
11828
12381
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
11829
12382
|
graph,
|
|
11830
12383
|
service.pkg.name,
|
|
@@ -11851,15 +12404,15 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
11851
12404
|
nodesAdded++;
|
|
11852
12405
|
}
|
|
11853
12406
|
if (runtimeNode.id !== anchorId) {
|
|
11854
|
-
const runsOnId = (0, import_types3.extractedEdgeId)(anchorId, runtimeNode.id,
|
|
12407
|
+
const runsOnId = (0, import_types3.extractedEdgeId)(anchorId, runtimeNode.id, import_types43.EdgeType.RUNS_ON);
|
|
11855
12408
|
if (!graph.hasEdge(runsOnId)) {
|
|
11856
12409
|
const edge = {
|
|
11857
12410
|
id: runsOnId,
|
|
11858
12411
|
source: anchorId,
|
|
11859
12412
|
target: runtimeNode.id,
|
|
11860
|
-
type:
|
|
11861
|
-
provenance:
|
|
11862
|
-
confidence: (0,
|
|
12413
|
+
type: import_types43.EdgeType.RUNS_ON,
|
|
12414
|
+
provenance: import_types43.Provenance.EXTRACTED,
|
|
12415
|
+
confidence: (0, import_types43.confidenceForExtracted)("structural"),
|
|
11863
12416
|
evidence: {
|
|
11864
12417
|
file: evidenceFile,
|
|
11865
12418
|
...config.compatibility_date ? { snippet: `compatibility_date = ${config.compatibility_date}`.slice(0, 120) } : {}
|
|
@@ -11873,7 +12426,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
11873
12426
|
const result = addResourceEdge(
|
|
11874
12427
|
graph,
|
|
11875
12428
|
anchorId,
|
|
11876
|
-
|
|
12429
|
+
import_types43.EdgeType.CONNECTS_TO,
|
|
11877
12430
|
"cloudflare-route",
|
|
11878
12431
|
route,
|
|
11879
12432
|
evidenceFile,
|
|
@@ -11897,7 +12450,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
11897
12450
|
const result = addResourceEdge(
|
|
11898
12451
|
graph,
|
|
11899
12452
|
anchorId,
|
|
11900
|
-
|
|
12453
|
+
import_types43.EdgeType.DEPENDS_ON,
|
|
11901
12454
|
group.kind,
|
|
11902
12455
|
name,
|
|
11903
12456
|
evidenceFile,
|
|
@@ -11911,7 +12464,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
11911
12464
|
const result = addResourceEdge(
|
|
11912
12465
|
graph,
|
|
11913
12466
|
anchorId,
|
|
11914
|
-
|
|
12467
|
+
import_types43.EdgeType.DEPENDS_ON,
|
|
11915
12468
|
"cloudflare-cron",
|
|
11916
12469
|
cron,
|
|
11917
12470
|
evidenceFile,
|
|
@@ -11924,7 +12477,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
11924
12477
|
const result = addResourceEdge(
|
|
11925
12478
|
graph,
|
|
11926
12479
|
anchorId,
|
|
11927
|
-
|
|
12480
|
+
import_types43.EdgeType.DEPENDS_ON,
|
|
11928
12481
|
"cloudflare-env-var",
|
|
11929
12482
|
varName,
|
|
11930
12483
|
evidenceFile,
|
|
@@ -11937,15 +12490,15 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
11937
12490
|
if (!svc.service) continue;
|
|
11938
12491
|
const target = workerIndex.get(svc.service);
|
|
11939
12492
|
if (target && target.anchorId !== anchorId) {
|
|
11940
|
-
const edgeId = (0, import_types3.extractedEdgeId)(anchorId, target.anchorId,
|
|
12493
|
+
const edgeId = (0, import_types3.extractedEdgeId)(anchorId, target.anchorId, import_types43.EdgeType.CALLS);
|
|
11941
12494
|
if (!graph.hasEdge(edgeId)) {
|
|
11942
12495
|
const edge = {
|
|
11943
12496
|
id: edgeId,
|
|
11944
12497
|
source: anchorId,
|
|
11945
12498
|
target: target.anchorId,
|
|
11946
|
-
type:
|
|
11947
|
-
provenance:
|
|
11948
|
-
confidence: (0,
|
|
12499
|
+
type: import_types43.EdgeType.CALLS,
|
|
12500
|
+
provenance: import_types43.Provenance.EXTRACTED,
|
|
12501
|
+
confidence: (0, import_types43.confidenceForExtracted)("structural"),
|
|
11949
12502
|
evidence: { file: evidenceFile, line: lineContaining2(raw, svc.service) }
|
|
11950
12503
|
};
|
|
11951
12504
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -11956,7 +12509,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
11956
12509
|
const result = addResourceEdge(
|
|
11957
12510
|
graph,
|
|
11958
12511
|
anchorId,
|
|
11959
|
-
|
|
12512
|
+
import_types43.EdgeType.DEPENDS_ON,
|
|
11960
12513
|
"cloudflare-service-binding",
|
|
11961
12514
|
svc.service,
|
|
11962
12515
|
evidenceFile,
|
|
@@ -11972,12 +12525,12 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
11972
12525
|
// src/extract/infra/vercel.ts
|
|
11973
12526
|
init_cjs_shims();
|
|
11974
12527
|
var import_node_fs23 = require("fs");
|
|
11975
|
-
var
|
|
11976
|
-
var
|
|
12528
|
+
var import_node_path55 = __toESM(require("path"), 1);
|
|
12529
|
+
var import_types44 = require("@neat.is/types");
|
|
11977
12530
|
var VERCEL_CONFIG_FILENAMES = ["vercel.json", "vercel.jsonc"];
|
|
11978
12531
|
async function readVercelConfig(dir) {
|
|
11979
12532
|
for (const filename of VERCEL_CONFIG_FILENAMES) {
|
|
11980
|
-
const abs =
|
|
12533
|
+
const abs = import_node_path55.default.join(dir, filename);
|
|
11981
12534
|
if (!await exists(abs)) continue;
|
|
11982
12535
|
const raw = await import_node_fs23.promises.readFile(abs, "utf8");
|
|
11983
12536
|
const config = JSON.parse(maskCommentsInSource(raw));
|
|
@@ -11986,7 +12539,7 @@ async function readVercelConfig(dir) {
|
|
|
11986
12539
|
return null;
|
|
11987
12540
|
}
|
|
11988
12541
|
async function readLinkedProjectName(dir) {
|
|
11989
|
-
const abs =
|
|
12542
|
+
const abs = import_node_path55.default.join(dir, ".vercel", "project.json");
|
|
11990
12543
|
if (!await exists(abs)) return void 0;
|
|
11991
12544
|
const parsed = JSON.parse(await import_node_fs23.promises.readFile(abs, "utf8"));
|
|
11992
12545
|
return typeof parsed.projectName === "string" ? parsed.projectName : void 0;
|
|
@@ -12004,7 +12557,7 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
12004
12557
|
read = await readVercelConfig(service.dir);
|
|
12005
12558
|
projectName = await readLinkedProjectName(service.dir);
|
|
12006
12559
|
} catch (err) {
|
|
12007
|
-
recordExtractionError("infra vercel",
|
|
12560
|
+
recordExtractionError("infra vercel", import_node_path55.default.relative(scanPath, service.dir), err);
|
|
12008
12561
|
continue;
|
|
12009
12562
|
}
|
|
12010
12563
|
if (!read && !projectName) continue;
|
|
@@ -12020,7 +12573,7 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
12020
12573
|
const anchorId = service.node.id;
|
|
12021
12574
|
if (!read) continue;
|
|
12022
12575
|
const { config, relFile, raw } = read;
|
|
12023
|
-
const evidenceFile = toPosix(
|
|
12576
|
+
const evidenceFile = toPosix(import_node_path55.default.relative(scanPath, import_node_path55.default.join(service.dir, relFile)));
|
|
12024
12577
|
const add = (edgeType, kind, name) => {
|
|
12025
12578
|
if (!name) return;
|
|
12026
12579
|
const result = emitPlatformResourceEdge(
|
|
@@ -12036,12 +12589,12 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
12036
12589
|
nodesAdded += result.nodesAdded;
|
|
12037
12590
|
edgesAdded += result.edgesAdded;
|
|
12038
12591
|
};
|
|
12039
|
-
add(
|
|
12040
|
-
for (const cron of config.crons ?? []) add(
|
|
12041
|
-
for (const varName of Object.keys(config.env ?? {})) add(
|
|
12042
|
-
for (const varName of Object.keys(config.build?.env ?? {})) add(
|
|
12592
|
+
add(import_types44.EdgeType.RUNS_ON, "vercel", "vercel");
|
|
12593
|
+
for (const cron of config.crons ?? []) add(import_types44.EdgeType.DEPENDS_ON, "vercel-cron", cron.path ?? cron.schedule);
|
|
12594
|
+
for (const varName of Object.keys(config.env ?? {})) add(import_types44.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
|
|
12595
|
+
for (const varName of Object.keys(config.build?.env ?? {})) add(import_types44.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
|
|
12043
12596
|
for (const route of [...config.rewrites ?? [], ...config.redirects ?? [], ...config.routes ?? []]) {
|
|
12044
|
-
add(
|
|
12597
|
+
add(import_types44.EdgeType.CONNECTS_TO, "vercel-route", routeSource(route));
|
|
12045
12598
|
}
|
|
12046
12599
|
}
|
|
12047
12600
|
return { nodesAdded, edgesAdded };
|
|
@@ -12050,13 +12603,13 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
12050
12603
|
// src/extract/infra/railway.ts
|
|
12051
12604
|
init_cjs_shims();
|
|
12052
12605
|
var import_node_fs24 = require("fs");
|
|
12053
|
-
var
|
|
12606
|
+
var import_node_path56 = __toESM(require("path"), 1);
|
|
12054
12607
|
var import_smol_toml3 = require("smol-toml");
|
|
12055
|
-
var
|
|
12608
|
+
var import_types45 = require("@neat.is/types");
|
|
12056
12609
|
var RAILWAY_FILENAMES = ["railway.toml", "railway.json", "railway.jsonc"];
|
|
12057
12610
|
async function readRailwayConfig(dir) {
|
|
12058
12611
|
for (const filename of RAILWAY_FILENAMES) {
|
|
12059
|
-
const abs =
|
|
12612
|
+
const abs = import_node_path56.default.join(dir, filename);
|
|
12060
12613
|
if (!await exists(abs)) continue;
|
|
12061
12614
|
const raw = await import_node_fs24.promises.readFile(abs, "utf8");
|
|
12062
12615
|
const config = filename === "railway.toml" ? (0, import_smol_toml3.parse)(raw) : JSON.parse(maskCommentsInSource(raw));
|
|
@@ -12072,7 +12625,7 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
12072
12625
|
try {
|
|
12073
12626
|
read = await readRailwayConfig(service.dir);
|
|
12074
12627
|
} catch (err) {
|
|
12075
|
-
recordExtractionError("infra railway",
|
|
12628
|
+
recordExtractionError("infra railway", import_node_path56.default.relative(scanPath, service.dir), err);
|
|
12076
12629
|
continue;
|
|
12077
12630
|
}
|
|
12078
12631
|
if (!read) continue;
|
|
@@ -12082,7 +12635,7 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
12082
12635
|
}
|
|
12083
12636
|
const anchorId = service.node.id;
|
|
12084
12637
|
const { config, relFile, raw } = read;
|
|
12085
|
-
const evidenceFile = toPosix(
|
|
12638
|
+
const evidenceFile = toPosix(import_node_path56.default.relative(scanPath, import_node_path56.default.join(service.dir, relFile)));
|
|
12086
12639
|
const add = (edgeType, kind, name) => {
|
|
12087
12640
|
if (!name) return;
|
|
12088
12641
|
const result = emitPlatformResourceEdge(
|
|
@@ -12098,9 +12651,9 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
12098
12651
|
nodesAdded += result.nodesAdded;
|
|
12099
12652
|
edgesAdded += result.edgesAdded;
|
|
12100
12653
|
};
|
|
12101
|
-
add(
|
|
12102
|
-
add(
|
|
12103
|
-
add(
|
|
12654
|
+
add(import_types45.EdgeType.RUNS_ON, "railway", "railway");
|
|
12655
|
+
add(import_types45.EdgeType.CONNECTS_TO, "railway-route", config.deploy?.healthcheckPath);
|
|
12656
|
+
add(import_types45.EdgeType.DEPENDS_ON, "railway-cron", config.deploy?.cronSchedule);
|
|
12104
12657
|
}
|
|
12105
12658
|
return { nodesAdded, edgesAdded };
|
|
12106
12659
|
}
|
|
@@ -12108,12 +12661,12 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
12108
12661
|
// src/extract/infra/supabase.ts
|
|
12109
12662
|
init_cjs_shims();
|
|
12110
12663
|
var import_node_fs25 = require("fs");
|
|
12111
|
-
var
|
|
12664
|
+
var import_node_path57 = __toESM(require("path"), 1);
|
|
12112
12665
|
var import_smol_toml4 = require("smol-toml");
|
|
12113
|
-
var
|
|
12666
|
+
var import_types46 = require("@neat.is/types");
|
|
12114
12667
|
async function readSupabaseConfig(dir) {
|
|
12115
|
-
const relFile =
|
|
12116
|
-
const abs =
|
|
12668
|
+
const relFile = import_node_path57.default.join("supabase", "config.toml");
|
|
12669
|
+
const abs = import_node_path57.default.join(dir, relFile);
|
|
12117
12670
|
if (!await exists(abs)) return null;
|
|
12118
12671
|
const raw = await import_node_fs25.promises.readFile(abs, "utf8");
|
|
12119
12672
|
const config = (0, import_smol_toml4.parse)(raw);
|
|
@@ -12127,7 +12680,7 @@ async function addSupabaseProjects(graph, services, scanPath) {
|
|
|
12127
12680
|
try {
|
|
12128
12681
|
read = await readSupabaseConfig(service.dir);
|
|
12129
12682
|
} catch (err) {
|
|
12130
|
-
recordExtractionError("infra supabase",
|
|
12683
|
+
recordExtractionError("infra supabase", import_node_path57.default.relative(scanPath, service.dir), err);
|
|
12131
12684
|
continue;
|
|
12132
12685
|
}
|
|
12133
12686
|
if (!read) continue;
|
|
@@ -12142,7 +12695,7 @@ async function addSupabaseProjects(graph, services, scanPath) {
|
|
|
12142
12695
|
});
|
|
12143
12696
|
}
|
|
12144
12697
|
const anchorId = service.node.id;
|
|
12145
|
-
const evidenceFile = toPosix(
|
|
12698
|
+
const evidenceFile = toPosix(import_node_path57.default.relative(scanPath, import_node_path57.default.join(service.dir, relFile)));
|
|
12146
12699
|
const add = (edgeType, kind, name) => {
|
|
12147
12700
|
if (!name) return;
|
|
12148
12701
|
const result = emitPlatformResourceEdge(
|
|
@@ -12158,10 +12711,10 @@ async function addSupabaseProjects(graph, services, scanPath) {
|
|
|
12158
12711
|
nodesAdded += result.nodesAdded;
|
|
12159
12712
|
edgesAdded += result.edgesAdded;
|
|
12160
12713
|
};
|
|
12161
|
-
add(
|
|
12162
|
-
for (const fn of Object.keys(config.functions ?? {})) add(
|
|
12163
|
-
if (config.storage) add(
|
|
12164
|
-
if (config.auth) add(
|
|
12714
|
+
add(import_types46.EdgeType.RUNS_ON, "supabase", "supabase");
|
|
12715
|
+
for (const fn of Object.keys(config.functions ?? {})) add(import_types46.EdgeType.DEPENDS_ON, "supabase-function", fn);
|
|
12716
|
+
if (config.storage) add(import_types46.EdgeType.DEPENDS_ON, "supabase-storage", "storage");
|
|
12717
|
+
if (config.auth) add(import_types46.EdgeType.DEPENDS_ON, "supabase-auth", "auth");
|
|
12165
12718
|
}
|
|
12166
12719
|
return { nodesAdded, edgesAdded };
|
|
12167
12720
|
}
|
|
@@ -12184,14 +12737,14 @@ async function addInfra(graph, scanPath, services) {
|
|
|
12184
12737
|
|
|
12185
12738
|
// src/extract/zod-shapes.ts
|
|
12186
12739
|
init_cjs_shims();
|
|
12187
|
-
var
|
|
12188
|
-
var
|
|
12740
|
+
var import_node_path58 = __toESM(require("path"), 1);
|
|
12741
|
+
var import_tree_sitter16 = __toESM(require("tree-sitter"), 1);
|
|
12189
12742
|
var import_tree_sitter_javascript8 = __toESM(require("tree-sitter-javascript"), 1);
|
|
12190
|
-
var
|
|
12743
|
+
var import_types47 = require("@neat.is/types");
|
|
12191
12744
|
var ZOD_IMPORT_RE = /\bzod\b/;
|
|
12192
12745
|
var ZOD_OBJECTS = /* @__PURE__ */ new Set(["z", "zod"]);
|
|
12193
12746
|
function parserForExt3(ext) {
|
|
12194
|
-
const p = new
|
|
12747
|
+
const p = new import_tree_sitter16.default();
|
|
12195
12748
|
p.setLanguage(GRAMMAR_BY_EXT[ext] ?? import_tree_sitter_javascript8.default);
|
|
12196
12749
|
return p;
|
|
12197
12750
|
}
|
|
@@ -12279,7 +12832,7 @@ function topLevelSchemas(root) {
|
|
|
12279
12832
|
}
|
|
12280
12833
|
function zodShapesFromFile(file, serviceDir) {
|
|
12281
12834
|
if (!ZOD_IMPORT_RE.test(file.content)) return [];
|
|
12282
|
-
const tree = parseSource3(parserForExt3(
|
|
12835
|
+
const tree = parseSource3(parserForExt3(import_node_path58.default.extname(file.path)), file.content);
|
|
12283
12836
|
const out = [];
|
|
12284
12837
|
const seen = /* @__PURE__ */ new Set();
|
|
12285
12838
|
for (const { name, call } of topLevelSchemas(tree.rootNode)) {
|
|
@@ -12293,11 +12846,11 @@ function zodShapesFromFile(file, serviceDir) {
|
|
|
12293
12846
|
seen.add(name);
|
|
12294
12847
|
const line = call.startPosition.row + 1;
|
|
12295
12848
|
out.push({
|
|
12296
|
-
infraId: (0,
|
|
12849
|
+
infraId: (0, import_types47.infraId)("zod-schema", name),
|
|
12297
12850
|
name,
|
|
12298
12851
|
fields,
|
|
12299
12852
|
evidence: {
|
|
12300
|
-
file:
|
|
12853
|
+
file: import_node_path58.default.relative(serviceDir, file.path),
|
|
12301
12854
|
line,
|
|
12302
12855
|
snippet: snippet(file.content, line)
|
|
12303
12856
|
}
|
|
@@ -12328,7 +12881,7 @@ async function addZodShapes(graph, services) {
|
|
|
12328
12881
|
if (!graph.hasNode(shape.infraId)) {
|
|
12329
12882
|
const node = {
|
|
12330
12883
|
id: shape.infraId,
|
|
12331
|
-
type:
|
|
12884
|
+
type: import_types47.NodeType.InfraNode,
|
|
12332
12885
|
name: shape.name,
|
|
12333
12886
|
provider: "self",
|
|
12334
12887
|
kind: "zod-schema"
|
|
@@ -12338,14 +12891,14 @@ async function addZodShapes(graph, services) {
|
|
|
12338
12891
|
}
|
|
12339
12892
|
if (shape.fields.length > 0) {
|
|
12340
12893
|
const node = graph.getNodeAttributes(shape.infraId);
|
|
12341
|
-
if (node.type ===
|
|
12894
|
+
if (node.type === import_types47.NodeType.InfraNode) {
|
|
12342
12895
|
graph.replaceNodeAttributes(shape.infraId, {
|
|
12343
12896
|
...node,
|
|
12344
12897
|
columns: foldColumns(
|
|
12345
12898
|
node.columns,
|
|
12346
12899
|
shape.fields,
|
|
12347
|
-
|
|
12348
|
-
(0,
|
|
12900
|
+
import_types47.Provenance.EXTRACTED,
|
|
12901
|
+
(0, import_types47.confidenceForExtracted)("structural")
|
|
12349
12902
|
)
|
|
12350
12903
|
});
|
|
12351
12904
|
}
|
|
@@ -12359,15 +12912,15 @@ async function addZodShapes(graph, services) {
|
|
|
12359
12912
|
);
|
|
12360
12913
|
nodesAdded += n;
|
|
12361
12914
|
edgesAdded += e;
|
|
12362
|
-
const edgeId = (0,
|
|
12915
|
+
const edgeId = (0, import_types47.extractedEdgeId)(fileNodeId, shape.infraId, import_types47.EdgeType.CONTAINS);
|
|
12363
12916
|
if (!graph.hasEdge(edgeId)) {
|
|
12364
12917
|
const edge = {
|
|
12365
12918
|
id: edgeId,
|
|
12366
12919
|
source: fileNodeId,
|
|
12367
12920
|
target: shape.infraId,
|
|
12368
|
-
type:
|
|
12369
|
-
provenance:
|
|
12370
|
-
confidence: (0,
|
|
12921
|
+
type: import_types47.EdgeType.CONTAINS,
|
|
12922
|
+
provenance: import_types47.Provenance.EXTRACTED,
|
|
12923
|
+
confidence: (0, import_types47.confidenceForExtracted)("structural"),
|
|
12371
12924
|
evidence: shape.evidence
|
|
12372
12925
|
};
|
|
12373
12926
|
graph.addEdgeWithKey(edgeId, fileNodeId, shape.infraId, edge);
|
|
@@ -12381,7 +12934,7 @@ async function addZodShapes(graph, services) {
|
|
|
12381
12934
|
|
|
12382
12935
|
// src/extract/firestore-rules.ts
|
|
12383
12936
|
init_cjs_shims();
|
|
12384
|
-
var
|
|
12937
|
+
var import_types48 = require("@neat.is/types");
|
|
12385
12938
|
var FIRESTORE_COLLECTION_KIND = "firestore-collection";
|
|
12386
12939
|
var WRITE_METHODS = /* @__PURE__ */ new Set(["write", "create", "update"]);
|
|
12387
12940
|
function stripComments(src) {
|
|
@@ -12521,7 +13074,7 @@ async function addFirestoreRules(graph, services) {
|
|
|
12521
13074
|
if (guards.size === 0) return { nodesAdded: 0, edgesAdded: 0 };
|
|
12522
13075
|
graph.forEachNode((id, attrs) => {
|
|
12523
13076
|
const node = attrs;
|
|
12524
|
-
if (node.type !==
|
|
13077
|
+
if (node.type !== import_types48.NodeType.InfraNode) return;
|
|
12525
13078
|
if (node.kind !== FIRESTORE_COLLECTION_KIND) return;
|
|
12526
13079
|
const fields = guards.get(collectionKeyFromName(node.name));
|
|
12527
13080
|
if (!fields || fields.size === 0) return;
|
|
@@ -12534,17 +13087,17 @@ async function addFirestoreRules(graph, services) {
|
|
|
12534
13087
|
}
|
|
12535
13088
|
|
|
12536
13089
|
// src/extract/index.ts
|
|
12537
|
-
var
|
|
13090
|
+
var import_node_path60 = __toESM(require("path"), 1);
|
|
12538
13091
|
|
|
12539
13092
|
// src/extract/retire.ts
|
|
12540
13093
|
init_cjs_shims();
|
|
12541
13094
|
var import_node_fs26 = require("fs");
|
|
12542
|
-
var
|
|
12543
|
-
var
|
|
13095
|
+
var import_node_path59 = __toESM(require("path"), 1);
|
|
13096
|
+
var import_types49 = require("@neat.is/types");
|
|
12544
13097
|
function dropOrphanedFileNodes(graph) {
|
|
12545
13098
|
const orphans = [];
|
|
12546
13099
|
graph.forEachNode((id, attrs) => {
|
|
12547
|
-
if (attrs.type !==
|
|
13100
|
+
if (attrs.type !== import_types49.NodeType.FileNode) return;
|
|
12548
13101
|
if (graph.inboundEdges(id).length === 0 && graph.outboundEdges(id).length === 0) {
|
|
12549
13102
|
orphans.push(id);
|
|
12550
13103
|
}
|
|
@@ -12557,7 +13110,7 @@ function retireEdgesByFile(graph, file) {
|
|
|
12557
13110
|
const toDrop = [];
|
|
12558
13111
|
graph.forEachEdge((id, attrs) => {
|
|
12559
13112
|
const edge = attrs;
|
|
12560
|
-
if (edge.provenance !==
|
|
13113
|
+
if (edge.provenance !== import_types49.Provenance.EXTRACTED) return;
|
|
12561
13114
|
if (!edge.evidence?.file) return;
|
|
12562
13115
|
if (edge.evidence.file === normalized) toDrop.push(id);
|
|
12563
13116
|
});
|
|
@@ -12570,14 +13123,14 @@ function retireExtractedEdgesByMissingFile(graph, scanPath, serviceDirs = []) {
|
|
|
12570
13123
|
const bases = [scanPath, ...serviceDirs];
|
|
12571
13124
|
graph.forEachEdge((id, attrs) => {
|
|
12572
13125
|
const edge = attrs;
|
|
12573
|
-
if (edge.provenance !==
|
|
13126
|
+
if (edge.provenance !== import_types49.Provenance.EXTRACTED) return;
|
|
12574
13127
|
const evidenceFile = edge.evidence?.file;
|
|
12575
13128
|
if (!evidenceFile) return;
|
|
12576
|
-
if (
|
|
13129
|
+
if (import_node_path59.default.isAbsolute(evidenceFile)) {
|
|
12577
13130
|
if (!(0, import_node_fs26.existsSync)(evidenceFile)) toDrop.push(id);
|
|
12578
13131
|
return;
|
|
12579
13132
|
}
|
|
12580
|
-
const found = bases.some((base) => (0, import_node_fs26.existsSync)(
|
|
13133
|
+
const found = bases.some((base) => (0, import_node_fs26.existsSync)(import_node_path59.default.join(base, evidenceFile)));
|
|
12581
13134
|
if (!found) toDrop.push(id);
|
|
12582
13135
|
});
|
|
12583
13136
|
for (const id of toDrop) graph.dropEdge(id);
|
|
@@ -12634,7 +13187,7 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
12634
13187
|
}
|
|
12635
13188
|
const droppedEntries = drainDroppedExtracted();
|
|
12636
13189
|
if (isRejectedLogEnabled() && opts.errorsPath && droppedEntries.length > 0) {
|
|
12637
|
-
const rejectedPath =
|
|
13190
|
+
const rejectedPath = import_node_path60.default.join(import_node_path60.default.dirname(opts.errorsPath), "rejected.ndjson");
|
|
12638
13191
|
try {
|
|
12639
13192
|
await writeRejectedExtracted(droppedEntries, rejectedPath);
|
|
12640
13193
|
} catch (err) {
|
|
@@ -12668,39 +13221,39 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
12668
13221
|
|
|
12669
13222
|
// src/divergences.ts
|
|
12670
13223
|
init_cjs_shims();
|
|
12671
|
-
var
|
|
13224
|
+
var import_types50 = require("@neat.is/types");
|
|
12672
13225
|
function bucketKey(source, target, type) {
|
|
12673
13226
|
return `${type}|${source}|${target}`;
|
|
12674
13227
|
}
|
|
12675
13228
|
function bucketSourceFor(graph, edge) {
|
|
12676
|
-
if (edge.type !==
|
|
12677
|
-
const parsed = (0,
|
|
13229
|
+
if (edge.type !== import_types50.EdgeType.CONNECTS_TO) return edge.source;
|
|
13230
|
+
const parsed = (0, import_types50.parseFileId)(edge.source);
|
|
12678
13231
|
if (!parsed || !graph.hasNode(edge.target)) return edge.source;
|
|
12679
13232
|
const target = graph.getNodeAttributes(edge.target);
|
|
12680
|
-
if (target.type !==
|
|
12681
|
-
return (0,
|
|
13233
|
+
if (target.type !== import_types50.NodeType.DatabaseNode) return edge.source;
|
|
13234
|
+
return (0, import_types50.serviceId)(parsed.service);
|
|
12682
13235
|
}
|
|
12683
13236
|
function bucketEdges(graph) {
|
|
12684
13237
|
const buckets2 = /* @__PURE__ */ new Map();
|
|
12685
13238
|
graph.forEachEdge((id, attrs) => {
|
|
12686
13239
|
const e = attrs;
|
|
12687
|
-
const parsed = (0,
|
|
13240
|
+
const parsed = (0, import_types50.parseEdgeId)(id);
|
|
12688
13241
|
const provenance = parsed?.provenance ?? e.provenance;
|
|
12689
13242
|
const source = bucketSourceFor(graph, e);
|
|
12690
13243
|
const key = bucketKey(source, e.target, e.type);
|
|
12691
13244
|
const cur = buckets2.get(key) ?? { source, target: e.target, type: e.type };
|
|
12692
13245
|
switch (provenance) {
|
|
12693
|
-
case
|
|
13246
|
+
case import_types50.Provenance.EXTRACTED:
|
|
12694
13247
|
cur.extracted = e;
|
|
12695
13248
|
break;
|
|
12696
|
-
case
|
|
13249
|
+
case import_types50.Provenance.OBSERVED:
|
|
12697
13250
|
cur.observed = e;
|
|
12698
13251
|
break;
|
|
12699
|
-
case
|
|
13252
|
+
case import_types50.Provenance.INFERRED:
|
|
12700
13253
|
cur.inferred = e;
|
|
12701
13254
|
break;
|
|
12702
13255
|
default:
|
|
12703
|
-
if (e.provenance ===
|
|
13256
|
+
if (e.provenance === import_types50.Provenance.STALE) cur.stale = e;
|
|
12704
13257
|
}
|
|
12705
13258
|
buckets2.set(key, cur);
|
|
12706
13259
|
});
|
|
@@ -12709,22 +13262,22 @@ function bucketEdges(graph) {
|
|
|
12709
13262
|
function nodeIsFrontier(graph, nodeId) {
|
|
12710
13263
|
if (!graph.hasNode(nodeId)) return false;
|
|
12711
13264
|
const attrs = graph.getNodeAttributes(nodeId);
|
|
12712
|
-
return attrs.type ===
|
|
13265
|
+
return attrs.type === import_types50.NodeType.FrontierNode;
|
|
12713
13266
|
}
|
|
12714
13267
|
function nodeIsWebsocketChannel(graph, nodeId) {
|
|
12715
13268
|
if (!graph.hasNode(nodeId)) return false;
|
|
12716
13269
|
const attrs = graph.getNodeAttributes(nodeId);
|
|
12717
|
-
return attrs.type ===
|
|
13270
|
+
return attrs.type === import_types50.NodeType.WebSocketChannelNode;
|
|
12718
13271
|
}
|
|
12719
13272
|
function nodeIsServerAction(graph, nodeId) {
|
|
12720
13273
|
if (!graph.hasNode(nodeId)) return false;
|
|
12721
13274
|
const attrs = graph.getNodeAttributes(nodeId);
|
|
12722
|
-
return attrs.type ===
|
|
13275
|
+
return attrs.type === import_types50.NodeType.ServerActionNode;
|
|
12723
13276
|
}
|
|
12724
13277
|
function nodeIsSymbol(graph, nodeId) {
|
|
12725
13278
|
if (!graph.hasNode(nodeId)) return false;
|
|
12726
13279
|
const attrs = graph.getNodeAttributes(nodeId);
|
|
12727
|
-
return attrs.type ===
|
|
13280
|
+
return attrs.type === import_types50.NodeType.SymbolNode;
|
|
12728
13281
|
}
|
|
12729
13282
|
function clampConfidence(n) {
|
|
12730
13283
|
if (!Number.isFinite(n)) return 0;
|
|
@@ -12744,14 +13297,14 @@ function gradedConfidence(edge) {
|
|
|
12744
13297
|
return clampConfidence(confidenceForEdge(edge));
|
|
12745
13298
|
}
|
|
12746
13299
|
var OBSERVABLE_EDGE_TYPES = /* @__PURE__ */ new Set([
|
|
12747
|
-
|
|
12748
|
-
|
|
12749
|
-
|
|
12750
|
-
|
|
13300
|
+
import_types50.EdgeType.CALLS,
|
|
13301
|
+
import_types50.EdgeType.CONNECTS_TO,
|
|
13302
|
+
import_types50.EdgeType.PUBLISHES_TO,
|
|
13303
|
+
import_types50.EdgeType.CONSUMES_FROM
|
|
12751
13304
|
]);
|
|
12752
13305
|
function detectMissingDivergences(graph, bucket) {
|
|
12753
13306
|
const out = [];
|
|
12754
|
-
if (bucket.type ===
|
|
13307
|
+
if (bucket.type === import_types50.EdgeType.CONTAINS) return out;
|
|
12755
13308
|
if (nodeIsSymbol(graph, bucket.source) || nodeIsSymbol(graph, bucket.target)) return out;
|
|
12756
13309
|
if (bucket.extracted && !bucket.observed && OBSERVABLE_EDGE_TYPES.has(bucket.type)) {
|
|
12757
13310
|
if (!nodeIsFrontier(graph, bucket.target) && !nodeIsServerAction(graph, bucket.target)) {
|
|
@@ -12793,7 +13346,7 @@ function declaredHostFor(svc) {
|
|
|
12793
13346
|
function hasExtractedConfiguredBy(graph, svcId) {
|
|
12794
13347
|
for (const edgeId of graph.outboundEdges(svcId)) {
|
|
12795
13348
|
const e = graph.getEdgeAttributes(edgeId);
|
|
12796
|
-
if (e.type ===
|
|
13349
|
+
if (e.type === import_types50.EdgeType.CONFIGURED_BY && e.provenance === import_types50.Provenance.EXTRACTED) {
|
|
12797
13350
|
return true;
|
|
12798
13351
|
}
|
|
12799
13352
|
}
|
|
@@ -12806,10 +13359,10 @@ function detectHostMismatch(graph, svcId, svc) {
|
|
|
12806
13359
|
const out = [];
|
|
12807
13360
|
for (const edgeId of graph.outboundEdges(svcId)) {
|
|
12808
13361
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
12809
|
-
if (edge.type !==
|
|
12810
|
-
if (edge.provenance !==
|
|
13362
|
+
if (edge.type !== import_types50.EdgeType.CONNECTS_TO) continue;
|
|
13363
|
+
if (edge.provenance !== import_types50.Provenance.OBSERVED) continue;
|
|
12811
13364
|
const target = graph.getNodeAttributes(edge.target);
|
|
12812
|
-
if (target.type !==
|
|
13365
|
+
if (target.type !== import_types50.NodeType.DatabaseNode) continue;
|
|
12813
13366
|
const observedHost = target.host?.trim();
|
|
12814
13367
|
if (!observedHost) continue;
|
|
12815
13368
|
if (observedHost === declaredHost) continue;
|
|
@@ -12831,10 +13384,10 @@ function detectCompatDivergences(graph, svcId, svc) {
|
|
|
12831
13384
|
const deps = svc.dependencies ?? {};
|
|
12832
13385
|
for (const edgeId of graph.outboundEdges(svcId)) {
|
|
12833
13386
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
12834
|
-
if (edge.type !==
|
|
12835
|
-
if (edge.provenance !==
|
|
13387
|
+
if (edge.type !== import_types50.EdgeType.CONNECTS_TO) continue;
|
|
13388
|
+
if (edge.provenance !== import_types50.Provenance.OBSERVED) continue;
|
|
12836
13389
|
const target = graph.getNodeAttributes(edge.target);
|
|
12837
|
-
if (target.type !==
|
|
13390
|
+
if (target.type !== import_types50.NodeType.DatabaseNode) continue;
|
|
12838
13391
|
for (const pair of compatPairs()) {
|
|
12839
13392
|
if (pair.engine !== target.engine) continue;
|
|
12840
13393
|
const declared = deps[pair.driver];
|
|
@@ -12931,7 +13484,7 @@ function suppressHostMismatchHalves(all) {
|
|
|
12931
13484
|
for (const d of all) {
|
|
12932
13485
|
if (d.type !== "host-mismatch") continue;
|
|
12933
13486
|
observedHalf.add(`${d.source}->${d.target}`);
|
|
12934
|
-
declaredHalf.add((0,
|
|
13487
|
+
declaredHalf.add((0, import_types50.databaseId)(d.extractedHost));
|
|
12935
13488
|
}
|
|
12936
13489
|
if (observedHalf.size === 0) return all;
|
|
12937
13490
|
return all.filter((d) => {
|
|
@@ -12950,13 +13503,13 @@ function computeDivergences(graph, opts = {}) {
|
|
|
12950
13503
|
}
|
|
12951
13504
|
graph.forEachNode((nodeId, attrs) => {
|
|
12952
13505
|
const n = attrs;
|
|
12953
|
-
if (n.type ===
|
|
13506
|
+
if (n.type === import_types50.NodeType.ServiceNode) {
|
|
12954
13507
|
const svc = n;
|
|
12955
13508
|
for (const d of detectHostMismatch(graph, nodeId, svc)) all.push(d);
|
|
12956
13509
|
for (const d of detectCompatDivergences(graph, nodeId, svc)) all.push(d);
|
|
12957
13510
|
return;
|
|
12958
13511
|
}
|
|
12959
|
-
if (n.type ===
|
|
13512
|
+
if (n.type === import_types50.NodeType.InfraNode && n.kind === "sql-table") {
|
|
12960
13513
|
for (const d of detectColumnDrift(n)) all.push(d);
|
|
12961
13514
|
}
|
|
12962
13515
|
});
|
|
@@ -12992,7 +13545,7 @@ function computeDivergences(graph, opts = {}) {
|
|
|
12992
13545
|
const bc = "column" in b && b.column ? b.column : "";
|
|
12993
13546
|
return ac.localeCompare(bc);
|
|
12994
13547
|
});
|
|
12995
|
-
return
|
|
13548
|
+
return import_types50.DivergenceResultSchema.parse({
|
|
12996
13549
|
divergences: filtered,
|
|
12997
13550
|
totalAffected: filtered.length,
|
|
12998
13551
|
computedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -13002,8 +13555,8 @@ function computeDivergences(graph, opts = {}) {
|
|
|
13002
13555
|
// src/persist.ts
|
|
13003
13556
|
init_cjs_shims();
|
|
13004
13557
|
var import_node_fs27 = require("fs");
|
|
13005
|
-
var
|
|
13006
|
-
var
|
|
13558
|
+
var import_node_path61 = __toESM(require("path"), 1);
|
|
13559
|
+
var import_types51 = require("@neat.is/types");
|
|
13007
13560
|
var SCHEMA_VERSION = 7;
|
|
13008
13561
|
function migrateV1ToV2(payload) {
|
|
13009
13562
|
const nodes = payload.graph.nodes;
|
|
@@ -13027,7 +13580,7 @@ function migrateV5ToV6(payload) {
|
|
|
13027
13580
|
if (Array.isArray(nodes)) {
|
|
13028
13581
|
for (const node of nodes) {
|
|
13029
13582
|
const attrs = node.attributes;
|
|
13030
|
-
if (!attrs || attrs.type !==
|
|
13583
|
+
if (!attrs || attrs.type !== import_types51.NodeType.InfraNode) continue;
|
|
13031
13584
|
if (attrs.kind !== "sql-table" && attrs.kind !== "supabase-table") continue;
|
|
13032
13585
|
if (!Array.isArray(attrs.columns)) attrs.columns = [];
|
|
13033
13586
|
}
|
|
@@ -13043,12 +13596,12 @@ function migrateV2ToV3(payload) {
|
|
|
13043
13596
|
for (const edge of edges) {
|
|
13044
13597
|
const attrs = edge.attributes;
|
|
13045
13598
|
if (!attrs || attrs.provenance !== "FRONTIER") continue;
|
|
13046
|
-
attrs.provenance =
|
|
13599
|
+
attrs.provenance = import_types51.Provenance.OBSERVED;
|
|
13047
13600
|
const type = typeof attrs.type === "string" ? attrs.type : void 0;
|
|
13048
13601
|
const source = typeof attrs.source === "string" ? attrs.source : void 0;
|
|
13049
13602
|
const target = typeof attrs.target === "string" ? attrs.target : void 0;
|
|
13050
13603
|
if (type && source && target) {
|
|
13051
|
-
const newId = (0,
|
|
13604
|
+
const newId = (0, import_types51.observedEdgeId)(source, target, type);
|
|
13052
13605
|
attrs.id = newId;
|
|
13053
13606
|
if (edge.key) edge.key = newId;
|
|
13054
13607
|
}
|
|
@@ -13057,7 +13610,7 @@ function migrateV2ToV3(payload) {
|
|
|
13057
13610
|
return { ...payload, schemaVersion: 3 };
|
|
13058
13611
|
}
|
|
13059
13612
|
async function ensureDir(filePath) {
|
|
13060
|
-
await import_node_fs27.promises.mkdir(
|
|
13613
|
+
await import_node_fs27.promises.mkdir(import_node_path61.default.dirname(filePath), { recursive: true });
|
|
13061
13614
|
}
|
|
13062
13615
|
async function saveGraphToDisk(graph, outPath) {
|
|
13063
13616
|
await ensureDir(outPath);
|
|
@@ -13148,7 +13701,7 @@ function startPersistLoop(graph, outPath, opts = {}) {
|
|
|
13148
13701
|
// src/gitignore.ts
|
|
13149
13702
|
init_cjs_shims();
|
|
13150
13703
|
var import_node_fs28 = require("fs");
|
|
13151
|
-
var
|
|
13704
|
+
var import_node_path62 = __toESM(require("path"), 1);
|
|
13152
13705
|
var NEAT_OUT_LINE = "neat-out/";
|
|
13153
13706
|
var NEAT_HEADER = "# NEAT \u2014 machine-local snapshots and events";
|
|
13154
13707
|
function isNeatOutLine(line) {
|
|
@@ -13156,7 +13709,7 @@ function isNeatOutLine(line) {
|
|
|
13156
13709
|
return trimmed === "neat-out/" || trimmed === "neat-out";
|
|
13157
13710
|
}
|
|
13158
13711
|
async function ensureNeatOutIgnored(projectDir) {
|
|
13159
|
-
const file =
|
|
13712
|
+
const file = import_node_path62.default.join(projectDir, ".gitignore");
|
|
13160
13713
|
let existing = null;
|
|
13161
13714
|
try {
|
|
13162
13715
|
existing = await import_node_fs28.promises.readFile(file, "utf8");
|
|
@@ -13183,7 +13736,7 @@ ${NEAT_OUT_LINE}
|
|
|
13183
13736
|
|
|
13184
13737
|
// src/summary.ts
|
|
13185
13738
|
init_cjs_shims();
|
|
13186
|
-
var
|
|
13739
|
+
var import_types52 = require("@neat.is/types");
|
|
13187
13740
|
function renderOtelEnvBlock() {
|
|
13188
13741
|
return [
|
|
13189
13742
|
"for prod OTel routing, set these in your deploy platform's env:",
|
|
@@ -13193,19 +13746,19 @@ function renderOtelEnvBlock() {
|
|
|
13193
13746
|
}
|
|
13194
13747
|
function findIncompatServices(nodes) {
|
|
13195
13748
|
return nodes.filter(
|
|
13196
|
-
(n) => n.type ===
|
|
13749
|
+
(n) => n.type === import_types52.NodeType.ServiceNode && Array.isArray(n.incompatibilities) && (n.incompatibilities ?? []).length > 0
|
|
13197
13750
|
);
|
|
13198
13751
|
}
|
|
13199
13752
|
function servicesWithoutObserved(nodes, edges) {
|
|
13200
13753
|
const seen = /* @__PURE__ */ new Set();
|
|
13201
13754
|
for (const e of edges) {
|
|
13202
|
-
if (e.provenance ===
|
|
13755
|
+
if (e.provenance === import_types52.Provenance.OBSERVED) {
|
|
13203
13756
|
seen.add(e.source);
|
|
13204
13757
|
seen.add(e.target);
|
|
13205
13758
|
}
|
|
13206
13759
|
}
|
|
13207
13760
|
return nodes.filter(
|
|
13208
|
-
(n) => n.type ===
|
|
13761
|
+
(n) => n.type === import_types52.NodeType.ServiceNode && !seen.has(n.id)
|
|
13209
13762
|
);
|
|
13210
13763
|
}
|
|
13211
13764
|
function formatDivergence(d) {
|
|
@@ -13280,26 +13833,26 @@ function formatIncompat(inc) {
|
|
|
13280
13833
|
// src/watch.ts
|
|
13281
13834
|
init_cjs_shims();
|
|
13282
13835
|
var import_node_fs37 = __toESM(require("fs"), 1);
|
|
13283
|
-
var
|
|
13836
|
+
var import_node_path71 = __toESM(require("path"), 1);
|
|
13284
13837
|
var import_chokidar = __toESM(require("chokidar"), 1);
|
|
13285
13838
|
|
|
13286
13839
|
// src/api.ts
|
|
13287
13840
|
init_cjs_shims();
|
|
13288
13841
|
var import_fastify2 = __toESM(require("fastify"), 1);
|
|
13289
13842
|
var import_cors = __toESM(require("@fastify/cors"), 1);
|
|
13290
|
-
var
|
|
13843
|
+
var import_types81 = require("@neat.is/types");
|
|
13291
13844
|
|
|
13292
13845
|
// src/extend/index.ts
|
|
13293
13846
|
init_cjs_shims();
|
|
13294
13847
|
var import_node_fs30 = require("fs");
|
|
13295
|
-
var
|
|
13848
|
+
var import_node_path64 = __toESM(require("path"), 1);
|
|
13296
13849
|
var import_node_os2 = __toESM(require("os"), 1);
|
|
13297
13850
|
var import_instrumentation_registry = require("@neat.is/instrumentation-registry");
|
|
13298
13851
|
|
|
13299
13852
|
// src/installers/package-manager.ts
|
|
13300
13853
|
init_cjs_shims();
|
|
13301
13854
|
var import_node_fs29 = require("fs");
|
|
13302
|
-
var
|
|
13855
|
+
var import_node_path63 = __toESM(require("path"), 1);
|
|
13303
13856
|
var import_node_child_process = require("child_process");
|
|
13304
13857
|
var LOCKFILE_PRIORITY = [
|
|
13305
13858
|
{ lockfile: "bun.lockb", pm: "bun", args: ["install", "--no-summary"] },
|
|
@@ -13321,22 +13874,22 @@ async function exists2(p) {
|
|
|
13321
13874
|
}
|
|
13322
13875
|
}
|
|
13323
13876
|
async function detectPackageManager(serviceDir) {
|
|
13324
|
-
let dir =
|
|
13877
|
+
let dir = import_node_path63.default.resolve(serviceDir);
|
|
13325
13878
|
const stops = /* @__PURE__ */ new Set();
|
|
13326
13879
|
for (let i = 0; i < 64; i++) {
|
|
13327
13880
|
if (stops.has(dir)) break;
|
|
13328
13881
|
stops.add(dir);
|
|
13329
13882
|
for (const candidate of LOCKFILE_PRIORITY) {
|
|
13330
|
-
const lockPath =
|
|
13883
|
+
const lockPath = import_node_path63.default.join(dir, candidate.lockfile);
|
|
13331
13884
|
if (await exists2(lockPath)) {
|
|
13332
13885
|
return { pm: candidate.pm, cwd: dir, args: [...candidate.args] };
|
|
13333
13886
|
}
|
|
13334
13887
|
}
|
|
13335
|
-
const parent =
|
|
13888
|
+
const parent = import_node_path63.default.dirname(dir);
|
|
13336
13889
|
if (parent === dir) break;
|
|
13337
13890
|
dir = parent;
|
|
13338
13891
|
}
|
|
13339
|
-
return { pm: "npm", cwd:
|
|
13892
|
+
return { pm: "npm", cwd: import_node_path63.default.resolve(serviceDir), args: [...NPM_FALLBACK_ARGS] };
|
|
13340
13893
|
}
|
|
13341
13894
|
async function runPackageManagerInstall(cmd) {
|
|
13342
13895
|
return new Promise((resolve) => {
|
|
@@ -13385,7 +13938,7 @@ async function fileExists2(p) {
|
|
|
13385
13938
|
}
|
|
13386
13939
|
}
|
|
13387
13940
|
async function readPackageJson(scanPath) {
|
|
13388
|
-
const pkgPath =
|
|
13941
|
+
const pkgPath = import_node_path64.default.join(scanPath, "package.json");
|
|
13389
13942
|
const raw = await import_node_fs30.promises.readFile(pkgPath, "utf8");
|
|
13390
13943
|
return JSON.parse(raw);
|
|
13391
13944
|
}
|
|
@@ -13399,27 +13952,27 @@ var HOOK_WALK_SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
|
13399
13952
|
]);
|
|
13400
13953
|
async function findHookFiles(scanPath) {
|
|
13401
13954
|
const found = [];
|
|
13402
|
-
const
|
|
13955
|
+
const walk9 = async (dir) => {
|
|
13403
13956
|
const entries = await import_node_fs30.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
13404
13957
|
for (const entry2 of entries) {
|
|
13405
13958
|
if (entry2.isDirectory()) {
|
|
13406
13959
|
if (entry2.name.startsWith(".") || HOOK_WALK_SKIP_DIRS.has(entry2.name)) continue;
|
|
13407
|
-
await
|
|
13960
|
+
await walk9(import_node_path64.default.join(dir, entry2.name));
|
|
13408
13961
|
} else if (entry2.isFile()) {
|
|
13409
13962
|
if ((entry2.name.startsWith("instrumentation") || entry2.name.startsWith("otel-init")) && /\.(ts|js|cjs|mjs)$/.test(entry2.name)) {
|
|
13410
|
-
const rel =
|
|
13411
|
-
found.push(rel.split(
|
|
13963
|
+
const rel = import_node_path64.default.relative(scanPath, import_node_path64.default.join(dir, entry2.name));
|
|
13964
|
+
found.push(rel.split(import_node_path64.default.sep).join("/"));
|
|
13412
13965
|
}
|
|
13413
13966
|
}
|
|
13414
13967
|
}
|
|
13415
13968
|
};
|
|
13416
|
-
await
|
|
13969
|
+
await walk9(scanPath);
|
|
13417
13970
|
return found.sort();
|
|
13418
13971
|
}
|
|
13419
13972
|
async function pickPrimaryHookFile(scanPath, hookFiles, snippet2) {
|
|
13420
13973
|
let fallback = null;
|
|
13421
13974
|
for (const file of hookFiles) {
|
|
13422
|
-
const content = await import_node_fs30.promises.readFile(
|
|
13975
|
+
const content = await import_node_fs30.promises.readFile(import_node_path64.default.join(scanPath, file), "utf8");
|
|
13423
13976
|
const patched = splicedContent(content, snippet2);
|
|
13424
13977
|
if (patched !== null) return { file, content, patched };
|
|
13425
13978
|
if (fallback === null) fallback = { file, content };
|
|
@@ -13427,11 +13980,11 @@ async function pickPrimaryHookFile(scanPath, hookFiles, snippet2) {
|
|
|
13427
13980
|
return { file: fallback.file, content: fallback.content, patched: null };
|
|
13428
13981
|
}
|
|
13429
13982
|
function extendLogPath() {
|
|
13430
|
-
return process.env.NEAT_EXTEND_LOG ??
|
|
13983
|
+
return process.env.NEAT_EXTEND_LOG ?? import_node_path64.default.join(import_node_os2.default.homedir(), ".neat", "extend-log.ndjson");
|
|
13431
13984
|
}
|
|
13432
13985
|
async function appendExtendLog(entry2) {
|
|
13433
13986
|
const logPath = extendLogPath();
|
|
13434
|
-
await import_node_fs30.promises.mkdir(
|
|
13987
|
+
await import_node_fs30.promises.mkdir(import_node_path64.default.dirname(logPath), { recursive: true });
|
|
13435
13988
|
await import_node_fs30.promises.appendFile(logPath, JSON.stringify(entry2) + "\n", "utf8");
|
|
13436
13989
|
}
|
|
13437
13990
|
function splicedContent(fileContent, snippet2) {
|
|
@@ -13490,7 +14043,7 @@ function lookupInstrumentation(library, installedVersion) {
|
|
|
13490
14043
|
}
|
|
13491
14044
|
async function describeProjectInstrumentation(ctx) {
|
|
13492
14045
|
const hookFiles = await findHookFiles(ctx.scanPath);
|
|
13493
|
-
const envNeat = await fileExists2(
|
|
14046
|
+
const envNeat = await fileExists2(import_node_path64.default.join(ctx.scanPath, ".env.neat"));
|
|
13494
14047
|
const registryInstrPackages = new Set(
|
|
13495
14048
|
(0, import_instrumentation_registry.list)().map((e) => e.instrumentation_package).filter((p) => !!p)
|
|
13496
14049
|
);
|
|
@@ -13512,7 +14065,7 @@ async function applyExtension(ctx, args, options) {
|
|
|
13512
14065
|
);
|
|
13513
14066
|
}
|
|
13514
14067
|
for (const file of hookFiles) {
|
|
13515
|
-
const content = await import_node_fs30.promises.readFile(
|
|
14068
|
+
const content = await import_node_fs30.promises.readFile(import_node_path64.default.join(ctx.scanPath, file), "utf8");
|
|
13516
14069
|
if (content.includes(args.registration_snippet)) {
|
|
13517
14070
|
return { library: args.library, filesTouched: [], depsAdded: [], installOutput: "", alreadyApplied: true };
|
|
13518
14071
|
}
|
|
@@ -13524,10 +14077,10 @@ async function applyExtension(ctx, args, options) {
|
|
|
13524
14077
|
);
|
|
13525
14078
|
}
|
|
13526
14079
|
const primaryFile = primary.file;
|
|
13527
|
-
const primaryPath =
|
|
14080
|
+
const primaryPath = import_node_path64.default.join(ctx.scanPath, primaryFile);
|
|
13528
14081
|
const filesTouched = [];
|
|
13529
14082
|
const depsAdded = [];
|
|
13530
|
-
const pkgPath =
|
|
14083
|
+
const pkgPath = import_node_path64.default.join(ctx.scanPath, "package.json");
|
|
13531
14084
|
const pkg = await readPackageJson(ctx.scanPath);
|
|
13532
14085
|
if (!(pkg.dependencies ?? {})[args.instrumentation_package]) {
|
|
13533
14086
|
pkg.dependencies = { ...pkg.dependencies ?? {}, [args.instrumentation_package]: args.version };
|
|
@@ -13566,7 +14119,7 @@ async function dryRunExtension(ctx, args) {
|
|
|
13566
14119
|
};
|
|
13567
14120
|
}
|
|
13568
14121
|
for (const file of hookFiles) {
|
|
13569
|
-
const content = await import_node_fs30.promises.readFile(
|
|
14122
|
+
const content = await import_node_fs30.promises.readFile(import_node_path64.default.join(ctx.scanPath, file), "utf8");
|
|
13570
14123
|
if (content.includes(args.registration_snippet)) {
|
|
13571
14124
|
return {
|
|
13572
14125
|
library: args.library,
|
|
@@ -13607,7 +14160,7 @@ async function rollbackExtension(ctx, args) {
|
|
|
13607
14160
|
if (!match) {
|
|
13608
14161
|
return { undone: false, message: "no apply found for library" };
|
|
13609
14162
|
}
|
|
13610
|
-
const pkgPath =
|
|
14163
|
+
const pkgPath = import_node_path64.default.join(ctx.scanPath, "package.json");
|
|
13611
14164
|
if (await fileExists2(pkgPath)) {
|
|
13612
14165
|
const pkg = await readPackageJson(ctx.scanPath);
|
|
13613
14166
|
if (pkg.dependencies?.[match.instrumentation_package]) {
|
|
@@ -13618,7 +14171,7 @@ async function rollbackExtension(ctx, args) {
|
|
|
13618
14171
|
}
|
|
13619
14172
|
const hookFiles = await findHookFiles(ctx.scanPath);
|
|
13620
14173
|
for (const file of hookFiles) {
|
|
13621
|
-
const filePath =
|
|
14174
|
+
const filePath = import_node_path64.default.join(ctx.scanPath, file);
|
|
13622
14175
|
const content = await import_node_fs30.promises.readFile(filePath, "utf8");
|
|
13623
14176
|
if (content.includes(match.registration_snippet)) {
|
|
13624
14177
|
const filtered = content.split("\n").filter((line) => !line.includes(match.registration_snippet)).join("\n");
|
|
@@ -13756,23 +14309,23 @@ function canonicalJson(value) {
|
|
|
13756
14309
|
|
|
13757
14310
|
// src/projects.ts
|
|
13758
14311
|
init_cjs_shims();
|
|
13759
|
-
var
|
|
14312
|
+
var import_node_path65 = __toESM(require("path"), 1);
|
|
13760
14313
|
function pathsForProject(project, baseDir) {
|
|
13761
14314
|
if (project === DEFAULT_PROJECT) {
|
|
13762
14315
|
return {
|
|
13763
|
-
snapshotPath:
|
|
13764
|
-
errorsPath:
|
|
13765
|
-
staleEventsPath:
|
|
13766
|
-
embeddingsCachePath:
|
|
13767
|
-
policyViolationsPath:
|
|
14316
|
+
snapshotPath: import_node_path65.default.join(baseDir, "graph.json"),
|
|
14317
|
+
errorsPath: import_node_path65.default.join(baseDir, "errors.ndjson"),
|
|
14318
|
+
staleEventsPath: import_node_path65.default.join(baseDir, "stale-events.ndjson"),
|
|
14319
|
+
embeddingsCachePath: import_node_path65.default.join(baseDir, "embeddings.json"),
|
|
14320
|
+
policyViolationsPath: import_node_path65.default.join(baseDir, "policy-violations.ndjson")
|
|
13768
14321
|
};
|
|
13769
14322
|
}
|
|
13770
14323
|
return {
|
|
13771
|
-
snapshotPath:
|
|
13772
|
-
errorsPath:
|
|
13773
|
-
staleEventsPath:
|
|
13774
|
-
embeddingsCachePath:
|
|
13775
|
-
policyViolationsPath:
|
|
14324
|
+
snapshotPath: import_node_path65.default.join(baseDir, `${project}.json`),
|
|
14325
|
+
errorsPath: import_node_path65.default.join(baseDir, `errors.${project}.ndjson`),
|
|
14326
|
+
staleEventsPath: import_node_path65.default.join(baseDir, `stale-events.${project}.ndjson`),
|
|
14327
|
+
embeddingsCachePath: import_node_path65.default.join(baseDir, `embeddings.${project}.json`),
|
|
14328
|
+
policyViolationsPath: import_node_path65.default.join(baseDir, `policy-violations.${project}.ndjson`)
|
|
13776
14329
|
};
|
|
13777
14330
|
}
|
|
13778
14331
|
var Projects = class {
|
|
@@ -13810,26 +14363,26 @@ var Projects = class {
|
|
|
13810
14363
|
init_cjs_shims();
|
|
13811
14364
|
var import_node_fs32 = require("fs");
|
|
13812
14365
|
var import_node_os3 = __toESM(require("os"), 1);
|
|
13813
|
-
var
|
|
13814
|
-
var
|
|
14366
|
+
var import_node_path66 = __toESM(require("path"), 1);
|
|
14367
|
+
var import_types53 = require("@neat.is/types");
|
|
13815
14368
|
var LOCK_TIMEOUT_MS = 5e3;
|
|
13816
14369
|
var LOCK_RETRY_MS = 50;
|
|
13817
14370
|
function neatHome() {
|
|
13818
14371
|
const override = process.env.NEAT_HOME;
|
|
13819
|
-
if (override && override.length > 0) return
|
|
13820
|
-
return
|
|
14372
|
+
if (override && override.length > 0) return import_node_path66.default.resolve(override);
|
|
14373
|
+
return import_node_path66.default.join(import_node_os3.default.homedir(), ".neat");
|
|
13821
14374
|
}
|
|
13822
14375
|
function registryPath() {
|
|
13823
|
-
return
|
|
14376
|
+
return import_node_path66.default.join(neatHome(), "projects.json");
|
|
13824
14377
|
}
|
|
13825
14378
|
function registryLockPath() {
|
|
13826
|
-
return
|
|
14379
|
+
return import_node_path66.default.join(neatHome(), "projects.json.lock");
|
|
13827
14380
|
}
|
|
13828
14381
|
function daemonPidPath() {
|
|
13829
|
-
return
|
|
14382
|
+
return import_node_path66.default.join(neatHome(), "neatd.pid");
|
|
13830
14383
|
}
|
|
13831
14384
|
function daemonsDir() {
|
|
13832
|
-
return
|
|
14385
|
+
return import_node_path66.default.join(neatHome(), "daemons");
|
|
13833
14386
|
}
|
|
13834
14387
|
function isFiniteInt(v) {
|
|
13835
14388
|
return typeof v === "number" && Number.isFinite(v);
|
|
@@ -13870,7 +14423,7 @@ async function discoverDaemons(probe = defaultDiscoveryProbe) {
|
|
|
13870
14423
|
const out = [];
|
|
13871
14424
|
for (const name of names) {
|
|
13872
14425
|
if (!name.endsWith(".json")) continue;
|
|
13873
|
-
const file =
|
|
14426
|
+
const file = import_node_path66.default.join(dir, name);
|
|
13874
14427
|
let raw;
|
|
13875
14428
|
try {
|
|
13876
14429
|
raw = await import_node_fs32.promises.readFile(file, "utf8");
|
|
@@ -13991,7 +14544,7 @@ function lockHolderMessage(holder, lockPath, timeoutMs) {
|
|
|
13991
14544
|
}
|
|
13992
14545
|
}
|
|
13993
14546
|
async function normalizeProjectPath(input) {
|
|
13994
|
-
const resolved =
|
|
14547
|
+
const resolved = import_node_path66.default.resolve(input);
|
|
13995
14548
|
try {
|
|
13996
14549
|
return await import_node_fs32.promises.realpath(resolved);
|
|
13997
14550
|
} catch {
|
|
@@ -13999,7 +14552,7 @@ async function normalizeProjectPath(input) {
|
|
|
13999
14552
|
}
|
|
14000
14553
|
}
|
|
14001
14554
|
async function writeAtomically(target, contents) {
|
|
14002
|
-
await import_node_fs32.promises.mkdir(
|
|
14555
|
+
await import_node_fs32.promises.mkdir(import_node_path66.default.dirname(target), { recursive: true });
|
|
14003
14556
|
const tmp = `${target}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}.tmp`;
|
|
14004
14557
|
const fd = await import_node_fs32.promises.open(tmp, "w");
|
|
14005
14558
|
try {
|
|
@@ -14012,7 +14565,7 @@ async function writeAtomically(target, contents) {
|
|
|
14012
14565
|
}
|
|
14013
14566
|
async function acquireLock(lockPath, timeoutMs = LOCK_TIMEOUT_MS, probe = defaultLockHolderProbe) {
|
|
14014
14567
|
const deadline = Date.now() + timeoutMs;
|
|
14015
|
-
await import_node_fs32.promises.mkdir(
|
|
14568
|
+
await import_node_fs32.promises.mkdir(import_node_path66.default.dirname(lockPath), { recursive: true });
|
|
14016
14569
|
let probedHolder = false;
|
|
14017
14570
|
while (true) {
|
|
14018
14571
|
try {
|
|
@@ -14065,10 +14618,10 @@ async function readRegistry() {
|
|
|
14065
14618
|
throw err;
|
|
14066
14619
|
}
|
|
14067
14620
|
const parsed = JSON.parse(raw);
|
|
14068
|
-
return
|
|
14621
|
+
return import_types53.RegistryFileSchema.parse(parsed);
|
|
14069
14622
|
}
|
|
14070
14623
|
async function writeRegistry(reg) {
|
|
14071
|
-
const validated =
|
|
14624
|
+
const validated = import_types53.RegistryFileSchema.parse(reg);
|
|
14072
14625
|
await writeAtomically(registryPath(), JSON.stringify(validated, null, 2) + "\n");
|
|
14073
14626
|
}
|
|
14074
14627
|
var ProjectNameCollisionError = class extends Error {
|
|
@@ -14254,7 +14807,7 @@ init_auth();
|
|
|
14254
14807
|
// src/connectors-config.ts
|
|
14255
14808
|
init_cjs_shims();
|
|
14256
14809
|
var import_node_os4 = __toESM(require("os"), 1);
|
|
14257
|
-
var
|
|
14810
|
+
var import_node_path67 = __toESM(require("path"), 1);
|
|
14258
14811
|
var import_node_fs33 = require("fs");
|
|
14259
14812
|
var CONNECTORS_CONFIG_VERSION = 1;
|
|
14260
14813
|
var EnvRefUnsetError = class extends Error {
|
|
@@ -14269,11 +14822,11 @@ var EnvRefUnsetError = class extends Error {
|
|
|
14269
14822
|
};
|
|
14270
14823
|
function neatHome2() {
|
|
14271
14824
|
const override = process.env.NEAT_HOME;
|
|
14272
|
-
if (override && override.length > 0) return
|
|
14273
|
-
return
|
|
14825
|
+
if (override && override.length > 0) return import_node_path67.default.resolve(override);
|
|
14826
|
+
return import_node_path67.default.join(import_node_os4.default.homedir(), ".neat");
|
|
14274
14827
|
}
|
|
14275
14828
|
function connectorsConfigPath(home = neatHome2()) {
|
|
14276
|
-
return
|
|
14829
|
+
return import_node_path67.default.join(home, "connectors.json");
|
|
14277
14830
|
}
|
|
14278
14831
|
var MODE_MASK_LOOSER_THAN_0600 = 63;
|
|
14279
14832
|
async function warnIfModeLooserThan0600(file) {
|
|
@@ -14404,7 +14957,7 @@ function connectorMatchesProject(entry2, project) {
|
|
|
14404
14957
|
var CONNECTORS_LOCK_TIMEOUT_MS = 5e3;
|
|
14405
14958
|
var CONNECTORS_LOCK_RETRY_MS = 50;
|
|
14406
14959
|
function connectorsConfigLockPath(home = neatHome2()) {
|
|
14407
|
-
return
|
|
14960
|
+
return import_node_path67.default.join(home, "connectors.json.lock");
|
|
14408
14961
|
}
|
|
14409
14962
|
function isEnvRef(value) {
|
|
14410
14963
|
return value.length > 1 && value.startsWith("$");
|
|
@@ -14417,7 +14970,7 @@ function redactCredentialRef(ref) {
|
|
|
14417
14970
|
return out;
|
|
14418
14971
|
}
|
|
14419
14972
|
async function writeConfigAtomically0600(file, contents) {
|
|
14420
|
-
await import_node_fs33.promises.mkdir(
|
|
14973
|
+
await import_node_fs33.promises.mkdir(import_node_path67.default.dirname(file), { recursive: true });
|
|
14421
14974
|
const tmp = `${file}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}.tmp`;
|
|
14422
14975
|
const fd = await import_node_fs33.promises.open(tmp, "w", 384);
|
|
14423
14976
|
try {
|
|
@@ -14431,7 +14984,7 @@ async function writeConfigAtomically0600(file, contents) {
|
|
|
14431
14984
|
}
|
|
14432
14985
|
async function acquireConnectorsLock(lockPath, timeoutMs = CONNECTORS_LOCK_TIMEOUT_MS) {
|
|
14433
14986
|
const deadline = Date.now() + timeoutMs;
|
|
14434
|
-
await import_node_fs33.promises.mkdir(
|
|
14987
|
+
await import_node_fs33.promises.mkdir(import_node_path67.default.dirname(lockPath), { recursive: true });
|
|
14435
14988
|
for (; ; ) {
|
|
14436
14989
|
try {
|
|
14437
14990
|
const fd = await import_node_fs33.promises.open(lockPath, "wx");
|
|
@@ -14581,15 +15134,15 @@ function getConnectorStatus(id, now = Date.now(), thresholdMs = CONNECTOR_STALE_
|
|
|
14581
15134
|
|
|
14582
15135
|
// src/connectors/index.ts
|
|
14583
15136
|
init_cjs_shims();
|
|
14584
|
-
var
|
|
15137
|
+
var import_types54 = require("@neat.is/types");
|
|
14585
15138
|
var NO_ENV = "unknown";
|
|
14586
15139
|
function staticCallSiteFor(graph, serviceName, targetNodeId) {
|
|
14587
15140
|
if (!graph.hasNode(targetNodeId)) return void 0;
|
|
14588
15141
|
const sites = [];
|
|
14589
15142
|
for (const edgeId of graph.inboundEdges(targetNodeId)) {
|
|
14590
15143
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
14591
|
-
if (edge.provenance !==
|
|
14592
|
-
const parsed = (0,
|
|
15144
|
+
if (edge.provenance !== import_types54.Provenance.EXTRACTED) continue;
|
|
15145
|
+
const parsed = (0, import_types54.parseFileId)(edge.source);
|
|
14593
15146
|
if (!parsed || parsed.service !== serviceName || !edge.evidence) continue;
|
|
14594
15147
|
const site = { relPath: edge.evidence.file };
|
|
14595
15148
|
if (edge.evidence.line !== void 0) site.line = edge.evidence.line;
|
|
@@ -14600,7 +15153,7 @@ function staticCallSiteFor(graph, serviceName, targetNodeId) {
|
|
|
14600
15153
|
function routeCallSiteFor(graph, targetNodeId) {
|
|
14601
15154
|
if (!graph.hasNode(targetNodeId)) return void 0;
|
|
14602
15155
|
const attrs = graph.getNodeAttributes(targetNodeId);
|
|
14603
|
-
if (attrs.type !==
|
|
15156
|
+
if (attrs.type !== import_types54.NodeType.RouteNode || !attrs.path) return void 0;
|
|
14604
15157
|
const site = { relPath: attrs.path };
|
|
14605
15158
|
if (attrs.line !== void 0) site.line = attrs.line;
|
|
14606
15159
|
return site;
|
|
@@ -15081,10 +15634,10 @@ var SUPABASE_RPC_TARGET_KIND = "supabase-rpc";
|
|
|
15081
15634
|
// src/connectors/supabase/map.ts
|
|
15082
15635
|
var REST_RPC_PATH_RE = /^\/rest\/v1\/rpc\/([^/?]+)/;
|
|
15083
15636
|
var REST_TABLE_PATH_RE = /^\/rest\/v1\/([^/?]+)/;
|
|
15084
|
-
function targetFromRestPath(
|
|
15085
|
-
const rpcMatch = REST_RPC_PATH_RE.exec(
|
|
15637
|
+
function targetFromRestPath(path82) {
|
|
15638
|
+
const rpcMatch = REST_RPC_PATH_RE.exec(path82);
|
|
15086
15639
|
if (rpcMatch) return { targetKind: SUPABASE_RPC_TARGET_KIND, name: rpcMatch[1] };
|
|
15087
|
-
const tableMatch = REST_TABLE_PATH_RE.exec(
|
|
15640
|
+
const tableMatch = REST_TABLE_PATH_RE.exec(path82);
|
|
15088
15641
|
if (tableMatch) return { targetKind: SUPABASE_TABLE_TARGET_KIND, name: tableMatch[1] };
|
|
15089
15642
|
return null;
|
|
15090
15643
|
}
|
|
@@ -15195,23 +15748,23 @@ async function fetchPgStatStatements(connectionString, limit = DEFAULT_STATEMENT
|
|
|
15195
15748
|
|
|
15196
15749
|
// src/connectors/supabase/resolve.ts
|
|
15197
15750
|
init_cjs_shims();
|
|
15198
|
-
var
|
|
15751
|
+
var import_types56 = require("@neat.is/types");
|
|
15199
15752
|
function createSupabaseResolveTarget(graph, config) {
|
|
15200
15753
|
return (signal, _ctx) => {
|
|
15201
15754
|
if (signal.targetKind !== SUPABASE_TABLE_TARGET_KIND && signal.targetKind !== SUPABASE_RPC_TARGET_KIND) {
|
|
15202
15755
|
return null;
|
|
15203
15756
|
}
|
|
15204
|
-
const subResourceId = (0,
|
|
15757
|
+
const subResourceId = (0, import_types56.infraId)(signal.targetKind, `${config.nodeRef}/${signal.targetName}`);
|
|
15205
15758
|
if (graph.hasNode(subResourceId)) {
|
|
15206
|
-
return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType:
|
|
15759
|
+
return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType: import_types56.EdgeType.CALLS };
|
|
15207
15760
|
}
|
|
15208
|
-
const bareResourceId = (0,
|
|
15761
|
+
const bareResourceId = (0, import_types56.infraId)(signal.targetKind, signal.targetName);
|
|
15209
15762
|
if (graph.hasNode(bareResourceId)) {
|
|
15210
|
-
return { targetNodeId: bareResourceId, serviceName: config.serviceName, edgeType:
|
|
15763
|
+
return { targetNodeId: bareResourceId, serviceName: config.serviceName, edgeType: import_types56.EdgeType.CALLS };
|
|
15211
15764
|
}
|
|
15212
|
-
const projectLevelId = (0,
|
|
15765
|
+
const projectLevelId = (0, import_types56.infraId)("supabase", config.nodeRef);
|
|
15213
15766
|
if (graph.hasNode(projectLevelId)) {
|
|
15214
|
-
return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType:
|
|
15767
|
+
return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType: import_types56.EdgeType.CALLS };
|
|
15215
15768
|
}
|
|
15216
15769
|
return null;
|
|
15217
15770
|
};
|
|
@@ -15304,7 +15857,7 @@ function createSupabaseConnector(graph, config, deps = {}) {
|
|
|
15304
15857
|
|
|
15305
15858
|
// src/connectors/railway/index.ts
|
|
15306
15859
|
init_cjs_shims();
|
|
15307
|
-
var
|
|
15860
|
+
var import_types60 = require("@neat.is/types");
|
|
15308
15861
|
|
|
15309
15862
|
// src/connectors/railway/client.ts
|
|
15310
15863
|
init_cjs_shims();
|
|
@@ -15455,7 +16008,7 @@ function buildRailwayRouteIndex(graph, serviceName) {
|
|
|
15455
16008
|
const out = [];
|
|
15456
16009
|
graph.forEachNode((_id, attrs) => {
|
|
15457
16010
|
const node = attrs;
|
|
15458
|
-
if (node.type !==
|
|
16011
|
+
if (node.type !== import_types60.NodeType.RouteNode) return;
|
|
15459
16012
|
const route = attrs;
|
|
15460
16013
|
if (route.service !== serviceName) return;
|
|
15461
16014
|
out.push({
|
|
@@ -15559,12 +16112,12 @@ function createRailwayResolveTarget(config) {
|
|
|
15559
16112
|
const serviceName = config.serviceNameById[config.serviceId];
|
|
15560
16113
|
if (!serviceName) return null;
|
|
15561
16114
|
if (signal.targetKind === ROUTE_TARGET_KIND) {
|
|
15562
|
-
return { targetNodeId: signal.targetName, serviceName, edgeType:
|
|
16115
|
+
return { targetNodeId: signal.targetName, serviceName, edgeType: import_types60.EdgeType.CALLS };
|
|
15563
16116
|
}
|
|
15564
16117
|
if (signal.targetKind === PEER_SERVICE_TARGET_KIND) {
|
|
15565
16118
|
const peerName = config.serviceNameById[signal.targetName];
|
|
15566
16119
|
if (!peerName) return null;
|
|
15567
|
-
return { targetNodeId: (0,
|
|
16120
|
+
return { targetNodeId: (0, import_types60.serviceId)(peerName), serviceName, edgeType: import_types60.EdgeType.CONNECTS_TO };
|
|
15568
16121
|
}
|
|
15569
16122
|
return null;
|
|
15570
16123
|
};
|
|
@@ -15688,9 +16241,9 @@ function parseFirebaseTargetName(targetName) {
|
|
|
15688
16241
|
const secondSep = rest.indexOf(FIELD_SEP);
|
|
15689
16242
|
if (secondSep === -1) return null;
|
|
15690
16243
|
const method = rest.slice(0, secondSep);
|
|
15691
|
-
const
|
|
15692
|
-
if (!resourceName || !method || !
|
|
15693
|
-
return { resourceName, method, path:
|
|
16244
|
+
const path82 = rest.slice(secondSep + 1);
|
|
16245
|
+
if (!resourceName || !method || !path82) return null;
|
|
16246
|
+
return { resourceName, method, path: path82 };
|
|
15694
16247
|
}
|
|
15695
16248
|
function resourceNameFor(type, labels) {
|
|
15696
16249
|
if (!labels) return null;
|
|
@@ -15728,14 +16281,14 @@ function mapLogEntryToSignal(entry2) {
|
|
|
15728
16281
|
if (!req) return null;
|
|
15729
16282
|
if (typeof req.requestMethod !== "string" || req.requestMethod.length === 0) return null;
|
|
15730
16283
|
const method = req.requestMethod.toUpperCase();
|
|
15731
|
-
const
|
|
15732
|
-
if (
|
|
16284
|
+
const path82 = pathFromRequestUrl(req.requestUrl);
|
|
16285
|
+
if (path82 === null) return null;
|
|
15733
16286
|
const timestamp = entry2.timestamp;
|
|
15734
16287
|
if (typeof timestamp !== "string" || timestamp.length === 0) return null;
|
|
15735
16288
|
const isError = typeof req.status === "number" && req.status >= ERROR_STATUS_THRESHOLD2;
|
|
15736
16289
|
return {
|
|
15737
16290
|
targetKind: resourceType,
|
|
15738
|
-
targetName: packFirebaseTargetName({ resourceName, method, path:
|
|
16291
|
+
targetName: packFirebaseTargetName({ resourceName, method, path: path82 }),
|
|
15739
16292
|
callCount: 1,
|
|
15740
16293
|
errorCount: isError ? 1 : 0,
|
|
15741
16294
|
lastObservedIso: timestamp
|
|
@@ -15752,7 +16305,7 @@ function mapLogEntriesToSignals(entries) {
|
|
|
15752
16305
|
|
|
15753
16306
|
// src/connectors/firebase/resolve.ts
|
|
15754
16307
|
init_cjs_shims();
|
|
15755
|
-
var
|
|
16308
|
+
var import_types61 = require("@neat.is/types");
|
|
15756
16309
|
function neatServiceNameFor(resourceType, resourceName, serviceMap) {
|
|
15757
16310
|
switch (resourceType) {
|
|
15758
16311
|
case "cloud_function":
|
|
@@ -15767,7 +16320,7 @@ function routeEntriesFor(graph, serviceName) {
|
|
|
15767
16320
|
const entries = [];
|
|
15768
16321
|
graph.forEachNode((_id, attrs) => {
|
|
15769
16322
|
const node = attrs;
|
|
15770
|
-
if (node.type !==
|
|
16323
|
+
if (node.type !== import_types61.NodeType.RouteNode) return;
|
|
15771
16324
|
const route = attrs;
|
|
15772
16325
|
if (route.service !== serviceName) return;
|
|
15773
16326
|
entries.push({
|
|
@@ -15799,7 +16352,7 @@ function createFirebaseResolveTarget(graph, serviceMap) {
|
|
|
15799
16352
|
return {
|
|
15800
16353
|
targetNodeId: match.routeNodeId,
|
|
15801
16354
|
serviceName,
|
|
15802
|
-
edgeType:
|
|
16355
|
+
edgeType: import_types61.EdgeType.CALLS
|
|
15803
16356
|
};
|
|
15804
16357
|
};
|
|
15805
16358
|
}
|
|
@@ -15826,7 +16379,7 @@ init_cjs_shims();
|
|
|
15826
16379
|
|
|
15827
16380
|
// src/connectors/cloudflare/connector.ts
|
|
15828
16381
|
init_cjs_shims();
|
|
15829
|
-
var
|
|
16382
|
+
var import_types63 = require("@neat.is/types");
|
|
15830
16383
|
|
|
15831
16384
|
// src/connectors/cloudflare/client.ts
|
|
15832
16385
|
init_cjs_shims();
|
|
@@ -15942,7 +16495,7 @@ function mapEventToSignal(event) {
|
|
|
15942
16495
|
if (Number.isNaN(observedAt.getTime())) return null;
|
|
15943
16496
|
const statusCode = metadata?.statusCode;
|
|
15944
16497
|
const isError = typeof statusCode === "number" && statusCode >= ERROR_STATUS_THRESHOLD3;
|
|
15945
|
-
const
|
|
16498
|
+
const path82 = metadata?.trigger ? parsePathFromTrigger(metadata.trigger) : void 0;
|
|
15946
16499
|
return {
|
|
15947
16500
|
targetKind: CLOUDFLARE_TARGET_KIND,
|
|
15948
16501
|
targetName: scriptName,
|
|
@@ -15950,7 +16503,7 @@ function mapEventToSignal(event) {
|
|
|
15950
16503
|
errorCount: isError ? 1 : 0,
|
|
15951
16504
|
lastObservedIso: observedAt.toISOString(),
|
|
15952
16505
|
method,
|
|
15953
|
-
...
|
|
16506
|
+
...path82 ? { path: path82 } : {},
|
|
15954
16507
|
...typeof statusCode === "number" ? { statusCode } : {},
|
|
15955
16508
|
...typeof metadata?.duration === "number" ? { duration: metadata.duration } : {}
|
|
15956
16509
|
};
|
|
@@ -15990,19 +16543,19 @@ function findTaggedWorkerFileNode(graph, workerName) {
|
|
|
15990
16543
|
graph.forEachNode((id, attrs) => {
|
|
15991
16544
|
if (found) return;
|
|
15992
16545
|
const a = attrs;
|
|
15993
|
-
if (a.type ===
|
|
16546
|
+
if (a.type === import_types63.NodeType.FileNode && a.platform === "cloudflare" && a.platformName === workerName) {
|
|
15994
16547
|
found = id;
|
|
15995
16548
|
}
|
|
15996
16549
|
});
|
|
15997
16550
|
return found;
|
|
15998
16551
|
}
|
|
15999
|
-
function findMatchingRouteNode(graph, serviceName, method,
|
|
16000
|
-
const normalizedPath = normalizePathTemplate(
|
|
16552
|
+
function findMatchingRouteNode(graph, serviceName, method, path82) {
|
|
16553
|
+
const normalizedPath = normalizePathTemplate(path82);
|
|
16001
16554
|
let found = null;
|
|
16002
16555
|
graph.forEachNode((id, attrs) => {
|
|
16003
16556
|
if (found) return;
|
|
16004
16557
|
const a = attrs;
|
|
16005
|
-
if (a.type !==
|
|
16558
|
+
if (a.type !== import_types63.NodeType.RouteNode || a.service !== serviceName) return;
|
|
16006
16559
|
if (!a.pathTemplate || normalizePathTemplate(a.pathTemplate) !== normalizedPath) return;
|
|
16007
16560
|
const routeMethod = (a.method ?? "").toUpperCase();
|
|
16008
16561
|
if (routeMethod !== "ALL" && routeMethod !== method) return;
|
|
@@ -16014,18 +16567,18 @@ function createCloudflareResolveTarget(config, graph) {
|
|
|
16014
16567
|
return (signal) => {
|
|
16015
16568
|
if (signal.targetKind !== CLOUDFLARE_TARGET_KIND) return null;
|
|
16016
16569
|
const scriptName = signal.targetName;
|
|
16017
|
-
const { method, path:
|
|
16570
|
+
const { method, path: path82 } = signal;
|
|
16018
16571
|
const resolveRouteGrain = (serviceName, wholeFileId) => {
|
|
16019
|
-
if (!method || !
|
|
16020
|
-
return findMatchingRouteNode(graph, serviceName, method,
|
|
16572
|
+
if (!method || !path82) return wholeFileId;
|
|
16573
|
+
return findMatchingRouteNode(graph, serviceName, method, path82) ?? wholeFileId;
|
|
16021
16574
|
};
|
|
16022
16575
|
const mapping = config.workers?.[scriptName];
|
|
16023
16576
|
if (mapping) {
|
|
16024
|
-
const wholeFileId = (0,
|
|
16577
|
+
const wholeFileId = (0, import_types63.fileId)(mapping.service, mapping.entryFile);
|
|
16025
16578
|
return {
|
|
16026
16579
|
targetNodeId: resolveRouteGrain(mapping.service, wholeFileId),
|
|
16027
16580
|
serviceName: mapping.service,
|
|
16028
|
-
edgeType:
|
|
16581
|
+
edgeType: import_types63.EdgeType.CALLS
|
|
16029
16582
|
};
|
|
16030
16583
|
}
|
|
16031
16584
|
const taggedFileId = findTaggedWorkerFileNode(graph, scriptName);
|
|
@@ -16034,13 +16587,13 @@ function createCloudflareResolveTarget(config, graph) {
|
|
|
16034
16587
|
return {
|
|
16035
16588
|
targetNodeId: resolveRouteGrain(fileNode.service, taggedFileId),
|
|
16036
16589
|
serviceName: fileNode.service,
|
|
16037
|
-
edgeType:
|
|
16590
|
+
edgeType: import_types63.EdgeType.CALLS
|
|
16038
16591
|
};
|
|
16039
16592
|
}
|
|
16040
16593
|
return {
|
|
16041
|
-
targetNodeId: (0,
|
|
16594
|
+
targetNodeId: (0, import_types63.infraId)("cloudflare-worker", scriptName),
|
|
16042
16595
|
serviceName: scriptName,
|
|
16043
|
-
edgeType:
|
|
16596
|
+
edgeType: import_types63.EdgeType.CALLS,
|
|
16044
16597
|
ensureInfraNode: { kind: "cloudflare-worker", name: scriptName, provider: "cloudflare" }
|
|
16045
16598
|
};
|
|
16046
16599
|
};
|
|
@@ -16236,14 +16789,14 @@ function diffNeonStatementsToSignals(rows, previous, observedAtIso) {
|
|
|
16236
16789
|
|
|
16237
16790
|
// src/connectors/neon/resolve.ts
|
|
16238
16791
|
init_cjs_shims();
|
|
16239
|
-
var
|
|
16792
|
+
var import_types67 = require("@neat.is/types");
|
|
16240
16793
|
function createNeonResolveTarget(config) {
|
|
16241
16794
|
return (signal) => {
|
|
16242
16795
|
if (signal.targetKind !== NEON_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
|
|
16243
16796
|
return {
|
|
16244
|
-
targetNodeId: (0,
|
|
16797
|
+
targetNodeId: (0, import_types67.infraId)("sql-table", signal.targetName),
|
|
16245
16798
|
serviceName: config.serviceName,
|
|
16246
|
-
edgeType:
|
|
16799
|
+
edgeType: import_types67.EdgeType.CALLS,
|
|
16247
16800
|
ensureInfraNode: { kind: "sql-table", name: signal.targetName, provider: "neon" }
|
|
16248
16801
|
};
|
|
16249
16802
|
};
|
|
@@ -16369,9 +16922,9 @@ function parseCloudRunTargetName(targetName) {
|
|
|
16369
16922
|
const secondSep = rest.indexOf(FIELD_SEP2);
|
|
16370
16923
|
if (secondSep === -1) return null;
|
|
16371
16924
|
const method = rest.slice(0, secondSep);
|
|
16372
|
-
const
|
|
16373
|
-
if (!serviceName || !method || !
|
|
16374
|
-
return { serviceName, method, path:
|
|
16925
|
+
const path82 = rest.slice(secondSep + 1);
|
|
16926
|
+
if (!serviceName || !method || !path82) return null;
|
|
16927
|
+
return { serviceName, method, path: path82 };
|
|
16375
16928
|
}
|
|
16376
16929
|
|
|
16377
16930
|
// src/connectors/cloud-run/map.ts
|
|
@@ -16400,14 +16953,14 @@ function mapLogEntryToSignal2(entry2) {
|
|
|
16400
16953
|
if (!req) return null;
|
|
16401
16954
|
if (typeof req.requestMethod !== "string" || req.requestMethod.length === 0) return null;
|
|
16402
16955
|
const method = req.requestMethod.toUpperCase();
|
|
16403
|
-
const
|
|
16404
|
-
if (
|
|
16956
|
+
const path82 = pathFromRequestUrl2(req.requestUrl);
|
|
16957
|
+
if (path82 === null) return null;
|
|
16405
16958
|
const timestamp = entry2.timestamp;
|
|
16406
16959
|
if (typeof timestamp !== "string" || timestamp.length === 0) return null;
|
|
16407
16960
|
const isError = typeof req.status === "number" && req.status >= ERROR_STATUS_THRESHOLD4;
|
|
16408
16961
|
return {
|
|
16409
16962
|
targetKind: CLOUD_RUN_TARGET_KIND,
|
|
16410
|
-
targetName: packCloudRunTargetName({ serviceName, method, path:
|
|
16963
|
+
targetName: packCloudRunTargetName({ serviceName, method, path: path82 }),
|
|
16411
16964
|
callCount: 1,
|
|
16412
16965
|
errorCount: isError ? 1 : 0,
|
|
16413
16966
|
lastObservedIso: timestamp
|
|
@@ -16424,14 +16977,14 @@ function mapLogEntriesToSignals2(entries) {
|
|
|
16424
16977
|
|
|
16425
16978
|
// src/connectors/cloud-run/resolve.ts
|
|
16426
16979
|
init_cjs_shims();
|
|
16427
|
-
var
|
|
16980
|
+
var import_types71 = require("@neat.is/types");
|
|
16428
16981
|
var CLOUD_RUN_SERVICE_INFRA_KIND = "cloud-run-service";
|
|
16429
16982
|
function findMatchingRouteNode2(graph, serviceName, method, normalizedPath) {
|
|
16430
16983
|
let found = null;
|
|
16431
16984
|
graph.forEachNode((_id, attrs) => {
|
|
16432
16985
|
if (found) return;
|
|
16433
16986
|
const node = attrs;
|
|
16434
|
-
if (node.type !==
|
|
16987
|
+
if (node.type !== import_types71.NodeType.RouteNode) return;
|
|
16435
16988
|
const route = attrs;
|
|
16436
16989
|
if (route.service !== serviceName || !route.pathTemplate) return;
|
|
16437
16990
|
if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
|
|
@@ -16446,23 +16999,23 @@ function createCloudRunResolveTarget(graph, config) {
|
|
|
16446
16999
|
if (signal.targetKind !== CLOUD_RUN_TARGET_KIND) return null;
|
|
16447
17000
|
const identity = parseCloudRunTargetName(signal.targetName);
|
|
16448
17001
|
if (!identity) return null;
|
|
16449
|
-
const { serviceName: gcpServiceName, method, path:
|
|
17002
|
+
const { serviceName: gcpServiceName, method, path: path82 } = identity;
|
|
16450
17003
|
const mappedService = config.serviceMap?.[gcpServiceName];
|
|
16451
17004
|
if (mappedService) {
|
|
16452
17005
|
const routeNodeId = findMatchingRouteNode2(
|
|
16453
17006
|
graph,
|
|
16454
17007
|
mappedService,
|
|
16455
17008
|
method,
|
|
16456
|
-
normalizePathTemplate(
|
|
17009
|
+
normalizePathTemplate(path82)
|
|
16457
17010
|
);
|
|
16458
17011
|
if (routeNodeId) {
|
|
16459
|
-
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType:
|
|
17012
|
+
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types71.EdgeType.CALLS };
|
|
16460
17013
|
}
|
|
16461
17014
|
}
|
|
16462
17015
|
return {
|
|
16463
|
-
targetNodeId: (0,
|
|
17016
|
+
targetNodeId: (0, import_types71.infraId)(CLOUD_RUN_SERVICE_INFRA_KIND, gcpServiceName),
|
|
16464
17017
|
serviceName: mappedService ?? gcpServiceName,
|
|
16465
|
-
edgeType:
|
|
17018
|
+
edgeType: import_types71.EdgeType.CALLS,
|
|
16466
17019
|
ensureInfraNode: {
|
|
16467
17020
|
kind: CLOUD_RUN_SERVICE_INFRA_KIND,
|
|
16468
17021
|
name: gcpServiceName,
|
|
@@ -16503,7 +17056,7 @@ function createCloudRunConnector(graph, config = {}) {
|
|
|
16503
17056
|
|
|
16504
17057
|
// src/connectors/render/index.ts
|
|
16505
17058
|
init_cjs_shims();
|
|
16506
|
-
var
|
|
17059
|
+
var import_types74 = require("@neat.is/types");
|
|
16507
17060
|
|
|
16508
17061
|
// src/connectors/render/types.ts
|
|
16509
17062
|
init_cjs_shims();
|
|
@@ -16581,7 +17134,7 @@ function buildRenderRouteIndex(graph, serviceName) {
|
|
|
16581
17134
|
const out = [];
|
|
16582
17135
|
graph.forEachNode((_id, attrs) => {
|
|
16583
17136
|
const node = attrs;
|
|
16584
|
-
if (node.type !==
|
|
17137
|
+
if (node.type !== import_types74.NodeType.RouteNode) return;
|
|
16585
17138
|
const route = attrs;
|
|
16586
17139
|
if (route.service !== serviceName) return;
|
|
16587
17140
|
out.push({
|
|
@@ -16666,7 +17219,7 @@ function mapRenderRequestLogsToSignals(entries, routeIndex) {
|
|
|
16666
17219
|
function createRenderResolveTarget(config) {
|
|
16667
17220
|
return (signal) => {
|
|
16668
17221
|
if (signal.targetKind === ROUTE_TARGET_KIND2) {
|
|
16669
|
-
return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType:
|
|
17222
|
+
return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType: import_types74.EdgeType.CALLS };
|
|
16670
17223
|
}
|
|
16671
17224
|
return null;
|
|
16672
17225
|
};
|
|
@@ -16804,21 +17357,21 @@ function mapInsightsToSignals(rows, observedAtIso) {
|
|
|
16804
17357
|
|
|
16805
17358
|
// src/connectors/planetscale/resolve.ts
|
|
16806
17359
|
init_cjs_shims();
|
|
16807
|
-
var
|
|
17360
|
+
var import_types78 = require("@neat.is/types");
|
|
16808
17361
|
var PLANETSCALE_DATABASE_KIND = "planetscale-database";
|
|
16809
17362
|
function createPlanetscaleResolveTarget(graph, config) {
|
|
16810
17363
|
const databaseName = `${config.organization}/${config.database}`;
|
|
16811
17364
|
return (signal, _ctx) => {
|
|
16812
17365
|
if (signal.targetKind !== PLANETSCALE_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
|
|
16813
|
-
const tableId = (0,
|
|
17366
|
+
const tableId = (0, import_types78.infraId)("sql-table", signal.targetName);
|
|
16814
17367
|
if (graph.hasNode(tableId)) {
|
|
16815
|
-
return { targetNodeId: tableId, serviceName: config.serviceName, edgeType:
|
|
17368
|
+
return { targetNodeId: tableId, serviceName: config.serviceName, edgeType: import_types78.EdgeType.CALLS };
|
|
16816
17369
|
}
|
|
16817
|
-
const providerId = (0,
|
|
17370
|
+
const providerId = (0, import_types78.infraId)(PLANETSCALE_DATABASE_KIND, databaseName);
|
|
16818
17371
|
return {
|
|
16819
17372
|
targetNodeId: providerId,
|
|
16820
17373
|
serviceName: config.serviceName,
|
|
16821
|
-
edgeType:
|
|
17374
|
+
edgeType: import_types78.EdgeType.CALLS,
|
|
16822
17375
|
ensureInfraNode: { kind: PLANETSCALE_DATABASE_KIND, name: databaseName, provider: "planetscale" }
|
|
16823
17376
|
};
|
|
16824
17377
|
};
|
|
@@ -17567,11 +18120,11 @@ function registerRoutes(scope, ctx) {
|
|
|
17567
18120
|
const candidates = req.query.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
17568
18121
|
const parsed = [];
|
|
17569
18122
|
for (const c of candidates) {
|
|
17570
|
-
const r =
|
|
18123
|
+
const r = import_types81.DivergenceTypeSchema.safeParse(c);
|
|
17571
18124
|
if (!r.success) {
|
|
17572
18125
|
return reply.code(400).send({
|
|
17573
18126
|
error: `unknown divergence type "${c}"`,
|
|
17574
|
-
allowed:
|
|
18127
|
+
allowed: import_types81.DivergenceTypeSchema.options
|
|
17575
18128
|
});
|
|
17576
18129
|
}
|
|
17577
18130
|
parsed.push(r.data);
|
|
@@ -17880,7 +18433,7 @@ function registerRoutes(scope, ctx) {
|
|
|
17880
18433
|
const log = new PolicyViolationsLog(proj.paths.policyViolationsPath);
|
|
17881
18434
|
let violations = await log.readAll();
|
|
17882
18435
|
if (req.query.severity) {
|
|
17883
|
-
const sev =
|
|
18436
|
+
const sev = import_types81.PolicySeveritySchema.safeParse(req.query.severity);
|
|
17884
18437
|
if (!sev.success) {
|
|
17885
18438
|
return reply.code(400).send({
|
|
17886
18439
|
error: "invalid severity",
|
|
@@ -17919,7 +18472,7 @@ function registerRoutes(scope, ctx) {
|
|
|
17919
18472
|
scope.post("/policies/check", async (req, reply) => {
|
|
17920
18473
|
const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
|
|
17921
18474
|
if (!proj) return;
|
|
17922
|
-
const parsed =
|
|
18475
|
+
const parsed = import_types81.PoliciesCheckBodySchema.safeParse(req.body ?? {});
|
|
17923
18476
|
if (!parsed.success) {
|
|
17924
18477
|
return reply.code(400).send({
|
|
17925
18478
|
error: "invalid /policies/check body",
|
|
@@ -18241,7 +18794,7 @@ init_otel();
|
|
|
18241
18794
|
// src/daemon.ts
|
|
18242
18795
|
init_cjs_shims();
|
|
18243
18796
|
var import_node_fs35 = require("fs");
|
|
18244
|
-
var
|
|
18797
|
+
var import_node_path69 = __toESM(require("path"), 1);
|
|
18245
18798
|
var import_node_module = require("module");
|
|
18246
18799
|
init_otel();
|
|
18247
18800
|
init_auth();
|
|
@@ -18249,28 +18802,28 @@ init_auth();
|
|
|
18249
18802
|
// src/unrouted.ts
|
|
18250
18803
|
init_cjs_shims();
|
|
18251
18804
|
var import_node_fs34 = require("fs");
|
|
18252
|
-
var
|
|
18805
|
+
var import_node_path68 = __toESM(require("path"), 1);
|
|
18253
18806
|
|
|
18254
18807
|
// src/daemon.ts
|
|
18255
|
-
var
|
|
18808
|
+
var import_types82 = require("@neat.is/types");
|
|
18256
18809
|
function daemonJsonPath(scanPath) {
|
|
18257
|
-
return
|
|
18810
|
+
return import_node_path69.default.join(scanPath, "neat-out", "daemon.json");
|
|
18258
18811
|
}
|
|
18259
18812
|
function daemonsDiscoveryDir(home) {
|
|
18260
18813
|
const base = home && home.length > 0 ? home : neatHomeFromEnv();
|
|
18261
|
-
return
|
|
18814
|
+
return import_node_path69.default.join(base, "daemons");
|
|
18262
18815
|
}
|
|
18263
18816
|
function daemonDiscoveryPath(project, home) {
|
|
18264
|
-
return
|
|
18817
|
+
return import_node_path69.default.join(daemonsDiscoveryDir(home), `${sanitizeDiscoveryName(project)}.json`);
|
|
18265
18818
|
}
|
|
18266
18819
|
function sanitizeDiscoveryName(project) {
|
|
18267
18820
|
return project.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
18268
18821
|
}
|
|
18269
18822
|
function neatHomeFromEnv() {
|
|
18270
18823
|
const env = process.env.NEAT_HOME;
|
|
18271
|
-
if (env && env.length > 0) return
|
|
18824
|
+
if (env && env.length > 0) return import_node_path69.default.resolve(env);
|
|
18272
18825
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
18273
|
-
return
|
|
18826
|
+
return import_node_path69.default.join(home, ".neat");
|
|
18274
18827
|
}
|
|
18275
18828
|
async function readDaemonRecord(scanPath) {
|
|
18276
18829
|
try {
|
|
@@ -18341,7 +18894,7 @@ init_otel_grpc();
|
|
|
18341
18894
|
// src/search.ts
|
|
18342
18895
|
init_cjs_shims();
|
|
18343
18896
|
var import_node_fs36 = require("fs");
|
|
18344
|
-
var
|
|
18897
|
+
var import_node_path70 = __toESM(require("path"), 1);
|
|
18345
18898
|
var import_node_crypto4 = require("crypto");
|
|
18346
18899
|
var DEFAULT_LIMIT = 10;
|
|
18347
18900
|
var NOMIC_DIM = 768;
|
|
@@ -18504,7 +19057,7 @@ async function readCache(cachePath) {
|
|
|
18504
19057
|
}
|
|
18505
19058
|
}
|
|
18506
19059
|
async function writeCache(cachePath, cache) {
|
|
18507
|
-
await import_node_fs36.promises.mkdir(
|
|
19060
|
+
await import_node_fs36.promises.mkdir(import_node_path70.default.dirname(cachePath), { recursive: true });
|
|
18508
19061
|
await import_node_fs36.promises.writeFile(cachePath, JSON.stringify(cache));
|
|
18509
19062
|
}
|
|
18510
19063
|
var VectorIndex = class {
|
|
@@ -18664,8 +19217,8 @@ var ALL_PHASES = [
|
|
|
18664
19217
|
];
|
|
18665
19218
|
function classifyChange(relPath) {
|
|
18666
19219
|
const phases = /* @__PURE__ */ new Set();
|
|
18667
|
-
const base =
|
|
18668
|
-
const segments = relPath.split(
|
|
19220
|
+
const base = import_node_path71.default.basename(relPath).toLowerCase();
|
|
19221
|
+
const segments = relPath.split(import_node_path71.default.sep).map((s) => s.toLowerCase());
|
|
18669
19222
|
if (base === "package.json" || base === "requirements.txt" || base === "pyproject.toml" || base === "setup.py") {
|
|
18670
19223
|
phases.add("services");
|
|
18671
19224
|
phases.add("aliases");
|
|
@@ -18805,9 +19358,9 @@ function countWatchableDirs(scanPath, limit) {
|
|
|
18805
19358
|
for (const e of entries) {
|
|
18806
19359
|
if (count >= limit) return;
|
|
18807
19360
|
if (!e.isDirectory()) continue;
|
|
18808
|
-
if (IGNORED_WATCH_PATHS.some((re) => re.test(
|
|
19361
|
+
if (IGNORED_WATCH_PATHS.some((re) => re.test(import_node_path71.default.join(dir, e.name) + import_node_path71.default.sep))) continue;
|
|
18809
19362
|
count++;
|
|
18810
|
-
if (depth < 2) visit(
|
|
19363
|
+
if (depth < 2) visit(import_node_path71.default.join(dir, e.name), depth + 1);
|
|
18811
19364
|
}
|
|
18812
19365
|
};
|
|
18813
19366
|
visit(scanPath, 0);
|
|
@@ -18825,8 +19378,8 @@ async function startWatch(graph, opts) {
|
|
|
18825
19378
|
const projectName = opts.project ?? DEFAULT_PROJECT;
|
|
18826
19379
|
await loadGraphFromDisk(graph, opts.outPath);
|
|
18827
19380
|
const detachEventBus = attachGraphToEventBus(graph, { project: projectName });
|
|
18828
|
-
const policyFilePath =
|
|
18829
|
-
const policyViolationsPath =
|
|
19381
|
+
const policyFilePath = import_node_path71.default.join(opts.scanPath, "policy.json");
|
|
19382
|
+
const policyViolationsPath = import_node_path71.default.join(import_node_path71.default.dirname(opts.outPath), "policy-violations.ndjson");
|
|
18830
19383
|
let policies = [];
|
|
18831
19384
|
try {
|
|
18832
19385
|
policies = await loadPolicyFile(policyFilePath);
|
|
@@ -18886,7 +19439,7 @@ async function startWatch(graph, opts) {
|
|
|
18886
19439
|
assertBindAuthority(host, auth.authToken);
|
|
18887
19440
|
const port = opts.port ?? 8080;
|
|
18888
19441
|
const otelPort = opts.otelPort ?? 4318;
|
|
18889
|
-
const cachePath = opts.embeddingsCachePath ??
|
|
19442
|
+
const cachePath = opts.embeddingsCachePath ?? import_node_path71.default.join(import_node_path71.default.dirname(opts.outPath), "embeddings.json");
|
|
18890
19443
|
let searchIndex;
|
|
18891
19444
|
try {
|
|
18892
19445
|
searchIndex = await buildSearchIndex(graph, { cachePath });
|
|
@@ -18904,7 +19457,7 @@ async function startWatch(graph, opts) {
|
|
|
18904
19457
|
// Paths are derived from the explicit options the watch caller passes
|
|
18905
19458
|
// — pathsForProject is only used to fill in the embeddings/snapshot
|
|
18906
19459
|
// fields so the registry shape is complete.
|
|
18907
|
-
...pathsForProject(projectName,
|
|
19460
|
+
...pathsForProject(projectName, import_node_path71.default.dirname(opts.outPath)),
|
|
18908
19461
|
snapshotPath: opts.outPath,
|
|
18909
19462
|
errorsPath: opts.errorsPath,
|
|
18910
19463
|
staleEventsPath: opts.staleEventsPath
|
|
@@ -19022,9 +19575,9 @@ async function startWatch(graph, opts) {
|
|
|
19022
19575
|
};
|
|
19023
19576
|
const onPath = (absPath) => {
|
|
19024
19577
|
if (shouldIgnore(absPath)) return;
|
|
19025
|
-
const rel =
|
|
19578
|
+
const rel = import_node_path71.default.relative(opts.scanPath, absPath);
|
|
19026
19579
|
if (!rel || rel.startsWith("..")) return;
|
|
19027
|
-
pendingPaths.add(rel.split(
|
|
19580
|
+
pendingPaths.add(rel.split(import_node_path71.default.sep).join("/"));
|
|
19028
19581
|
const phases = classifyChange(rel);
|
|
19029
19582
|
if (phases.size === 0) {
|
|
19030
19583
|
for (const p of ALL_PHASES) pending.add(p);
|
|
@@ -19082,7 +19635,7 @@ async function startWatch(graph, opts) {
|
|
|
19082
19635
|
// src/deploy/detect.ts
|
|
19083
19636
|
init_cjs_shims();
|
|
19084
19637
|
var import_node_fs38 = require("fs");
|
|
19085
|
-
var
|
|
19638
|
+
var import_node_path72 = __toESM(require("path"), 1);
|
|
19086
19639
|
var import_node_child_process2 = require("child_process");
|
|
19087
19640
|
var import_node_crypto5 = require("crypto");
|
|
19088
19641
|
function generateToken() {
|
|
@@ -19182,7 +19735,7 @@ async function runDeploy(opts = {}) {
|
|
|
19182
19735
|
const token = generateToken();
|
|
19183
19736
|
switch (substrate) {
|
|
19184
19737
|
case "docker-compose": {
|
|
19185
|
-
const artifactPath =
|
|
19738
|
+
const artifactPath = import_node_path72.default.join(cwd, "docker-compose.neat.yml");
|
|
19186
19739
|
const contents = emitDockerCompose(cwd);
|
|
19187
19740
|
await import_node_fs38.promises.writeFile(artifactPath, contents, "utf8");
|
|
19188
19741
|
return {
|
|
@@ -19190,11 +19743,11 @@ async function runDeploy(opts = {}) {
|
|
|
19190
19743
|
artifactPath,
|
|
19191
19744
|
token,
|
|
19192
19745
|
contents,
|
|
19193
|
-
startCommand: `NEAT_AUTH_TOKEN=${token} docker compose -f ${
|
|
19746
|
+
startCommand: `NEAT_AUTH_TOKEN=${token} docker compose -f ${import_node_path72.default.basename(artifactPath)} up -d`
|
|
19194
19747
|
};
|
|
19195
19748
|
}
|
|
19196
19749
|
case "systemd": {
|
|
19197
|
-
const artifactPath =
|
|
19750
|
+
const artifactPath = import_node_path72.default.join(cwd, "neat.service");
|
|
19198
19751
|
const contents = emitSystemdUnit(cwd);
|
|
19199
19752
|
await import_node_fs38.promises.writeFile(artifactPath, contents, "utf8");
|
|
19200
19753
|
return {
|
|
@@ -19230,7 +19783,7 @@ init_cjs_shims();
|
|
|
19230
19783
|
// src/installers/javascript.ts
|
|
19231
19784
|
init_cjs_shims();
|
|
19232
19785
|
var import_node_fs39 = require("fs");
|
|
19233
|
-
var
|
|
19786
|
+
var import_node_path73 = __toESM(require("path"), 1);
|
|
19234
19787
|
var import_semver2 = __toESM(require("semver"), 1);
|
|
19235
19788
|
|
|
19236
19789
|
// src/installers/templates.ts
|
|
@@ -19897,11 +20450,11 @@ var OTEL_ENV = {
|
|
|
19897
20450
|
value: "http://localhost:4318/projects/<project>/v1/traces"
|
|
19898
20451
|
};
|
|
19899
20452
|
function serviceNodeName(pkg, serviceDir) {
|
|
19900
|
-
return pkg.name ??
|
|
20453
|
+
return pkg.name ?? import_node_path73.default.basename(serviceDir);
|
|
19901
20454
|
}
|
|
19902
20455
|
function projectToken(pkg, serviceDir, project) {
|
|
19903
20456
|
if (project && project.length > 0) return project;
|
|
19904
|
-
return pkg.name ??
|
|
20457
|
+
return pkg.name ?? import_node_path73.default.basename(serviceDir);
|
|
19905
20458
|
}
|
|
19906
20459
|
async function readJsonFile(p) {
|
|
19907
20460
|
try {
|
|
@@ -19914,16 +20467,16 @@ async function readJsonFile(p) {
|
|
|
19914
20467
|
async function detectRuntimeKind(pkgRoot, pkg) {
|
|
19915
20468
|
const deps = allDeps(pkg);
|
|
19916
20469
|
if ("react-native" in deps || "expo" in deps) return "react-native";
|
|
19917
|
-
const appJson = await readJsonFile(
|
|
20470
|
+
const appJson = await readJsonFile(import_node_path73.default.join(pkgRoot, "app.json"));
|
|
19918
20471
|
if (appJson && typeof appJson === "object" && "expo" in appJson) {
|
|
19919
20472
|
return "react-native";
|
|
19920
20473
|
}
|
|
19921
|
-
if (await exists3(
|
|
20474
|
+
if (await exists3(import_node_path73.default.join(pkgRoot, "vite.config.js")) || await exists3(import_node_path73.default.join(pkgRoot, "vite.config.ts")) || await exists3(import_node_path73.default.join(pkgRoot, "vite.config.mjs")) || "vite" in deps) {
|
|
19922
20475
|
return "browser-bundle";
|
|
19923
20476
|
}
|
|
19924
|
-
if (await exists3(
|
|
19925
|
-
if (await exists3(
|
|
19926
|
-
if (await exists3(
|
|
20477
|
+
if (await exists3(import_node_path73.default.join(pkgRoot, "wrangler.toml"))) return "cloudflare-workers";
|
|
20478
|
+
if (await exists3(import_node_path73.default.join(pkgRoot, "bun.lockb"))) return "bun";
|
|
20479
|
+
if (await exists3(import_node_path73.default.join(pkgRoot, "deno.json")) || await exists3(import_node_path73.default.join(pkgRoot, "deno.lock"))) {
|
|
19927
20480
|
return "deno";
|
|
19928
20481
|
}
|
|
19929
20482
|
const engines = pkg.engines ?? {};
|
|
@@ -19932,7 +20485,7 @@ async function detectRuntimeKind(pkgRoot, pkg) {
|
|
|
19932
20485
|
}
|
|
19933
20486
|
async function readPackageJson2(serviceDir) {
|
|
19934
20487
|
try {
|
|
19935
|
-
const raw = await import_node_fs39.promises.readFile(
|
|
20488
|
+
const raw = await import_node_fs39.promises.readFile(import_node_path73.default.join(serviceDir, "package.json"), "utf8");
|
|
19936
20489
|
return JSON.parse(raw);
|
|
19937
20490
|
} catch {
|
|
19938
20491
|
return null;
|
|
@@ -19976,7 +20529,7 @@ function needsVersionUpgrade(installed, expected) {
|
|
|
19976
20529
|
var NEXT_CONFIG_CANDIDATES = ["next.config.js", "next.config.ts", "next.config.mjs"];
|
|
19977
20530
|
async function findNextConfig(serviceDir) {
|
|
19978
20531
|
for (const name of NEXT_CONFIG_CANDIDATES) {
|
|
19979
|
-
const candidate =
|
|
20532
|
+
const candidate = import_node_path73.default.join(serviceDir, name);
|
|
19980
20533
|
if (await exists3(candidate)) return candidate;
|
|
19981
20534
|
}
|
|
19982
20535
|
return null;
|
|
@@ -20045,7 +20598,7 @@ function hasRemixDependency(pkg) {
|
|
|
20045
20598
|
}
|
|
20046
20599
|
async function findRemixEntry(serviceDir) {
|
|
20047
20600
|
for (const rel of REMIX_ENTRY_CANDIDATES) {
|
|
20048
|
-
const candidate =
|
|
20601
|
+
const candidate = import_node_path73.default.join(serviceDir, rel);
|
|
20049
20602
|
if (await exists3(candidate)) return candidate;
|
|
20050
20603
|
}
|
|
20051
20604
|
return null;
|
|
@@ -20057,14 +20610,14 @@ function hasSvelteKitDependency(pkg) {
|
|
|
20057
20610
|
}
|
|
20058
20611
|
async function findSvelteKitHooks(serviceDir) {
|
|
20059
20612
|
for (const rel of SVELTEKIT_HOOKS_CANDIDATES) {
|
|
20060
|
-
const candidate =
|
|
20613
|
+
const candidate = import_node_path73.default.join(serviceDir, rel);
|
|
20061
20614
|
if (await exists3(candidate)) return candidate;
|
|
20062
20615
|
}
|
|
20063
20616
|
return null;
|
|
20064
20617
|
}
|
|
20065
20618
|
async function findSvelteKitConfig(serviceDir) {
|
|
20066
20619
|
for (const rel of SVELTEKIT_CONFIG_CANDIDATES) {
|
|
20067
|
-
const candidate =
|
|
20620
|
+
const candidate = import_node_path73.default.join(serviceDir, rel);
|
|
20068
20621
|
if (await exists3(candidate)) return candidate;
|
|
20069
20622
|
}
|
|
20070
20623
|
return null;
|
|
@@ -20075,7 +20628,7 @@ function hasNuxtDependency(pkg) {
|
|
|
20075
20628
|
}
|
|
20076
20629
|
async function findNuxtConfig(serviceDir) {
|
|
20077
20630
|
for (const name of NUXT_CONFIG_CANDIDATES) {
|
|
20078
|
-
const candidate =
|
|
20631
|
+
const candidate = import_node_path73.default.join(serviceDir, name);
|
|
20079
20632
|
if (await exists3(candidate)) return candidate;
|
|
20080
20633
|
}
|
|
20081
20634
|
return null;
|
|
@@ -20086,7 +20639,7 @@ function hasAstroDependency(pkg) {
|
|
|
20086
20639
|
}
|
|
20087
20640
|
async function findAstroConfig(serviceDir) {
|
|
20088
20641
|
for (const name of ASTRO_CONFIG_CANDIDATES) {
|
|
20089
|
-
const candidate =
|
|
20642
|
+
const candidate = import_node_path73.default.join(serviceDir, name);
|
|
20090
20643
|
if (await exists3(candidate)) return candidate;
|
|
20091
20644
|
}
|
|
20092
20645
|
return null;
|
|
@@ -20100,7 +20653,7 @@ function parseNextMajor(range) {
|
|
|
20100
20653
|
return Number.isFinite(n) ? n : null;
|
|
20101
20654
|
}
|
|
20102
20655
|
async function isTypeScriptProject(serviceDir) {
|
|
20103
|
-
return exists3(
|
|
20656
|
+
return exists3(import_node_path73.default.join(serviceDir, "tsconfig.json"));
|
|
20104
20657
|
}
|
|
20105
20658
|
var INDEX_EXTENSIONS = [".ts", ".tsx", ".js", ".mjs", ".cjs"];
|
|
20106
20659
|
var INDEX_CANDIDATES = INDEX_EXTENSIONS.map((ext) => `index${ext}`);
|
|
@@ -20149,7 +20702,7 @@ function entryFromScript(script) {
|
|
|
20149
20702
|
}
|
|
20150
20703
|
async function resolveEntry(serviceDir, pkg) {
|
|
20151
20704
|
if (typeof pkg.main === "string" && pkg.main.length > 0) {
|
|
20152
|
-
const candidate =
|
|
20705
|
+
const candidate = import_node_path73.default.resolve(serviceDir, pkg.main);
|
|
20153
20706
|
if (await exists3(candidate)) return candidate;
|
|
20154
20707
|
}
|
|
20155
20708
|
if (pkg.bin) {
|
|
@@ -20163,40 +20716,40 @@ async function resolveEntry(serviceDir, pkg) {
|
|
|
20163
20716
|
if (typeof first === "string") binEntry = first;
|
|
20164
20717
|
}
|
|
20165
20718
|
if (binEntry) {
|
|
20166
|
-
const candidate =
|
|
20719
|
+
const candidate = import_node_path73.default.resolve(serviceDir, binEntry);
|
|
20167
20720
|
if (await exists3(candidate)) return candidate;
|
|
20168
20721
|
}
|
|
20169
20722
|
}
|
|
20170
20723
|
const startEntry = entryFromScript(pkg.scripts?.start);
|
|
20171
20724
|
if (startEntry) {
|
|
20172
|
-
const candidate =
|
|
20725
|
+
const candidate = import_node_path73.default.resolve(serviceDir, startEntry);
|
|
20173
20726
|
if (await exists3(candidate)) return candidate;
|
|
20174
20727
|
}
|
|
20175
20728
|
const devEntry = entryFromScript(pkg.scripts?.dev);
|
|
20176
20729
|
if (devEntry) {
|
|
20177
|
-
const candidate =
|
|
20730
|
+
const candidate = import_node_path73.default.resolve(serviceDir, devEntry);
|
|
20178
20731
|
if (await exists3(candidate)) return candidate;
|
|
20179
20732
|
}
|
|
20180
20733
|
for (const rel of SRC_INDEX_CANDIDATES) {
|
|
20181
|
-
const candidate =
|
|
20734
|
+
const candidate = import_node_path73.default.join(serviceDir, rel);
|
|
20182
20735
|
if (await exists3(candidate)) return candidate;
|
|
20183
20736
|
}
|
|
20184
20737
|
for (const rel of SRC_NAMED_CANDIDATES) {
|
|
20185
|
-
const candidate =
|
|
20738
|
+
const candidate = import_node_path73.default.join(serviceDir, rel);
|
|
20186
20739
|
if (await exists3(candidate)) return candidate;
|
|
20187
20740
|
}
|
|
20188
20741
|
for (const rel of ROOT_NAMED_CANDIDATES) {
|
|
20189
|
-
const candidate =
|
|
20742
|
+
const candidate = import_node_path73.default.join(serviceDir, rel);
|
|
20190
20743
|
if (await exists3(candidate)) return candidate;
|
|
20191
20744
|
}
|
|
20192
20745
|
for (const name of INDEX_CANDIDATES) {
|
|
20193
|
-
const candidate =
|
|
20746
|
+
const candidate = import_node_path73.default.join(serviceDir, name);
|
|
20194
20747
|
if (await exists3(candidate)) return candidate;
|
|
20195
20748
|
}
|
|
20196
20749
|
return null;
|
|
20197
20750
|
}
|
|
20198
20751
|
function dispatchEntry(entryFile, pkg) {
|
|
20199
|
-
const ext =
|
|
20752
|
+
const ext = import_node_path73.default.extname(entryFile).toLowerCase();
|
|
20200
20753
|
if (ext === ".ts" || ext === ".tsx") return pkg.type === "module" ? "ts" : "ts-cjs";
|
|
20201
20754
|
if (ext === ".mjs") return "esm";
|
|
20202
20755
|
if (ext === ".cjs") return "cjs";
|
|
@@ -20214,9 +20767,9 @@ function otelInitContents(flavor) {
|
|
|
20214
20767
|
return OTEL_INIT_CJS;
|
|
20215
20768
|
}
|
|
20216
20769
|
function injectionLine(flavor, entryFile, otelInitFile) {
|
|
20217
|
-
let rel =
|
|
20770
|
+
let rel = import_node_path73.default.relative(import_node_path73.default.dirname(entryFile), otelInitFile);
|
|
20218
20771
|
if (!rel.startsWith(".")) rel = `./${rel}`;
|
|
20219
|
-
rel = rel.split(
|
|
20772
|
+
rel = rel.split(import_node_path73.default.sep).join("/");
|
|
20220
20773
|
if (flavor === "cjs") return `require('${rel}')`;
|
|
20221
20774
|
if (flavor === "esm") return `import '${rel}'`;
|
|
20222
20775
|
const tsRel = rel.replace(/\.ts$/, "");
|
|
@@ -20229,27 +20782,27 @@ function lineIsOtelInjection(line) {
|
|
|
20229
20782
|
}
|
|
20230
20783
|
async function detectsSrcLayout(serviceDir) {
|
|
20231
20784
|
const [hasSrcApp, hasSrcPages, hasRootApp, hasRootPages] = await Promise.all([
|
|
20232
|
-
exists3(
|
|
20233
|
-
exists3(
|
|
20234
|
-
exists3(
|
|
20235
|
-
exists3(
|
|
20785
|
+
exists3(import_node_path73.default.join(serviceDir, "src", "app")),
|
|
20786
|
+
exists3(import_node_path73.default.join(serviceDir, "src", "pages")),
|
|
20787
|
+
exists3(import_node_path73.default.join(serviceDir, "app")),
|
|
20788
|
+
exists3(import_node_path73.default.join(serviceDir, "pages"))
|
|
20236
20789
|
]);
|
|
20237
20790
|
return (hasSrcApp || hasSrcPages) && !hasRootApp && !hasRootPages;
|
|
20238
20791
|
}
|
|
20239
20792
|
async function planNext(serviceDir, pkg, manifestPath, nextConfigPath, project) {
|
|
20240
20793
|
const useTs = await isTypeScriptProject(serviceDir);
|
|
20241
20794
|
const srcLayout = await detectsSrcLayout(serviceDir);
|
|
20242
|
-
const baseDir = srcLayout ?
|
|
20243
|
-
const instrumentationFile =
|
|
20244
|
-
const instrumentationNodeFile =
|
|
20795
|
+
const baseDir = srcLayout ? import_node_path73.default.join(serviceDir, "src") : serviceDir;
|
|
20796
|
+
const instrumentationFile = import_node_path73.default.join(baseDir, useTs ? "instrumentation.ts" : "instrumentation.js");
|
|
20797
|
+
const instrumentationNodeFile = import_node_path73.default.join(
|
|
20245
20798
|
baseDir,
|
|
20246
20799
|
useTs ? "instrumentation.node.ts" : "instrumentation.node.js"
|
|
20247
20800
|
);
|
|
20248
|
-
const instrumentationEdgeFile =
|
|
20801
|
+
const instrumentationEdgeFile = import_node_path73.default.join(
|
|
20249
20802
|
baseDir,
|
|
20250
20803
|
useTs ? "instrumentation.edge.ts" : "instrumentation.edge.js"
|
|
20251
20804
|
);
|
|
20252
|
-
const envNeatFile =
|
|
20805
|
+
const envNeatFile = import_node_path73.default.join(baseDir, ".env.neat");
|
|
20253
20806
|
const existingDeps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
|
|
20254
20807
|
const dependencyEdits = [];
|
|
20255
20808
|
for (const sdk of SDK_PACKAGES) {
|
|
@@ -20374,7 +20927,7 @@ function buildDependencyEdits(pkg, manifestPath) {
|
|
|
20374
20927
|
return edits;
|
|
20375
20928
|
}
|
|
20376
20929
|
async function queueEnvNeat(serviceDir, pkg, project, generatedFiles) {
|
|
20377
|
-
const envNeatFile =
|
|
20930
|
+
const envNeatFile = import_node_path73.default.join(serviceDir, ".env.neat");
|
|
20378
20931
|
if (!await exists3(envNeatFile)) {
|
|
20379
20932
|
generatedFiles.push({
|
|
20380
20933
|
file: envNeatFile,
|
|
@@ -20409,7 +20962,7 @@ function fileImportsOtelHook(raw, specifiers) {
|
|
|
20409
20962
|
}
|
|
20410
20963
|
async function planRemix(serviceDir, pkg, manifestPath, entryFile, project) {
|
|
20411
20964
|
const useTs = await isTypeScriptProject(serviceDir);
|
|
20412
|
-
const otelServerFile =
|
|
20965
|
+
const otelServerFile = import_node_path73.default.join(
|
|
20413
20966
|
serviceDir,
|
|
20414
20967
|
useTs ? "app/otel.server.ts" : "app/otel.server.js"
|
|
20415
20968
|
);
|
|
@@ -20466,11 +21019,11 @@ async function planRemix(serviceDir, pkg, manifestPath, entryFile, project) {
|
|
|
20466
21019
|
}
|
|
20467
21020
|
async function planSvelteKit(serviceDir, pkg, manifestPath, hooksFile, project) {
|
|
20468
21021
|
const useTs = await isTypeScriptProject(serviceDir);
|
|
20469
|
-
const otelInitFile =
|
|
21022
|
+
const otelInitFile = import_node_path73.default.join(
|
|
20470
21023
|
serviceDir,
|
|
20471
21024
|
useTs ? "src/otel-init.ts" : "src/otel-init.js"
|
|
20472
21025
|
);
|
|
20473
|
-
const resolvedHooksFile = hooksFile ??
|
|
21026
|
+
const resolvedHooksFile = hooksFile ?? import_node_path73.default.join(serviceDir, useTs ? "src/hooks.server.ts" : "src/hooks.server.js");
|
|
20474
21027
|
const dependencyEdits = buildDependencyEdits(pkg, manifestPath);
|
|
20475
21028
|
const generatedFiles = [];
|
|
20476
21029
|
const entrypointEdits = [];
|
|
@@ -20532,11 +21085,11 @@ async function planSvelteKit(serviceDir, pkg, manifestPath, hooksFile, project)
|
|
|
20532
21085
|
}
|
|
20533
21086
|
async function planNuxt(serviceDir, pkg, manifestPath, project) {
|
|
20534
21087
|
const useTs = await isTypeScriptProject(serviceDir);
|
|
20535
|
-
const otelPluginFile =
|
|
21088
|
+
const otelPluginFile = import_node_path73.default.join(
|
|
20536
21089
|
serviceDir,
|
|
20537
21090
|
useTs ? "server/plugins/otel.ts" : "server/plugins/otel.js"
|
|
20538
21091
|
);
|
|
20539
|
-
const otelInitFile =
|
|
21092
|
+
const otelInitFile = import_node_path73.default.join(
|
|
20540
21093
|
serviceDir,
|
|
20541
21094
|
useTs ? "server/plugins/otel-init.ts" : "server/plugins/otel-init.js"
|
|
20542
21095
|
);
|
|
@@ -20587,19 +21140,19 @@ async function planNuxt(serviceDir, pkg, manifestPath, project) {
|
|
|
20587
21140
|
var ASTRO_MIDDLEWARE_CANDIDATES = ["src/middleware.ts", "src/middleware.js"];
|
|
20588
21141
|
async function findAstroMiddleware(serviceDir) {
|
|
20589
21142
|
for (const rel of ASTRO_MIDDLEWARE_CANDIDATES) {
|
|
20590
|
-
const candidate =
|
|
21143
|
+
const candidate = import_node_path73.default.join(serviceDir, rel);
|
|
20591
21144
|
if (await exists3(candidate)) return candidate;
|
|
20592
21145
|
}
|
|
20593
21146
|
return null;
|
|
20594
21147
|
}
|
|
20595
21148
|
async function planAstro(serviceDir, pkg, manifestPath, project) {
|
|
20596
21149
|
const useTs = await isTypeScriptProject(serviceDir);
|
|
20597
|
-
const otelInitFile =
|
|
21150
|
+
const otelInitFile = import_node_path73.default.join(
|
|
20598
21151
|
serviceDir,
|
|
20599
21152
|
useTs ? "src/otel-init.ts" : "src/otel-init.js"
|
|
20600
21153
|
);
|
|
20601
21154
|
const existingMiddleware = await findAstroMiddleware(serviceDir);
|
|
20602
|
-
const middlewareFile = existingMiddleware ??
|
|
21155
|
+
const middlewareFile = existingMiddleware ?? import_node_path73.default.join(serviceDir, useTs ? "src/middleware.ts" : "src/middleware.js");
|
|
20603
21156
|
const dependencyEdits = buildDependencyEdits(pkg, manifestPath);
|
|
20604
21157
|
const generatedFiles = [];
|
|
20605
21158
|
const entrypointEdits = [];
|
|
@@ -20695,7 +21248,7 @@ async function findFrameworkDispatch(serviceDir, pkg, manifestPath, project) {
|
|
|
20695
21248
|
}
|
|
20696
21249
|
async function plan(serviceDir, opts) {
|
|
20697
21250
|
const pkg = await readPackageJson2(serviceDir);
|
|
20698
|
-
const manifestPath =
|
|
21251
|
+
const manifestPath = import_node_path73.default.join(serviceDir, "package.json");
|
|
20699
21252
|
const project = opts?.project;
|
|
20700
21253
|
const empty = {
|
|
20701
21254
|
language: "javascript",
|
|
@@ -20730,8 +21283,8 @@ async function plan(serviceDir, opts) {
|
|
|
20730
21283
|
return { ...empty, libOnly: true };
|
|
20731
21284
|
}
|
|
20732
21285
|
const flavor = dispatchEntry(entryFile, pkg);
|
|
20733
|
-
const otelInitFile =
|
|
20734
|
-
const envNeatFile =
|
|
21286
|
+
const otelInitFile = import_node_path73.default.join(import_node_path73.default.dirname(entryFile), otelInitFilename(flavor));
|
|
21287
|
+
const envNeatFile = import_node_path73.default.join(serviceDir, ".env.neat");
|
|
20735
21288
|
const existingDeps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
|
|
20736
21289
|
const dependencyEdits = [];
|
|
20737
21290
|
for (const sdk of SDK_PACKAGES) {
|
|
@@ -20800,13 +21353,13 @@ async function plan(serviceDir, opts) {
|
|
|
20800
21353
|
};
|
|
20801
21354
|
}
|
|
20802
21355
|
function isAllowedWritePath(serviceDir, target) {
|
|
20803
|
-
const rel =
|
|
21356
|
+
const rel = import_node_path73.default.relative(serviceDir, target);
|
|
20804
21357
|
if (rel.startsWith("..")) return false;
|
|
20805
|
-
const base =
|
|
21358
|
+
const base = import_node_path73.default.basename(target);
|
|
20806
21359
|
if (base === "package.json") return true;
|
|
20807
21360
|
if (base === ".env.neat") return true;
|
|
20808
21361
|
if (/^otel-init\.(?:js|cjs|mjs|ts)$/.test(base)) return true;
|
|
20809
|
-
const relPosix = rel.split(
|
|
21362
|
+
const relPosix = rel.split(import_node_path73.default.sep).join("/");
|
|
20810
21363
|
if (/^instrumentation(?:\.(?:node|edge))?\.(?:js|cjs|mjs|ts)$/.test(base)) {
|
|
20811
21364
|
if (relPosix === base) return true;
|
|
20812
21365
|
if (relPosix === `src/${base}`) return true;
|
|
@@ -20823,7 +21376,7 @@ function isAllowedWritePath(serviceDir, target) {
|
|
|
20823
21376
|
return false;
|
|
20824
21377
|
}
|
|
20825
21378
|
async function writeAtomic(file, contents) {
|
|
20826
|
-
await import_node_fs39.promises.mkdir(
|
|
21379
|
+
await import_node_fs39.promises.mkdir(import_node_path73.default.dirname(file), { recursive: true });
|
|
20827
21380
|
const tmp = `${file}.${process.pid}.${Date.now()}.tmp`;
|
|
20828
21381
|
await import_node_fs39.promises.writeFile(tmp, contents, "utf8");
|
|
20829
21382
|
await import_node_fs39.promises.rename(tmp, file);
|
|
@@ -21007,7 +21560,7 @@ async function rollback(installPlan, originals, createdFiles) {
|
|
|
21007
21560
|
...removed.map((f) => `removed: ${f}`),
|
|
21008
21561
|
""
|
|
21009
21562
|
];
|
|
21010
|
-
const rollbackPath =
|
|
21563
|
+
const rollbackPath = import_node_path73.default.join(installPlan.serviceDir, "neat-rollback.patch");
|
|
21011
21564
|
await import_node_fs39.promises.writeFile(rollbackPath, lines.join("\n"), "utf8");
|
|
21012
21565
|
}
|
|
21013
21566
|
function injectInstrumentationHook(raw) {
|
|
@@ -21038,7 +21591,7 @@ var javascriptInstaller = {
|
|
|
21038
21591
|
// src/installers/python.ts
|
|
21039
21592
|
init_cjs_shims();
|
|
21040
21593
|
var import_node_fs40 = require("fs");
|
|
21041
|
-
var
|
|
21594
|
+
var import_node_path74 = __toESM(require("path"), 1);
|
|
21042
21595
|
var SDK_PACKAGES2 = [
|
|
21043
21596
|
{ name: "opentelemetry-distro", version: ">=0.49b0" },
|
|
21044
21597
|
{ name: "opentelemetry-exporter-otlp", version: ">=1.28.0" }
|
|
@@ -21136,7 +21689,7 @@ async function writeFileAtomic(file, contents) {
|
|
|
21136
21689
|
await import_node_fs40.promises.rename(tmp, file);
|
|
21137
21690
|
}
|
|
21138
21691
|
async function resolvePyEntrypoint(serviceDir) {
|
|
21139
|
-
const procfile =
|
|
21692
|
+
const procfile = import_node_path74.default.join(serviceDir, "Procfile");
|
|
21140
21693
|
if (await exists4(procfile)) {
|
|
21141
21694
|
const raw = await import_node_fs40.promises.readFile(procfile, "utf8");
|
|
21142
21695
|
for (const line of raw.split(/\r?\n/)) {
|
|
@@ -21146,20 +21699,20 @@ async function resolvePyEntrypoint(serviceDir) {
|
|
|
21146
21699
|
const asgi = cmd.match(/\b(?:uvicorn|gunicorn|hypercorn|daphne)\s+([\w.]+):/);
|
|
21147
21700
|
if (asgi) {
|
|
21148
21701
|
const modPath = asgi[1].replace(/\./g, "/");
|
|
21149
|
-
const asFile =
|
|
21702
|
+
const asFile = import_node_path74.default.join(serviceDir, `${modPath}.py`);
|
|
21150
21703
|
if (await exists4(asFile)) return asFile;
|
|
21151
|
-
const asPkg =
|
|
21704
|
+
const asPkg = import_node_path74.default.join(serviceDir, modPath, "__init__.py");
|
|
21152
21705
|
if (await exists4(asPkg)) return asPkg;
|
|
21153
21706
|
}
|
|
21154
21707
|
const runFile = cmd.match(/\b(?:python3?|fastapi\s+(?:run|dev))\s+([\w./-]+\.py)\b/);
|
|
21155
21708
|
if (runFile) {
|
|
21156
|
-
const p =
|
|
21709
|
+
const p = import_node_path74.default.join(serviceDir, runFile[1]);
|
|
21157
21710
|
if (await exists4(p)) return p;
|
|
21158
21711
|
}
|
|
21159
21712
|
}
|
|
21160
21713
|
}
|
|
21161
21714
|
for (const name of ["main.py", "app.py", "asgi.py", "wsgi.py", "manage.py", "server.py"]) {
|
|
21162
|
-
const p =
|
|
21715
|
+
const p = import_node_path74.default.join(serviceDir, name);
|
|
21163
21716
|
if (await exists4(p)) return p;
|
|
21164
21717
|
}
|
|
21165
21718
|
return null;
|
|
@@ -21185,7 +21738,7 @@ async function exists4(p) {
|
|
|
21185
21738
|
async function detect2(serviceDir) {
|
|
21186
21739
|
const markers = ["requirements.txt", "pyproject.toml", "setup.py"];
|
|
21187
21740
|
for (const m of markers) {
|
|
21188
|
-
if (await exists4(
|
|
21741
|
+
if (await exists4(import_node_path74.default.join(serviceDir, m))) return true;
|
|
21189
21742
|
}
|
|
21190
21743
|
return false;
|
|
21191
21744
|
}
|
|
@@ -21195,7 +21748,7 @@ function reqPackageName(line) {
|
|
|
21195
21748
|
return head.replace(/[<>=!~].*$/, "").toLowerCase();
|
|
21196
21749
|
}
|
|
21197
21750
|
async function planRequirementsTxtEdits(serviceDir) {
|
|
21198
|
-
const file =
|
|
21751
|
+
const file = import_node_path74.default.join(serviceDir, "requirements.txt");
|
|
21199
21752
|
if (!await exists4(file)) return null;
|
|
21200
21753
|
const raw = await import_node_fs40.promises.readFile(file, "utf8");
|
|
21201
21754
|
const presentNames = new Set(
|
|
@@ -21205,7 +21758,7 @@ async function planRequirementsTxtEdits(serviceDir) {
|
|
|
21205
21758
|
return { manifest: file, missing: [...missing] };
|
|
21206
21759
|
}
|
|
21207
21760
|
async function planProcfileEdits(serviceDir) {
|
|
21208
|
-
const procfile =
|
|
21761
|
+
const procfile = import_node_path74.default.join(serviceDir, "Procfile");
|
|
21209
21762
|
if (!await exists4(procfile)) return [];
|
|
21210
21763
|
const raw = await import_node_fs40.promises.readFile(procfile, "utf8");
|
|
21211
21764
|
const edits = [];
|
|
@@ -21243,7 +21796,7 @@ async function plan2(serviceDir) {
|
|
|
21243
21796
|
}
|
|
21244
21797
|
const entrypointEdits = await planProcfileEdits(serviceDir);
|
|
21245
21798
|
const entryFile = await resolvePyEntrypoint(serviceDir);
|
|
21246
|
-
const generatedFiles = entryFile ? [{ file:
|
|
21799
|
+
const generatedFiles = entryFile ? [{ file: import_node_path74.default.join(serviceDir, NEAT_OTEL_FILENAME), contents: neatOtelPy() }] : [];
|
|
21247
21800
|
if (dependencyEdits.length === 0 && entrypointEdits.length === 0 && !entryFile) {
|
|
21248
21801
|
return empty;
|
|
21249
21802
|
}
|
|
@@ -21311,7 +21864,7 @@ async function apply2(installPlan) {
|
|
|
21311
21864
|
if (raw === void 0) {
|
|
21312
21865
|
throw new Error(`python installer: cannot read ${file} during apply`);
|
|
21313
21866
|
}
|
|
21314
|
-
const base =
|
|
21867
|
+
const base = import_node_path74.default.basename(file);
|
|
21315
21868
|
if (base === "requirements.txt") {
|
|
21316
21869
|
const edits = installPlan.dependencyEdits.filter((e) => e.file === file);
|
|
21317
21870
|
if (edits.length > 0) {
|
|
@@ -21366,7 +21919,7 @@ async function rollback2(installPlan, originals, createdFiles = []) {
|
|
|
21366
21919
|
...removed.map((f) => `removed: ${f}`),
|
|
21367
21920
|
""
|
|
21368
21921
|
];
|
|
21369
|
-
const rollbackPath =
|
|
21922
|
+
const rollbackPath = import_node_path74.default.join(installPlan.serviceDir, "neat-rollback.patch");
|
|
21370
21923
|
await import_node_fs40.promises.writeFile(rollbackPath, lines.join("\n"), "utf8");
|
|
21371
21924
|
}
|
|
21372
21925
|
var pythonInstaller = {
|
|
@@ -21379,7 +21932,7 @@ var pythonInstaller = {
|
|
|
21379
21932
|
// src/installers/go.ts
|
|
21380
21933
|
init_cjs_shims();
|
|
21381
21934
|
var import_node_fs41 = require("fs");
|
|
21382
|
-
var
|
|
21935
|
+
var import_node_path75 = __toESM(require("path"), 1);
|
|
21383
21936
|
var GO_DEPS = [
|
|
21384
21937
|
{ name: "go.opentelemetry.io/otel", version: "v1.38.0" },
|
|
21385
21938
|
{ name: "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp", version: "v1.38.0" },
|
|
@@ -21389,13 +21942,13 @@ async function exists5(file) {
|
|
|
21389
21942
|
return import_node_fs41.promises.stat(file).then(() => true, () => false);
|
|
21390
21943
|
}
|
|
21391
21944
|
async function findMain(serviceDir) {
|
|
21392
|
-
const root =
|
|
21945
|
+
const root = import_node_path75.default.join(serviceDir, "main.go");
|
|
21393
21946
|
if (await exists5(root)) return root;
|
|
21394
|
-
const cmd =
|
|
21947
|
+
const cmd = import_node_path75.default.join(serviceDir, "cmd");
|
|
21395
21948
|
const entries = await import_node_fs41.promises.readdir(cmd, { withFileTypes: true }).catch(() => []);
|
|
21396
21949
|
for (const entry2 of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
21397
21950
|
if (!entry2.isDirectory()) continue;
|
|
21398
|
-
const candidate =
|
|
21951
|
+
const candidate = import_node_path75.default.join(cmd, entry2.name, "main.go");
|
|
21399
21952
|
if (await exists5(candidate)) return candidate;
|
|
21400
21953
|
}
|
|
21401
21954
|
return null;
|
|
@@ -21470,17 +22023,17 @@ func init() {
|
|
|
21470
22023
|
`;
|
|
21471
22024
|
}
|
|
21472
22025
|
async function detect3(serviceDir) {
|
|
21473
|
-
return exists5(
|
|
22026
|
+
return exists5(import_node_path75.default.join(serviceDir, "go.mod"));
|
|
21474
22027
|
}
|
|
21475
22028
|
async function plan3(serviceDir) {
|
|
21476
|
-
const manifest =
|
|
22029
|
+
const manifest = import_node_path75.default.join(serviceDir, "go.mod");
|
|
21477
22030
|
const raw = await import_node_fs41.promises.readFile(manifest, "utf8");
|
|
21478
22031
|
const main2 = await findMain(serviceDir);
|
|
21479
22032
|
const dependencyEdits = GO_DEPS.filter((dep) => !raw.includes(dep.name)).map((dep) => ({ file: manifest, kind: "add", ...dep }));
|
|
21480
22033
|
if (!main2) return { language: "go", serviceDir, dependencyEdits: [], entrypointEdits: [], envEdits: [], libOnly: true };
|
|
21481
22034
|
const source = await import_node_fs41.promises.readFile(main2, "utf8");
|
|
21482
22035
|
const packageName = source.match(/^\s*package\s+(\w+)\s*$/m)?.[1] ?? "main";
|
|
21483
|
-
const generated =
|
|
22036
|
+
const generated = import_node_path75.default.join(import_node_path75.default.dirname(main2), "neat_otel.go");
|
|
21484
22037
|
const generatedFiles = await exists5(generated) ? [] : [{ file: generated, contents: neatOtelGo(packageName) }];
|
|
21485
22038
|
return { language: "go", serviceDir, dependencyEdits, entrypointEdits: [], envEdits: [], generatedFiles, entryFile: main2 };
|
|
21486
22039
|
}
|
|
@@ -21622,7 +22175,7 @@ init_cjs_shims();
|
|
|
21622
22175
|
var import_node_fs42 = require("fs");
|
|
21623
22176
|
var import_node_http = __toESM(require("http"), 1);
|
|
21624
22177
|
var import_node_net = __toESM(require("net"), 1);
|
|
21625
|
-
var
|
|
22178
|
+
var import_node_path76 = __toESM(require("path"), 1);
|
|
21626
22179
|
var import_node_url4 = require("url");
|
|
21627
22180
|
var import_node_child_process3 = require("child_process");
|
|
21628
22181
|
var import_node_readline = __toESM(require("readline"), 1);
|
|
@@ -21632,7 +22185,7 @@ async function extractAndPersist(opts) {
|
|
|
21632
22185
|
const graphKey = opts.projectExplicit ? opts.project : DEFAULT_PROJECT;
|
|
21633
22186
|
resetGraph(graphKey);
|
|
21634
22187
|
const graph = getGraph(graphKey);
|
|
21635
|
-
const projectPaths = pathsForProject(graphKey,
|
|
22188
|
+
const projectPaths = pathsForProject(graphKey, import_node_path76.default.join(opts.scanPath, "neat-out"));
|
|
21636
22189
|
const extraction = await extractFromDirectory(graph, opts.scanPath, {
|
|
21637
22190
|
errorsPath: projectPaths.errorsPath
|
|
21638
22191
|
});
|
|
@@ -21684,7 +22237,7 @@ async function applyInstallersOver(services, project, options = {}) {
|
|
|
21684
22237
|
libOnly++;
|
|
21685
22238
|
const appDeps = svc.pkg ? appFrameworkDependencies(svc.pkg) : [];
|
|
21686
22239
|
if (appDeps.length > 0) {
|
|
21687
|
-
const svcName =
|
|
22240
|
+
const svcName = import_node_path76.default.basename(svc.dir);
|
|
21688
22241
|
const list = appDeps.join(", ");
|
|
21689
22242
|
console.warn(
|
|
21690
22243
|
`neat: runtime layer won't engage for ${svcName}: no entry point found.
|
|
@@ -21697,7 +22250,7 @@ async function applyInstallersOver(services, project, options = {}) {
|
|
|
21697
22250
|
console.log(`skipping ${svc.dir}: browser bundle; browser-OTel support lands in a future release.`);
|
|
21698
22251
|
} else if (outcome.outcome === "react-native") {
|
|
21699
22252
|
reactNative++;
|
|
21700
|
-
const svcName =
|
|
22253
|
+
const svcName = import_node_path76.default.basename(svc.dir);
|
|
21701
22254
|
console.log(
|
|
21702
22255
|
`neat: ${svc.dir} detected as React Native / Expo
|
|
21703
22256
|
The installer doesn't cover this runtime deterministically.
|
|
@@ -21708,7 +22261,7 @@ async function applyInstallersOver(services, project, options = {}) {
|
|
|
21708
22261
|
);
|
|
21709
22262
|
} else if (outcome.outcome === "bun") {
|
|
21710
22263
|
bun++;
|
|
21711
|
-
const svcName =
|
|
22264
|
+
const svcName = import_node_path76.default.basename(svc.dir);
|
|
21712
22265
|
console.log(
|
|
21713
22266
|
`neat: ${svc.dir} detected as Bun
|
|
21714
22267
|
The installer doesn't cover this runtime deterministically.
|
|
@@ -21719,7 +22272,7 @@ async function applyInstallersOver(services, project, options = {}) {
|
|
|
21719
22272
|
);
|
|
21720
22273
|
} else if (outcome.outcome === "deno") {
|
|
21721
22274
|
deno++;
|
|
21722
|
-
const svcName =
|
|
22275
|
+
const svcName = import_node_path76.default.basename(svc.dir);
|
|
21723
22276
|
console.log(
|
|
21724
22277
|
`neat: ${svc.dir} detected as Deno
|
|
21725
22278
|
The installer doesn't cover this runtime deterministically.
|
|
@@ -21730,7 +22283,7 @@ async function applyInstallersOver(services, project, options = {}) {
|
|
|
21730
22283
|
);
|
|
21731
22284
|
} else if (outcome.outcome === "cloudflare-workers") {
|
|
21732
22285
|
cloudflareWorkers++;
|
|
21733
|
-
const svcName =
|
|
22286
|
+
const svcName = import_node_path76.default.basename(svc.dir);
|
|
21734
22287
|
console.log(
|
|
21735
22288
|
`neat: ${svc.dir} detected as Cloudflare Workers
|
|
21736
22289
|
The installer doesn't cover this runtime deterministically.
|
|
@@ -21741,7 +22294,7 @@ async function applyInstallersOver(services, project, options = {}) {
|
|
|
21741
22294
|
);
|
|
21742
22295
|
} else if (outcome.outcome === "electron") {
|
|
21743
22296
|
electron++;
|
|
21744
|
-
const svcName =
|
|
22297
|
+
const svcName = import_node_path76.default.basename(svc.dir);
|
|
21745
22298
|
console.log(
|
|
21746
22299
|
`neat: ${svc.dir} detected as Electron
|
|
21747
22300
|
The installer doesn't cover this runtime deterministically.
|
|
@@ -21754,7 +22307,7 @@ async function applyInstallersOver(services, project, options = {}) {
|
|
|
21754
22307
|
if (svc.pkg && (outcome.outcome === "instrumented" || outcome.outcome === "already-instrumented")) {
|
|
21755
22308
|
const gaps = uninstrumentedLibraries(svc.pkg);
|
|
21756
22309
|
if (gaps.length > 0) {
|
|
21757
|
-
const svcName =
|
|
22310
|
+
const svcName = import_node_path76.default.basename(svc.dir);
|
|
21758
22311
|
const list = gaps.join(", ");
|
|
21759
22312
|
const subject = gaps.length === 1 ? "this library" : "these libraries";
|
|
21760
22313
|
const aux = gaps.length === 1 ? "isn't" : "aren't";
|
|
@@ -21960,8 +22513,8 @@ async function persistedPortsFor(scanPath) {
|
|
|
21960
22513
|
return { rest: record.ports.rest, otlp: record.ports.otlp, web: record.ports.web };
|
|
21961
22514
|
}
|
|
21962
22515
|
async function acquireSpawnLock(scanPath) {
|
|
21963
|
-
const lockPath =
|
|
21964
|
-
await import_node_fs42.promises.mkdir(
|
|
22516
|
+
const lockPath = import_node_path76.default.join(scanPath, "neat-out", "daemon.spawn.lock");
|
|
22517
|
+
await import_node_fs42.promises.mkdir(import_node_path76.default.dirname(lockPath), { recursive: true });
|
|
21965
22518
|
const STALE_LOCK_MS = 6e4;
|
|
21966
22519
|
try {
|
|
21967
22520
|
const fd = await import_node_fs42.promises.open(lockPath, "wx");
|
|
@@ -22006,13 +22559,13 @@ async function healthIsForProject(restPort, project) {
|
|
|
22006
22559
|
return false;
|
|
22007
22560
|
}
|
|
22008
22561
|
function daemonLogPath(projectPath3) {
|
|
22009
|
-
return
|
|
22562
|
+
return import_node_path76.default.join(projectPath3, "neat-out", "daemon.log");
|
|
22010
22563
|
}
|
|
22011
22564
|
function spawnDaemonDetached(spec) {
|
|
22012
|
-
const here =
|
|
22565
|
+
const here = import_node_path76.default.dirname((0, import_node_url4.fileURLToPath)(importMetaUrl));
|
|
22013
22566
|
const candidates = [
|
|
22014
|
-
|
|
22015
|
-
|
|
22567
|
+
import_node_path76.default.join(here, "neatd.cjs"),
|
|
22568
|
+
import_node_path76.default.join(here, "neatd.js")
|
|
22016
22569
|
];
|
|
22017
22570
|
let entry2 = null;
|
|
22018
22571
|
const fsSync = require("fs");
|
|
@@ -22042,7 +22595,7 @@ function spawnDaemonDetached(spec) {
|
|
|
22042
22595
|
let logFd = null;
|
|
22043
22596
|
if (spec) {
|
|
22044
22597
|
const logPath = daemonLogPath(spec.projectPath);
|
|
22045
|
-
fsSync.mkdirSync(
|
|
22598
|
+
fsSync.mkdirSync(import_node_path76.default.dirname(logPath), { recursive: true });
|
|
22046
22599
|
logFd = fsSync.openSync(logPath, "a");
|
|
22047
22600
|
}
|
|
22048
22601
|
const child = (0, import_node_child_process3.spawn)(process.execPath, [entry2, "start"], {
|
|
@@ -22241,7 +22794,7 @@ async function runOrchestrator(opts) {
|
|
|
22241
22794
|
result.steps.browser = openBrowser(dashboardUrl);
|
|
22242
22795
|
}
|
|
22243
22796
|
const daemonRunning = result.steps.daemon === "spawned" || result.steps.daemon === "already-running";
|
|
22244
|
-
const daemonLog = daemonRunning ?
|
|
22797
|
+
const daemonLog = daemonRunning ? import_node_path76.default.relative(opts.scanPath, daemonLogPath(opts.scanPath)) : null;
|
|
22245
22798
|
printSummary(result, graph, dashboardUrl, daemonLog);
|
|
22246
22799
|
return result;
|
|
22247
22800
|
}
|
|
@@ -22700,7 +23253,7 @@ async function runConnectorCommand(rawArgs, deps = {}) {
|
|
|
22700
23253
|
|
|
22701
23254
|
// src/hooks-cli.ts
|
|
22702
23255
|
init_cjs_shims();
|
|
22703
|
-
var
|
|
23256
|
+
var import_node_path77 = __toESM(require("path"), 1);
|
|
22704
23257
|
var import_node_os5 = __toESM(require("os"), 1);
|
|
22705
23258
|
var import_node_fs43 = require("fs");
|
|
22706
23259
|
var import_node_url5 = require("url");
|
|
@@ -22709,14 +23262,14 @@ var GUIDE_FILENAME = "GRAPH_FIRST.md";
|
|
|
22709
23262
|
var GUIDE_INSTALL_NAME = "neat-graph-first.md";
|
|
22710
23263
|
var HOOK_MATCHER = "Grep|Glob|Bash";
|
|
22711
23264
|
function moduleDir() {
|
|
22712
|
-
return typeof __dirname !== "undefined" ? __dirname :
|
|
23265
|
+
return typeof __dirname !== "undefined" ? __dirname : import_node_path77.default.dirname((0, import_node_url5.fileURLToPath)(importMetaUrl));
|
|
22713
23266
|
}
|
|
22714
23267
|
async function readSkillAsset(rel) {
|
|
22715
23268
|
const here = moduleDir();
|
|
22716
23269
|
const candidates = [
|
|
22717
|
-
|
|
22718
|
-
|
|
22719
|
-
|
|
23270
|
+
import_node_path77.default.resolve(here, "../../claude-skill", rel),
|
|
23271
|
+
import_node_path77.default.resolve(here, "../../../claude-skill", rel),
|
|
23272
|
+
import_node_path77.default.resolve(here, "../claude-skill", rel)
|
|
22720
23273
|
];
|
|
22721
23274
|
for (const candidate of candidates) {
|
|
22722
23275
|
try {
|
|
@@ -22730,17 +23283,17 @@ async function readSkillAsset(rel) {
|
|
|
22730
23283
|
}
|
|
22731
23284
|
function neatHome3() {
|
|
22732
23285
|
const override = process.env.NEAT_HOME;
|
|
22733
|
-
if (override && override.length > 0) return
|
|
22734
|
-
return
|
|
23286
|
+
if (override && override.length > 0) return import_node_path77.default.resolve(override);
|
|
23287
|
+
return import_node_path77.default.join(import_node_os5.default.homedir(), ".neat");
|
|
22735
23288
|
}
|
|
22736
23289
|
function claudeSettingsPath() {
|
|
22737
23290
|
const override = process.env.NEAT_CLAUDE_SETTINGS;
|
|
22738
|
-
if (override && override.length > 0) return
|
|
23291
|
+
if (override && override.length > 0) return import_node_path77.default.resolve(override);
|
|
22739
23292
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? import_node_os5.default.homedir();
|
|
22740
|
-
return
|
|
23293
|
+
return import_node_path77.default.join(home, ".claude", "settings.json");
|
|
22741
23294
|
}
|
|
22742
23295
|
function installedHookPath() {
|
|
22743
|
-
return
|
|
23296
|
+
return import_node_path77.default.join(neatHome3(), "hooks", HOOK_FILENAME);
|
|
22744
23297
|
}
|
|
22745
23298
|
function isNeatSearchEntry(entry2) {
|
|
22746
23299
|
return (entry2.hooks ?? []).some(
|
|
@@ -22773,9 +23326,9 @@ async function runHooks(opts) {
|
|
|
22773
23326
|
const hookScript = await readSkillAsset(`hooks/${HOOK_FILENAME}`);
|
|
22774
23327
|
const guide = await readSkillAsset(GUIDE_FILENAME);
|
|
22775
23328
|
const scriptPath = installedHookPath();
|
|
22776
|
-
await import_node_fs43.promises.mkdir(
|
|
23329
|
+
await import_node_fs43.promises.mkdir(import_node_path77.default.dirname(scriptPath), { recursive: true });
|
|
22777
23330
|
await import_node_fs43.promises.writeFile(scriptPath, hookScript, { mode: 493 });
|
|
22778
|
-
const guidePath =
|
|
23331
|
+
const guidePath = import_node_path77.default.join(neatHome3(), GUIDE_INSTALL_NAME);
|
|
22779
23332
|
await import_node_fs43.promises.writeFile(guidePath, guide, "utf8");
|
|
22780
23333
|
const settingsFile = claudeSettingsPath();
|
|
22781
23334
|
let settings = {};
|
|
@@ -22802,7 +23355,7 @@ async function runHooks(opts) {
|
|
|
22802
23355
|
...settings,
|
|
22803
23356
|
hooks: { ...hooks, PreToolUse: preToolUse }
|
|
22804
23357
|
};
|
|
22805
|
-
await import_node_fs43.promises.mkdir(
|
|
23358
|
+
await import_node_fs43.promises.mkdir(import_node_path77.default.dirname(settingsFile), { recursive: true });
|
|
22806
23359
|
await import_node_fs43.promises.writeFile(settingsFile, JSON.stringify(merged, null, 2) + "\n", "utf8");
|
|
22807
23360
|
console.log(`neat hooks: installed the search-nudge hook`);
|
|
22808
23361
|
console.log(` script: ${scriptPath}`);
|
|
@@ -22874,7 +23427,7 @@ async function runHooksCommand(args) {
|
|
|
22874
23427
|
|
|
22875
23428
|
// src/codex-cli.ts
|
|
22876
23429
|
init_cjs_shims();
|
|
22877
|
-
var
|
|
23430
|
+
var import_node_path78 = __toESM(require("path"), 1);
|
|
22878
23431
|
var import_node_os6 = __toESM(require("os"), 1);
|
|
22879
23432
|
var import_node_fs44 = require("fs");
|
|
22880
23433
|
var import_node_util = require("util");
|
|
@@ -22894,14 +23447,14 @@ var NEAT_GRAPH_FIRST_START = "<!-- neat:graph-first -->";
|
|
|
22894
23447
|
var NEAT_GRAPH_FIRST_END = "<!-- /neat:graph-first -->";
|
|
22895
23448
|
function codexConfigPath() {
|
|
22896
23449
|
const override = process.env.NEAT_CODEX_CONFIG;
|
|
22897
|
-
if (override && override.length > 0) return
|
|
23450
|
+
if (override && override.length > 0) return import_node_path78.default.resolve(override);
|
|
22898
23451
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? import_node_os6.default.homedir();
|
|
22899
|
-
return
|
|
23452
|
+
return import_node_path78.default.join(home, ".codex", "config.toml");
|
|
22900
23453
|
}
|
|
22901
23454
|
function agentsFilePath() {
|
|
22902
23455
|
const override = process.env.NEAT_CODEX_AGENTS;
|
|
22903
|
-
if (override && override.length > 0) return
|
|
22904
|
-
return
|
|
23456
|
+
if (override && override.length > 0) return import_node_path78.default.resolve(override);
|
|
23457
|
+
return import_node_path78.default.join(process.cwd(), "AGENTS.md");
|
|
22905
23458
|
}
|
|
22906
23459
|
function isTableHeader(line) {
|
|
22907
23460
|
return /^\s*\[\[?[^\]]+\]\]?\s*$/.test(line);
|
|
@@ -23084,14 +23637,14 @@ async function runCodex(opts) {
|
|
|
23084
23637
|
return { exitCode: 0 };
|
|
23085
23638
|
}
|
|
23086
23639
|
if (config.changed) {
|
|
23087
|
-
await import_node_fs44.promises.mkdir(
|
|
23640
|
+
await import_node_fs44.promises.mkdir(import_node_path78.default.dirname(configPath), { recursive: true });
|
|
23088
23641
|
await import_node_fs44.promises.writeFile(configPath, config.text, "utf8");
|
|
23089
23642
|
console.log(`neat codex: wrote [mcp_servers.neat] to ${configPath}`);
|
|
23090
23643
|
} else {
|
|
23091
23644
|
console.log(`neat codex: ${configPath} already has NEAT's MCP server`);
|
|
23092
23645
|
}
|
|
23093
23646
|
if (agents.changed) {
|
|
23094
|
-
await import_node_fs44.promises.mkdir(
|
|
23647
|
+
await import_node_fs44.promises.mkdir(import_node_path78.default.dirname(agentsPath), { recursive: true });
|
|
23095
23648
|
await import_node_fs44.promises.writeFile(agentsPath, agents.text, "utf8");
|
|
23096
23649
|
console.log(`neat codex: wrote the graph-first block to ${agentsPath}`);
|
|
23097
23650
|
} else {
|
|
@@ -23149,7 +23702,7 @@ async function runCodexCommand(args) {
|
|
|
23149
23702
|
|
|
23150
23703
|
// src/editors-cli.ts
|
|
23151
23704
|
init_cjs_shims();
|
|
23152
|
-
var
|
|
23705
|
+
var import_node_path79 = __toESM(require("path"), 1);
|
|
23153
23706
|
var import_node_os7 = __toESM(require("os"), 1);
|
|
23154
23707
|
var import_node_fs45 = require("fs");
|
|
23155
23708
|
var import_node_util2 = require("util");
|
|
@@ -23175,17 +23728,17 @@ function homeDir() {
|
|
|
23175
23728
|
}
|
|
23176
23729
|
function xdgConfigDir() {
|
|
23177
23730
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
23178
|
-
return xdg && xdg.length > 0 ?
|
|
23731
|
+
return xdg && xdg.length > 0 ? import_node_path79.default.resolve(xdg) : import_node_path79.default.join(homeDir(), ".config");
|
|
23179
23732
|
}
|
|
23180
23733
|
function envOverride(name) {
|
|
23181
23734
|
const v = process.env[name];
|
|
23182
|
-
return v && v.length > 0 ?
|
|
23735
|
+
return v && v.length > 0 ? import_node_path79.default.resolve(v) : void 0;
|
|
23183
23736
|
}
|
|
23184
23737
|
var CURSOR_CLIENT = {
|
|
23185
23738
|
id: "cursor",
|
|
23186
23739
|
label: "Cursor",
|
|
23187
23740
|
docsUrl: "https://docs.cursor.com/context/mcp",
|
|
23188
|
-
mcpConfigPath: () => envOverride("NEAT_CURSOR_CONFIG") ??
|
|
23741
|
+
mcpConfigPath: () => envOverride("NEAT_CURSOR_CONFIG") ?? import_node_path79.default.join(homeDir(), ".cursor", "mcp.json"),
|
|
23189
23742
|
mcpContainerKey: "mcpServers",
|
|
23190
23743
|
format: "json",
|
|
23191
23744
|
// Cursor still reads a single `.cursorrules` at the project root (the modern
|
|
@@ -23197,7 +23750,7 @@ var DEVIN_CLIENT = {
|
|
|
23197
23750
|
id: "devin",
|
|
23198
23751
|
label: "Devin Desktop (Cascade)",
|
|
23199
23752
|
docsUrl: "https://docs.devin.ai/desktop/cascade/mcp",
|
|
23200
|
-
mcpConfigPath: () => envOverride("NEAT_DEVIN_CONFIG") ??
|
|
23753
|
+
mcpConfigPath: () => envOverride("NEAT_DEVIN_CONFIG") ?? import_node_path79.default.join(homeDir(), ".codeium", "windsurf", "mcp_config.json"),
|
|
23201
23754
|
mcpContainerKey: "mcpServers",
|
|
23202
23755
|
format: "json",
|
|
23203
23756
|
rulesFileName: ".windsurfrules"
|
|
@@ -23206,7 +23759,7 @@ var GEMINI_CLIENT = {
|
|
|
23206
23759
|
id: "gemini",
|
|
23207
23760
|
label: "Gemini CLI",
|
|
23208
23761
|
docsUrl: "https://github.com/google-gemini/gemini-cli/blob/main/docs/tools/mcp-server.md",
|
|
23209
|
-
mcpConfigPath: () => envOverride("NEAT_GEMINI_CONFIG") ??
|
|
23762
|
+
mcpConfigPath: () => envOverride("NEAT_GEMINI_CONFIG") ?? import_node_path79.default.join(homeDir(), ".gemini", "settings.json"),
|
|
23210
23763
|
mcpContainerKey: "mcpServers",
|
|
23211
23764
|
format: "json",
|
|
23212
23765
|
rulesFileName: "GEMINI.md"
|
|
@@ -23215,7 +23768,7 @@ var QWEN_CLIENT = {
|
|
|
23215
23768
|
id: "qwen",
|
|
23216
23769
|
label: "Qwen Code",
|
|
23217
23770
|
docsUrl: "https://qwenlm.github.io/qwen-code-docs/en/users/features/mcp/",
|
|
23218
|
-
mcpConfigPath: () => envOverride("NEAT_QWEN_CONFIG") ??
|
|
23771
|
+
mcpConfigPath: () => envOverride("NEAT_QWEN_CONFIG") ?? import_node_path79.default.join(homeDir(), ".qwen", "settings.json"),
|
|
23219
23772
|
mcpContainerKey: "mcpServers",
|
|
23220
23773
|
format: "json",
|
|
23221
23774
|
rulesFileName: "QWEN.md"
|
|
@@ -23224,7 +23777,7 @@ var AMAZONQ_CLIENT = {
|
|
|
23224
23777
|
id: "amazonq",
|
|
23225
23778
|
label: "Amazon Q Developer CLI",
|
|
23226
23779
|
docsUrl: "https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/command-line-mcp-configuration.html",
|
|
23227
|
-
mcpConfigPath: () => envOverride("NEAT_AMAZONQ_CONFIG") ??
|
|
23780
|
+
mcpConfigPath: () => envOverride("NEAT_AMAZONQ_CONFIG") ?? import_node_path79.default.join(homeDir(), ".aws", "amazonq", "mcp.json"),
|
|
23228
23781
|
mcpContainerKey: "mcpServers",
|
|
23229
23782
|
format: "json"
|
|
23230
23783
|
};
|
|
@@ -23232,7 +23785,7 @@ var ROOCODE_CLIENT = {
|
|
|
23232
23785
|
id: "roocode",
|
|
23233
23786
|
label: "Roo Code",
|
|
23234
23787
|
docsUrl: "https://roocodeinc.github.io/Roo-Code/features/mcp/using-mcp-in-roo",
|
|
23235
|
-
mcpConfigPath: () => envOverride("NEAT_ROOCODE_CONFIG") ??
|
|
23788
|
+
mcpConfigPath: () => envOverride("NEAT_ROOCODE_CONFIG") ?? import_node_path79.default.join(process.cwd(), ".roo", "mcp.json"),
|
|
23236
23789
|
mcpContainerKey: "mcpServers",
|
|
23237
23790
|
format: "json"
|
|
23238
23791
|
};
|
|
@@ -23245,9 +23798,9 @@ var ZED_CLIENT = {
|
|
|
23245
23798
|
if (override) return override;
|
|
23246
23799
|
if (process.platform === "win32") {
|
|
23247
23800
|
const appData = process.env.APPDATA;
|
|
23248
|
-
if (appData && appData.length > 0) return
|
|
23801
|
+
if (appData && appData.length > 0) return import_node_path79.default.join(appData, "Zed", "settings.json");
|
|
23249
23802
|
}
|
|
23250
|
-
return
|
|
23803
|
+
return import_node_path79.default.join(homeDir(), ".config", "zed", "settings.json");
|
|
23251
23804
|
},
|
|
23252
23805
|
mcpContainerKey: "context_servers",
|
|
23253
23806
|
format: "jsonc",
|
|
@@ -23257,7 +23810,7 @@ var OPENCODE_CLIENT = {
|
|
|
23257
23810
|
id: "opencode",
|
|
23258
23811
|
label: "OpenCode",
|
|
23259
23812
|
docsUrl: "https://opencode.ai/docs/mcp-servers/",
|
|
23260
|
-
mcpConfigPath: () => envOverride("NEAT_OPENCODE_CONFIG") ??
|
|
23813
|
+
mcpConfigPath: () => envOverride("NEAT_OPENCODE_CONFIG") ?? import_node_path79.default.join(xdgConfigDir(), "opencode", "opencode.json"),
|
|
23261
23814
|
mcpContainerKey: "mcp",
|
|
23262
23815
|
format: "json",
|
|
23263
23816
|
serverEntry: NEAT_OPENCODE_SERVER,
|
|
@@ -23267,7 +23820,7 @@ var CRUSH_CLIENT = {
|
|
|
23267
23820
|
id: "crush",
|
|
23268
23821
|
label: "Crush",
|
|
23269
23822
|
docsUrl: "https://charmbracelet-crush.mintlify.app/configuration/mcp",
|
|
23270
|
-
mcpConfigPath: () => envOverride("NEAT_CRUSH_CONFIG") ??
|
|
23823
|
+
mcpConfigPath: () => envOverride("NEAT_CRUSH_CONFIG") ?? import_node_path79.default.join(xdgConfigDir(), "crush", "crush.json"),
|
|
23271
23824
|
mcpContainerKey: "mcp",
|
|
23272
23825
|
format: "json",
|
|
23273
23826
|
serverEntry: NEAT_CRUSH_SERVER,
|
|
@@ -23372,7 +23925,7 @@ async function runEditorInstall(client, opts) {
|
|
|
23372
23925
|
const mcpPath = client.mcpConfigPath();
|
|
23373
23926
|
const serverEntry = client.serverEntry ?? NEAT_MCP_SERVER;
|
|
23374
23927
|
const hasRules = typeof client.rulesFileName === "string";
|
|
23375
|
-
const rulesPath = hasRules ?
|
|
23928
|
+
const rulesPath = hasRules ? import_node_path79.default.join(opts.projectDir, client.rulesFileName) : "";
|
|
23376
23929
|
const mcp = await planMcp(client, mcpPath);
|
|
23377
23930
|
if (mcp === null) return { exitCode: 1 };
|
|
23378
23931
|
let existingRules = "";
|
|
@@ -23415,10 +23968,10 @@ async function runEditorInstall(client, opts) {
|
|
|
23415
23968
|
);
|
|
23416
23969
|
return { exitCode: 0 };
|
|
23417
23970
|
}
|
|
23418
|
-
await import_node_fs45.promises.mkdir(
|
|
23971
|
+
await import_node_fs45.promises.mkdir(import_node_path79.default.dirname(mcpPath), { recursive: true });
|
|
23419
23972
|
await import_node_fs45.promises.writeFile(mcpPath, mcp.text, "utf8");
|
|
23420
23973
|
if (hasRules) {
|
|
23421
|
-
await import_node_fs45.promises.mkdir(
|
|
23974
|
+
await import_node_fs45.promises.mkdir(import_node_path79.default.dirname(rulesPath), { recursive: true });
|
|
23422
23975
|
await import_node_fs45.promises.writeFile(rulesPath, newRules, "utf8");
|
|
23423
23976
|
}
|
|
23424
23977
|
console.log(`neat ${client.id}: wired NEAT into ${client.label}`);
|
|
@@ -23482,11 +24035,11 @@ async function runEditorCommand(clientId, args, projectDir = process.cwd()) {
|
|
|
23482
24035
|
|
|
23483
24036
|
// src/monitor.ts
|
|
23484
24037
|
init_cjs_shims();
|
|
23485
|
-
var
|
|
24038
|
+
var import_types84 = require("@neat.is/types");
|
|
23486
24039
|
|
|
23487
24040
|
// src/cli-client.ts
|
|
23488
24041
|
init_cjs_shims();
|
|
23489
|
-
var
|
|
24042
|
+
var import_types83 = require("@neat.is/types");
|
|
23490
24043
|
var HttpError = class extends Error {
|
|
23491
24044
|
constructor(status2, message, responseBody = "") {
|
|
23492
24045
|
super(message);
|
|
@@ -23511,10 +24064,10 @@ function createHttpClient(baseUrl, bearerToken) {
|
|
|
23511
24064
|
const root = baseUrl.replace(/\/$/, "");
|
|
23512
24065
|
const authHeader = bearerToken && bearerToken.length > 0 ? { authorization: `Bearer ${bearerToken}` } : {};
|
|
23513
24066
|
return {
|
|
23514
|
-
async get(
|
|
24067
|
+
async get(path82) {
|
|
23515
24068
|
let res;
|
|
23516
24069
|
try {
|
|
23517
|
-
res = await fetch(`${root}${
|
|
24070
|
+
res = await fetch(`${root}${path82}`, {
|
|
23518
24071
|
headers: { ...authHeader }
|
|
23519
24072
|
});
|
|
23520
24073
|
} catch (err) {
|
|
@@ -23526,16 +24079,16 @@ function createHttpClient(baseUrl, bearerToken) {
|
|
|
23526
24079
|
const body = await res.text().catch(() => "");
|
|
23527
24080
|
throw new HttpError(
|
|
23528
24081
|
res.status,
|
|
23529
|
-
`${res.status} ${res.statusText} on GET ${
|
|
24082
|
+
`${res.status} ${res.statusText} on GET ${path82}: ${body}`,
|
|
23530
24083
|
body
|
|
23531
24084
|
);
|
|
23532
24085
|
}
|
|
23533
24086
|
return await res.json();
|
|
23534
24087
|
},
|
|
23535
|
-
async post(
|
|
24088
|
+
async post(path82, body) {
|
|
23536
24089
|
let res;
|
|
23537
24090
|
try {
|
|
23538
|
-
res = await fetch(`${root}${
|
|
24091
|
+
res = await fetch(`${root}${path82}`, {
|
|
23539
24092
|
method: "POST",
|
|
23540
24093
|
headers: { "content-type": "application/json", ...authHeader },
|
|
23541
24094
|
body: JSON.stringify(body)
|
|
@@ -23549,7 +24102,7 @@ function createHttpClient(baseUrl, bearerToken) {
|
|
|
23549
24102
|
const text = await res.text().catch(() => "");
|
|
23550
24103
|
throw new HttpError(
|
|
23551
24104
|
res.status,
|
|
23552
|
-
`${res.status} ${res.statusText} on POST ${
|
|
24105
|
+
`${res.status} ${res.statusText} on POST ${path82}: ${text}`,
|
|
23553
24106
|
text
|
|
23554
24107
|
);
|
|
23555
24108
|
}
|
|
@@ -23563,12 +24116,12 @@ function projectPath(project, suffix) {
|
|
|
23563
24116
|
}
|
|
23564
24117
|
async function runRootCause(client, input) {
|
|
23565
24118
|
const qs = input.errorId ? `?errorId=${encodeURIComponent(input.errorId)}` : "";
|
|
23566
|
-
const
|
|
24119
|
+
const path82 = projectPath(
|
|
23567
24120
|
input.project,
|
|
23568
24121
|
`/graph/root-cause/${encodeURIComponent(input.errorNode)}${qs}`
|
|
23569
24122
|
);
|
|
23570
24123
|
try {
|
|
23571
|
-
const result = await client.get(
|
|
24124
|
+
const result = await client.get(path82);
|
|
23572
24125
|
const arrowPath = result.traversalPath.join(" \u2190 ");
|
|
23573
24126
|
const provenances = result.edgeProvenances.length ? result.edgeProvenances.join(", ") : "(direct, no edges traversed)";
|
|
23574
24127
|
const summary = `Root cause for ${input.errorNode} is ${result.rootCauseNode}. ` + result.rootCauseReason + (result.fixRecommendation ? ` Recommended fix: ${result.fixRecommendation}.` : "");
|
|
@@ -23594,12 +24147,12 @@ async function runRootCause(client, input) {
|
|
|
23594
24147
|
}
|
|
23595
24148
|
async function runBlastRadius(client, input) {
|
|
23596
24149
|
const qs = input.depth !== void 0 ? `?depth=${input.depth}` : "";
|
|
23597
|
-
const
|
|
24150
|
+
const path82 = projectPath(
|
|
23598
24151
|
input.project,
|
|
23599
24152
|
`/graph/blast-radius/${encodeURIComponent(input.nodeId)}${qs}`
|
|
23600
24153
|
);
|
|
23601
24154
|
try {
|
|
23602
|
-
const result = await client.get(
|
|
24155
|
+
const result = await client.get(path82);
|
|
23603
24156
|
if (result.totalAffected === 0) {
|
|
23604
24157
|
return {
|
|
23605
24158
|
summary: `${result.origin} has no dependents. Nothing else would break if it failed.`
|
|
@@ -23628,17 +24181,17 @@ async function runBlastRadius(client, input) {
|
|
|
23628
24181
|
}
|
|
23629
24182
|
}
|
|
23630
24183
|
function formatBlastEntry(n) {
|
|
23631
|
-
const tag = n.edgeProvenance ===
|
|
24184
|
+
const tag = n.edgeProvenance === import_types83.Provenance.STALE ? " [STALE \u2014 last seen too long ago]" : "";
|
|
23632
24185
|
return ` \u2022 ${n.nodeId} (distance ${n.distance}, ${n.edgeProvenance})${tag}`;
|
|
23633
24186
|
}
|
|
23634
24187
|
async function runDependencies(client, input) {
|
|
23635
24188
|
const depth = input.depth ?? 3;
|
|
23636
|
-
const
|
|
24189
|
+
const path82 = projectPath(
|
|
23637
24190
|
input.project,
|
|
23638
24191
|
`/graph/dependencies/${encodeURIComponent(input.nodeId)}?depth=${depth}`
|
|
23639
24192
|
);
|
|
23640
24193
|
try {
|
|
23641
|
-
const result = await client.get(
|
|
24194
|
+
const result = await client.get(path82);
|
|
23642
24195
|
if (result.total === 0) {
|
|
23643
24196
|
return {
|
|
23644
24197
|
summary: depth === 1 ? `${input.nodeId} has no direct dependencies in the graph.` : `${input.nodeId} has no dependencies (BFS to depth ${depth}).`
|
|
@@ -23685,7 +24238,7 @@ async function runObservedDependencies(client, input) {
|
|
|
23685
24238
|
if (result.observed) {
|
|
23686
24239
|
return {
|
|
23687
24240
|
summary: `${input.nodeId} makes no outbound runtime calls, but OTel has observed it receiving traffic on ${result.inboundObservedCount} inbound call path${result.inboundObservedCount === 1 ? "" : "s"} \u2014 it's a pure receiver.`,
|
|
23688
|
-
provenance:
|
|
24241
|
+
provenance: import_types83.Provenance.OBSERVED
|
|
23689
24242
|
};
|
|
23690
24243
|
}
|
|
23691
24244
|
const note = result.hasExtractedOutbound ? " Static (EXTRACTED) dependencies exist but no runtime traffic has been seen \u2014 is OTel running?" : "";
|
|
@@ -23695,7 +24248,7 @@ async function runObservedDependencies(client, input) {
|
|
|
23695
24248
|
return {
|
|
23696
24249
|
summary: `${input.nodeId} has ${result.dependencies.length} runtime dependenc${result.dependencies.length === 1 ? "y" : "ies"} confirmed by OTel.`,
|
|
23697
24250
|
block: blockLines.join("\n"),
|
|
23698
|
-
provenance:
|
|
24251
|
+
provenance: import_types83.Provenance.OBSERVED
|
|
23699
24252
|
};
|
|
23700
24253
|
} catch (err) {
|
|
23701
24254
|
if (err instanceof HttpError && err.status === 404) {
|
|
@@ -23730,9 +24283,9 @@ function formatDuration(ms) {
|
|
|
23730
24283
|
return `${Math.round(h / 24)}d`;
|
|
23731
24284
|
}
|
|
23732
24285
|
async function runIncidents(client, input) {
|
|
23733
|
-
const
|
|
24286
|
+
const path82 = input.nodeId ? projectPath(input.project, `/incidents/${encodeURIComponent(input.nodeId)}`) : projectPath(input.project, "/incidents");
|
|
23734
24287
|
try {
|
|
23735
|
-
const body = await client.get(
|
|
24288
|
+
const body = await client.get(path82);
|
|
23736
24289
|
const events = body.events;
|
|
23737
24290
|
if (events.length === 0) {
|
|
23738
24291
|
return {
|
|
@@ -23749,7 +24302,7 @@ async function runIncidents(client, input) {
|
|
|
23749
24302
|
return {
|
|
23750
24303
|
summary: `${target} has ${body.total} recorded incident${body.total === 1 ? "" : "s"}; showing the ${ordered.length} most recent.`,
|
|
23751
24304
|
block: blockLines.join("\n"),
|
|
23752
|
-
provenance:
|
|
24305
|
+
provenance: import_types83.Provenance.OBSERVED
|
|
23753
24306
|
};
|
|
23754
24307
|
} catch (err) {
|
|
23755
24308
|
if (err instanceof HttpError && err.status === 404) {
|
|
@@ -23858,7 +24411,7 @@ async function runStaleEdges(client, input) {
|
|
|
23858
24411
|
return {
|
|
23859
24412
|
summary: `${events.length} stale-edge transition${events.length === 1 ? "" : "s"} recorded${input.edgeType ? ` for ${input.edgeType}` : ""}.`,
|
|
23860
24413
|
block: blockLines.join("\n"),
|
|
23861
|
-
provenance:
|
|
24414
|
+
provenance: import_types83.Provenance.STALE
|
|
23862
24415
|
};
|
|
23863
24416
|
}
|
|
23864
24417
|
async function runPolicies(client, input) {
|
|
@@ -24017,10 +24570,10 @@ async function pushSnapshotToRemote(input) {
|
|
|
24017
24570
|
|
|
24018
24571
|
// src/monitor.ts
|
|
24019
24572
|
var OBSERVED_DEP_EDGE_TYPES = /* @__PURE__ */ new Set([
|
|
24020
|
-
|
|
24021
|
-
|
|
24022
|
-
|
|
24023
|
-
|
|
24573
|
+
import_types84.EdgeType.CALLS,
|
|
24574
|
+
import_types84.EdgeType.CONNECTS_TO,
|
|
24575
|
+
import_types84.EdgeType.PUBLISHES_TO,
|
|
24576
|
+
import_types84.EdgeType.CONSUMES_FROM
|
|
24024
24577
|
]);
|
|
24025
24578
|
function divergenceKey(d) {
|
|
24026
24579
|
const column = "column" in d && d.column ? d.column : "";
|
|
@@ -24065,7 +24618,7 @@ function formatDivergenceLine2(d) {
|
|
|
24065
24618
|
}
|
|
24066
24619
|
}
|
|
24067
24620
|
function formatStaleLine(edgeId) {
|
|
24068
|
-
const parsed = (0,
|
|
24621
|
+
const parsed = (0, import_types84.parseEdgeId)(edgeId);
|
|
24069
24622
|
if (parsed) {
|
|
24070
24623
|
return `\u22EF stale ${parsed.source} \u2192 ${parsed.target} (observed edge went quiet)`;
|
|
24071
24624
|
}
|
|
@@ -24078,7 +24631,7 @@ function divergenceJson(d) {
|
|
|
24078
24631
|
return JSON.stringify({ kind: "divergence", ...d });
|
|
24079
24632
|
}
|
|
24080
24633
|
function staleJson(edgeId) {
|
|
24081
|
-
const parsed = (0,
|
|
24634
|
+
const parsed = (0, import_types84.parseEdgeId)(edgeId);
|
|
24082
24635
|
return JSON.stringify({
|
|
24083
24636
|
kind: "stale",
|
|
24084
24637
|
edgeId,
|
|
@@ -24148,7 +24701,7 @@ var MonitorEmitter = class {
|
|
|
24148
24701
|
// ignores non-OBSERVED edges and non-dependency edge types (structural
|
|
24149
24702
|
// ownership), so only real runtime dependencies reach stdout.
|
|
24150
24703
|
emitObservedEdge(edge) {
|
|
24151
|
-
if (edge.provenance !==
|
|
24704
|
+
if (edge.provenance !== import_types84.Provenance.OBSERVED) return false;
|
|
24152
24705
|
if (!OBSERVED_DEP_EDGE_TYPES.has(edge.type)) return false;
|
|
24153
24706
|
const key = `edge|${edge.id}`;
|
|
24154
24707
|
if (this.seen.has(key)) return false;
|
|
@@ -24306,7 +24859,7 @@ async function runMonitor(opts) {
|
|
|
24306
24859
|
case "edge-added": {
|
|
24307
24860
|
const payload = safeParse(frame.data);
|
|
24308
24861
|
const edge = payload?.edge;
|
|
24309
|
-
if (edge && edge.provenance ===
|
|
24862
|
+
if (edge && edge.provenance === import_types84.Provenance.OBSERVED) {
|
|
24310
24863
|
emitter.emitObservedEdge(edge);
|
|
24311
24864
|
divergences.schedule();
|
|
24312
24865
|
}
|
|
@@ -24386,7 +24939,7 @@ function sleep(ms, signal) {
|
|
|
24386
24939
|
|
|
24387
24940
|
// src/cli-verbs.ts
|
|
24388
24941
|
init_cjs_shims();
|
|
24389
|
-
var
|
|
24942
|
+
var import_node_path80 = __toESM(require("path"), 1);
|
|
24390
24943
|
async function resolveProjectEntry(opts) {
|
|
24391
24944
|
const entries = await listProjects();
|
|
24392
24945
|
if (opts.project) {
|
|
@@ -24396,7 +24949,7 @@ async function resolveProjectEntry(opts) {
|
|
|
24396
24949
|
const cwd = opts.cwd ?? process.cwd();
|
|
24397
24950
|
const resolvedCwd = await normalizeProjectPath(cwd);
|
|
24398
24951
|
for (const entry2 of entries) {
|
|
24399
|
-
if (resolvedCwd === entry2.path || resolvedCwd.startsWith(`${entry2.path}${
|
|
24952
|
+
if (resolvedCwd === entry2.path || resolvedCwd.startsWith(`${entry2.path}${import_node_path80.default.sep}`)) {
|
|
24400
24953
|
return entry2;
|
|
24401
24954
|
}
|
|
24402
24955
|
}
|
|
@@ -24549,7 +25102,7 @@ async function runSync(opts) {
|
|
|
24549
25102
|
}
|
|
24550
25103
|
|
|
24551
25104
|
// src/cli.ts
|
|
24552
|
-
var
|
|
25105
|
+
var import_types85 = require("@neat.is/types");
|
|
24553
25106
|
function isNpxInvocation() {
|
|
24554
25107
|
if (process.env.npm_command === "exec") return true;
|
|
24555
25108
|
const execpath = process.env.npm_execpath ?? "";
|
|
@@ -24920,12 +25473,12 @@ async function runInit(opts) {
|
|
|
24920
25473
|
printDiscoveryReport(opts, services);
|
|
24921
25474
|
const sections = opts.noInstall ? [] : await buildPatchSections(services, opts.project);
|
|
24922
25475
|
const patch = renderPatch(sections);
|
|
24923
|
-
const patchPath =
|
|
25476
|
+
const patchPath = import_node_path81.default.join(opts.scanPath, "neat.patch");
|
|
24924
25477
|
if (opts.dryRun) {
|
|
24925
25478
|
await import_node_fs46.promises.writeFile(patchPath, patch, "utf8");
|
|
24926
25479
|
written.push(patchPath);
|
|
24927
25480
|
console.log(`dry-run: patch written to ${patchPath}`);
|
|
24928
|
-
const gitignorePath =
|
|
25481
|
+
const gitignorePath = import_node_path81.default.join(opts.scanPath, ".gitignore");
|
|
24929
25482
|
const gitignoreExists = await import_node_fs46.promises.stat(gitignorePath).then(() => true).catch(() => false);
|
|
24930
25483
|
const verb = gitignoreExists ? "append" : "create";
|
|
24931
25484
|
console.log(`dry-run: would ${verb} ${gitignorePath} (add neat-out/)`);
|
|
@@ -24937,9 +25490,9 @@ async function runInit(opts) {
|
|
|
24937
25490
|
const graph = getGraph(graphKey);
|
|
24938
25491
|
const projectPaths = pathsForProject(
|
|
24939
25492
|
graphKey,
|
|
24940
|
-
|
|
25493
|
+
import_node_path81.default.join(opts.scanPath, "neat-out")
|
|
24941
25494
|
);
|
|
24942
|
-
const errorsPath =
|
|
25495
|
+
const errorsPath = import_node_path81.default.join(import_node_path81.default.dirname(opts.outPath), import_node_path81.default.basename(projectPaths.errorsPath));
|
|
24943
25496
|
const result = await extractFromDirectory(graph, opts.scanPath, { errorsPath });
|
|
24944
25497
|
await saveGraphToDisk(graph, opts.outPath);
|
|
24945
25498
|
written.push(opts.outPath);
|
|
@@ -25058,9 +25611,9 @@ var CLAUDE_SKILL_CONFIG = {
|
|
|
25058
25611
|
};
|
|
25059
25612
|
function claudeConfigPath() {
|
|
25060
25613
|
const override = process.env.NEAT_CLAUDE_CONFIG;
|
|
25061
|
-
if (override && override.length > 0) return
|
|
25614
|
+
if (override && override.length > 0) return import_node_path81.default.resolve(override);
|
|
25062
25615
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
25063
|
-
return
|
|
25616
|
+
return import_node_path81.default.join(home, ".claude.json");
|
|
25064
25617
|
}
|
|
25065
25618
|
async function runSkill(opts) {
|
|
25066
25619
|
const snippet2 = JSON.stringify(CLAUDE_SKILL_CONFIG, null, 2) + "\n";
|
|
@@ -25084,7 +25637,7 @@ async function runSkill(opts) {
|
|
|
25084
25637
|
...existing,
|
|
25085
25638
|
mcpServers: { ...mcp, neat: CLAUDE_SKILL_CONFIG.mcpServers.neat }
|
|
25086
25639
|
};
|
|
25087
|
-
await import_node_fs46.promises.mkdir(
|
|
25640
|
+
await import_node_fs46.promises.mkdir(import_node_path81.default.dirname(target), { recursive: true });
|
|
25088
25641
|
await import_node_fs46.promises.writeFile(target, JSON.stringify(merged, null, 2) + "\n", "utf8");
|
|
25089
25642
|
console.log(`neat skill: wrote mcpServers.neat to ${target}`);
|
|
25090
25643
|
console.log("restart Claude Code to pick up the new MCP server.");
|
|
@@ -25171,12 +25724,12 @@ async function main() {
|
|
|
25171
25724
|
console.error("neat init: --apply and --dry-run are mutually exclusive");
|
|
25172
25725
|
process.exit(2);
|
|
25173
25726
|
}
|
|
25174
|
-
const scanPath =
|
|
25727
|
+
const scanPath = import_node_path81.default.resolve(target);
|
|
25175
25728
|
const projectExplicit = parsed.project !== null;
|
|
25176
|
-
const projectName = projectExplicit ? project :
|
|
25729
|
+
const projectName = projectExplicit ? project : import_node_path81.default.basename(scanPath);
|
|
25177
25730
|
const projectKey = projectExplicit ? project : DEFAULT_PROJECT;
|
|
25178
|
-
const fallback = pathsForProject(projectKey,
|
|
25179
|
-
const outPath =
|
|
25731
|
+
const fallback = pathsForProject(projectKey, import_node_path81.default.join(scanPath, "neat-out")).snapshotPath;
|
|
25732
|
+
const outPath = import_node_path81.default.resolve(process.env.NEAT_OUT_PATH ?? fallback);
|
|
25180
25733
|
const result = await runInit({
|
|
25181
25734
|
scanPath,
|
|
25182
25735
|
outPath,
|
|
@@ -25197,21 +25750,21 @@ async function main() {
|
|
|
25197
25750
|
usage4();
|
|
25198
25751
|
process.exit(2);
|
|
25199
25752
|
}
|
|
25200
|
-
const scanPath =
|
|
25753
|
+
const scanPath = import_node_path81.default.resolve(target);
|
|
25201
25754
|
const stat = await import_node_fs46.promises.stat(scanPath).catch(() => null);
|
|
25202
25755
|
if (!stat || !stat.isDirectory()) {
|
|
25203
25756
|
console.error(`neat watch: ${scanPath} is not a directory`);
|
|
25204
25757
|
process.exit(2);
|
|
25205
25758
|
}
|
|
25206
|
-
const projectPaths = pathsForProject(project,
|
|
25207
|
-
const outPath =
|
|
25208
|
-
const errorsPath =
|
|
25209
|
-
process.env.NEAT_ERRORS_PATH ??
|
|
25759
|
+
const projectPaths = pathsForProject(project, import_node_path81.default.join(scanPath, "neat-out"));
|
|
25760
|
+
const outPath = import_node_path81.default.resolve(process.env.NEAT_OUT_PATH ?? projectPaths.snapshotPath);
|
|
25761
|
+
const errorsPath = import_node_path81.default.resolve(
|
|
25762
|
+
process.env.NEAT_ERRORS_PATH ?? import_node_path81.default.join(import_node_path81.default.dirname(outPath), import_node_path81.default.basename(projectPaths.errorsPath))
|
|
25210
25763
|
);
|
|
25211
|
-
const staleEventsPath =
|
|
25212
|
-
process.env.NEAT_STALE_EVENTS_PATH ??
|
|
25764
|
+
const staleEventsPath = import_node_path81.default.resolve(
|
|
25765
|
+
process.env.NEAT_STALE_EVENTS_PATH ?? import_node_path81.default.join(import_node_path81.default.dirname(outPath), import_node_path81.default.basename(projectPaths.staleEventsPath))
|
|
25213
25766
|
);
|
|
25214
|
-
const embeddingsCachePath = process.env.NEAT_EMBEDDINGS_CACHE_PATH ?
|
|
25767
|
+
const embeddingsCachePath = process.env.NEAT_EMBEDDINGS_CACHE_PATH ? import_node_path81.default.resolve(process.env.NEAT_EMBEDDINGS_CACHE_PATH) : void 0;
|
|
25215
25768
|
const handle = await startWatch(getGraph(project), {
|
|
25216
25769
|
scanPath,
|
|
25217
25770
|
outPath,
|
|
@@ -25220,7 +25773,7 @@ async function main() {
|
|
|
25220
25773
|
project,
|
|
25221
25774
|
// Resolve NEAT_HOME so a `neat watch` picks up connectors added to
|
|
25222
25775
|
// ~/.neat/connectors.json (#871). Same resolution the rest of the CLI uses.
|
|
25223
|
-
neatHome: process.env.NEAT_HOME ?
|
|
25776
|
+
neatHome: process.env.NEAT_HOME ? import_node_path81.default.resolve(process.env.NEAT_HOME) : import_node_path81.default.join(import_node_os8.default.homedir(), ".neat"),
|
|
25224
25777
|
...embeddingsCachePath ? { embeddingsCachePath } : {},
|
|
25225
25778
|
host: process.env.HOST ?? "0.0.0.0",
|
|
25226
25779
|
port: Number(process.env.PORT ?? 8080),
|
|
@@ -25402,11 +25955,11 @@ async function main() {
|
|
|
25402
25955
|
process.exit(1);
|
|
25403
25956
|
}
|
|
25404
25957
|
async function tryOrchestrator(cmd, parsed) {
|
|
25405
|
-
const scanPath =
|
|
25958
|
+
const scanPath = import_node_path81.default.resolve(cmd);
|
|
25406
25959
|
const stat = await import_node_fs46.promises.stat(scanPath).catch(() => null);
|
|
25407
25960
|
if (!stat || !stat.isDirectory()) return null;
|
|
25408
25961
|
const projectExplicit = parsed.project !== null;
|
|
25409
|
-
const projectName = projectExplicit ? parsed.project :
|
|
25962
|
+
const projectName = projectExplicit ? parsed.project : import_node_path81.default.basename(scanPath);
|
|
25410
25963
|
const result = await runOrchestrator({
|
|
25411
25964
|
scanPath,
|
|
25412
25965
|
project: projectName,
|
|
@@ -25595,10 +26148,10 @@ async function runQueryVerb(cmd, parsed) {
|
|
|
25595
26148
|
const parts = parsed.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
25596
26149
|
const out = [];
|
|
25597
26150
|
for (const p of parts) {
|
|
25598
|
-
const r =
|
|
26151
|
+
const r = import_types85.DivergenceTypeSchema.safeParse(p);
|
|
25599
26152
|
if (!r.success) {
|
|
25600
26153
|
console.error(
|
|
25601
|
-
`neat divergences: unknown --type "${p}". allowed: ${
|
|
26154
|
+
`neat divergences: unknown --type "${p}". allowed: ${import_types85.DivergenceTypeSchema.options.join(", ")}`
|
|
25602
26155
|
);
|
|
25603
26156
|
return 2;
|
|
25604
26157
|
}
|